OSDN Git Service

Make parts of ioctl_linux.c slightly less ugly
[android-x86/external-modules-rtl8723au.git] / os_dep / ioctl_linux.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * 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_conf.h>
23 #include <osdep_service.h>
24 #include <drv_types.h>
25 #include <wlan_bssdef.h>
26 #include <rtw_debug.h>
27 #include <linux/ieee80211.h>
28 #include <wifi.h>
29 #include <rtw_mlme.h>
30 #include <rtw_mlme_ext.h>
31 #include <rtw_ioctl.h>
32 #include <rtw_ioctl_set.h>
33
34 #include <usb_ops.h>
35 #include <rtw_version.h>
36
37 #ifdef CONFIG_RTL8192C
38 #include <rtl8192c_hal.h>
39 #endif
40 #ifdef CONFIG_RTL8192D
41 #include <rtl8192d_hal.h>
42 #endif
43 #ifdef CONFIG_RTL8723A
44 #include <rtl8723a_pg.h>
45 #include <rtl8723a_hal.h>
46 #endif
47 #ifdef CONFIG_RTL8188E
48 #include <rtl8188e_hal.h>
49 #endif
50
51 extern s32 FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer);
52
53 #define RTL_IOCTL_WPA_SUPPLICANT        SIOCIWFIRSTPRIV+30
54
55 #define SCAN_ITEM_SIZE 768
56 #define MAX_CUSTOM_LEN 64
57 #define RATE_COUNT 4
58
59 #ifdef CONFIG_GLOBAL_UI_PID
60 extern int ui_pid[3];
61 #endif
62
63 // combo scan
64 #define WEXT_CSCAN_AMOUNT 9
65 #define WEXT_CSCAN_BUF_LEN              360
66 #define WEXT_CSCAN_HEADER               "CSCAN S\x01\x00\x00S\x00"
67 #define WEXT_CSCAN_HEADER_SIZE          12
68 #define WEXT_CSCAN_SSID_SECTION         'S'
69 #define WEXT_CSCAN_CHANNEL_SECTION      'C'
70 #define WEXT_CSCAN_NPROBE_SECTION       'N'
71 #define WEXT_CSCAN_ACTV_DWELL_SECTION   'A'
72 #define WEXT_CSCAN_PASV_DWELL_SECTION   'P'
73 #define WEXT_CSCAN_HOME_DWELL_SECTION   'H'
74 #define WEXT_CSCAN_TYPE_SECTION         'T'
75
76
77 extern u8 key_2char2num(u8 hch, u8 lch);
78 extern u8 str_2char2num(u8 hch, u8 lch);
79 extern u8 convert_ip_addr(u8 hch, u8 mch, u8 lch);
80
81 u32 rtw_rates[] =
82 {
83         1000000,
84         2000000,
85         5500000,
86         11000000,
87         6000000,
88         9000000,
89         12000000,
90         18000000,
91         24000000,
92         36000000,
93         48000000,
94         54000000
95 };
96
97 static const char *const iw_operation_mode[] =
98 {
99         "Auto",
100         "Ad-Hoc",
101         "Managed",
102         "Master",
103         "Repeater",
104         "Secondary",
105         "Monitor"
106 };
107
108 static int hex2num_i(char c)
109 {
110         if (c >= '0' && c <= '9')
111                 return c - '0';
112         if (c >= 'a' && c <= 'f')
113                 return c - 'a' + 10;
114         if (c >= 'A' && c <= 'F')
115                 return c - 'A' + 10;
116         return -1;
117 }
118
119 static int hex2byte_i(const char *hex)
120 {
121         int a, b;
122         a = hex2num_i(*hex++);
123         if (a < 0)
124                 return -1;
125         b = hex2num_i(*hex++);
126         if (b < 0)
127                 return -1;
128         return (a << 4) | b;
129 }
130
131 /**
132  * hwaddr_aton - Convert ASCII string to MAC address
133  * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
134  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
135  * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
136  */
137 static int hwaddr_aton_i(const char *txt, u8 *addr)
138 {
139         int i;
140
141         for (i = 0; i < 6; i++) {
142                 int a, b;
143
144                 a = hex2num_i(*txt++);
145                 if (a < 0)
146                         return -1;
147                 b = hex2num_i(*txt++);
148                 if (b < 0)
149                         return -1;
150                 *addr++ = (a << 4) | b;
151                 if (i < 5 && *txt++ != ':')
152                         return -1;
153         }
154
155         return 0;
156 }
157
158 static void indicate_wx_custom_event(struct rtw_adapter *padapter, char *msg)
159 {
160         u8 *buff, *p;
161         union iwreq_data wrqu;
162
163         if (strlen(msg) > IW_CUSTOM_MAX) {
164                 DBG_8723A("%s strlen(msg):%zu > IW_CUSTOM_MAX:%u\n",
165                           __func__ , strlen(msg), IW_CUSTOM_MAX);
166                 return;
167         }
168
169         buff = kzalloc(IW_CUSTOM_MAX + 1, GFP_KERNEL);
170         if (!buff)
171                 return;
172
173         memcpy(buff, msg, strlen(msg));
174
175         memset(&wrqu, 0, sizeof(wrqu));
176         wrqu.data.length = strlen(msg);
177
178         DBG_8723A("%s %s\n", __func__, buff);
179 #ifndef CONFIG_IOCTL_CFG80211
180         wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
181 #endif
182
183         kfree(buff);
184 }
185
186
187 static void request_wps_pbc_event(struct rtw_adapter *padapter)
188 {
189         u8 *buff, *p;
190         union iwreq_data wrqu;
191
192         buff = kzalloc(IW_CUSTOM_MAX, GFP_KERNEL);
193         if(!buff)
194                 return;
195
196         p = buff;
197         p += sprintf(p, "WPS_PBC_START.request=TRUE");
198
199         memset(&wrqu, 0, sizeof(wrqu));
200
201         wrqu.data.length = p-buff;
202
203         wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ? wrqu.data.length:IW_CUSTOM_MAX;
204
205         DBG_8723A("%s\n", __func__);
206
207 #ifndef CONFIG_IOCTL_CFG80211
208         wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
209 #endif
210
211         if (buff)
212                 kfree(buff);
213 }
214
215
216 void indicate_wx_scan_complete_event(struct rtw_adapter *padapter)
217 {
218         union iwreq_data wrqu;
219         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
220
221         memset(&wrqu, 0, sizeof(union iwreq_data));
222
223         //DBG_8723A("+rtw_indicate_wx_scan_complete_event\n");
224 #ifndef CONFIG_IOCTL_CFG80211
225         wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
226 #endif
227 }
228
229
230 void rtw_indicate_wx_assoc_event(struct rtw_adapter *padapter)
231 {
232         union iwreq_data wrqu;
233         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
234
235         memset(&wrqu, 0, sizeof(union iwreq_data));
236
237         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
238
239         memcpy(wrqu.ap_addr.sa_data,
240                pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
241
242         DBG_8723A_LEVEL(_drv_always_, "assoc success\n");
243 #ifndef CONFIG_IOCTL_CFG80211
244         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
245 #endif
246 }
247
248 void rtw_indicate_wx_disassoc_event(struct rtw_adapter *padapter)
249 {
250         union iwreq_data wrqu;
251
252         memset(&wrqu, 0, sizeof(union iwreq_data));
253
254         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
255         memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
256
257 #ifndef CONFIG_IOCTL_CFG80211
258         DBG_8723A_LEVEL(_drv_always_, "indicate disassoc\n");
259         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
260 #endif
261 }
262
263 /*
264 uint    rtw_is_cckrates_included(u8 *rate)
265 {
266                 u32     i = 0;
267
268                 while(rate[i]!=0)
269                 {
270                         if  (  (((rate[i]) & 0x7f) == 2)        || (((rate[i]) & 0x7f) == 4) ||
271                         (((rate[i]) & 0x7f) == 11)  || (((rate[i]) & 0x7f) == 22) )
272                         return _TRUE;
273                         i++;
274                 }
275
276                 return _FALSE;
277 }
278
279 uint    rtw_is_cckratesonly_included(u8 *rate)
280 {
281         u32 i = 0;
282
283         while(rate[i]!=0)
284         {
285                         if  (  (((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
286                                 (((rate[i]) & 0x7f) != 11)  && (((rate[i]) & 0x7f) != 22) )
287                         return _FALSE;
288                         i++;
289         }
290
291         return _TRUE;
292 }
293 */
294
295 static char *translate_scan(struct rtw_adapter *padapter,
296                             struct iw_request_info* info,
297                             struct wlan_network *pnetwork,
298                             char *start, char *stop)
299 {
300         struct iw_event iwe;
301         u16 cap;
302         u32 ht_ielen = 0;
303         char custom[MAX_CUSTOM_LEN];
304         char *p;
305         u16 max_rate=0, rate, ht_cap=_FALSE;
306         u32 i = 0;
307         char *current_val;
308         long rssi;
309         u8 bw_40MHz=0, short_GI=0;
310         u16 mcs_rate=0;
311         struct registry_priv *pregpriv = &padapter->registrypriv;
312 #ifdef CONFIG_P2P
313         struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
314 #endif //CONFIG_P2P
315
316 #ifdef CONFIG_P2P
317 #ifdef CONFIG_WFD
318         if (pwdinfo->wfd_info->scan_result_type == SCAN_RESULT_ALL) {
319         } else if ((pwdinfo->wfd_info->scan_result_type == SCAN_RESULT_P2P_ONLY) ||
320                    (pwdinfo->wfd_info->scan_result_type == SCAN_RESULT_WFD_TYPE))
321 #endif // CONFIG_WFD
322         {
323                 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
324                         u32     blnGotP2PIE = _FALSE;
325
326                         /*
327                          * User is doing the P2P device discovery
328                          * The prefix of SSID should be "DIRECT-" and the IE
329                          * should contains the P2P IE. If not, the driver
330                          * should ignore this AP and go to the next AP.
331                          *
332                          * Verifying the SSID
333                          */
334                         if (!memcmp(pnetwork->network.Ssid.Ssid,
335                                     pwdinfo->p2p_wildcard_ssid,
336                                     P2P_WILDCARD_SSID_LEN)) {
337                                 u32 p2pielen = 0;
338
339                                 /* Probe Request */
340                                 if (pnetwork->network.Reserved[0] == 2) {
341                                         /* Verifying the P2P IE */
342                                         if (rtw_get_p2p_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &p2pielen)) {
343                                                 blnGotP2PIE = _TRUE;
344                                         }
345                                 } else { /* Beacon or Probe Respones */
346                                          /*     Verifying the P2P IE */
347                                         if (rtw_get_p2p_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen)) {
348                                                 blnGotP2PIE = _TRUE;
349                                         }
350                                 }
351                         }
352
353                         if (blnGotP2PIE == _FALSE)
354                         {
355                                 return start;
356                         }
357
358                 }
359         }
360
361 #ifdef CONFIG_WFD
362         if (pwdinfo->wfd_info->scan_result_type == SCAN_RESULT_WFD_TYPE) {
363                 u32     blnGotWFD = _FALSE;
364                 u8      wfd_ie[128] = {0x00};
365                 uint    wfd_ielen = 0;
366
367                 if (rtw_get_wfd_ie(&pnetwork->network.IEs[12],
368                                    pnetwork->network.IELength - 12,
369                                    wfd_ie, &wfd_ielen)) {
370                         u8      wfd_devinfo[6] = {0x00};
371                         uint    wfd_devlen = 6;
372
373                         if (rtw_get_wfd_attr_content(wfd_ie, wfd_ielen,
374                                                      WFD_ATTR_DEVICE_INFO,
375                                                      wfd_devinfo,
376                                                      &wfd_devlen)) {
377                                 if (pwdinfo->wfd_info->wfd_device_type ==
378                                     WFD_DEVINFO_PSINK) {
379                                         /* the first two bits will indicate
380                                            the WFD device type */
381                                         if ((wfd_devinfo[1] & 0x03) ==
382                                             WFD_DEVINFO_SOURCE) {
383                                                 /* If this device is Miracast
384                                                  * PSink device, the scan
385                                                  * reuslt should just provide
386                                                  * the Miracast source. */
387                                                 blnGotWFD = _TRUE;
388                                         }
389                                 }
390                                 else if (pwdinfo->wfd_info->wfd_device_type ==
391                                          WFD_DEVINFO_SOURCE) {
392                                         /* the first two bits will indicate
393                                            the WFD device type */
394                                         if ((wfd_devinfo[1] & 0x03) ==
395                                             WFD_DEVINFO_PSINK) {
396                                                 /*
397                                                  * If this device is Miracast
398                                                  * source device, the scan
399                                                  * reuslt should just provide
400                                                  * the Miracast PSink.
401                                                  * Todo: How about the SSink?!
402                                                  */
403                                                 blnGotWFD = _TRUE;
404                                         }
405                                 }
406                         }
407                 }
408
409                 if (blnGotWFD == _FALSE)
410                 {
411                         return start;
412                 }
413         }
414 #endif // CONFIG_WFD
415
416 #endif //CONFIG_P2P
417
418         /*  AP MAC address  */
419         iwe.cmd = SIOCGIWAP;
420         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
421
422         memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
423         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
424
425         /* Add the ESSID */
426         iwe.cmd = SIOCGIWESSID;
427         iwe.u.data.flags = 1;
428         iwe.u.data.length = min((u16)pnetwork->network.Ssid.SsidLength,
429                                 (u16)32);
430         start = iwe_stream_add_point(info, start, stop, &iwe,
431                                      pnetwork->network.Ssid.Ssid);
432
433         //parsing HT_CAP_IE
434         p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
435                        &ht_ielen, pnetwork->network.IELength - 12);
436
437         if (p && ht_ielen>0)
438         {
439                 struct ieee80211_ht_cap *pht_capie;
440                 ht_cap = _TRUE;
441                 pht_capie = (struct ieee80211_ht_cap *)(p+2);
442                 memcpy(&mcs_rate , &pht_capie->mcs, 2);
443                 bw_40MHz = (pht_capie->cap_info &
444                             IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0;
445                 short_GI = (pht_capie->cap_info & 
446                             (IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1:0;
447         }
448
449         /* Add the protocol name */
450         iwe.cmd = SIOCGIWNAME;
451         if ((rtw_is_cckratesonly_included((u8*)&pnetwork->network.SupportedRates)) == _TRUE) {
452                 if (ht_cap == _TRUE)
453                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
454                 else
455                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
456         } else if ((rtw_is_cckrates_included((u8*)&pnetwork->network.SupportedRates)) == _TRUE) {
457                 if(ht_cap == _TRUE)
458                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
459                 else
460                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
461         } else {
462                 if (pnetwork->network.Configuration.DSConfig > 14)
463                 {
464                         if(ht_cap == _TRUE)
465                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
466                         else
467                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
468                 } else {
469                         if (ht_cap == _TRUE)
470                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
471                         else
472                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
473                 }
474         }
475
476         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
477
478           /* Add mode */
479         iwe.cmd = SIOCGIWMODE;
480         memcpy((u8 *)&cap,
481                rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
482
483
484         cap = le16_to_cpu(cap);
485
486         if (cap & (WLAN_CAPABILITY_IBSS |WLAN_CAPABILITY_ESS)) {
487                 if (cap & WLAN_CAPABILITY_ESS)
488                         iwe.u.mode = IW_MODE_MASTER;
489                 else
490                         iwe.u.mode = IW_MODE_ADHOC;
491
492                 start = iwe_stream_add_event(info, start, stop, &iwe,
493                                              IW_EV_UINT_LEN);
494         }
495
496         if (pnetwork->network.Configuration.DSConfig<1 /*|| pnetwork->network.Configuration.DSConfig>14*/)
497                 pnetwork->network.Configuration.DSConfig = 1;
498
499          /* Add frequency/channel */
500         iwe.cmd = SIOCGIWFREQ;
501         iwe.u.freq.m =
502                 rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
503         iwe.u.freq.e = 1;
504         iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
505         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
506
507         /* Add encryption capability */
508         iwe.cmd = SIOCGIWENCODE;
509         if (cap & WLAN_CAPABILITY_PRIVACY)
510                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
511         else
512                 iwe.u.data.flags = IW_ENCODE_DISABLED;
513         iwe.u.data.length = 0;
514         start = iwe_stream_add_point(info, start, stop, &iwe,
515                                      pnetwork->network.Ssid.Ssid);
516
517         /*Add basic and extended rates */
518         max_rate = 0;
519         p = custom;
520         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
521         while (pnetwork->network.SupportedRates[i] != 0) {
522                 rate = pnetwork->network.SupportedRates[i]&0x7F;
523                 if (rate > max_rate)
524                         max_rate = rate;
525                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
526                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
527                 i++;
528         }
529
530         if (ht_cap == _TRUE)
531         {
532                 if (mcs_rate & 0x8000)//MCS15
533                 {
534                         max_rate = (bw_40MHz) ?
535                                 ((short_GI) ? 300 : 270) : ((short_GI)?144:130);
536
537                 } else if (mcs_rate & 0x0080)//MCS7
538                 {
539                         max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
540                 } else { //default MCS7
541                         //DBG_8723A("wx_get_scan, mcs_rate_bitmap=0x%x\n", mcs_rate);
542                         max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
543                 }
544
545                 max_rate = max_rate*2;//Mbps/2;
546         }
547
548         iwe.cmd = SIOCGIWRATE;
549         iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
550         iwe.u.bitrate.value = max_rate * 500000;
551         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
552
553         //parsing WPA/WPA2 IE
554         {
555                 u8 buf[MAX_WPA_IE_LEN];
556                 u8 wpa_ie[255],rsn_ie[255];
557                 u16 wpa_len=0,rsn_len=0;
558                 u8 *p;
559                 int out_len=0;
560                 out_len=rtw_get_sec_ie(pnetwork->network.IEs ,pnetwork->network.IELength,rsn_ie,&rsn_len,wpa_ie,&wpa_len);
561                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: ssid=%s\n",pnetwork->network.Ssid.Ssid));
562                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: wpa_len=%d rsn_len=%d\n",wpa_len,rsn_len));
563
564                 if (wpa_len > 0) {
565                         p=buf;
566                         memset(buf, 0, MAX_WPA_IE_LEN);
567                         p += sprintf(p, "wpa_ie=");
568                         for (i = 0; i < wpa_len; i++) {
569                                 p += sprintf(p, "%02x", wpa_ie[i]);
570                         }
571
572                         memset(&iwe, 0, sizeof(iwe));
573                         iwe.cmd = IWEVCUSTOM;
574                         iwe.u.data.length = strlen(buf);
575                         start = iwe_stream_add_point(info, start, stop,
576                                                      &iwe,buf);
577
578                         memset(&iwe, 0, sizeof(iwe));
579                         iwe.cmd =IWEVGENIE;
580                         iwe.u.data.length = wpa_len;
581                         start = iwe_stream_add_point(info, start, stop,
582                                                      &iwe, wpa_ie);
583                 }
584                 if (rsn_len > 0) {
585                         p = buf;
586                         memset(buf, 0, MAX_WPA_IE_LEN);
587                         p += sprintf(p, "rsn_ie=");
588                         for (i = 0; i < rsn_len; i++) {
589                                 p += sprintf(p, "%02x", rsn_ie[i]);
590                         }
591                         memset(&iwe, 0, sizeof(iwe));
592                         iwe.cmd = IWEVCUSTOM;
593                         iwe.u.data.length = strlen(buf);
594                         start = iwe_stream_add_point(info, start, stop,
595                                                      &iwe,buf);
596
597                         memset(&iwe, 0, sizeof(iwe));
598                         iwe.cmd =IWEVGENIE;
599                         iwe.u.data.length = rsn_len;
600                         start = iwe_stream_add_point(info, start, stop,
601                                                      &iwe, rsn_ie);
602                 }
603         }
604
605         /* parsing WPS IE */
606         {
607                 uint cnt = 0,total_ielen;
608                 u8 *wpsie_ptr=NULL;
609                 uint wps_ielen = 0;
610
611                 u8 *ie_ptr = pnetwork->network.IEs +_FIXED_IE_LENGTH_;
612                 total_ielen= pnetwork->network.IELength - _FIXED_IE_LENGTH_;
613
614                 while(cnt < total_ielen)
615                 {
616                         if(rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen>2))
617                         {
618                                 wpsie_ptr = &ie_ptr[cnt];
619                                 iwe.cmd =IWEVGENIE;
620                                 iwe.u.data.length = (u16)wps_ielen;
621                                 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
622                         }
623                         cnt+=ie_ptr[cnt+1]+2; //goto next
624                 }
625         }
626
627 {
628         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
629         u8 ss, sq;
630
631         /* Add quality statistics */
632         iwe.cmd = IWEVQUAL;
633         iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID
634 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
635                 | IW_QUAL_DBM
636 #endif
637         ;
638
639         if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&
640             is_same_network(&pmlmepriv->cur_network.network,
641                             &pnetwork->network)) {
642                 ss = padapter->recvpriv.signal_strength;
643                 sq = padapter->recvpriv.signal_qual;
644         } else {
645                 ss = pnetwork->network.PhyInfo.SignalStrength;
646                 sq = pnetwork->network.PhyInfo.SignalQuality;
647         }
648
649
650 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
651         iwe.u.qual.level = (u8) translate_percentage_to_dbm(ss);//dbm
652 #else
653         iwe.u.qual.level = (u8)ss;//%
654 #ifdef CONFIG_BT_COEXIST
655         BT_SignalCompensation(padapter, &iwe.u.qual.level, NULL);
656 #endif // CONFIG_BT_COEXIST
657 #endif
658
659         iwe.u.qual.qual = (u8)sq;   // signal quality
660
661         iwe.u.qual.noise = 0; // noise level
662
663         //DBG_8723A("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);
664
665         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
666 }
667
668         return start;
669 }
670
671 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
672 {
673         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
674         int ret = 0;
675
676         if ((value & AUTH_ALG_SHARED_KEY)&&(value & AUTH_ALG_OPEN_SYSTEM))
677         {
678                 DBG_8723A("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and  AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n",value);
679                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
680                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
681                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
682         }
683         else if (value & AUTH_ALG_SHARED_KEY)
684         {
685                 DBG_8723A("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY  [value:0x%x]\n",value);
686                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
687
688                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
689                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
690         }
691         else if(value & AUTH_ALG_OPEN_SYSTEM)
692         {
693                 DBG_8723A("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
694                 //padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
695                 if(padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK)
696                 {
697                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
698                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
699                 }
700
701         }
702         else if(value & AUTH_ALG_LEAP)
703         {
704                 DBG_8723A("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
705         }
706         else
707         {
708                 DBG_8723A("wpa_set_auth_algs, error!\n");
709                 ret = -EINVAL;
710         }
711
712         return ret;
713
714 }
715
716 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
717 {
718         int ret = 0;
719         u32 wep_key_idx, wep_key_len,wep_total_len;
720         NDIS_802_11_WEP  *pwep = NULL;
721         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
722         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
723         struct security_priv *psecuritypriv = &padapter->securitypriv;
724 #ifdef CONFIG_P2P
725         struct wifidirect_info* pwdinfo = &padapter->wdinfo;
726 #endif //CONFIG_P2P
727
728 _func_enter_;
729
730         param->u.crypt.err = 0;
731         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
732
733         if (param_len < (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len)
734         {
735                 ret =  -EINVAL;
736                 goto exit;
737         }
738
739         if (is_broadcast_ether_addr(param->sta_addr)) {
740                 if (param->u.crypt.idx >= WEP_KEYS)
741                 {
742                         ret = -EINVAL;
743                         goto exit;
744                 }
745         } else {
746                         {
747                 ret = -EINVAL;
748                 goto exit;
749         }
750         }
751
752         if (strcmp(param->u.crypt.alg, "WEP") == 0)
753         {
754                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("wpa_set_encryption, crypt.alg = WEP\n"));
755                 DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n");
756
757                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
758                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
759                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP40_;
760
761                 wep_key_idx = param->u.crypt.idx;
762                 wep_key_len = param->u.crypt.key_len;
763
764                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("(1)wep_key_idx=%d\n", wep_key_idx));
765                 DBG_8723A("(1)wep_key_idx=%d\n", wep_key_idx);
766
767                 if (wep_key_idx > WEP_KEYS)
768                         return -EINVAL;
769
770                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("(2)wep_key_idx=%d\n", wep_key_idx));
771
772                 if (wep_key_len > 0)
773                 {
774                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
775                         wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
776                         pwep =(NDIS_802_11_WEP   *) kzalloc(wep_total_len, GFP_KERNEL);
777                         if (pwep == NULL){
778                                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,(" wpa_set_encryption: pwep allocate fail !!!\n"));
779                                 goto exit;
780                         }
781
782                         pwep->KeyLength = wep_key_len;
783                         pwep->Length = wep_total_len;
784
785                         if(wep_key_len==13)
786                         {
787                                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;
788                                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP104_;
789                         }
790                 }
791                 else {
792                         ret = -EINVAL;
793                         goto exit;
794                 }
795
796                 pwep->KeyIndex = wep_key_idx;
797                 pwep->KeyIndex |= 0x80000000;
798
799                 memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
800
801                 if(param->u.crypt.set_tx)
802                 {
803                         DBG_8723A("wep, set_tx=1\n");
804
805                         if(rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
806                         {
807                                 ret = -EOPNOTSUPP ;
808                         }
809                 }
810                 else
811                 {
812                         DBG_8723A("wep, set_tx=0\n");
813
814                         //don't update "psecuritypriv->dot11PrivacyAlgrthm" and
815                         //"psecuritypriv->dot11PrivacyKeyIndex=keyid", but can rtw_set_key to fw/cam
816
817                         if (wep_key_idx >= WEP_KEYS) {
818                                 ret = -EOPNOTSUPP ;
819                                 goto exit;
820                         }
821
822                       memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
823                         psecuritypriv->dot11DefKeylen[wep_key_idx]=pwep->KeyLength;
824                         rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
825                 }
826
827                 goto exit;
828         }
829
830         if(padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) // 802_1x
831         {
832                 struct sta_info * psta,*pbcmc_sta;
833                 struct sta_priv * pstapriv = &padapter->stapriv;
834
835                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == _TRUE) //sta mode
836                 {
837                         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
838                         if (psta == NULL) {
839                                 //DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail \n"));
840                         }
841                         else
842                         {
843                                 //Jeff: don't disable ieee8021x_blocked while clearing key
844                                 if (strcmp(param->u.crypt.alg, "none") != 0)
845                                         psta->ieee8021x_blocked = _FALSE;
846
847                                 if((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)||
848                                                 (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
849                                 {
850                                         psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
851                                 }
852
853                                 if(param->u.crypt.set_tx ==1)//pairwise key
854                                 {
855                                         memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
856
857                                         if(strcmp(param->u.crypt.alg, "TKIP") == 0)//set mic key
858                                         {
859                                                 //DEBUG_ERR(("\nset key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len));
860                                                 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
861                                                 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
862
863                                                 padapter->securitypriv.busetkipkey=_FALSE;
864                                                 //_set_timer(&padapter->securitypriv.tkip_timer, 50);
865                                         }
866
867                                         //DEBUG_ERR((" param->u.crypt.key_len=%d\n",param->u.crypt.key_len));
868                                         DBG_8723A(" ~~~~set sta key:unicastkey\n");
869
870                                         rtw_setstakey_cmd(padapter, (unsigned char *)psta, _TRUE);
871                                 }
872                                 else//group key
873                                 {
874                                         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));
875                                         memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[16]),8);
876                                         memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[24]),8);
877                                         padapter->securitypriv.binstallGrpkey = _TRUE;
878                                         //DEBUG_ERR((" param->u.crypt.key_len=%d\n", param->u.crypt.key_len));
879                                         DBG_8723A(" ~~~~set sta key:groupkey\n");
880
881                                         padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
882
883                                         rtw_set_key(padapter,&padapter->securitypriv,param->u.crypt.idx, 1);
884 #ifdef CONFIG_P2P
885                                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
886                                         {
887                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
888                                         }
889 #endif //CONFIG_P2P
890
891                                 }
892                         }
893
894                         pbcmc_sta=rtw_get_bcmc_stainfo(padapter);
895                         if(pbcmc_sta==NULL)
896                         {
897                                 //DEBUG_ERR( ("Set OID_802_11_ADD_KEY: bcmc stainfo is null \n"));
898                         }
899                         else
900                         {
901                                 //Jeff: don't disable ieee8021x_blocked while clearing key
902                                 if (strcmp(param->u.crypt.alg, "none") != 0)
903                                         pbcmc_sta->ieee8021x_blocked = _FALSE;
904
905                                 if((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)||
906                                                 (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
907                                 {
908                                         pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
909                                 }
910                         }
911                 }
912                 else if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) //adhoc mode
913                 {
914                 }
915         }
916
917 exit:
918
919         if (pwep) {
920                 kfree((u8 *)pwep);
921         }
922
923 _func_exit_;
924
925         return ret;
926 }
927
928 static int rtw_set_wpa_ie(struct rtw_adapter *padapter, char *pie, unsigned short ielen)
929 {
930         u8 *buf=NULL, *pos=NULL;
931         u32 left;
932         int group_cipher = 0, pairwise_cipher = 0;
933         int ret = 0;
934         u8 null_addr[]= {0,0,0,0,0,0};
935 #ifdef CONFIG_P2P
936         struct wifidirect_info* pwdinfo = &padapter->wdinfo;
937 #endif //CONFIG_P2P
938
939         if((ielen > MAX_WPA_IE_LEN) || (pie == NULL)){
940                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
941                 if(pie == NULL)
942                         return ret;
943                 else
944                         return -EINVAL;
945         }
946
947         if(ielen)
948         {
949                 buf = kmalloc(ielen, GFP_KERNEL);
950                 if (buf == NULL){
951                         ret =  -ENOMEM;
952                         goto exit;
953                 }
954
955                 memcpy(buf, pie , ielen);
956
957                 //dump
958                 {
959                         int i;
960                         DBG_8723A("\n wpa_ie(length:%d):\n", ielen);
961                         for(i=0;i<ielen;i=i+8)
962                                 DBG_8723A("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]);
963                 }
964
965                 pos = buf;
966                 if(ielen < RSN_HEADER_LEN){
967                         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("Ie len too short %d\n", ielen));
968                         ret  = -1;
969                         goto exit;
970                 }
971
972                 if(rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
973                 {
974                         padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
975                         padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPAPSK;
976                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
977                 }
978
979                 if(rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
980                 {
981                         padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
982                         padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPA2PSK;
983                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
984                 }
985
986                 if (group_cipher == 0)
987                 {
988                         group_cipher = WPA_CIPHER_NONE;
989                 }
990                 if (pairwise_cipher == 0)
991                 {
992                         pairwise_cipher = WPA_CIPHER_NONE;
993                 }
994
995                 switch(group_cipher)
996                 {
997                         case WPA_CIPHER_NONE:
998                                 padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
999                                 padapter->securitypriv.ndisencryptstatus=Ndis802_11EncryptionDisabled;
1000                                 break;
1001                         case WPA_CIPHER_WEP40:
1002                                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP40_;
1003                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1004                                 break;
1005                         case WPA_CIPHER_TKIP:
1006                                 padapter->securitypriv.dot118021XGrpPrivacy=_TKIP_;
1007                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1008                                 break;
1009                         case WPA_CIPHER_CCMP:
1010                                 padapter->securitypriv.dot118021XGrpPrivacy=_AES_;
1011                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1012                                 break;
1013                         case WPA_CIPHER_WEP104:
1014                                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP104_;
1015                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1016                                 break;
1017                 }
1018
1019                 switch(pairwise_cipher)
1020                 {
1021                         case WPA_CIPHER_NONE:
1022                                 padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
1023                                 padapter->securitypriv.ndisencryptstatus=Ndis802_11EncryptionDisabled;
1024                                 break;
1025                         case WPA_CIPHER_WEP40:
1026                                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
1027                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1028                                 break;
1029                         case WPA_CIPHER_TKIP:
1030                                 padapter->securitypriv.dot11PrivacyAlgrthm=_TKIP_;
1031                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1032                                 break;
1033                         case WPA_CIPHER_CCMP:
1034                                 padapter->securitypriv.dot11PrivacyAlgrthm=_AES_;
1035                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1036                                 break;
1037                         case WPA_CIPHER_WEP104:
1038                                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;
1039                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1040                                 break;
1041                 }
1042
1043                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1044                 {//set wps_ie
1045                         u16 cnt = 0;
1046                         u8 eid, wps_oui[4]={0x0,0x50,0xf2,0x04};
1047
1048                         while( cnt < ielen )
1049                         {
1050                                 eid = buf[cnt];
1051
1052                                 if ((eid ==_VENDOR_SPECIFIC_IE_) &&
1053                                     (!memcmp(&buf[cnt+2], wps_oui, 4))) {
1054                                         DBG_8723A("SET WPS_IE\n");
1055
1056                                         padapter->securitypriv.wps_ie_len = ( (buf[cnt+1]+2) < (MAX_WPA_IE_LEN<<2)) ? (buf[cnt+1]+2):(MAX_WPA_IE_LEN<<2);
1057
1058                                         memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
1059
1060                                         set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
1061
1062 #ifdef CONFIG_P2P
1063                                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
1064                                         {
1065                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
1066                                         }
1067 #endif //CONFIG_P2P
1068                                         cnt += buf[cnt+1]+2;
1069
1070                                         break;
1071                                 } else {
1072                                         cnt += buf[cnt+1]+2; //goto next
1073                                 }
1074                         }
1075                 }
1076         }
1077
1078         //TKIP and AES disallow multicast packets until installing group key
1079         if(padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
1080                 || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
1081                 || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
1082                 //WPS open need to enable multicast
1083                 //|| check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == _TRUE)
1084                 rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
1085
1086         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1087                  ("rtw_set_wpa_ie: pairwise_cipher=0x%08x padapter->securitypriv.ndisencryptstatus=%d padapter->securitypriv.ndisauthtype=%d\n",
1088                   pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
1089
1090 exit:
1091
1092         if (buf)
1093                 kfree(buf);
1094
1095         return ret;
1096 }
1097
1098 static int rtw_wx_get_name(struct net_device *dev,
1099                              struct iw_request_info *info,
1100                              union iwreq_data *wrqu, char *extra)
1101 {
1102         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1103         u16 cap;
1104         u32 ht_ielen = 0;
1105         char *p;
1106         u8 ht_cap=_FALSE;
1107         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1108         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
1109         NDIS_802_11_RATES_EX* prates = NULL;
1110
1111         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("cmd_code=%x\n", info->cmd));
1112
1113         _func_enter_;
1114
1115         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == _TRUE)
1116         {
1117                 //parsing HT_CAP_IE
1118                 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
1119                 if(p && ht_ielen>0)
1120                 {
1121                         ht_cap = _TRUE;
1122                 }
1123
1124                 prates = &pcur_bss->SupportedRates;
1125
1126                 if (rtw_is_cckratesonly_included((u8*)prates) == _TRUE)
1127                 {
1128                         if(ht_cap == _TRUE)
1129                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
1130                         else
1131                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
1132                 }
1133                 else if ((rtw_is_cckrates_included((u8*)prates)) == _TRUE)
1134                 {
1135                         if(ht_cap == _TRUE)
1136                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
1137                         else
1138                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
1139                 }
1140                 else
1141                 {
1142                         if(pcur_bss->Configuration.DSConfig > 14)
1143                         {
1144                                 if(ht_cap == _TRUE)
1145                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
1146                                 else
1147                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
1148                         }
1149                         else
1150                         {
1151                                 if(ht_cap == _TRUE)
1152                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
1153                                 else
1154                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
1155                         }
1156                 }
1157         }
1158         else
1159         {
1160                 //prates = &padapter->registrypriv.dev_network.SupportedRates;
1161                 //snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
1162                 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
1163         }
1164
1165         _func_exit_;
1166
1167         return 0;
1168 }
1169
1170 static int rtw_wx_set_freq(struct net_device *dev,
1171                              struct iw_request_info *info,
1172                              union iwreq_data *wrqu, char *extra)
1173 {
1174         _func_enter_;
1175
1176         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
1177
1178         _func_exit_;
1179
1180         return 0;
1181 }
1182
1183 static int rtw_wx_get_freq(struct net_device *dev,
1184                              struct iw_request_info *info,
1185                              union iwreq_data *wrqu, char *extra)
1186 {
1187         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1188         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1189         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
1190
1191         if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1192         {
1193                 //wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000;
1194                 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
1195                 wrqu->freq.e = 1;
1196                 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
1197
1198         }
1199         else{
1200                 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
1201                 wrqu->freq.e = 1;
1202                 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
1203         }
1204
1205         return 0;
1206 }
1207
1208 static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
1209                              union iwreq_data *wrqu, char *b)
1210 {
1211         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1212         NDIS_802_11_NETWORK_INFRASTRUCTURE networkType ;
1213         int ret = 0;
1214
1215         _func_enter_;
1216
1217         if(_FAIL == rtw_pwr_wakeup(padapter)) {
1218                 ret= -EPERM;
1219                 goto exit;
1220         }
1221
1222         if (padapter->hw_init_completed==_FALSE){
1223                 ret = -EPERM;
1224                 goto exit;
1225         }
1226
1227         switch(wrqu->mode)
1228         {
1229                 case IW_MODE_AUTO:
1230                         networkType = Ndis802_11AutoUnknown;
1231                         DBG_8723A("set_mode = IW_MODE_AUTO\n");
1232                         break;
1233                 case IW_MODE_ADHOC:
1234                         networkType = Ndis802_11IBSS;
1235                         DBG_8723A("set_mode = IW_MODE_ADHOC\n");
1236                         break;
1237                 case IW_MODE_MASTER:
1238                         networkType = Ndis802_11APMode;
1239                         DBG_8723A("set_mode = IW_MODE_MASTER\n");
1240                         //rtw_setopmode_cmd(padapter, networkType);
1241                         break;
1242                 case IW_MODE_INFRA:
1243                         networkType = Ndis802_11Infrastructure;
1244                         DBG_8723A("set_mode = IW_MODE_INFRA\n");
1245                         break;
1246
1247                 default :
1248                         ret = -EINVAL;;
1249                         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("\n Mode: %s is not supported  \n", iw_operation_mode[wrqu->mode]));
1250                         goto exit;
1251         }
1252
1253 /*
1254         if(Ndis802_11APMode == networkType)
1255         {
1256                 rtw_setopmode_cmd(padapter, networkType);
1257         }
1258         else
1259         {
1260                 rtw_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
1261         }
1262 */
1263
1264         if (rtw_set_802_11_infrastructure_mode(padapter, networkType) ==_FALSE){
1265
1266                 ret = -EPERM;
1267                 goto exit;
1268
1269         }
1270
1271         rtw_setopmode_cmd(padapter, networkType);
1272
1273 exit:
1274
1275         _func_exit_;
1276
1277         return ret;
1278
1279 }
1280
1281 static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
1282                              union iwreq_data *wrqu, char *b)
1283 {
1284         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1285         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1286
1287         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,(" rtw_wx_get_mode \n"));
1288
1289         _func_enter_;
1290
1291         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
1292         {
1293                 wrqu->mode = IW_MODE_INFRA;
1294         }
1295         else if  ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) ||
1296                        (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
1297
1298         {
1299                 wrqu->mode = IW_MODE_ADHOC;
1300         }
1301         else if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
1302         {
1303                 wrqu->mode = IW_MODE_MASTER;
1304         }
1305         else
1306         {
1307                 wrqu->mode = IW_MODE_AUTO;
1308         }
1309
1310         _func_exit_;
1311
1312         return 0;
1313
1314 }
1315
1316
1317 static int rtw_wx_set_pmkid(struct net_device *dev,
1318                              struct iw_request_info *a,
1319                              union iwreq_data *wrqu, char *extra)
1320 {
1321         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1322         u8          j,blInserted = _FALSE;
1323         int         intReturn = _FALSE;
1324         struct mlme_priv  *pmlmepriv = &padapter->mlmepriv;
1325         struct security_priv *psecuritypriv = &padapter->securitypriv;
1326         struct iw_pmksa*  pPMK = ( struct iw_pmksa* ) extra;
1327         u8     strZeroMacAddress[ ETH_ALEN ] = { 0x00 };
1328         u8     strIssueBssid[ ETH_ALEN ] = { 0x00 };
1329
1330 /*
1331         struct iw_pmksa
1332         {
1333             __u32   cmd;
1334             struct sockaddr bssid;
1335             __u8    pmkid[IW_PMKID_LEN];   //IW_PMKID_LEN=16
1336         }
1337         There are the BSSID information in the bssid.sa_data array.
1338         If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information.
1339         If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID/BSSID to driver.
1340         If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID/BSSID from driver.
1341         */
1342
1343         memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
1344         if ( pPMK->cmd == IW_PMKSA_ADD )
1345         {
1346                 DBG_8723A( "[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n" );
1347                 if (!memcmp( strIssueBssid, strZeroMacAddress, ETH_ALEN))
1348                 {
1349                     return intReturn;
1350                 }
1351                 else
1352                 {
1353                     intReturn = _TRUE;
1354                 }
1355                 blInserted = _FALSE;
1356
1357                 //overwrite PMKID
1358                 for(j=0 ; j<NUM_PMKID_CACHE; j++)
1359                 {
1360                         if (!memcmp( psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN))
1361                         { // BSSID is matched, the same AP => rewrite with new PMKID.
1362
1363                                 DBG_8723A( "[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n" );
1364
1365                                 memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
1366                                 psecuritypriv->PMKIDList[ j ].bUsed = _TRUE;
1367                                 psecuritypriv->PMKIDIndex = j+1;
1368                                 blInserted = _TRUE;
1369                                 break;
1370                         }
1371                 }
1372
1373                 if(!blInserted)
1374                 {
1375                     // Find a new entry
1376                     DBG_8723A( "[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
1377                             psecuritypriv->PMKIDIndex );
1378
1379                     memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
1380                     memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
1381
1382                     psecuritypriv->PMKIDList[ psecuritypriv->PMKIDIndex ].bUsed = _TRUE;
1383                     psecuritypriv->PMKIDIndex++ ;
1384                     if(psecuritypriv->PMKIDIndex==16)
1385                     {
1386                         psecuritypriv->PMKIDIndex =0;
1387                     }
1388                 }
1389         }
1390         else if ( pPMK->cmd == IW_PMKSA_REMOVE )
1391         {
1392                 DBG_8723A( "[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n" );
1393                 intReturn = _TRUE;
1394                 for(j=0 ; j<NUM_PMKID_CACHE; j++)
1395                 {
1396                         if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN))
1397                         { // BSSID is matched, the same AP => Remove this PMKID information and reset it.
1398                                 memset( psecuritypriv->PMKIDList[ j ].Bssid, 0x00, ETH_ALEN );
1399                                 psecuritypriv->PMKIDList[ j ].bUsed = _FALSE;
1400                                 break;
1401                         }
1402                 }
1403         }
1404         else if ( pPMK->cmd == IW_PMKSA_FLUSH )
1405         {
1406             DBG_8723A( "[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n" );
1407             memset( &psecuritypriv->PMKIDList[ 0 ], 0x00, sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
1408             psecuritypriv->PMKIDIndex = 0;
1409             intReturn = _TRUE;
1410         }
1411     return( intReturn );
1412 }
1413
1414 static int rtw_wx_get_sens(struct net_device *dev,
1415                              struct iw_request_info *info,
1416                              union iwreq_data *wrqu, char *extra)
1417 {
1418         {
1419                 wrqu->sens.value = 0;
1420                 wrqu->sens.fixed = 0;   /* no auto select */
1421                 wrqu->sens.disabled = 1;
1422         }
1423         return 0;
1424 }
1425
1426 static int rtw_wx_get_range(struct net_device *dev,
1427                                 struct iw_request_info *info,
1428                                 union iwreq_data *wrqu, char *extra)
1429 {
1430         struct iw_range *range = (struct iw_range *)extra;
1431         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1432         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1433
1434         u16 val;
1435         int i;
1436
1437         _func_enter_;
1438
1439         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_range. cmd_code=%x\n", info->cmd));
1440
1441         wrqu->data.length = sizeof(*range);
1442         memset(range, 0, sizeof(*range));
1443
1444         /* Let's try to keep this struct in the same order as in
1445          * linux/include/wireless.h
1446          */
1447
1448         /* TODO: See what values we can set, and remove the ones we can't
1449          * set, or fill them with some default data.
1450          */
1451
1452         /* ~5 Mb/s real (802.11b) */
1453         range->throughput = 5 * 1000 * 1000;
1454
1455         // TODO: Not used in 802.11b?
1456 //      range->min_nwid;        /* Minimal NWID we are able to set */
1457         // TODO: Not used in 802.11b?
1458 //      range->max_nwid;        /* Maximal NWID we are able to set */
1459
1460         /* Old Frequency (backward compat - moved lower ) */
1461 //      range->old_num_channels;
1462 //      range->old_num_frequency;
1463 //      range->old_freq[6]; /* Filler to keep "version" at the same offset */
1464
1465         /* signal level threshold range */
1466
1467         //percent values between 0 and 100.
1468         range->max_qual.qual = 100;
1469         range->max_qual.level = 100;
1470         range->max_qual.noise = 100;
1471         range->max_qual.updated = 7; /* Updated all three */
1472
1473
1474         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
1475         /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
1476         range->avg_qual.level = 178; /* -78 dBm */
1477         range->avg_qual.noise = 0;
1478         range->avg_qual.updated = 7; /* Updated all three */
1479
1480         range->num_bitrates = RATE_COUNT;
1481
1482         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
1483                 range->bitrate[i] = rtw_rates[i];
1484
1485         range->min_frag = MIN_FRAG_THRESHOLD;
1486         range->max_frag = MAX_FRAG_THRESHOLD;
1487
1488         range->pm_capa = 0;
1489
1490         range->we_version_compiled = WIRELESS_EXT;
1491         range->we_version_source = 16;
1492
1493 //      range->retry_capa;      /* What retry options are supported */
1494 //      range->retry_flags;     /* How to decode max/min retry limit */
1495 //      range->r_time_flags;    /* How to decode max/min retry life */
1496 //      range->min_retry;       /* Minimal number of retries */
1497 //      range->max_retry;       /* Maximal number of retries */
1498 //      range->min_r_time;      /* Minimal retry lifetime */
1499 //      range->max_r_time;      /* Maximal retry lifetime */
1500
1501         for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
1502
1503                 // Include only legal frequencies for some countries
1504                 if(pmlmeext->channel_set[i].ChannelNum != 0)
1505                 {
1506                         range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
1507                         range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
1508                         range->freq[val].e = 1;
1509                         val++;
1510                 }
1511
1512                 if (val == IW_MAX_FREQUENCIES)
1513                         break;
1514         }
1515
1516         range->num_channels = val;
1517         range->num_frequency = val;
1518
1519 // Commented by Albert 2009/10/13
1520 // The following code will proivde the security capability to network manager.
1521 // If the driver doesn't provide this capability to network manager,
1522 // the WPA/WPA2 routers can't be choosen in the network manager.
1523
1524 /*
1525 #define IW_SCAN_CAPA_NONE               0x00
1526 #define IW_SCAN_CAPA_ESSID              0x01
1527 #define IW_SCAN_CAPA_BSSID              0x02
1528 #define IW_SCAN_CAPA_CHANNEL    0x04
1529 #define IW_SCAN_CAPA_MODE               0x08
1530 #define IW_SCAN_CAPA_RATE               0x10
1531 #define IW_SCAN_CAPA_TYPE               0x20
1532 #define IW_SCAN_CAPA_TIME               0x40
1533 */
1534
1535         range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
1536                           IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
1537
1538 #ifdef IW_SCAN_CAPA_ESSID //WIRELESS_EXT > 21
1539         range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |IW_SCAN_CAPA_BSSID|
1540                                         IW_SCAN_CAPA_CHANNEL|IW_SCAN_CAPA_MODE|IW_SCAN_CAPA_RATE;
1541 #endif
1542
1543
1544         _func_exit_;
1545
1546         return 0;
1547
1548 }
1549
1550 //set bssid flow
1551 //s1. rtw_set_802_11_infrastructure_mode()
1552 //s2. rtw_set_802_11_authentication_mode()
1553 //s3. set_802_11_encryption_mode()
1554 //s4. rtw_set_802_11_bssid()
1555 static int rtw_wx_set_wap(struct net_device *dev,
1556                          struct iw_request_info *info,
1557                          union iwreq_data *awrq,
1558                          char *extra)
1559 {
1560         uint ret = 0;
1561         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1562         struct sockaddr *temp = (struct sockaddr *)awrq;
1563         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1564         struct list_head        *phead;
1565         u8 *dst_bssid, *src_bssid;
1566         _queue  *queue  = &(pmlmepriv->scanned_queue);
1567         struct  wlan_network    *pnetwork = NULL;
1568         NDIS_802_11_AUTHENTICATION_MODE authmode;
1569
1570         _func_enter_;
1571 /*
1572 #ifdef CONFIG_CONCURRENT_MODE
1573         if(padapter->iface_type > PRIMARY_IFACE)
1574         {
1575                 ret = -EINVAL;
1576                 goto exit;
1577         }
1578 #endif
1579 */
1580
1581 #ifdef CONFIG_CONCURRENT_MODE
1582         if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
1583         {
1584                 DBG_8723A("set bssid, but buddy_intf is under scanning or linking\n");
1585
1586                 ret = -EINVAL;
1587
1588                 goto exit;
1589         }
1590 #endif
1591
1592 #ifdef CONFIG_DUALMAC_CONCURRENT
1593         if (dc_check_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)== _TRUE)
1594         {
1595                 DBG_8723A("set bssid, but buddy_intf is under scanning or linking\n");
1596                 ret = -EINVAL;
1597                 goto exit;
1598         }
1599 #endif
1600
1601         if(_FAIL == rtw_pwr_wakeup(padapter))
1602         {
1603                 ret= -1;
1604                 goto exit;
1605         }
1606
1607         if(!padapter->bup){
1608                 ret = -1;
1609                 goto exit;
1610         }
1611
1612
1613         if (temp->sa_family != ARPHRD_ETHER){
1614                 ret = -EINVAL;
1615                 goto exit;
1616         }
1617
1618         authmode = padapter->securitypriv.ndisauthtype;
1619         spin_lock_bh(&queue->lock);
1620        phead = get_list_head(queue);
1621        pmlmepriv->pscanned = phead->next;
1622
1623         while (1)
1624          {
1625
1626                 if ((rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) == _TRUE)
1627                         break;
1628
1629                 pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1630
1631                 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1632
1633                 dst_bssid = pnetwork->network.MacAddress;
1634
1635                 src_bssid = temp->sa_data;
1636
1637                 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN)))
1638                 {
1639                         if(!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode))
1640                         {
1641                                 ret = -1;
1642                                 spin_unlock_bh(&queue->lock);
1643                                 goto exit;
1644                         }
1645
1646                                 break;
1647                 }
1648
1649         }
1650         spin_unlock_bh(&queue->lock);
1651
1652         rtw_set_802_11_authentication_mode(padapter, authmode);
1653         //set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus);
1654         if (rtw_set_802_11_bssid(padapter, temp->sa_data) == _FALSE) {
1655                 ret = -1;
1656                 goto exit;
1657         }
1658
1659 exit:
1660
1661         _func_exit_;
1662
1663         return ret;
1664 }
1665
1666 static int rtw_wx_get_wap(struct net_device *dev,
1667                             struct iw_request_info *info,
1668                             union iwreq_data *wrqu, char *extra)
1669 {
1670
1671         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1672         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1673         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
1674
1675         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1676
1677         memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1678
1679         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_wap\n"));
1680
1681         _func_enter_;
1682
1683         if  ( ((check_fwstate(pmlmepriv, _FW_LINKED)) == _TRUE) ||
1684                         ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == _TRUE) ||
1685                         ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == _TRUE) )
1686         {
1687
1688                 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1689         }
1690         else
1691         {
1692                 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1693         }
1694
1695         _func_exit_;
1696
1697         return 0;
1698
1699 }
1700
1701 static int rtw_wx_set_mlme(struct net_device *dev,
1702                              struct iw_request_info *info,
1703                              union iwreq_data *wrqu, char *extra)
1704 {
1705         int ret=0;
1706         u16 reason;
1707         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1708         struct iw_mlme *mlme = (struct iw_mlme *) extra;
1709
1710
1711         if(mlme==NULL)
1712                 return -1;
1713
1714         DBG_8723A("%s\n", __func__);
1715
1716         reason = cpu_to_le16(mlme->reason_code);
1717
1718
1719         DBG_8723A("%s, cmd=%d, reason=%d\n", __func__, mlme->cmd, reason);
1720
1721
1722         switch (mlme->cmd)
1723         {
1724                 case IW_MLME_DEAUTH:
1725                                 if(!rtw_set_802_11_disassociate(padapter))
1726                                 ret = -1;
1727                                 break;
1728
1729                 case IW_MLME_DISASSOC:
1730                                 if(!rtw_set_802_11_disassociate(padapter))
1731                                                 ret = -1;
1732
1733                                 break;
1734
1735                 default:
1736                         return -EOPNOTSUPP;
1737         }
1738
1739         return ret;
1740 }
1741
1742 static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1743                              union iwreq_data *wrqu, char *extra)
1744 {
1745         u8 _status = _FALSE;
1746         int ret = 0;
1747         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1748         struct mlme_priv *pmlmepriv= &padapter->mlmepriv;
1749         NDIS_802_11_SSID ssid[RTW_SSID_SCAN_AMOUNT];
1750 #ifdef CONFIG_P2P
1751         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
1752 #endif //CONFIG_P2P
1753         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_set_scan\n"));
1754
1755 _func_enter_;
1756
1757         #ifdef DBG_IOCTL
1758         DBG_8723A("DBG_IOCTL %s:%d\n",__func__, __LINE__);
1759         #endif
1760 /*
1761 #ifdef CONFIG_CONCURRENT_MODE
1762         if(padapter->iface_type > PRIMARY_IFACE)
1763         {
1764                 ret = -1;
1765                 goto exit;
1766         }
1767 #endif
1768 */
1769
1770         if(_FAIL == rtw_pwr_wakeup(padapter))
1771         {
1772                 ret= -1;
1773                 goto exit;
1774         }
1775
1776         if(padapter->bDriverStopped){
1777            DBG_8723A("bDriverStopped=%d\n", padapter->bDriverStopped);
1778                 ret= -1;
1779                 goto exit;
1780         }
1781
1782         if(!padapter->bup){
1783                 ret = -1;
1784                 goto exit;
1785         }
1786
1787         if (padapter->hw_init_completed==_FALSE){
1788                 ret = -1;
1789                 goto exit;
1790         }
1791
1792         // When Busy Traffic, driver do not site survey. So driver return success.
1793         // wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout.
1794         // modify by thomas 2011-02-22.
1795         if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE)
1796         {
1797                 indicate_wx_scan_complete_event(padapter);
1798                 goto exit;
1799         }
1800
1801         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
1802         {
1803                 indicate_wx_scan_complete_event(padapter);
1804                 goto exit;
1805         }
1806
1807 #ifdef CONFIG_BT_COEXIST
1808         {
1809                 u32 curr_time, delta_time;
1810
1811                 // under DHCP(Special packet)
1812                 curr_time = rtw_get_current_time();
1813                 delta_time = curr_time - padapter->pwrctrlpriv.DelayLPSLastTimeStamp;
1814                 delta_time = rtw_systime_to_ms(delta_time);
1815                 if (delta_time < 500) // 500ms
1816                 {
1817                         DBG_8723A("%s: send DHCP pkt before %d ms, Skip scan\n", __func__, delta_time);
1818                         ret = -1;
1819                         goto exit;
1820                 }
1821         }
1822 #endif
1823
1824 #ifdef CONFIG_CONCURRENT_MODE
1825         if (check_buddy_fwstate(padapter,
1826                 _FW_UNDER_SURVEY|_FW_UNDER_LINKING|WIFI_UNDER_WPS) == _TRUE)
1827         {
1828                 if(check_buddy_fwstate(padapter, _FW_UNDER_SURVEY))
1829                 {
1830                         DBG_8723A("scanning_via_buddy_intf\n");
1831                         pmlmepriv->scanning_via_buddy_intf = _TRUE;
1832                 }
1833
1834                 indicate_wx_scan_complete_event(padapter);
1835
1836                 goto exit;
1837         }
1838 #endif
1839
1840 #ifdef CONFIG_DUALMAC_CONCURRENT
1841         if (dc_check_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)== _TRUE)
1842         {
1843                 indicate_wx_scan_complete_event(padapter);
1844                 goto exit;
1845         }
1846 #endif
1847
1848 //      Mareded by Albert 20101103
1849 //      For the DMP WiFi Display project, the driver won't to scan because
1850 //      the pmlmepriv->scan_interval is always equal to 3.
1851 //      So, the wpa_supplicant won't find out the WPS SoftAP.
1852
1853 /*
1854         if(pmlmepriv->scan_interval>10)
1855                 pmlmepriv->scan_interval = 0;
1856
1857         if(pmlmepriv->scan_interval > 0)
1858         {
1859                 DBG_8723A("scan done\n");
1860                 ret = 0;
1861                 goto exit;
1862         }
1863
1864 */
1865 #ifdef CONFIG_P2P
1866         if ( pwdinfo->p2p_state != P2P_STATE_NONE )
1867         {
1868                 rtw_p2p_set_pre_state( pwdinfo, rtw_p2p_state( pwdinfo ) );
1869                 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
1870                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
1871                 rtw_free_network_queue(padapter, _TRUE);
1872         }
1873 #endif //CONFIG_P2P
1874
1875         memset(ssid, 0, sizeof(NDIS_802_11_SSID)*RTW_SSID_SCAN_AMOUNT);
1876
1877         if (wrqu->data.length == sizeof(struct iw_scan_req))
1878         {
1879                 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1880
1881                 if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
1882                 {
1883                         int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
1884
1885                         memcpy(ssid[0].Ssid, req->essid, len);
1886                         ssid[0].SsidLength = len;
1887
1888                         DBG_8723A("IW_SCAN_THIS_ESSID, ssid=%s, len=%d\n", req->essid, req->essid_len);
1889
1890                         spin_lock_bh(&pmlmepriv->lock);
1891
1892                         _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
1893
1894                         spin_unlock_bh(&pmlmepriv->lock);
1895
1896                 }
1897                 else if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
1898                 {
1899                         DBG_8723A("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
1900                 }
1901
1902         }
1903         else
1904
1905         if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE &&
1906             !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
1907                 int len = wrqu->data.length -WEXT_CSCAN_HEADER_SIZE;
1908                 char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
1909                 char section;
1910                 char sec_len;
1911                 int ssid_index = 0;
1912
1913                 //DBG_8723A("%s COMBO_SCAN header is recognized\n", __func__);
1914
1915                 while(len >= 1) {
1916                         section = *(pos++); len-=1;
1917
1918                         switch(section) {
1919                                 case WEXT_CSCAN_SSID_SECTION:
1920                                         //DBG_8723A("WEXT_CSCAN_SSID_SECTION\n");
1921                                         if(len < 1) {
1922                                                 len = 0;
1923                                                 break;
1924                                         }
1925
1926                                         sec_len = *(pos++); len-=1;
1927
1928                                         if(sec_len>0 && sec_len<=len) {
1929                                                 ssid[ssid_index].SsidLength = sec_len;
1930                                                 memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
1931                                                 //DBG_8723A("%s COMBO_SCAN with specific ssid:%s, %d\n", __func__
1932                                                 //      , ssid[ssid_index].Ssid, ssid[ssid_index].SsidLength);
1933                                                 ssid_index++;
1934                                         }
1935
1936                                         pos+=sec_len; len-=sec_len;
1937                                         break;
1938
1939
1940                                 case WEXT_CSCAN_CHANNEL_SECTION:
1941                                         //DBG_8723A("WEXT_CSCAN_CHANNEL_SECTION\n");
1942                                         pos+=1; len-=1;
1943                                         break;
1944                                 case WEXT_CSCAN_ACTV_DWELL_SECTION:
1945                                         //DBG_8723A("WEXT_CSCAN_ACTV_DWELL_SECTION\n");
1946                                         pos+=2; len-=2;
1947                                         break;
1948                                 case WEXT_CSCAN_PASV_DWELL_SECTION:
1949                                         //DBG_8723A("WEXT_CSCAN_PASV_DWELL_SECTION\n");
1950                                         pos+=2; len-=2;
1951                                         break;
1952                                 case WEXT_CSCAN_HOME_DWELL_SECTION:
1953                                         //DBG_8723A("WEXT_CSCAN_HOME_DWELL_SECTION\n");
1954                                         pos+=2; len-=2;
1955                                         break;
1956                                 case WEXT_CSCAN_TYPE_SECTION:
1957                                         //DBG_8723A("WEXT_CSCAN_TYPE_SECTION\n");
1958                                         pos+=1; len-=1;
1959                                         break;
1960                                 default:
1961                                         //DBG_8723A("Unknown CSCAN section %c\n", section);
1962                                         len = 0; // stop parsing
1963                         }
1964                         //DBG_8723A("len:%d\n", len);
1965
1966                 }
1967
1968                 //jeff: it has still some scan paramater to parse, we only do this now...
1969                 _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1970
1971         } else
1972
1973         {
1974                 _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1975         }
1976
1977         if(_status == _FALSE)
1978                 ret = -1;
1979
1980 exit:
1981         #ifdef DBG_IOCTL
1982         DBG_8723A("DBG_IOCTL %s:%d return %d\n",__func__, __LINE__, ret);
1983         #endif
1984
1985 _func_exit_;
1986
1987         return ret;
1988 }
1989
1990 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1991                              union iwreq_data *wrqu, char *extra)
1992 {
1993         struct list_head                                        *plist, *phead;
1994         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
1995         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1996         _queue                          *queue  = &(pmlmepriv->scanned_queue);
1997         struct  wlan_network    *pnetwork = NULL;
1998         char *ev = extra;
1999         char *stop = ev + wrqu->data.length;
2000         u32 ret = 0;
2001         u32 cnt=0;
2002         u32 wait_for_surveydone;
2003         int wait_status;
2004 #ifdef CONFIG_CONCURRENT_MODE
2005         //struct rtw_adapter *pbuddy_adapter = padapter->pbuddy_adapter;
2006         //struct mlme_priv *pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
2007 #endif
2008 #ifdef CONFIG_P2P
2009         struct  wifidirect_info*        pwdinfo = &padapter->wdinfo;
2010 #endif //CONFIG_P2P
2011         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan\n"));
2012         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
2013
2014         _func_enter_;
2015
2016         #ifdef DBG_IOCTL
2017         DBG_8723A("DBG_IOCTL %s:%d\n",__func__, __LINE__);
2018         #endif
2019
2020 /*
2021 #ifdef CONFIG_CONCURRENT_MODE
2022         if(padapter->iface_type > PRIMARY_IFACE)
2023         {
2024                 ret = -EINVAL;
2025                 goto exit;
2026         }
2027 #endif
2028 */
2029         if(padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped)
2030         {
2031                 ret = -EINVAL;
2032                 goto exit;
2033         }
2034
2035 #ifdef CONFIG_P2P
2036         if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
2037         {
2038                 //      P2P is enabled
2039                 if ( padapter->chip_type == RTL8192D )
2040                         wait_for_surveydone = 300;      //      Because the 8192du supports more channels.
2041                 else
2042                         wait_for_surveydone = 200;
2043         }
2044         else
2045         {
2046                 //      P2P is disabled
2047                 wait_for_surveydone = 100;
2048         }
2049 #else
2050         {
2051                 wait_for_surveydone = 100;
2052         }
2053 #endif //CONFIG_P2P
2054
2055 /*
2056 #ifdef CONFIG_CONCURRENT_MODE
2057         if(pmlmepriv->scanning_via_buddy_intf == _TRUE)
2058         {
2059                 pmlmepriv->scanning_via_buddy_intf = _FALSE;//reset
2060
2061                 // change pointers to buddy interface
2062                 padapter = pbuddy_adapter;
2063                 pmlmepriv = pbuddy_mlmepriv;
2064                 queue = &(pbuddy_mlmepriv->scanned_queue);
2065
2066         }
2067 #endif // CONFIG_CONCURRENT_MODE
2068 */
2069
2070         wait_status = _FW_UNDER_SURVEY
2071                 #ifndef CONFIG_ANDROID
2072                 |_FW_UNDER_LINKING
2073                 #endif
2074         ;
2075
2076 #ifdef CONFIG_DUALMAC_CONCURRENT
2077         while(dc_check_fwstate(padapter, wait_status)== _TRUE)
2078         {
2079                 msleep(30);
2080                 cnt++;
2081                 if(cnt > wait_for_surveydone )
2082                         break;
2083         }
2084 #endif // CONFIG_DUALMAC_CONCURRENT
2085
2086         while(check_fwstate(pmlmepriv, wait_status) == _TRUE)
2087         {
2088                 msleep(30);
2089                 cnt++;
2090                 if(cnt > wait_for_surveydone )
2091                         break;
2092         }
2093
2094         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
2095
2096         phead = get_list_head(queue);
2097         plist = phead->next;
2098
2099         while(1)
2100         {
2101                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
2102                         break;
2103
2104                 if((stop - ev) < SCAN_ITEM_SIZE) {
2105                         ret = -E2BIG;
2106                         break;
2107                 }
2108
2109                 pnetwork = container_of(plist, struct wlan_network, list);
2110
2111                 //report network only if the current channel set contains the channel to which this network belongs
2112                 if(rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0
2113                         #ifdef CONFIG_VALIDATE_SSID
2114                         && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))
2115                         #endif
2116                 )
2117                 {
2118                         ev=translate_scan(padapter, a, pnetwork, ev, stop);
2119                 }
2120
2121                 plist = plist->next;
2122
2123         }
2124
2125         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
2126
2127        wrqu->data.length = ev-extra;
2128         wrqu->data.flags = 0;
2129
2130 exit:
2131
2132         _func_exit_;
2133
2134         #ifdef DBG_IOCTL
2135         DBG_8723A("DBG_IOCTL %s:%d return %d\n",__func__, __LINE__, ret);
2136         #endif
2137
2138         return ret ;
2139
2140 }
2141
2142 //set ssid flow
2143 //s1. rtw_set_802_11_infrastructure_mode()
2144 //s2. set_802_11_authenticaion_mode()
2145 //s3. set_802_11_encryption_mode()
2146 //s4. rtw_set_802_11_ssid()
2147 static int rtw_wx_set_essid(struct net_device *dev,
2148                               struct iw_request_info *a,
2149                               union iwreq_data *wrqu, char *extra)
2150 {
2151         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2152         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2153         _queue *queue = &pmlmepriv->scanned_queue;
2154         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
2155         struct list_head *phead;
2156         s8 status = _TRUE;
2157         struct wlan_network *pnetwork = NULL;
2158         NDIS_802_11_AUTHENTICATION_MODE authmode;
2159         NDIS_802_11_SSID ndis_ssid;
2160         u8 *dst_ssid, *src_ssid;
2161
2162         uint ret = 0, len;
2163
2164         _func_enter_;
2165
2166         #ifdef DBG_IOCTL
2167         DBG_8723A("DBG_IOCTL %s:%d\n",__func__, __LINE__);
2168         #endif
2169
2170 /*
2171 #ifdef CONFIG_CONCURRENT_MODE
2172         if(padapter->iface_type > PRIMARY_IFACE)
2173         {
2174                 ret = -EINVAL;
2175                 goto exit;
2176         }
2177 #endif
2178 */
2179
2180 #ifdef CONFIG_CONCURRENT_MODE
2181         if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
2182         {
2183                 DBG_8723A("set ssid, but buddy_intf is under scanning or linking\n");
2184
2185                 ret = -EINVAL;
2186
2187                 goto exit;
2188         }
2189 #endif
2190
2191 #ifdef CONFIG_DUALMAC_CONCURRENT
2192         if (dc_check_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)== _TRUE)
2193         {
2194                 DBG_8723A("set bssid, but buddy_intf is under scanning or linking\n");
2195                 ret = -EINVAL;
2196                 goto exit;
2197         }
2198 #endif
2199
2200         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2201                  ("+rtw_wx_set_essid: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
2202         if(_FAIL == rtw_pwr_wakeup(padapter))
2203         {
2204                 ret = -1;
2205                 goto exit;
2206         }
2207
2208         if(!padapter->bup){
2209                 ret = -1;
2210                 goto exit;
2211         }
2212
2213         if (wrqu->essid.length > IW_ESSID_MAX_SIZE){
2214                 ret= -E2BIG;
2215                 goto exit;
2216         }
2217
2218         if(check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2219                 ret = -1;
2220                 goto exit;
2221         }
2222
2223         authmode = padapter->securitypriv.ndisauthtype;
2224         DBG_8723A("=>%s\n",__func__);
2225         if (wrqu->essid.flags && wrqu->essid.length)
2226         {
2227                 // Commented by Albert 20100519
2228                 // We got the codes in "set_info" function of iwconfig source code.
2229                 //      =========================================
2230                 //      wrq.u.essid.length = strlen(essid) + 1;
2231                 //      if(we_kernel_version > 20)
2232                 //              wrq.u.essid.length--;
2233                 //      =========================================
2234                 //      That means, if the WIRELESS_EXT less than or equal to 20, the correct ssid len should subtract 1.
2235                 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
2236
2237                 if( wrqu->essid.length != 33 )
2238                         DBG_8723A("ssid=%s, len=%d\n", extra, wrqu->essid.length);
2239
2240                 memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
2241                 ndis_ssid.SsidLength = len;
2242                 memcpy(ndis_ssid.Ssid, extra, len);
2243                 src_ssid = ndis_ssid.Ssid;
2244
2245                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid=[%s]\n", src_ssid));
2246                 spin_lock_bh(&queue->lock);
2247                phead = get_list_head(queue);
2248               pmlmepriv->pscanned = phead->next;
2249
2250                 while (1)
2251                 {
2252                         if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) == _TRUE)
2253                         {
2254                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_warning_,
2255                                          ("rtw_wx_set_essid: scan_q is empty, set ssid to check if scanning again!\n"));
2256
2257                                 break;
2258                         }
2259
2260                         pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
2261
2262                         pmlmepriv->pscanned = pmlmepriv->pscanned->next;
2263
2264                         dst_ssid = pnetwork->network.Ssid.Ssid;
2265
2266                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2267                                  ("rtw_wx_set_essid: dst_ssid=%s\n",
2268                                   pnetwork->network.Ssid.Ssid));
2269
2270                         if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
2271                                 (pnetwork->network.Ssid.SsidLength==ndis_ssid.SsidLength))
2272                         {
2273                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2274                                          ("rtw_wx_set_essid: find match, set infra mode\n"));
2275
2276                                 if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE)
2277                                 {
2278                                         if(pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
2279                                                 continue;
2280                                 }
2281
2282                                 if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode) == _FALSE)
2283                                 {
2284                                         ret = -1;
2285                                         spin_unlock_bh(&queue->lock);
2286                                         goto exit;
2287                                 }
2288
2289                                 break;
2290                         }
2291                 }
2292                 spin_unlock_bh(&queue->lock);
2293                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2294                          ("set ssid: set_802_11_auth. mode=%d\n", authmode));
2295                 rtw_set_802_11_authentication_mode(padapter, authmode);
2296                 //set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus);
2297                 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == _FALSE) {
2298                         ret = -1;
2299                         goto exit;
2300                 }
2301         }
2302
2303 exit:
2304
2305         DBG_8723A("<=%s, ret %d\n",__func__, ret);
2306
2307         #ifdef DBG_IOCTL
2308         DBG_8723A("DBG_IOCTL %s:%d return %d\n",__func__, __LINE__, ret);
2309         #endif
2310
2311         _func_exit_;
2312
2313         return ret;
2314 }
2315
2316 static int rtw_wx_get_essid(struct net_device *dev,
2317                               struct iw_request_info *a,
2318                               union iwreq_data *wrqu, char *extra)
2319 {
2320         u32 len,ret = 0;
2321         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2322         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2323         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
2324
2325         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_essid\n"));
2326
2327         _func_enter_;
2328
2329         if ( (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) ||
2330               (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE))
2331         {
2332                 len = pcur_bss->Ssid.SsidLength;
2333
2334                 wrqu->essid.length = len;
2335
2336                 memcpy(extra, pcur_bss->Ssid.Ssid, len);
2337
2338                 wrqu->essid.flags = 1;
2339         }
2340         else
2341         {
2342                 ret = -1;
2343                 goto exit;
2344         }
2345
2346 exit:
2347
2348         _func_exit_;
2349
2350         return ret;
2351
2352 }
2353
2354 static int rtw_wx_set_rate(struct net_device *dev,
2355                               struct iw_request_info *a,
2356                               union iwreq_data *wrqu, char *extra)
2357 {
2358         int     i, ret = 0;
2359         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2360         u8      datarates[NumRates];
2361         u32     target_rate = wrqu->bitrate.value;
2362         u32     fixed = wrqu->bitrate.fixed;
2363         u32     ratevalue = 0;
2364          u8 mpdatarate[NumRates]={11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
2365
2366 _func_enter_;
2367
2368         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,(" rtw_wx_set_rate \n"));
2369         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("target_rate = %d, fixed = %d\n",target_rate,fixed));
2370
2371         if(target_rate == -1){
2372                 ratevalue = 11;
2373                 goto set_rate;
2374         }
2375         target_rate = target_rate/100000;
2376
2377         switch(target_rate){
2378                 case 10:
2379                         ratevalue = 0;
2380                         break;
2381                 case 20:
2382                         ratevalue = 1;
2383                         break;
2384                 case 55:
2385                         ratevalue = 2;
2386                         break;
2387                 case 60:
2388                         ratevalue = 3;
2389                         break;
2390                 case 90:
2391                         ratevalue = 4;
2392                         break;
2393                 case 110:
2394                         ratevalue = 5;
2395                         break;
2396                 case 120:
2397                         ratevalue = 6;
2398                         break;
2399                 case 180:
2400                         ratevalue = 7;
2401                         break;
2402                 case 240:
2403                         ratevalue = 8;
2404                         break;
2405                 case 360:
2406                         ratevalue = 9;
2407                         break;
2408                 case 480:
2409                         ratevalue = 10;
2410                         break;
2411                 case 540:
2412                         ratevalue = 11;
2413                         break;
2414                 default:
2415                         ratevalue = 11;
2416                         break;
2417         }
2418
2419 set_rate:
2420
2421         for(i=0; i<NumRates; i++)
2422         {
2423                 if(ratevalue==mpdatarate[i])
2424                 {
2425                         datarates[i] = mpdatarate[i];
2426                         if(fixed == 0)
2427                                 break;
2428                 }
2429                 else{
2430                         datarates[i] = 0xff;
2431                 }
2432
2433                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("datarate_inx=%d\n",datarates[i]));
2434         }
2435
2436         if( rtw_setdatarate_cmd(padapter, datarates) !=_SUCCESS){
2437                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("rtw_wx_set_rate Fail!!!\n"));
2438                 ret = -1;
2439         }
2440
2441 _func_exit_;
2442
2443         return ret;
2444 }
2445
2446 static int rtw_wx_get_rate(struct net_device *dev,
2447                              struct iw_request_info *info,
2448                              union iwreq_data *wrqu, char *extra)
2449 {
2450         u16 max_rate = 0;
2451
2452         max_rate = rtw_get_cur_max_rate((struct rtw_adapter *)rtw_netdev_priv(dev));
2453
2454         if(max_rate == 0)
2455                 return -EPERM;
2456
2457         wrqu->bitrate.fixed = 0;        /* no auto select */
2458         wrqu->bitrate.value = max_rate * 100000;
2459
2460         return 0;
2461 }
2462
2463 static int rtw_wx_set_rts(struct net_device *dev,
2464                              struct iw_request_info *info,
2465                              union iwreq_data *wrqu, char *extra)
2466 {
2467         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2468
2469         _func_enter_;
2470
2471         if (wrqu->rts.disabled)
2472                 padapter->registrypriv.rts_thresh = 2347;
2473         else {
2474                 if (wrqu->rts.value < 0 ||
2475                     wrqu->rts.value > 2347)
2476                         return -EINVAL;
2477
2478                 padapter->registrypriv.rts_thresh = wrqu->rts.value;
2479         }
2480
2481         DBG_8723A("%s, rts_thresh=%d\n", __func__, padapter->registrypriv.rts_thresh);
2482
2483         _func_exit_;
2484
2485         return 0;
2486
2487 }
2488
2489 static int rtw_wx_get_rts(struct net_device *dev,
2490                              struct iw_request_info *info,
2491                              union iwreq_data *wrqu, char *extra)
2492 {
2493         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2494
2495         _func_enter_;
2496
2497         DBG_8723A("%s, rts_thresh=%d\n", __func__, padapter->registrypriv.rts_thresh);
2498
2499         wrqu->rts.value = padapter->registrypriv.rts_thresh;
2500         wrqu->rts.fixed = 0;    /* no auto select */
2501         //wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
2502
2503         _func_exit_;
2504
2505         return 0;
2506 }
2507
2508 static int rtw_wx_set_frag(struct net_device *dev,
2509                              struct iw_request_info *info,
2510                              union iwreq_data *wrqu, char *extra)
2511 {
2512         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2513
2514         _func_enter_;
2515
2516         if (wrqu->frag.disabled)
2517                 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
2518         else {
2519                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
2520                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
2521                         return -EINVAL;
2522
2523                 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
2524         }
2525
2526         DBG_8723A("%s, frag_len=%d\n", __func__, padapter->xmitpriv.frag_len);
2527
2528         _func_exit_;
2529
2530         return 0;
2531
2532 }
2533
2534 static int rtw_wx_get_frag(struct net_device *dev,
2535                              struct iw_request_info *info,
2536                              union iwreq_data *wrqu, char *extra)
2537 {
2538         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2539
2540         _func_enter_;
2541
2542         DBG_8723A("%s, frag_len=%d\n", __func__, padapter->xmitpriv.frag_len);
2543
2544         wrqu->frag.value = padapter->xmitpriv.frag_len;
2545         wrqu->frag.fixed = 0;   /* no auto select */
2546         //wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
2547
2548         _func_exit_;
2549
2550         return 0;
2551 }
2552
2553 static int rtw_wx_get_retry(struct net_device *dev,
2554                              struct iw_request_info *info,
2555                              union iwreq_data *wrqu, char *extra)
2556 {
2557         //struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2558
2559
2560         wrqu->retry.value = 7;
2561         wrqu->retry.fixed = 0;  /* no auto select */
2562         wrqu->retry.disabled = 1;
2563
2564         return 0;
2565
2566 }
2567
2568 static int rtw_wx_set_enc(struct net_device *dev,
2569                             struct iw_request_info *info,
2570                             union iwreq_data *wrqu, char *keybuf)
2571 {
2572         u32 key, ret = 0;
2573         u32 keyindex_provided;
2574         NDIS_802_11_WEP  wep;
2575         NDIS_802_11_AUTHENTICATION_MODE authmode;
2576
2577         struct iw_point *erq = &(wrqu->encoding);
2578         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2579         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
2580         DBG_8723A("+rtw_wx_set_enc, flags=0x%x\n", erq->flags);
2581
2582         memset(&wep, 0, sizeof(NDIS_802_11_WEP));
2583
2584         key = erq->flags & IW_ENCODE_INDEX;
2585
2586         _func_enter_;
2587
2588         if (erq->flags & IW_ENCODE_DISABLED)
2589         {
2590                 DBG_8723A("EncryptionDisabled\n");
2591                 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
2592                 padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
2593                 padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
2594                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open; //open system
2595                 authmode = Ndis802_11AuthModeOpen;
2596                 padapter->securitypriv.ndisauthtype=authmode;
2597
2598                 goto exit;
2599         }
2600
2601         if (key) {
2602                 if (key > WEP_KEYS)
2603                         return -EINVAL;
2604                 key--;
2605                 keyindex_provided = 1;
2606         }
2607         else
2608         {
2609                 keyindex_provided = 0;
2610                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
2611                 DBG_8723A("rtw_wx_set_enc, key=%d\n", key);
2612         }
2613
2614         //set authentication mode
2615         if(erq->flags & IW_ENCODE_OPEN)
2616         {
2617                 DBG_8723A("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
2618                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;//Ndis802_11EncryptionDisabled;
2619
2620                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open;
2621
2622                 padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
2623                 padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
2624                 authmode = Ndis802_11AuthModeOpen;
2625                 padapter->securitypriv.ndisauthtype=authmode;
2626         }
2627         else if(erq->flags & IW_ENCODE_RESTRICTED)
2628         {
2629                 DBG_8723A("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
2630                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
2631
2632                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Shared;
2633
2634                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
2635                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP40_;
2636                 authmode = Ndis802_11AuthModeShared;
2637                 padapter->securitypriv.ndisauthtype=authmode;
2638         }
2639         else
2640         {
2641                 DBG_8723A("rtw_wx_set_enc():erq->flags=0x%x\n", erq->flags);
2642
2643                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;//Ndis802_11EncryptionDisabled;
2644                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open; //open system
2645                 padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
2646                 padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
2647                 authmode = Ndis802_11AuthModeOpen;
2648                 padapter->securitypriv.ndisauthtype=authmode;
2649         }
2650
2651         wep.KeyIndex = key;
2652         if (erq->length > 0)
2653         {
2654                 wep.KeyLength = erq->length <= 5 ? 5 : 13;
2655
2656                 wep.Length = wep.KeyLength + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
2657         }
2658         else
2659         {
2660                 wep.KeyLength = 0 ;
2661
2662                 if(keyindex_provided == 1)// set key_id only, no given KeyMaterial(erq->length==0).
2663                 {
2664                         padapter->securitypriv.dot11PrivacyKeyIndex = key;
2665
2666                         DBG_8723A("(keyindex_provided == 1), keyid=%d, key_len=%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
2667
2668                         switch(padapter->securitypriv.dot11DefKeylen[key])
2669                         {
2670                                 case 5:
2671                                         padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
2672                                         break;
2673                                 case 13:
2674                                         padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;
2675                                         break;
2676                                 default:
2677                                         padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
2678                                         break;
2679                         }
2680
2681                         goto exit;
2682
2683                 }
2684
2685         }
2686
2687         wep.KeyIndex |= 0x80000000;
2688
2689         memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
2690
2691         if (rtw_set_802_11_add_wep(padapter, &wep) == _FALSE) {
2692                 if(rf_on == pwrpriv->rf_pwrstate )
2693                         ret = -EOPNOTSUPP;
2694                 goto exit;
2695         }
2696
2697 exit:
2698
2699         _func_exit_;
2700
2701         return ret;
2702
2703 }
2704
2705 static int rtw_wx_get_enc(struct net_device *dev,
2706                             struct iw_request_info *info,
2707                             union iwreq_data *wrqu, char *keybuf)
2708 {
2709         uint key, ret =0;
2710         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2711         struct iw_point *erq = &(wrqu->encoding);
2712         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2713
2714         _func_enter_;
2715
2716         if(check_fwstate(pmlmepriv, _FW_LINKED) != _TRUE)
2717         {
2718                  if(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != _TRUE)
2719                  {
2720                 erq->length = 0;
2721                 erq->flags |= IW_ENCODE_DISABLED;
2722                 return 0;
2723         }
2724         }
2725
2726
2727         key = erq->flags & IW_ENCODE_INDEX;
2728
2729         if (key) {
2730                 if (key > WEP_KEYS)
2731                         return -EINVAL;
2732                 key--;
2733         } else
2734         {
2735                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
2736         }
2737
2738         erq->flags = key + 1;
2739
2740         //if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
2741         //{
2742         //      erq->flags |= IW_ENCODE_OPEN;
2743         //}
2744
2745         switch(padapter->securitypriv.ndisencryptstatus)
2746         {
2747                 case Ndis802_11EncryptionNotSupported:
2748                 case Ndis802_11EncryptionDisabled:
2749
2750                 erq->length = 0;
2751                 erq->flags |= IW_ENCODE_DISABLED;
2752
2753                 break;
2754
2755                 case Ndis802_11Encryption1Enabled:
2756
2757                 erq->length = padapter->securitypriv.dot11DefKeylen[key];
2758
2759                 if(erq->length)
2760                 {
2761                         memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
2762
2763                 erq->flags |= IW_ENCODE_ENABLED;
2764
2765                         if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
2766                         {
2767                                 erq->flags |= IW_ENCODE_OPEN;
2768                         }
2769                         else if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
2770                         {
2771                 erq->flags |= IW_ENCODE_RESTRICTED;
2772                         }
2773                 }
2774                 else
2775                 {
2776                         erq->length = 0;
2777                         erq->flags |= IW_ENCODE_DISABLED;
2778                 }
2779
2780                 break;
2781
2782                 case Ndis802_11Encryption2Enabled:
2783                 case Ndis802_11Encryption3Enabled:
2784
2785                 erq->length = 16;
2786                 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
2787
2788                 break;
2789
2790                 default:
2791                 erq->length = 0;
2792                 erq->flags |= IW_ENCODE_DISABLED;
2793
2794                 break;
2795
2796         }
2797
2798         _func_exit_;
2799
2800         return ret;
2801
2802 }
2803
2804 static int rtw_wx_get_power(struct net_device *dev,
2805                              struct iw_request_info *info,
2806                              union iwreq_data *wrqu, char *extra)
2807 {
2808         //struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2809
2810         wrqu->power.value = 0;
2811         wrqu->power.fixed = 0;  /* no auto select */
2812         wrqu->power.disabled = 1;
2813
2814         return 0;
2815
2816 }
2817
2818 static int rtw_wx_set_gen_ie(struct net_device *dev,
2819                              struct iw_request_info *info,
2820                              union iwreq_data *wrqu, char *extra)
2821 {
2822         int ret;
2823         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2824
2825         ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
2826
2827         return ret;
2828 }
2829
2830 static int rtw_wx_set_auth(struct net_device *dev,
2831                              struct iw_request_info *info,
2832                              union iwreq_data *wrqu, char *extra)
2833 {
2834         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
2835         struct iw_param *param = (struct iw_param*)&(wrqu->param);
2836         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
2837         struct security_priv *psecuritypriv = &padapter->securitypriv;
2838         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2839         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2840         u32 value = param->value;
2841         int ret = 0;
2842
2843         switch (param->flags & IW_AUTH_INDEX) {
2844
2845         case IW_AUTH_WPA_VERSION:
2846                 break;
2847         case IW_AUTH_CIPHER_PAIRWISE:
2848
2849                 break;
2850         case IW_AUTH_CIPHER_GROUP:
2851
2852                 break;
2853         case IW_AUTH_KEY_MGMT:
2854                 /*
2855                  *  ??? does not use these parameters
2856                  */
2857                 break;
2858
2859         case IW_AUTH_TKIP_COUNTERMEASURES:
2860         {
2861             if ( param->value )
2862             {  // wpa_supplicant is enabling the tkip countermeasure.
2863                padapter->securitypriv.btkip_countermeasure = _TRUE;
2864             }
2865             else
2866             {  // wpa_supplicant is disabling the tkip countermeasure.
2867                padapter->securitypriv.btkip_countermeasure = _FALSE;
2868             }
2869                 break;
2870         }
2871         case IW_AUTH_DROP_UNENCRYPTED:
2872                 {
2873                         /* HACK:
2874                          *
2875                          * wpa_supplicant calls set_wpa_enabled when the driver
2876                          * is loaded and unloaded, regardless of if WPA is being
2877                          * used.  No other calls are made which can be used to
2878                          * determine if encryption will be used or not prior to
2879                          * association being expected.  If encryption is not being
2880                          * used, drop_unencrypted is set to false, else true -- we
2881                          * can use this to determine if the CAP_PRIVACY_ON bit should
2882                          * be set.
2883                          */
2884
2885                         if(padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
2886                         {
2887                                 break;//it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled,
2888                                                 // then it needn't reset it;
2889                         }
2890
2891                         if(param->value){
2892                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
2893                                 padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
2894                                 padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
2895                                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open; //open system
2896                                 padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeOpen;
2897                         }
2898
2899                         break;
2900                 }
2901
2902         case IW_AUTH_80211_AUTH_ALG:
2903
2904                 #if defined(CONFIG_ANDROID) || 1
2905                 /*
2906                  *  It's the starting point of a link layer connection using wpa_supplicant
2907                 */
2908                 if(check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2909                         LeaveAllPowerSaveMode(padapter);
2910                         rtw_disassoc_cmd(padapter, 500, _FALSE);
2911                         DBG_8723A("%s...call rtw_indicate_disconnect\n ",__func__);
2912                         rtw_indicate_disconnect(padapter);
2913                         rtw_free_assoc_resources(padapter, 1);
2914                 }
2915                 #endif
2916
2917
2918                 ret = wpa_set_auth_algs(dev, (u32)param->value);
2919
2920                 break;
2921
2922         case IW_AUTH_WPA_ENABLED:
2923
2924                 //if(param->value)
2925                 //      padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; //802.1x
2926                 //else
2927                 //      padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;//open system
2928
2929                 //_disassociate(priv);
2930
2931                 break;
2932
2933         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2934                 //ieee->ieee802_1x = param->value;
2935                 break;
2936
2937         case IW_AUTH_PRIVACY_INVOKED:
2938                 //ieee->privacy_invoked = param->value;
2939                 break;
2940
2941         default:
2942                 return -EOPNOTSUPP;
2943
2944         }
2945
2946         return ret;
2947
2948 }
2949
2950 static int rtw_wx_set_enc_ext(struct net_device *dev,
2951                              struct iw_request_info *info,
2952                              union iwreq_data *wrqu, char *extra)
2953 {
2954         char *alg_name;
2955         u32 param_len;
2956         struct ieee_param *param = NULL;
2957         struct iw_point *pencoding = &wrqu->encoding;
2958         struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
2959         int ret = 0;
2960
2961         param_len = sizeof(struct ieee_param) + pext->key_len;
2962         param = (struct ieee_param *)kzalloc(param_len, GFP_KERNEL);
2963         if (param == NULL)
2964                 return -ENOMEM;
2965
2966         param->cmd = IEEE_CMD_SET_ENCRYPTION;
2967         memset(param->sta_addr, 0xff, ETH_ALEN);
2968
2969
2970         switch (pext->alg) {
2971         case IW_ENCODE_ALG_NONE:
2972                 //todo: remove key
2973                 //remove = 1;
2974                 alg_name = "none";
2975                 break;
2976         case IW_ENCODE_ALG_WEP:
2977                 alg_name = "WEP";
2978                 break;
2979         case IW_ENCODE_ALG_TKIP:
2980                 alg_name = "TKIP";
2981                 break;
2982         case IW_ENCODE_ALG_CCMP:
2983                 alg_name = "CCMP";
2984                 break;
2985         default:
2986                 ret = -1;
2987                 goto out;
2988         }
2989
2990         strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
2991
2992         if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
2993         {
2994                 param->u.crypt.set_tx = 1;
2995         }
2996
2997         /* cliW: WEP does not have group key
2998          * just not checking GROUP key setting
2999          */
3000         if ((pext->alg != IW_ENCODE_ALG_WEP) &&
3001                 (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
3002         {
3003                 param->u.crypt.set_tx = 0;
3004         }
3005
3006         param->u.crypt.idx = (pencoding->flags&0x00FF) -1 ;
3007
3008         if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
3009         {
3010                 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
3011         }
3012
3013         if(pext->key_len)
3014         {
3015                 param->u.crypt.key_len = pext->key_len;
3016                 //memcpy(param + 1, pext + 1, pext->key_len);
3017                 memcpy(param->u.crypt.key, pext + 1, pext->key_len);
3018         }
3019
3020         if (pencoding->flags & IW_ENCODE_DISABLED)
3021         {
3022                 //todo: remove key
3023                 //remove = 1;
3024         }
3025
3026         ret =  wpa_set_encryption(dev, param, param_len);
3027
3028 out:
3029         kfree(param);
3030
3031         return ret;
3032 }
3033
3034
3035 static int rtw_wx_get_nick(struct net_device *dev,
3036                              struct iw_request_info *info,
3037                              union iwreq_data *wrqu, char *extra)
3038 {
3039         //struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3040          //struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3041          //struct security_priv *psecuritypriv = &padapter->securitypriv;
3042
3043         if(extra)
3044         {
3045                 wrqu->data.length = 14;
3046                 wrqu->data.flags = 1;
3047                 memcpy(extra, "<WIFI@REALTEK>", 14);
3048         }
3049         return 0;
3050 }
3051
3052 static int rtw_wx_read32(struct net_device *dev,
3053                             struct iw_request_info *info,
3054                             union iwreq_data *wrqu, char *extra)
3055 {
3056         struct rtw_adapter *padapter;
3057         struct iw_point *p;
3058         u16 len;
3059         u32 addr;
3060         u32 data32;
3061         u32 bytes;
3062         u8 *ptmp;
3063         int ret = 0;
3064
3065
3066         padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3067         p = &wrqu->data;
3068         len = p->length;
3069         ptmp = (u8*)kmalloc(len, GFP_KERNEL);
3070         if (ptmp == NULL)
3071                 return -ENOMEM;
3072
3073         if (copy_from_user(ptmp, p->pointer, len)) {
3074                 ret = -EFAULT;
3075                 goto out;
3076         }
3077
3078         bytes = 0;
3079         addr = 0;
3080         sscanf(ptmp, "%d,%x", &bytes, &addr);
3081
3082         switch (bytes) {
3083                 case 1:
3084                         data32 = rtw_read8(padapter, addr);
3085                         sprintf(extra, "0x%02X", data32);
3086                         break;
3087                 case 2:
3088                         data32 = rtw_read16(padapter, addr);
3089                         sprintf(extra, "0x%04X", data32);
3090                         break;
3091                 case 4:
3092                         data32 = rtw_read32(padapter, addr);
3093                         sprintf(extra, "0x%08X", data32);
3094                         break;
3095                 default:
3096                         DBG_8723A(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
3097                         ret = -EINVAL;
3098                         goto out;
3099         }
3100         DBG_8723A(KERN_INFO "%s: addr=0x%08X data=%s\n", __func__, addr, extra);
3101
3102 out:
3103         kfree(ptmp);
3104         return ret;
3105 }
3106
3107 static int rtw_wx_write32(struct net_device *dev,
3108                             struct iw_request_info *info,
3109                             union iwreq_data *wrqu, char *extra)
3110 {
3111         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3112
3113         u32 addr;
3114         u32 data32;
3115         u32 bytes;
3116
3117         bytes = 0;
3118         addr = 0;
3119         data32 = 0;
3120         sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
3121
3122         switch (bytes) {
3123                 case 1:
3124                         rtw_write8(padapter, addr, (u8)data32);
3125                         DBG_8723A(KERN_INFO "%s: addr=0x%08X data=0x%02X\n", __func__, addr, (u8)data32);
3126                         break;
3127                 case 2:
3128                         rtw_write16(padapter, addr, (u16)data32);
3129                         DBG_8723A(KERN_INFO "%s: addr=0x%08X data=0x%04X\n", __func__, addr, (u16)data32);
3130                         break;
3131                 case 4:
3132                         rtw_write32(padapter, addr, data32);
3133                         DBG_8723A(KERN_INFO "%s: addr=0x%08X data=0x%08X\n", __func__, addr, data32);
3134                         break;
3135                 default:
3136                         DBG_8723A(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
3137                         return -EINVAL;
3138         }
3139
3140         return 0;
3141 }
3142
3143 static int rtw_wx_read_rf(struct net_device *dev,
3144                             struct iw_request_info *info,
3145                             union iwreq_data *wrqu, char *extra)
3146 {
3147         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3148         u32 path, addr, data32;
3149
3150
3151         path = *(u32*)extra;
3152         addr = *((u32*)extra + 1);
3153         data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
3154 //      DBG_8723A("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32);
3155         /*
3156          * IMPORTANT!!
3157          * Only when wireless private ioctl is at odd order,
3158          * "extra" would be copied to user space.
3159          */
3160         sprintf(extra, "0x%05x", data32);
3161
3162         return 0;
3163 }
3164
3165 static int rtw_wx_write_rf(struct net_device *dev,
3166                             struct iw_request_info *info,
3167                             union iwreq_data *wrqu, char *extra)
3168 {
3169         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3170         u32 path, addr, data32;
3171
3172
3173         path = *(u32*)extra;
3174         addr = *((u32*)extra + 1);
3175         data32 = *((u32*)extra + 2);
3176 //      DBG_8723A("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32);
3177         rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
3178
3179         return 0;
3180 }
3181
3182 static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
3183                  union iwreq_data *wrqu, char *b)
3184 {
3185         return -1;
3186 }
3187
3188 static int dummy(struct net_device *dev, struct iw_request_info *a,
3189                  union iwreq_data *wrqu, char *b)
3190 {
3191         //struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3192         //struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3193
3194         //DBG_8723A("cmd_code=%x, fwstate=0x%x\n", a->cmd, get_fwstate(pmlmepriv));
3195
3196         return -1;
3197
3198 }
3199
3200 static int rtw_wx_set_channel_plan(struct net_device *dev,
3201                                struct iw_request_info *info,
3202                                union iwreq_data *wrqu, char *extra)
3203 {
3204         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3205         struct registry_priv *pregistrypriv = &padapter->registrypriv;
3206         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3207         extern int rtw_channel_plan;
3208         u8 channel_plan_req = (u8) (*((int *)wrqu));
3209
3210         if( _SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1) ) {
3211                 DBG_8723A("%s set channel_plan = 0x%02X\n", __func__, pmlmepriv->ChannelPlan);
3212         } else
3213                 return -EPERM;
3214
3215         return 0;
3216 }
3217
3218 static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
3219                 struct iw_request_info *a,
3220                 union iwreq_data *wrqu, char *b)
3221 {
3222         return 0;
3223 }
3224
3225 static int rtw_wx_get_sensitivity(struct net_device *dev,
3226                                 struct iw_request_info *info,
3227                                 union iwreq_data *wrqu, char *buf)
3228 {
3229         return 0;
3230 }
3231
3232 static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
3233                                 struct iw_request_info *info,
3234                                 union iwreq_data *wrqu, char *extra)
3235 {
3236         return 0;
3237 }
3238
3239 /*
3240 typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
3241                           union iwreq_data *wrqu, char *extra);
3242 */
3243 /*
3244  *      For all data larger than 16 octets, we need to use a
3245  *      pointer to memory allocated in user space.
3246  */
3247 static  int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
3248                                                 union iwreq_data *wrqu, char *extra)
3249 {
3250 #ifdef CONFIG_DRVEXT_MODULE
3251         u8 res;
3252         struct drvext_handler *phandler;
3253         struct drvext_oidparam *poidparam;
3254         int ret;
3255         u16 len;
3256         u8 *pparmbuf, bset;
3257         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3258         struct iw_point *p = &wrqu->data;
3259
3260         if( (!p->length) || (!p->pointer)){
3261                 ret = -EINVAL;
3262                 goto _rtw_drvext_hdl_exit;
3263         }
3264
3265
3266         bset = (u8)(p->flags&0xFFFF);
3267         len = p->length;
3268         pparmbuf = (u8*)kmalloc(len, GFP_KERNEL);
3269         if (pparmbuf == NULL){
3270                 ret = -ENOMEM;
3271                 goto out;
3272         }
3273
3274         if(bset)//set info
3275         {
3276                 if (copy_from_user(pparmbuf, p->pointer,len)) {
3277                         ret = -EFAULT;
3278                         goto _rtw_drvext_hdl_exit;
3279                 }
3280         }
3281         else//query info
3282         {
3283
3284         }
3285
3286
3287         //
3288         poidparam = (struct drvext_oidparam *)pparmbuf;
3289
3290         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("drvext set oid subcode [%d], len[%d], InformationBufferLength[%d]\r\n",
3291                                                  poidparam->subcode, poidparam->len, len));
3292
3293
3294         //check subcode
3295         if ( poidparam->subcode >= MAX_DRVEXT_HANDLERS)
3296         {
3297                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("no matching drvext handlers\r\n"));
3298                 ret = -EINVAL;
3299                 goto _rtw_drvext_hdl_exit;
3300         }
3301
3302
3303         if ( poidparam->subcode >= MAX_DRVEXT_OID_SUBCODES)
3304         {
3305                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("no matching drvext subcodes\r\n"));
3306                 ret = -EINVAL;
3307                 goto _rtw_drvext_hdl_exit;
3308         }
3309
3310
3311         phandler = drvextoidhandlers + poidparam->subcode;
3312
3313         if (poidparam->len != phandler->parmsize)
3314         {
3315                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("no matching drvext param size %d vs %d\r\n",
3316                                                 poidparam->len , phandler->parmsize));
3317                 ret = -EINVAL;
3318                 goto _rtw_drvext_hdl_exit;
3319         }
3320
3321
3322         res = phandler->handler(&padapter->drvextpriv, bset, poidparam->data);
3323
3324         if(res==0)
3325         {
3326                 ret = 0;
3327
3328                 if (bset == 0x00) {//query info
3329                         //memcpy(p->pointer, pparmbuf, len);
3330                         if (copy_to_user(p->pointer, pparmbuf, len))
3331                                 ret = -EFAULT;
3332                 }
3333         }
3334         else
3335                 ret = -EFAULT;
3336
3337
3338 _rtw_drvext_hdl_exit:
3339         kfree(pparmbuf);
3340 out:
3341         return ret;
3342
3343 #endif
3344
3345         return 0;
3346
3347 }
3348
3349 static int rtw_get_ap_info(struct net_device *dev,
3350                                struct iw_request_info *info,
3351                                union iwreq_data *wrqu, char *extra)
3352 {
3353         int bssid_match, ret = 0;
3354         u32 cnt=0, wpa_ielen;
3355         struct list_head        *plist, *phead;
3356         unsigned char *pbuf;
3357         u8 bssid[ETH_ALEN];
3358         char data[32];
3359         struct wlan_network *pnetwork = NULL;
3360         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3361         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3362         _queue *queue = &(pmlmepriv->scanned_queue);
3363         struct iw_point *pdata = &wrqu->data;
3364
3365         DBG_8723A("+rtw_get_aplist_info\n");
3366
3367         if((padapter->bDriverStopped) || (pdata==NULL))
3368         {
3369                 ret= -EINVAL;
3370                 goto exit;
3371         }
3372
3373         while((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) == _TRUE)
3374         {
3375                 msleep(30);
3376                 cnt++;
3377                 if(cnt > 100)
3378                         break;
3379         }
3380
3381
3382         //pdata->length = 0;//?
3383         pdata->flags = 0;
3384         if(pdata->length>=32)
3385         {
3386                 if(copy_from_user(data, pdata->pointer, 32))
3387                 {
3388                         ret= -EINVAL;
3389                         goto exit;
3390                 }
3391         }
3392         else
3393         {
3394                 ret= -EINVAL;
3395                 goto exit;
3396         }
3397
3398         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3399
3400         phead = get_list_head(queue);
3401         plist = phead->next;
3402
3403         while(1)
3404         {
3405                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
3406                         break;
3407
3408
3409                 pnetwork = container_of(plist, struct wlan_network, list);
3410
3411                 //if(hwaddr_aton_i(pdata->pointer, bssid))
3412                 if(hwaddr_aton_i(data, bssid))
3413                 {
3414                         DBG_8723A("Invalid BSSID '%s'.\n", (u8*)data);
3415                         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
3416                         return -EINVAL;
3417                 }
3418
3419
3420                 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN))//BSSID match, then check if supporting wpa/wpa2
3421                 {
3422                         DBG_8723A("BSSID:" MAC_FMT "\n", MAC_ARG(bssid));
3423
3424                         pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
3425                         if(pbuf && (wpa_ielen>0))
3426                         {
3427                                 pdata->flags = 1;
3428                                 break;
3429                         }
3430
3431                         pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
3432                         if(pbuf && (wpa_ielen>0))
3433                         {
3434                                 pdata->flags = 2;
3435                                 break;
3436                         }
3437
3438                 }
3439
3440                 plist = plist->next;
3441
3442         }
3443
3444         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
3445
3446         if(pdata->length>=34)
3447         {
3448                 if(copy_to_user((u8*)pdata->pointer+32, (u8*)&pdata->flags, 1))
3449                 {
3450                         ret= -EINVAL;
3451                         goto exit;
3452                 }
3453         }
3454
3455 exit:
3456
3457         return ret;
3458
3459 }
3460
3461 static int rtw_set_pid(struct net_device *dev,
3462                                struct iw_request_info *info,
3463                                union iwreq_data *wrqu, char *extra)
3464 {
3465
3466         int ret = 0;
3467         struct rtw_adapter *padapter = rtw_netdev_priv(dev);
3468         int *pdata = (int *)wrqu;
3469         int selector;
3470
3471         if((padapter->bDriverStopped) || (pdata==NULL))
3472         {
3473                 ret= -EINVAL;
3474                 goto exit;
3475         }
3476
3477         selector = *pdata;
3478         if(selector < 3 && selector >=0) {
3479                 padapter->pid[selector] = *(pdata+1);
3480                 #ifdef CONFIG_GLOBAL_UI_PID
3481                 ui_pid[selector] = *(pdata+1);
3482                 #endif
3483                 DBG_8723A("%s set pid[%d]=%d\n", __func__, selector ,padapter->pid[selector]);
3484         }
3485         else
3486                 DBG_8723A("%s selector %d error\n", __func__, selector);
3487
3488 exit:
3489
3490         return ret;
3491
3492 }
3493
3494 static int rtw_wps_start(struct net_device *dev,
3495                                struct iw_request_info *info,
3496                                union iwreq_data *wrqu, char *extra)
3497 {
3498
3499         int ret = 0;
3500         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3501         struct iw_point *pdata = &wrqu->data;
3502         u32   u32wps_start = 0;
3503         unsigned int uintRet = 0;
3504
3505         uintRet = copy_from_user( ( void* ) &u32wps_start, pdata->pointer, 4 );
3506
3507         if((padapter->bDriverStopped) || (pdata==NULL))
3508         {
3509                 ret= -EINVAL;
3510                 goto exit;
3511         }
3512
3513         if ( u32wps_start == 0 )
3514         {
3515                 u32wps_start = *extra;
3516         }
3517
3518         DBG_8723A( "[%s] wps_start = %d\n", __func__, u32wps_start );
3519
3520         if ( u32wps_start == 1 ) // WPS Start
3521         {
3522                 rtw_led_control(padapter, LED_CTL_START_WPS);
3523         }
3524         else if ( u32wps_start == 2 ) // WPS Stop because of wps success
3525         {
3526                 rtw_led_control(padapter, LED_CTL_STOP_WPS);
3527         }
3528         else if ( u32wps_start == 3 ) // WPS Stop because of wps fail
3529         {
3530                 rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
3531         }
3532 exit:
3533
3534         return ret;
3535
3536 }
3537
3538 #ifdef CONFIG_P2P
3539 static int rtw_wext_p2p_enable(struct net_device *dev,
3540                                struct iw_request_info *info,
3541                                union iwreq_data *wrqu, char *extra)
3542 {
3543
3544         int ret = 0;
3545         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3546         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3547         struct iw_point *pdata = &wrqu->data;
3548         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
3549         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3550         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
3551         enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
3552
3553         if(*extra == '0' )
3554                 init_role = P2P_ROLE_DISABLE;
3555         else if(*extra == '1')
3556                 init_role = P2P_ROLE_DEVICE;
3557         else if(*extra == '2')
3558                 init_role = P2P_ROLE_CLIENT;
3559         else if(*extra == '3')
3560                 init_role = P2P_ROLE_GO;
3561
3562         if(_FAIL == rtw_p2p_enable(padapter, init_role))
3563         {
3564                 ret = -EFAULT;
3565                 goto exit;
3566         }
3567
3568         //set channel/bandwidth
3569         if(init_role != P2P_ROLE_DISABLE)
3570         {
3571                 u8 channel, ch_offset;
3572                 u16 bwmode;
3573
3574                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN))
3575                 {
3576                         //      Stay at the listen state and wait for discovery.
3577                         channel = pwdinfo->listen_channel;
3578                         pwdinfo->operating_channel = pwdinfo->listen_channel;
3579                         ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3580                         bwmode = HT_CHANNEL_WIDTH_20;
3581                 }
3582 #ifdef CONFIG_CONCURRENT_MODE
3583                 else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
3584                 {
3585                         struct rtw_adapter *pbuddy_adapter = padapter->pbuddy_adapter;
3586                         //struct wifidirect_info        *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
3587                         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
3588                         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3589
3590                         _set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval );
3591                         if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
3592                         {
3593                                 pwdinfo->operating_channel = pbuddy_mlmeext->cur_channel;
3594                                 //      How about the ch_offset and bwmode ??
3595                         }
3596                         else
3597                         {
3598                                 pwdinfo->operating_channel = pwdinfo->listen_channel;
3599                         }
3600
3601                         channel = pbuddy_mlmeext->cur_channel;
3602                         ch_offset = pbuddy_mlmeext->cur_ch_offset;
3603                         bwmode = pbuddy_mlmeext->cur_bwmode;
3604                 }
3605 #endif
3606                 else
3607                 {
3608                         pwdinfo->operating_channel = pmlmeext->cur_channel;
3609
3610                         channel = pwdinfo->operating_channel;
3611                         ch_offset = pmlmeext->cur_ch_offset;
3612                         bwmode = pmlmeext->cur_bwmode;
3613                 }
3614
3615                 set_channel_bwmode(padapter, channel, ch_offset, bwmode);
3616         }
3617
3618 exit:
3619         return ret;
3620
3621 }
3622
3623 static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
3624                                struct iw_request_info *info,
3625                                union iwreq_data *wrqu, char *extra)
3626 {
3627
3628         int ret = 0;
3629         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3630         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3631         struct iw_point *pdata = &wrqu->data;
3632         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
3633
3634         DBG_8723A( "[%s] ssid = %s, len = %zu\n", __func__, extra, strlen( extra ) );
3635         memcpy(pwdinfo->nego_ssid, extra, strlen( extra ) );
3636         pwdinfo->nego_ssidlen = strlen( extra );
3637
3638         return ret;
3639
3640 }
3641
3642
3643 static int rtw_p2p_set_intent(struct net_device *dev,
3644                                struct iw_request_info *info,
3645                                union iwreq_data *wrqu, char *extra)
3646 {
3647         int ret = 0;
3648         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3649         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
3650         u8 intent = pwdinfo->intent;
3651
3652         switch (wrqu->data.length) {
3653                 case 1:
3654                 {
3655                         intent = extra[ 0 ] - '0';
3656                         break;
3657                 }
3658                 case 2:
3659                 {
3660                         intent = str_2char2num( extra[ 0 ], extra[ 1 ]);
3661                         break;
3662                 }
3663         }
3664
3665         if ( intent <= 15 )
3666         {
3667                 pwdinfo->intent= intent;
3668         }
3669         else
3670         {
3671                 ret = -1;
3672         }
3673
3674         DBG_8723A( "[%s] intent = %d\n", __func__, intent);
3675
3676         return ret;
3677
3678 }
3679
3680 static int rtw_p2p_set_listen_ch(struct net_device *dev,
3681                                struct iw_request_info *info,
3682                                union iwreq_data *wrqu, char *extra)
3683 {
3684
3685         int ret = 0;
3686         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3687         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
3688         u8      listen_ch = pwdinfo->listen_channel;    //      Listen channel number
3689
3690         switch( wrqu->data.length )
3691         {
3692                 case 1:
3693                 {
3694                         listen_ch = extra[ 0 ] - '0';
3695                         break;
3696                 }
3697                 case 2:
3698                 {
3699                         listen_ch = str_2char2num( extra[ 0 ], extra[ 1 ]);
3700                         break;
3701                 }
3702         }
3703
3704         if ( ( listen_ch == 1 ) || ( listen_ch == 6 ) || ( listen_ch == 11 ) )
3705         {
3706                 pwdinfo->listen_channel = listen_ch;
3707                 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3708         }
3709         else
3710         {
3711                 ret = -1;
3712         }
3713
3714         DBG_8723A( "[%s] listen_ch = %d\n", __func__, pwdinfo->listen_channel );
3715
3716         return ret;
3717
3718 }
3719
3720 static int rtw_p2p_set_op_ch(struct net_device *dev,
3721                                struct iw_request_info *info,
3722                                union iwreq_data *wrqu, char *extra)
3723 {
3724 //      Commented by Albert 20110524
3725 //      This function is used to set the operating channel if the driver will become the group owner
3726
3727         int ret = 0;
3728         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3729         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
3730         u8      op_ch = pwdinfo->operating_channel;     //      Operating channel number
3731
3732         switch( wrqu->data.length )
3733         {
3734                 case 1:
3735                 {
3736                         op_ch = extra[ 0 ] - '0';
3737                         break;
3738                 }
3739                 case 2:
3740                 {
3741                         op_ch = str_2char2num( extra[ 0 ], extra[ 1 ]);
3742                         break;
3743                 }
3744         }
3745
3746         if ( op_ch > 0 )
3747         {
3748                 pwdinfo->operating_channel = op_ch;
3749         }
3750         else
3751         {
3752                 ret = -1;
3753         }
3754
3755         DBG_8723A( "[%s] op_ch = %d\n", __func__, pwdinfo->operating_channel );
3756
3757         return ret;
3758
3759 }
3760
3761
3762 static int rtw_p2p_profilefound(struct net_device *dev,
3763                                struct iw_request_info *info,
3764                                union iwreq_data *wrqu, char *extra)
3765 {
3766
3767         int ret = 0;
3768         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3769         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
3770
3771         //      Comment by Albert 2010/10/13
3772         //      Input data format:
3773         //      Ex:  0
3774         //      Ex:  1XX:XX:XX:XX:XX:XXYYSSID
3775         //      0 => Reflush the profile record list.
3776         //      1 => Add the profile list
3777         //      XX:XX:XX:XX:XX:XX => peer's MAC Address ( ex: 00:E0:4C:00:00:01 )
3778         //      YY => SSID Length
3779         //      SSID => SSID for persistence group
3780
3781         DBG_8723A( "[%s] In value = %s, len = %d \n", __func__, extra, wrqu->data.length -1);
3782
3783
3784         //      The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function.
3785         if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3786         {
3787                 if ( extra[ 0 ] == '0' )
3788                 {
3789                         //      Remove all the profile information of wifidirect_info structure.
3790                         memset( &pwdinfo->profileinfo[ 0 ], 0x00, sizeof( struct profile_info ) * P2P_MAX_PERSISTENT_GROUP_NUM );
3791                         pwdinfo->profileindex = 0;
3792                 }
3793                 else
3794                 {
3795                         if ( pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM )
3796                 {
3797                                 ret = -1;
3798                 }
3799                 else
3800                 {
3801                                 int jj, kk;
3802
3803                                 //      Add this profile information into pwdinfo->profileinfo
3804                                 //      Ex:  1XX:XX:XX:XX:XX:XXYYSSID
3805                                 for( jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3 )
3806                                 {
3807                                         pwdinfo->profileinfo[ pwdinfo->profileindex ].peermac[ jj ] = key_2char2num(extra[ kk ], extra[ kk+ 1 ]);
3808                                 }
3809
3810                                 pwdinfo->profileinfo[ pwdinfo->profileindex ].ssidlen = ( extra[18] - '0' ) * 10 + ( extra[ 19 ] - '0' );
3811                                 memcpy(pwdinfo->profileinfo[ pwdinfo->profileindex ].ssid, &extra[ 20 ], pwdinfo->profileinfo[ pwdinfo->profileindex ].ssidlen );
3812                                 pwdinfo->profileindex++;
3813                         }
3814                 }
3815         }
3816
3817         return ret;
3818
3819 }
3820
3821 static int rtw_p2p_setDN(struct net_device *dev,
3822                                struct iw_request_info *info,
3823                                union iwreq_data *wrqu, char *extra)
3824 {
3825
3826         int ret = 0;
3827         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3828         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
3829
3830
3831         DBG_8723A( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
3832         memset( pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN );
3833         memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1 );
3834         pwdinfo->device_name_len = wrqu->data.length - 1;
3835
3836         return ret;
3837
3838 }
3839
3840
3841 static int rtw_p2p_get_status(struct net_device *dev,
3842                                struct iw_request_info *info,
3843                                union iwreq_data *wrqu, char *extra)
3844 {
3845
3846         int ret = 0;
3847         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3848         struct iw_point *pdata = &wrqu->data;
3849         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
3850 #ifdef CONFIG_CONCURRENT_MODE
3851         struct rtw_adapter                              *pbuddy_adapter = padapter->pbuddy_adapter;
3852         struct wifidirect_info  *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
3853         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
3854         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3855 #endif
3856
3857         if ( padapter->bShowGetP2PState )
3858         {
3859                 DBG_8723A( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
3860                                 pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
3861                                 pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
3862         }
3863
3864         //      Commented by Albert 2010/10/12
3865         //      Because of the output size limitation, I had removed the "Role" information.
3866         //      About the "Role" information, we will use the new private IOCTL to get the "Role" information.
3867         sprintf( extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo) );
3868         wrqu->data.length = strlen( extra );
3869
3870         return ret;
3871
3872 }
3873
3874 //      Commented by Albert 20110520
3875 //      This function will return the config method description
3876 //      This config method description will show us which config method the remote P2P device is intented to use
3877 //      by sending the provisioning discovery request frame.
3878
3879 static int rtw_p2p_get_req_cm(struct net_device *dev,
3880                                struct iw_request_info *info,
3881                                union iwreq_data *wrqu, char *extra)
3882 {
3883
3884         int ret = 0;
3885         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3886         struct iw_point *pdata = &wrqu->data;
3887         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
3888
3889         sprintf( extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req );
3890         wrqu->data.length = strlen( extra );
3891         return ret;
3892
3893 }
3894
3895
3896 static int rtw_p2p_get_role(struct net_device *dev,
3897                                struct iw_request_info *info,
3898                                union iwreq_data *wrqu, char *extra)
3899 {
3900
3901         int ret = 0;
3902         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3903         struct iw_point *pdata = &wrqu->data;
3904         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
3905
3906
3907         DBG_8723A( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
3908                         pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
3909                         pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
3910
3911         sprintf( extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo) );
3912         wrqu->data.length = strlen( extra );
3913         return ret;
3914
3915 }
3916
3917
3918 static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
3919                                struct iw_request_info *info,
3920                                union iwreq_data *wrqu, char *extra)
3921 {
3922
3923         int ret = 0;
3924         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3925         struct iw_point *pdata = &wrqu->data;
3926         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
3927
3928
3929         DBG_8723A( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
3930                         pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
3931                         pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
3932
3933         sprintf( extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
3934                         pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
3935                         pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
3936         wrqu->data.length = strlen( extra );
3937         return ret;
3938
3939 }
3940
3941 static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
3942                                struct iw_request_info *info,
3943                                union iwreq_data *wrqu, char *extra)
3944
3945 {
3946
3947         int ret = 0;
3948         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3949         struct iw_point *pdata = &wrqu->data;
3950         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
3951
3952         DBG_8723A( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
3953                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 0 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 1 ],
3954                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 2 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 3 ],
3955                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 4 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 5 ]);
3956         sprintf( extra, "\n%.2X%.2X%.2X%.2X%.2X%.2X",
3957                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 0 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 1 ],
3958                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 2 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 3 ],
3959                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 4 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 5 ]);
3960         wrqu->data.length = strlen( extra );
3961         return ret;
3962
3963 }
3964
3965 static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev,
3966                                struct iw_request_info *info,
3967                                union iwreq_data *wrqu, char *extra)
3968
3969 {
3970
3971         int ret = 0;
3972         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3973         struct iw_point *pdata = &wrqu->data;
3974         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
3975
3976         DBG_8723A( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
3977                         pwdinfo->p2p_peer_device_addr[ 0 ], pwdinfo->p2p_peer_device_addr[ 1 ],
3978                         pwdinfo->p2p_peer_device_addr[ 2 ], pwdinfo->p2p_peer_device_addr[ 3 ],
3979                         pwdinfo->p2p_peer_device_addr[ 4 ], pwdinfo->p2p_peer_device_addr[ 5 ]);
3980         sprintf( extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
3981                         pwdinfo->p2p_peer_device_addr[ 0 ], pwdinfo->p2p_peer_device_addr[ 1 ],
3982                         pwdinfo->p2p_peer_device_addr[ 2 ], pwdinfo->p2p_peer_device_addr[ 3 ],
3983                         pwdinfo->p2p_peer_device_addr[ 4 ], pwdinfo->p2p_peer_device_addr[ 5 ]);
3984         wrqu->data.length = strlen( extra );
3985         return ret;
3986
3987 }
3988
3989 static int rtw_p2p_get_groupid(struct net_device *dev,
3990                                struct iw_request_info *info,
3991                                union iwreq_data *wrqu, char *extra)
3992
3993 {
3994
3995         int ret = 0;
3996         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
3997         struct iw_point *pdata = &wrqu->data;
3998         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
3999
4000         sprintf( extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
4001                         pwdinfo->groupid_info.go_device_addr[ 0 ], pwdinfo->groupid_info.go_device_addr[ 1 ],
4002                         pwdinfo->groupid_info.go_device_addr[ 2 ], pwdinfo->groupid_info.go_device_addr[ 3 ],
4003                         pwdinfo->groupid_info.go_device_addr[ 4 ], pwdinfo->groupid_info.go_device_addr[ 5 ],
4004                         pwdinfo->groupid_info.ssid);
4005         wrqu->data.length = strlen( extra );
4006         return ret;
4007
4008 }
4009
4010 static int rtw_p2p_get_op_ch(struct net_device *dev,
4011                                struct iw_request_info *info,
4012                                union iwreq_data *wrqu, char *extra)
4013
4014 {
4015
4016         int ret = 0;
4017         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4018         struct iw_point *pdata = &wrqu->data;
4019         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
4020
4021
4022         DBG_8723A( "[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel);
4023
4024         sprintf( extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel );
4025         wrqu->data.length = strlen( extra );
4026         return ret;
4027
4028 }
4029
4030 inline static void macstr2num(u8 *dst, u8 *src)
4031 {
4032         int     jj, kk;
4033         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
4034         {
4035                 dst[jj] = key_2char2num(src[kk], src[kk + 1]);
4036         }
4037 }
4038
4039 static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
4040                                                                                 struct iw_request_info *info,
4041                                                                                 union iwreq_data *wrqu, char *extra, char *subcmd)
4042 {
4043
4044         int ret = 0;
4045         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4046         u8 peerMAC[ETH_ALEN] = { 0x00 };
4047         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4048         struct list_head * plist,*phead;
4049         _queue *queue = &(pmlmepriv->scanned_queue);
4050         struct wlan_network *pnetwork = NULL;
4051         u8 blnMatch = 0;
4052         u16     attr_content = 0;
4053         uint attr_contentlen = 0;
4054         u8      attr_content_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
4055
4056         //      Commented by Albert 20110727
4057         //      The input data is the MAC address which the application wants to know its WPS config method.
4058         //      After knowing its WPS config method, the application can decide the config method for provisioning discovery.
4059         //      Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05
4060
4061         DBG_8723A("[%s] data = %s\n", __func__, subcmd);
4062
4063         macstr2num(peerMAC, subcmd);
4064
4065         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
4066
4067         phead = get_list_head(queue);
4068         plist = phead->next;
4069
4070         while (1)
4071         {
4072                 if (rtw_end_of_queue_search(phead, plist) == _TRUE) break;
4073
4074                 pnetwork = container_of(plist, struct wlan_network, list);
4075                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN))
4076                 {
4077                         u8 *wpsie;
4078                         uint    wpsie_len = 0;
4079
4080                         //      The mac address is matched.
4081
4082                         if ((wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len)))
4083                         {
4084                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *)&attr_content, &attr_contentlen);
4085                                 if (attr_contentlen)
4086                                 {
4087                                         attr_content = be16_to_cpu(attr_content);
4088                                         sprintf(attr_content_str, "\n\nM=%.4d", attr_content);
4089                                         blnMatch = 1;
4090                                 }
4091                         }
4092
4093                         break;
4094                 }
4095
4096                 plist = plist->next;
4097
4098         }
4099
4100         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
4101
4102         if (!blnMatch)
4103         {
4104                 sprintf(attr_content_str, "\n\nM=0000");
4105         }
4106
4107         wrqu->data.length = strlen(attr_content_str);
4108         memcpy(extra, attr_content_str, wrqu->data.length);
4109
4110         return ret;
4111
4112 }
4113
4114 #ifdef CONFIG_WFD
4115 static int rtw_p2p_get_peer_wfd_port(struct net_device *dev,
4116                                struct iw_request_info *info,
4117                                union iwreq_data *wrqu, char *extra)
4118 {
4119
4120         int ret = 0;
4121         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4122         struct iw_point *pdata = &wrqu->data;
4123         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
4124
4125         DBG_8723A( "[%s] p2p_state = %d\n", __func__, rtw_p2p_state(pwdinfo) );
4126
4127         sprintf( extra, "\n\nPort=%d\n", pwdinfo->wfd_info->peer_rtsp_ctrlport );
4128         DBG_8723A( "[%s] remote port = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport );
4129
4130         wrqu->data.length = strlen( extra );
4131         return ret;
4132
4133 }
4134
4135 static int rtw_p2p_get_peer_wfd_preferred_connection(struct net_device *dev,
4136                                struct iw_request_info *info,
4137                                union iwreq_data *wrqu, char *extra)
4138 {
4139
4140         int ret = 0;
4141         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4142         struct iw_point *pdata = &wrqu->data;
4143         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
4144
4145         sprintf( extra, "\n\nwfd_pc=%d\n", pwdinfo->wfd_info->wfd_pc );
4146         DBG_8723A( "[%s] wfd_pc = %d\n", __func__, pwdinfo->wfd_info->wfd_pc );
4147
4148         wrqu->data.length = strlen( extra );
4149         pwdinfo->wfd_info->wfd_pc = _FALSE;     //      Reset the WFD preferred connection to P2P
4150         return ret;
4151
4152 }
4153
4154 static int rtw_p2p_get_peer_wfd_session_available(struct net_device *dev,
4155                                struct iw_request_info *info,
4156                                union iwreq_data *wrqu, char *extra)
4157 {
4158
4159         int ret = 0;
4160         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4161         struct iw_point *pdata = &wrqu->data;
4162         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
4163
4164         sprintf( extra, "\n\nwfd_sa=%d\n", pwdinfo->wfd_info->peer_session_avail );
4165         DBG_8723A( "[%s] wfd_sa = %d\n", __func__, pwdinfo->wfd_info->peer_session_avail );
4166
4167         wrqu->data.length = strlen( extra );
4168         pwdinfo->wfd_info->peer_session_avail = _TRUE;  //      Reset the WFD session available
4169         return ret;
4170
4171 }
4172
4173 #endif // CONFIG_WFD
4174
4175 static int rtw_p2p_get_go_device_address(struct net_device *dev,
4176                                                                                  struct iw_request_info *info,
4177                                                                                  union iwreq_data *wrqu, char *extra, char *subcmd)
4178 {
4179
4180         int ret = 0;
4181         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4182         u8 peerMAC[ETH_ALEN] = { 0x00 };
4183         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4184         struct list_head *plist, *phead;
4185         _queue *queue   = &(pmlmepriv->scanned_queue);
4186         struct wlan_network *pnetwork = NULL;
4187         u8 blnMatch = 0;
4188         u8 *p2pie;
4189         uint p2pielen = 0, attr_contentlen = 0;
4190         u8 attr_content[100] = { 0x00 };
4191         u8 go_devadd_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
4192
4193         //      Commented by Albert 20121209
4194         //      The input data is the GO's interface address which the application wants to know its device address.
4195         //      Format: iwpriv wlanx p2p_get2 go_devadd=00:E0:4C:00:00:05
4196
4197         DBG_8723A("[%s] data = %s\n", __func__, subcmd);
4198
4199         macstr2num(peerMAC, subcmd);
4200
4201         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
4202
4203         phead = get_list_head(queue);
4204         plist = phead->next;
4205
4206         while (1)
4207         {
4208                 if (rtw_end_of_queue_search(phead, plist) == _TRUE) break;
4209
4210                 pnetwork = container_of(plist, struct wlan_network, list);
4211                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN))
4212                 {
4213                         //      Commented by Albert 2011/05/18
4214                         //      Match the device address located in the P2P IE
4215                         //      This is for the case that the P2P device address is not the same as the P2P interface address.
4216
4217                         if ((p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen)))
4218                         {
4219                                 while (p2pie)
4220                                 {
4221                                         //      The P2P Device ID attribute is included in the Beacon frame.
4222                                         //      The P2P Device Info attribute is included in the probe response frame.
4223
4224                                         memset(attr_content, 0x00, 100);
4225                                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen))
4226                                         {
4227                                                 //      Handle the P2P Device ID attribute of Beacon first
4228                                                 blnMatch = 1;
4229                                                 break;
4230
4231                                         } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen))
4232                                         {
4233                                                 //      Handle the P2P Device Info attribute of probe response
4234                                                 blnMatch = 1;
4235                                                 break;
4236                                         }
4237
4238                                         //Get the next P2P IE
4239                                         p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
4240                                 }
4241                         }
4242                 }
4243
4244                 plist = plist->next;
4245
4246         }
4247
4248         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
4249
4250         if (!blnMatch)
4251         {
4252                 sprintf(go_devadd_str, "\n\ndev_add=NULL");
4253         } else
4254         {
4255                 sprintf(go_devadd_str, "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
4256                                 attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
4257         }
4258
4259         wrqu->data.length = strlen(go_devadd_str);
4260         memcpy(extra, go_devadd_str, wrqu->data.length);
4261
4262         return ret;
4263
4264 }
4265
4266 static int rtw_p2p_get_device_type(struct net_device *dev,
4267                                                                    struct iw_request_info *info,
4268                                                                    union iwreq_data *wrqu, char *extra, char *subcmd)
4269 {
4270
4271         int ret = 0;
4272         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4273         u8 peerMAC[ETH_ALEN] = { 0x00 };
4274         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4275         struct list_head *plist, *phead;
4276         _queue *queue = &(pmlmepriv->scanned_queue);
4277         struct wlan_network *pnetwork = NULL;
4278         u8 blnMatch = 0;
4279         u8 dev_type[8] = { 0x00 };
4280         uint dev_type_len = 0;
4281         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
4282
4283         //      Commented by Albert 20121209
4284         //      The input data is the MAC address which the application wants to know its device type.
4285         //      Such user interface could know the device type.
4286         //      Format: iwpriv wlanx p2p_get2 dev_type=00:E0:4C:00:00:05
4287
4288         DBG_8723A("[%s] data = %s\n", __func__, subcmd);
4289
4290         macstr2num(peerMAC, subcmd);
4291
4292         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
4293
4294         phead = get_list_head(queue);
4295         plist = phead->next;
4296
4297         while (1)
4298         {
4299                 if (rtw_end_of_queue_search(phead, plist) == _TRUE) break;
4300
4301                 pnetwork = container_of(plist, struct wlan_network, list);
4302                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN))
4303                 {
4304                         u8 *wpsie;
4305                         uint    wpsie_len = 0;
4306
4307                         //      The mac address is matched.
4308
4309                         if ((wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len)))
4310                         {
4311                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
4312                                 if (dev_type_len)
4313                                 {
4314                                         u16     type = 0;
4315
4316                                         memcpy(&type, dev_type, 2);
4317                                         type = be16_to_cpu(type);
4318                                         sprintf(dev_type_str, "\n\nN=%.2d", type);
4319                                         blnMatch = 1;
4320                                 }
4321                         }
4322                         break;
4323                 }
4324
4325                 plist = plist->next;
4326
4327         }
4328
4329         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
4330
4331         if (!blnMatch)
4332         {
4333                 sprintf(dev_type_str, "\n\nN=00");
4334         }
4335
4336         wrqu->data.length = strlen(dev_type_str);
4337         memcpy(extra, dev_type_str, wrqu->data.length);
4338
4339         return ret;
4340
4341 }
4342
4343 static int rtw_p2p_get_device_name(struct net_device *dev,
4344                                                                    struct iw_request_info *info,
4345                                                                    union iwreq_data *wrqu, char *extra, char *subcmd)
4346 {
4347
4348         int ret = 0;
4349         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4350         u8 peerMAC[ETH_ALEN] = { 0x00 };
4351         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4352         struct list_head *plist, *phead;
4353         _queue *queue = &(pmlmepriv->scanned_queue);
4354         struct wlan_network *pnetwork = NULL;
4355         u8 blnMatch = 0;
4356         u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = { 0x00 };
4357         uint dev_len = 0;
4358         u8 dev_name_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
4359
4360         //      Commented by Albert 20121225
4361         //      The input data is the MAC address which the application wants to know its device name.
4362         //      Such user interface could show peer device's device name instead of ssid.
4363         //      Format: iwpriv wlanx p2p_get2 devN=00:E0:4C:00:00:05
4364
4365         DBG_8723A("[%s] data = %s\n", __func__, subcmd);
4366
4367         macstr2num(peerMAC, subcmd);
4368
4369         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
4370
4371         phead = get_list_head(queue);
4372         plist = phead->next;
4373
4374         while (1)
4375         {
4376                 if (rtw_end_of_queue_search(phead, plist) == _TRUE) break;
4377
4378                 pnetwork = container_of(plist, struct wlan_network, list);
4379                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN))
4380                 {
4381                         u8 *wpsie;
4382                         uint    wpsie_len = 0;
4383
4384                         //      The mac address is matched.
4385
4386                         if ((wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len)))
4387                         {
4388                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
4389                                 if (dev_len)
4390                                 {
4391                                         sprintf(dev_name_str, "\n\nN=%s", dev_name);
4392                                         blnMatch = 1;
4393                                 }
4394                         }
4395                         break;
4396                 }
4397
4398                 plist = plist->next;
4399
4400         }
4401
4402         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
4403
4404         if (!blnMatch)
4405         {
4406                 sprintf(dev_name_str, "\n\nN=0000");
4407         }
4408
4409         wrqu->data.length = strlen(dev_name_str);
4410         memcpy(extra, dev_name_str, wrqu->data.length);
4411
4412         return ret;
4413
4414 }
4415
4416 static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
4417                                                                                         struct iw_request_info *info,
4418                                                                                         union iwreq_data *wrqu, char *extra, char *subcmd)
4419 {
4420
4421         int ret = 0;
4422         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4423         u8 peerMAC[ETH_ALEN] = { 0x00 };
4424         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4425         struct list_head *plist, *phead;
4426         _queue *queue   = &(pmlmepriv->scanned_queue);
4427         struct wlan_network *pnetwork = NULL;
4428         u8 blnMatch = 0;
4429         u8 *p2pie;
4430         uint p2pielen = 0, attr_contentlen = 0;
4431         u8 attr_content[2] = { 0x00 };
4432         u8 inv_proc_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
4433
4434         //      Commented by Ouden 20121226
4435         //      The application wants to know P2P initation procedure is support or not.
4436         //      Format: iwpriv wlanx p2p_get2 InvProc=00:E0:4C:00:00:05
4437
4438         DBG_8723A("[%s] data = %s\n", __func__, subcmd);
4439
4440         macstr2num(peerMAC, subcmd);
4441
4442         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
4443
4444         phead = get_list_head(queue);
4445         plist = phead->next;
4446
4447         while (1) {
4448                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4449                         break;
4450
4451                 pnetwork = container_of(plist, struct wlan_network, list);
4452                 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
4453                         //      Commented by Albert 20121226
4454                         //      Match the device address located in the P2P IE
4455                         //      This is for the case that the P2P device address is not the same as the P2P interface address.
4456
4457                         if ((p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen))) {
4458                                 while (p2pie) {
4459                                         //memset( attr_content, 0x00, 2);
4460                                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) {
4461                                                 //      Handle the P2P capability attribute
4462                                                 blnMatch = 1;
4463                                                 break;
4464                                         }
4465
4466                                         //Get the next P2P IE
4467                                         p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
4468                                 }
4469                         }
4470                 }
4471                 plist = plist->next;
4472         }
4473
4474         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
4475
4476         if (!blnMatch) {
4477                 sprintf(inv_proc_str, "\nIP=-1");
4478         } else {
4479                 if (attr_content[0] & 0x20)
4480                         sprintf(inv_proc_str, "\nIP=1");
4481                 else
4482                         sprintf(inv_proc_str, "\nIP=0");
4483         }
4484
4485         wrqu->data.length = strlen(inv_proc_str);
4486         memcpy(extra, inv_proc_str, wrqu->data.length);
4487
4488         return ret;
4489 }
4490
4491 static int rtw_p2p_connect(struct net_device *dev,
4492                                struct iw_request_info *info,
4493                                union iwreq_data *wrqu, char *extra)
4494 {
4495
4496         int ret = 0;
4497         struct rtw_adapter                              *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4498         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
4499         u8                                      peerMAC[ ETH_ALEN ] = { 0x00 };
4500         int                                     jj,kk;
4501         u8                                      peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
4502         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
4503         struct list_head                                        *plist, *phead;
4504         _queue                          *queue  = &(pmlmepriv->scanned_queue);
4505         struct  wlan_network    *pnetwork = NULL;
4506         uint                                    uintPeerChannel = 0;
4507 #ifdef CONFIG_CONCURRENT_MODE
4508         struct rtw_adapter                              *pbuddy_adapter = padapter->pbuddy_adapter;
4509         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
4510         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4511 #endif // CONFIG_CONCURRENT_MODE
4512
4513         //      Commented by Albert 20110304
4514         //      The input data contains two informations.
4515         //      1. First information is the MAC address which wants to formate with
4516         //      2. Second information is the WPS PINCode or "pbc" string for push button method
4517         //      Format: 00:E0:4C:00:00:05
4518         //      Format: 00:E0:4C:00:00:05
4519
4520         DBG_8723A( "[%s] data = %s\n", __func__, extra );
4521
4522         if ( pwdinfo->p2p_state == P2P_STATE_NONE )
4523         {
4524                 DBG_8723A( "[%s] WiFi Direct is disable!\n", __func__ );
4525                 return ret;
4526         }
4527
4528         if ( pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO )
4529         {
4530                 return -1;
4531         }
4532
4533         for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
4534         {
4535                 peerMAC[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
4536         }
4537
4538         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
4539
4540         phead = get_list_head(queue);
4541         plist = phead->next;
4542
4543         while(1)
4544         {
4545                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
4546                         break;
4547
4548                 pnetwork = container_of(plist, struct wlan_network, list);
4549                 if (!memcmp( pnetwork->network.MacAddress, peerMAC, ETH_ALEN))
4550                 {
4551                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
4552                         break;
4553                 }
4554
4555                 plist = plist->next;
4556
4557         }
4558
4559         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
4560
4561         if ( uintPeerChannel )
4562         {
4563 #ifdef CONFIG_CONCURRENT_MODE
4564                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
4565                 {
4566                         _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
4567                 }
4568 #endif // CONFIG_CONCURRENT_MODE
4569
4570                 memset( &pwdinfo->nego_req_info, 0x00, sizeof( struct tx_nego_req_info ) );
4571                 memset( &pwdinfo->groupid_info, 0x00, sizeof( struct group_id_info ) );
4572
4573                 pwdinfo->nego_req_info.peer_channel_num[ 0 ] = uintPeerChannel;
4574                 memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN );
4575                 pwdinfo->nego_req_info.benable = _TRUE;
4576
4577                 _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
4578                 if ( rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK )
4579                 {
4580                         //      Restore to the listen state if the current p2p state is not nego OK
4581                         rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN );
4582                 }
4583
4584                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
4585                 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
4586
4587 #ifdef CONFIG_CONCURRENT_MODE
4588                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
4589                 {
4590                         //      Have to enter the power saving with the AP
4591                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
4592
4593                         issue_nulldata(pbuddy_adapter, NULL, 1, 3, 500);
4594                 }
4595 #endif // CONFIG_CONCURRENT_MODE
4596
4597                 DBG_8723A( "[%s] Start PreTx Procedure!\n", __func__ );
4598                 _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
4599 #ifdef CONFIG_CONCURRENT_MODE
4600                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
4601                 {
4602                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_GO_NEGO_TIMEOUT );
4603                 }
4604                 else
4605                 {
4606                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT );
4607                 }
4608 #else
4609                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT );
4610 #endif // CONFIG_CONCURRENT_MODE
4611
4612         }
4613         else
4614         {
4615                 DBG_8723A( "[%s] Not Found in Scanning Queue~\n", __func__ );
4616                 ret = -1;
4617         }
4618 exit:
4619         return ret;
4620 }
4621
4622 static int rtw_p2p_invite_req(struct net_device *dev,
4623                                struct iw_request_info *info,
4624                                union iwreq_data *wrqu, char *extra)
4625 {
4626
4627         int ret = 0;
4628         struct rtw_adapter                                      *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4629         struct iw_point                         *pdata = &wrqu->data;
4630         struct wifidirect_info          *pwdinfo = &( padapter->wdinfo );
4631         int                                             jj,kk;
4632         u8                                              peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
4633         struct mlme_priv                        *pmlmepriv = &padapter->mlmepriv;
4634         struct list_head                                                *plist, *phead;
4635         _queue                                  *queue  = &(pmlmepriv->scanned_queue);
4636         struct  wlan_network            *pnetwork = NULL;
4637         uint                                            uintPeerChannel = 0;
4638         u8                                              attr_content[50] = { 0x00 }, _status = 0;
4639         u8                                              *p2pie;
4640         uint                                            p2pielen = 0, attr_contentlen = 0;
4641         struct tx_invite_req_info*      pinvite_req_info = &pwdinfo->invitereq_info;
4642 #ifdef CONFIG_CONCURRENT_MODE
4643         struct rtw_adapter                                      *pbuddy_adapter = padapter->pbuddy_adapter;
4644         struct mlme_priv                        *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
4645         struct mlme_ext_priv            *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4646 #endif // CONFIG_CONCURRENT_MODE
4647
4648 #ifdef CONFIG_WFD
4649         struct wifi_display_info*       pwfd_info = pwdinfo->wfd_info;
4650 #endif // CONFIG_WFD
4651
4652         //      Commented by Albert 20120321
4653         //      The input data contains two informations.
4654         //      1. First information is the P2P device address which you want to send to.
4655         //      2. Second information is the group id which combines with GO's mac address, space and GO's ssid.
4656         //      Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy"
4657         //      Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy
4658
4659         DBG_8723A( "[%s] data = %s\n", __func__, extra );
4660
4661         if ( wrqu->data.length <=  37 )
4662         {
4663                 DBG_8723A( "[%s] Wrong format!\n", __func__ );
4664                 return ret;
4665         }
4666
4667         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4668         {
4669                 DBG_8723A( "[%s] WiFi Direct is disable!\n", __func__ );
4670                 return ret;
4671         }
4672         else
4673         {
4674                 //      Reset the content of struct tx_invite_req_info
4675                 pinvite_req_info->benable = _FALSE;
4676                 memset( pinvite_req_info->go_bssid, 0x00, ETH_ALEN );
4677                 memset( pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN );
4678                 pinvite_req_info->ssidlen = 0x00;
4679                 pinvite_req_info->operating_ch = pwdinfo->operating_channel;
4680                 memset( pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN );
4681                 pinvite_req_info->token = 3;
4682         }
4683
4684         for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
4685         {
4686                 pinvite_req_info->peer_macaddr[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
4687         }
4688
4689         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
4690
4691         phead = get_list_head(queue);
4692         plist = phead->next;
4693
4694         while(1)
4695         {
4696                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
4697                         break;
4698
4699                 pnetwork = container_of(plist, struct wlan_network, list);
4700
4701                 //      Commented by Albert 2011/05/18
4702                 //      Match the device address located in the P2P IE
4703                 //      This is for the case that the P2P device address is not the same as the P2P interface address.
4704
4705                 if ( (p2pie=rtw_get_p2p_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen)) )
4706                 {
4707                         //      The P2P Device ID attribute is included in the Beacon frame.
4708                         //      The P2P Device Info attribute is included in the probe response frame.
4709
4710                         if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen) )
4711                         {
4712                                 //      Handle the P2P Device ID attribute of Beacon first
4713                                 if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN))
4714                                 {
4715                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
4716                                         break;
4717                                 }
4718                         }
4719                         else if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen) )
4720                         {
4721                                 //      Handle the P2P Device Info attribute of probe response
4722                                 if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN))
4723                                 {
4724                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
4725                                         break;
4726                                 }
4727                         }
4728
4729                 }
4730
4731                 plist = plist->next;
4732
4733         }
4734
4735         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
4736
4737 #ifdef CONFIG_WFD
4738         if ( uintPeerChannel )
4739         {
4740                 u8      wfd_ie[ 128 ] = { 0x00 };
4741                 uint    wfd_ielen = 0;
4742
4743                 if ( rtw_get_wfd_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12,  wfd_ie, &wfd_ielen ) )
4744                 {
4745                         u8      wfd_devinfo[ 6 ] = { 0x00 };
4746                         uint    wfd_devlen = 6;
4747
4748                         DBG_8723A( "[%s] Found WFD IE!\n", __func__ );
4749                         if ( rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, wfd_devinfo, &wfd_devlen ) )
4750                         {
4751                                 u16     wfd_devinfo_field = 0;
4752
4753                                 //      Commented by Albert 20120319
4754                                 //      The first two bytes are the WFD device information field of WFD device information subelement.
4755                                 //      In big endian format.
4756                                 wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
4757                                 if ( wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL )
4758                                 {
4759                                         pwfd_info->peer_session_avail = _TRUE;
4760                                 }
4761                                 else
4762                                 {
4763                                         pwfd_info->peer_session_avail = _FALSE;
4764                                 }
4765                         }
4766                 }
4767
4768                 if ( _FALSE == pwfd_info->peer_session_avail )
4769                 {
4770                         DBG_8723A( "[%s] WFD Session not avaiable!\n", __func__ );
4771                         goto exit;
4772                 }
4773         }
4774 #endif // CONFIG_WFD
4775
4776         if ( uintPeerChannel )
4777         {
4778 #ifdef CONFIG_CONCURRENT_MODE
4779                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
4780                 {
4781                         _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
4782                 }
4783 #endif // CONFIG_CONCURRENT_MODE
4784
4785                 //      Store the GO's bssid
4786                 for( jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3 )
4787                 {
4788                         pinvite_req_info->go_bssid[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
4789                 }
4790
4791                 //      Store the GO's ssid
4792                 pinvite_req_info->ssidlen = wrqu->data.length - 36;
4793                 memcpy(pinvite_req_info->go_ssid, &extra[ 36 ], (u32) pinvite_req_info->ssidlen );
4794                 pinvite_req_info->benable = _TRUE;
4795                 pinvite_req_info->peer_ch = uintPeerChannel;
4796
4797                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
4798                 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
4799
4800 #ifdef CONFIG_CONCURRENT_MODE
4801                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
4802                 {
4803                         //      Have to enter the power saving with the AP
4804                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
4805
4806                         issue_nulldata(pbuddy_adapter, NULL, 1, 3, 500);
4807                 }
4808                 else
4809                 {
4810                         set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
4811                 }
4812 #else
4813                 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
4814 #endif
4815
4816                 _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
4817
4818 #ifdef CONFIG_CONCURRENT_MODE
4819                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
4820                 {
4821                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_INVITE_TIMEOUT );
4822                 }
4823                 else
4824                 {
4825                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT );
4826                 }
4827 #else
4828                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT );
4829 #endif // CONFIG_CONCURRENT_MODE
4830
4831
4832         }
4833         else
4834         {
4835                 DBG_8723A( "[%s] NOT Found in the Scanning Queue!\n", __func__ );
4836         }
4837 exit:
4838
4839         return ret;
4840
4841 }
4842
4843 static int rtw_p2p_set_persistent(struct net_device *dev,
4844                                struct iw_request_info *info,
4845                                union iwreq_data *wrqu, char *extra)
4846 {
4847
4848         int ret = 0;
4849         struct rtw_adapter                                      *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4850         struct iw_point                         *pdata = &wrqu->data;
4851         struct wifidirect_info          *pwdinfo = &( padapter->wdinfo );
4852         int                                             jj,kk;
4853         u8                                              peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
4854         struct mlme_priv                        *pmlmepriv = &padapter->mlmepriv;
4855         struct list_head                                                *plist, *phead;
4856         _queue                                  *queue  = &(pmlmepriv->scanned_queue);
4857         struct  wlan_network            *pnetwork = NULL;
4858         uint                                            uintPeerChannel = 0;
4859         u8                                              attr_content[50] = { 0x00 }, _status = 0;
4860         u8                                              *p2pie;
4861         uint                                            p2pielen = 0, attr_contentlen = 0;
4862         struct tx_invite_req_info*      pinvite_req_info = &pwdinfo->invitereq_info;
4863 #ifdef CONFIG_CONCURRENT_MODE
4864         struct rtw_adapter                                      *pbuddy_adapter = padapter->pbuddy_adapter;
4865         struct mlme_priv                        *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
4866         struct mlme_ext_priv            *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4867 #endif // CONFIG_CONCURRENT_MODE
4868
4869 #ifdef CONFIG_WFD
4870         struct wifi_display_info*       pwfd_info = pwdinfo->wfd_info;
4871 #endif // CONFIG_WFD
4872
4873         //      Commented by Albert 20120328
4874         //      The input data is 0 or 1
4875         //      0: disable persistent group functionality
4876         //      1: enable persistent group founctionality
4877
4878         DBG_8723A( "[%s] data = %s\n", __func__, extra );
4879
4880         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4881         {
4882                 DBG_8723A( "[%s] WiFi Direct is disable!\n", __func__ );
4883                 return ret;
4884         }
4885         else
4886         {
4887                 if ( extra[ 0 ] == '0' )        //      Disable the persistent group function.
4888                 {
4889                         pwdinfo->persistent_supported = _FALSE;
4890                 }
4891                 else if ( extra[ 0 ] == '1' )   //      Enable the persistent group function.
4892                 {
4893                         pwdinfo->persistent_supported = _TRUE;
4894                 }
4895                 else
4896                 {
4897                         pwdinfo->persistent_supported = _FALSE;
4898                 }
4899         }
4900         printk( "[%s] persistent_supported = %d\n", __func__, pwdinfo->persistent_supported );
4901
4902 exit:
4903
4904         return ret;
4905
4906 }
4907
4908 #ifdef CONFIG_WFD
4909 static int rtw_p2p_set_pc(struct net_device *dev,
4910                                struct iw_request_info *info,
4911                                union iwreq_data *wrqu, char *extra)
4912 {
4913
4914         int ret = 0;
4915         struct rtw_adapter                              *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
4916         struct iw_point                 *pdata = &wrqu->data;
4917         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
4918         u8                                      peerMAC[ ETH_ALEN ] = { 0x00 };
4919         int                                     jj,kk;
4920         u8                                      peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
4921         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
4922         struct list_head                                        *plist, *phead;
4923         _queue                          *queue  = &(pmlmepriv->scanned_queue);
4924         struct  wlan_network    *pnetwork = NULL;
4925         u8                                      attr_content[50] = { 0x00 }, _status = 0;
4926         u8 *p2pie;
4927         uint                                    p2pielen = 0, attr_contentlen = 0;
4928         uint                                    uintPeerChannel = 0;
4929 #ifdef CONFIG_CONCURRENT_MODE
4930         struct rtw_adapter                              *pbuddy_adapter = padapter->pbuddy_adapter;
4931         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4932 #endif // CONFIG_CONCURRENT_MODE
4933         struct wifi_display_info*       pwfd_info = pwdinfo->wfd_info;
4934
4935         //      Commented by Albert 20120512
4936         //      1. Input information is the MAC address which wants to know the Preferred Connection bit (PC bit)
4937         //      Format: 00:E0:4C:00:00:05
4938
4939         DBG_8723A( "[%s] data = %s\n", __func__, extra );
4940
4941         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4942         {
4943                 DBG_8723A( "[%s] WiFi Direct is disable!\n", __func__ );
4944                 return ret;
4945         }
4946
4947         for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
4948         {
4949                 peerMAC[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
4950         }
4951
4952         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
4953
4954         phead = get_list_head(queue);
4955         plist = phead->next;
4956
4957         while(1)
4958         {
4959                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
4960                         break;
4961
4962                 pnetwork = container_of(plist, struct wlan_network, list);
4963
4964                 //      Commented by Albert 2011/05/18
4965                 //      Match the device address located in the P2P IE
4966                 //      This is for the case that the P2P device address is not the same as the P2P interface address.
4967
4968                 if ( (p2pie=rtw_get_p2p_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen)) )
4969                 {
4970                         //      The P2P Device ID attribute is included in the Beacon frame.
4971                         //      The P2P Device Info attribute is included in the probe response frame.
4972                         printk( "[%s] Got P2P IE\n", __func__ );
4973                         if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen) )
4974                         {
4975                                 //      Handle the P2P Device ID attribute of Beacon first
4976                                 printk( "[%s] P2P_ATTR_DEVICE_ID \n", __func__ );
4977                                 if (!memcmp(attr_content, peerMAC, ETH_ALEN))
4978                                 {
4979                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
4980                                         break;
4981                                 }
4982                         }
4983                         else if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen) )
4984                         {
4985                                 //      Handle the P2P Device Info attribute of probe response
4986                                 printk( "[%s] P2P_ATTR_DEVICE_INFO \n", __func__ );
4987                                 if (!memcmp( attr_content, peerMAC, ETH_ALEN))
4988                                 {
4989                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
4990                                         break;
4991                                 }
4992                         }
4993
4994                 }
4995
4996                 plist = plist->next;
4997
4998         }
4999
5000         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
5001         printk( "[%s] channel = %d\n", __func__, uintPeerChannel );
5002
5003         if ( uintPeerChannel )
5004         {
5005                 u8      wfd_ie[ 128 ] = { 0x00 };
5006                 uint    wfd_ielen = 0;
5007
5008                 if ( rtw_get_wfd_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12,  wfd_ie, &wfd_ielen ) )
5009                 {
5010                         u8      wfd_devinfo[ 6 ] = { 0x00 };
5011                         uint    wfd_devlen = 6;
5012
5013                         DBG_8723A( "[%s] Found WFD IE!\n", __func__ );
5014                         if ( rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, wfd_devinfo, &wfd_devlen ) )
5015                         {
5016                                 u16     wfd_devinfo_field = 0;
5017
5018                                 //      Commented by Albert 20120319
5019                                 //      The first two bytes are the WFD device information field of WFD device information subelement.
5020                                 //      In big endian format.
5021                                 wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
5022                                 if ( wfd_devinfo_field & WFD_DEVINFO_PC_TDLS )
5023                                 {
5024                                         pwfd_info->wfd_pc = _TRUE;
5025                                 }
5026                                 else
5027                                 {
5028                                         pwfd_info->wfd_pc = _FALSE;
5029                                 }
5030                         }
5031                 }
5032         }
5033         else
5034         {
5035                 DBG_8723A( "[%s] NOT Found in the Scanning Queue!\n", __func__ );
5036         }
5037
5038 exit:
5039
5040         return ret;
5041
5042 }
5043
5044 static int rtw_p2p_set_wfd_device_type(struct net_device *dev,
5045                                struct iw_request_info *info,
5046                                union iwreq_data *wrqu, char *extra)
5047 {
5048
5049         int ret = 0;
5050         struct rtw_adapter                                      *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
5051         struct iw_point                         *pdata = &wrqu->data;
5052         struct wifidirect_info          *pwdinfo = &( padapter->wdinfo );
5053         struct wifi_display_info*       pwfd_info = pwdinfo->wfd_info;
5054
5055         //      Commented by Albert 20120328
5056         //      The input data is 0 or 1
5057         //      0: specify to Miracast source device
5058         //      1 or others: specify to Miracast sink device (display device)
5059
5060         DBG_8723A( "[%s] data = %s\n", __func__, extra );
5061
5062         if ( extra[ 0 ] == '0' )        //      Set to Miracast source device.
5063         {
5064                 pwfd_info->wfd_device_type = WFD_DEVINFO_SOURCE;
5065         }
5066         else                                    //      Set to Miracast sink device.
5067         {
5068                 pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
5069         }
5070
5071 exit:
5072
5073         return ret;
5074
5075 }
5076
5077 static int rtw_p2p_set_scan_result_type(struct net_device *dev,
5078                                struct iw_request_info *info,
5079                                union iwreq_data *wrqu, char *extra)
5080 {
5081
5082         int ret = 0;
5083         struct rtw_adapter                                      *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
5084         struct iw_point                         *pdata = &wrqu->data;
5085         struct wifidirect_info          *pwdinfo = &( padapter->wdinfo );
5086         struct wifi_display_info                *pwfd_info = pwdinfo->wfd_info;
5087
5088         //      Commented by Albert 20120328
5089         //      The input data is 0 , 1 , 2
5090         //      0: when the P2P is enabled, the scan result will return all the found P2P device.
5091         //      1: when the P2P is enabled, the scan result will return all the found P2P device and AP.
5092         //      2: when the P2P is enabled, the scan result will show up the found Miracast devices base on...
5093         //      It will show up all the Miracast source device if this device is sink.
5094         //      It will show up all the Miracast sink device if this device is source.
5095
5096         DBG_8723A( "[%s] data = %s\n", __func__, extra );
5097
5098         if ( extra[ 0 ] == '0' )
5099         {
5100                 pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
5101         }
5102         else if ( extra[ 0 ] == '1' )
5103         {
5104                 pwfd_info->scan_result_type = SCAN_RESULT_ALL;
5105         }
5106         else if ( extra[ 0 ] == '2' )
5107         {
5108                 pwfd_info->scan_result_type = SCAN_RESULT_WFD_TYPE;
5109         }
5110         else
5111         {
5112                 pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
5113         }
5114
5115 exit:
5116
5117         return ret;
5118
5119 }
5120
5121 //      To set the WFD session available to enable or disable
5122 static int rtw_p2p_set_sa(struct net_device *dev,
5123                                struct iw_request_info *info,
5124                                union iwreq_data *wrqu, char *extra)
5125 {
5126
5127         int ret = 0;
5128         struct rtw_adapter                                      *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
5129         struct iw_point                         *pdata = &wrqu->data;
5130         struct wifidirect_info          *pwdinfo = &( padapter->wdinfo );
5131         struct wifi_display_info                *pwfd_info = pwdinfo->wfd_info;
5132
5133         DBG_8723A( "[%s] data = %s\n", __func__, extra );
5134
5135         if( 0 )
5136         {
5137                 DBG_8723A( "[%s] WiFi Direct is disable!\n", __func__ );
5138                 return ret;
5139         }
5140         else
5141         {
5142                 if ( extra[ 0 ] == '0' )        //      Disable the session available.
5143                 {
5144                         pwdinfo->session_available = _FALSE;
5145                 }
5146                 else if ( extra[ 0 ] == '1' )   //      Enable the session available.
5147                 {
5148                         pwdinfo->session_available = _TRUE;
5149                 }
5150                 else
5151                 {
5152                         pwdinfo->session_available = _FALSE;
5153                 }
5154         }
5155         printk( "[%s] session available = %d\n", __func__, pwdinfo->session_available );
5156
5157 exit:
5158
5159         return ret;
5160
5161 }
5162 #endif // CONFIG_WFD
5163
5164 static int rtw_p2p_prov_disc(struct net_device *dev,
5165                                struct iw_request_info *info,
5166                                union iwreq_data *wrqu, char *extra)
5167 {
5168         int ret = 0;
5169         struct rtw_adapter                              *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
5170         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5171         u8                                      peerMAC[ ETH_ALEN ] = { 0x00 };
5172         int                                     jj,kk;
5173         u8                                      peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
5174         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
5175         struct list_head                                        *plist, *phead;
5176         _queue                          *queue  = &(pmlmepriv->scanned_queue);
5177         struct  wlan_network    *pnetwork = NULL;
5178         uint                                    uintPeerChannel = 0;
5179         u8                                      attr_content[100] = { 0x00 }, _status = 0;
5180         u8 *p2pie;
5181         uint                                    p2pielen = 0, attr_contentlen = 0;
5182 #ifdef CONFIG_CONCURRENT_MODE
5183         struct rtw_adapter                              *pbuddy_adapter = padapter->pbuddy_adapter;
5184         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
5185         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
5186 #endif // CONFIG_CONCURRENT_MODE
5187 #ifdef CONFIG_WFD
5188         struct wifi_display_info*       pwfd_info = pwdinfo->wfd_info;
5189 #endif // CONFIG_WFD
5190
5191         //      Commented by Albert 20110301
5192         //      The input data contains two informations.
5193         //      1. First information is the MAC address which wants to issue the provisioning discovery request frame.
5194         //      2. Second information is the WPS configuration method which wants to discovery
5195         //      Format: 00:E0:4C:00:00:05_display
5196         //      Format: 00:E0:4C:00:00:05_keypad
5197         //      Format: 00:E0:4C:00:00:05_pbc
5198         //      Format: 00:E0:4C:00:00:05_label
5199
5200         DBG_8723A( "[%s] data = %s\n", __func__, extra );
5201
5202         if ( pwdinfo->p2p_state == P2P_STATE_NONE )
5203         {
5204                 DBG_8723A( "[%s] WiFi Direct is disable!\n", __func__ );
5205                 return ret;
5206         }
5207         else
5208         {
5209                 //      Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request.
5210                 memset( pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN );
5211                 memset( pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN );
5212                 memset( &pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof( NDIS_802_11_SSID ) );
5213                 pwdinfo->tx_prov_disc_info.peer_channel_num[ 0 ] = 0;
5214                 pwdinfo->tx_prov_disc_info.peer_channel_num[ 1 ] = 0;
5215                 pwdinfo->tx_prov_disc_info.benable = _FALSE;
5216         }
5217
5218         for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
5219         {
5220                 peerMAC[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
5221         }
5222
5223         if (!memcmp(&extra[ 18 ], "display", 7))
5224         {
5225                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
5226         }
5227         else if (!memcmp( &extra[ 18 ], "keypad", 7))
5228         {
5229                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
5230         }
5231         else if (!memcmp( &extra[ 18 ], "pbc", 3))
5232         {
5233                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
5234         }
5235         else if (!memcmp( &extra[ 18 ], "label", 5))
5236         {
5237                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
5238         }
5239         else
5240         {
5241                 DBG_8723A( "[%s] Unknown WPS config methodn", __func__ );
5242                 return( ret );
5243         }
5244
5245         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
5246
5247         phead = get_list_head(queue);
5248         plist = phead->next;
5249
5250         while(1)
5251         {
5252                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
5253                         break;
5254
5255                 if( uintPeerChannel != 0 )
5256                         break;
5257
5258                 pnetwork = container_of(plist, struct wlan_network, list);
5259
5260                 //      Commented by Albert 2011/05/18
5261                 //      Match the device address located in the P2P IE
5262                 //      This is for the case that the P2P device address is not the same as the P2P interface address.
5263
5264                 if ( (p2pie=rtw_get_p2p_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen)) )
5265                 {
5266                         while ( p2pie )
5267                         {
5268                                 //      The P2P Device ID attribute is included in the Beacon frame.
5269                                 //      The P2P Device Info attribute is included in the probe response frame.
5270
5271                                 if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen) )
5272                                 {
5273                                         //      Handle the P2P Device ID attribute of Beacon first
5274                                         if (!memcmp( attr_content, peerMAC, ETH_ALEN))
5275                                         {
5276                                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5277                                                 break;
5278                                         }
5279                                 }
5280                                 else if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen) )
5281                                 {
5282                                         //      Handle the P2P Device Info attribute of probe response
5283                                         if (!memcmp( attr_content, peerMAC, ETH_ALEN))
5284                                         {
5285                                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5286                                                 break;
5287                                         }
5288                                 }
5289
5290                                 //Get the next P2P IE
5291                                 p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 -(p2pie -&pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
5292                         }
5293
5294                 }
5295
5296                 plist = plist->next;
5297
5298         }
5299
5300         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
5301
5302 #ifdef CONFIG_WFD
5303         {
5304                 u8      wfd_ie[ 128 ] = { 0x00 };
5305                 uint    wfd_ielen = 0;
5306
5307                 if ( rtw_get_wfd_ie( &pnetwork->network.IEs[12], pnetwork->network.IELength - 12,  wfd_ie, &wfd_ielen ) )
5308                 {
5309                         u8      wfd_devinfo[ 6 ] = { 0x00 };
5310                         uint    wfd_devlen = 6;
5311
5312                         DBG_8723A( "[%s] Found WFD IE!\n", __func__ );
5313                         if ( rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, wfd_devinfo, &wfd_devlen ) )
5314                         {
5315                                 u16     wfd_devinfo_field = 0;
5316
5317                                 //      Commented by Albert 20120319
5318                                 //      The first two bytes are the WFD device information field of WFD device information subelement.
5319                                 //      In big endian format.
5320                                 wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
5321                                 if ( wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL )
5322                                 {
5323                                         pwfd_info->peer_session_avail = _TRUE;
5324                                 }
5325                                 else
5326                                 {
5327                                         pwfd_info->peer_session_avail = _FALSE;
5328                                 }
5329                         }
5330                 }
5331
5332                 if ( _FALSE == pwfd_info->peer_session_avail )
5333                 {
5334                         DBG_8723A( "[%s] WFD Session not avaiable!\n", __func__ );
5335                         goto exit;
5336                 }
5337         }
5338 #endif // CONFIG_WFD
5339
5340         if ( uintPeerChannel )
5341         {
5342
5343                 DBG_8723A( "[%s] peer channel: %d!\n", __func__, uintPeerChannel );
5344 #ifdef CONFIG_CONCURRENT_MODE
5345                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
5346                 {
5347                         _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
5348                 }
5349 #endif // CONFIG_CONCURRENT_MODE
5350                 memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN );
5351                 memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN );
5352                 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = ( u16 ) uintPeerChannel;
5353                 pwdinfo->tx_prov_disc_info.benable = _TRUE;
5354                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
5355                 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
5356
5357                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
5358                 {
5359                         memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof( NDIS_802_11_SSID ) );
5360                 }
5361                 else if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
5362                 {
5363                         memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN );
5364                         pwdinfo->tx_prov_disc_info.ssid.SsidLength= P2P_WILDCARD_SSID_LEN;
5365                 }
5366
5367 #ifdef CONFIG_CONCURRENT_MODE
5368                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
5369                 {
5370                         //      Have to enter the power saving with the AP
5371                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
5372
5373                         issue_nulldata(pbuddy_adapter, NULL, 1, 3, 500);
5374                 }
5375                 else
5376                 {
5377                         set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
5378                 }
5379 #else
5380                 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
5381 #endif
5382
5383                 _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
5384
5385 #ifdef CONFIG_CONCURRENT_MODE
5386                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
5387                 {
5388                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_PROVISION_TIMEOUT );
5389                 }
5390                 else
5391                 {
5392                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
5393                 }
5394 #else
5395                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
5396 #endif // CONFIG_CONCURRENT_MODE
5397
5398         }
5399         else
5400         {
5401                 DBG_8723A( "[%s] NOT Found in the Scanning Queue!\n", __func__ );
5402         }
5403 exit:
5404
5405         return ret;
5406
5407 }
5408
5409 //      Added by Albert 20110328
5410 //      This function is used to inform the driver the user had specified the pin code value or pbc
5411 //      to application.
5412
5413 static int rtw_p2p_got_wpsinfo(struct net_device *dev,
5414                                struct iw_request_info *info,
5415                                union iwreq_data *wrqu, char *extra)
5416 {
5417
5418         int ret = 0;
5419         struct rtw_adapter                              *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
5420         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5421
5422
5423         DBG_8723A( "[%s] data = %s\n", __func__, extra );
5424         //      Added by Albert 20110328
5425         //      if the input data is P2P_NO_WPSINFO -> reset the wpsinfo
5426         //      if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device.
5427         //      if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself.
5428         //      if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC
5429
5430         if ( *extra == '0' )
5431         {
5432                 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
5433         }
5434         else if ( *extra == '1' )
5435         {
5436                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
5437         }
5438         else if ( *extra == '2' )
5439         {
5440                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
5441         }
5442         else if ( *extra == '3' )
5443         {
5444                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
5445         }
5446         else
5447         {
5448                 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
5449         }
5450
5451         return ret;
5452
5453 }
5454
5455 #endif //CONFIG_P2P
5456
5457 static int rtw_p2p_set(struct net_device *dev,
5458                                struct iw_request_info *info,
5459                                union iwreq_data *wrqu, char *extra)
5460 {
5461
5462         int ret = 0;
5463 #ifdef CONFIG_P2P
5464
5465         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
5466         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5467         struct iw_point *pdata = &wrqu->data;
5468         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
5469         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5470
5471         DBG_8723A( "[%s] extra = %s\n", __func__, extra );
5472
5473         if (!memcmp( extra, "enable=", 7))
5474         {
5475                 rtw_wext_p2p_enable( dev, info, wrqu, &extra[7] );
5476         }
5477         else if (!memcmp( extra, "setDN=", 6))
5478         {
5479                 wrqu->data.length -= 6;
5480                 rtw_p2p_setDN( dev, info, wrqu, &extra[6] );
5481         }
5482         else if (!memcmp( extra, "profilefound=", 13))
5483         {
5484                 wrqu->data.length -= 13;
5485                 rtw_p2p_profilefound( dev, info, wrqu, &extra[13] );
5486         }
5487         else if (!memcmp( extra, "prov_disc=", 10))
5488         {
5489                 wrqu->data.length -= 10;
5490                 rtw_p2p_prov_disc( dev, info, wrqu, &extra[10] );
5491         }
5492         else if (!memcmp( extra, "nego=", 5))
5493         {
5494                 wrqu->data.length -= 5;
5495                 rtw_p2p_connect( dev, info, wrqu, &extra[5] );
5496         }
5497         else if (!memcmp( extra, "intent=", 7))
5498         {
5499                 //      Commented by Albert 2011/03/23
5500                 //      The wrqu->data.length will include the null character
5501                 //      So, we will decrease 7 + 1
5502                 wrqu->data.length -= 8;
5503                 rtw_p2p_set_intent( dev, info, wrqu, &extra[7] );
5504         }
5505         else if (!memcmp( extra, "ssid=", 5))
5506         {
5507                 wrqu->data.length -= 5;
5508                 rtw_p2p_set_go_nego_ssid( dev, info, wrqu, &extra[5] );
5509         }
5510         else if (!memcmp( extra, "got_wpsinfo=", 12))
5511         {
5512                 wrqu->data.length -= 12;
5513                 rtw_p2p_got_wpsinfo( dev, info, wrqu, &extra[12] );
5514         }
5515         else if (!memcmp( extra, "listen_ch=", 10))
5516         {
5517                 //      Commented by Albert 2011/05/24
5518                 //      The wrqu->data.length will include the null character
5519                 //      So, we will decrease (10 + 1)
5520                 wrqu->data.length -= 11;
5521                 rtw_p2p_set_listen_ch( dev, info, wrqu, &extra[10] );
5522         }
5523         else if (!memcmp( extra, "op_ch=", 6))
5524         {
5525                 //      Commented by Albert 2011/05/24
5526                 //      The wrqu->data.length will include the null character
5527                 //      So, we will decrease (6 + 1)
5528                 wrqu->data.length -= 7;
5529                 rtw_p2p_set_op_ch( dev, info, wrqu, &extra[6] );
5530         }
5531         else if (!memcmp( extra, "invite=", 7))
5532         {
5533                 wrqu->data.length -= 8;
5534                 rtw_p2p_invite_req( dev, info, wrqu, &extra[7] );
5535         }
5536         else if (!memcmp( extra, "persistent=", 11))
5537         {
5538                 wrqu->data.length -= 11;
5539                 rtw_p2p_set_persistent( dev, info, wrqu, &extra[11] );
5540         }
5541 #ifdef CONFIG_WFD
5542         else if (!memcmp( extra, "sa=", 3))
5543         {
5544                 //      sa: WFD Session Available information
5545                 wrqu->data.length -= 3;
5546                 rtw_p2p_set_sa( dev, info, wrqu, &extra[3] );
5547         }
5548         else if (!memcmp( extra, "pc=", 3))
5549         {
5550                 //      pc: WFD Preferred Connection
5551                 wrqu->data.length -= 3;
5552                 rtw_p2p_set_pc( dev, info, wrqu, &extra[3] );
5553         }
5554         else if (!memcmp( extra, "wfd_type=", 9))
5555         {
5556                 //      Specify this device is Mircast source or sink
5557                 wrqu->data.length -= 9;
5558                 rtw_p2p_set_wfd_device_type( dev, info, wrqu, &extra[9] );
5559         }
5560         else if (!memcmp( extra, "scan_type=", 10))
5561         {
5562                 wrqu->data.length -= 10;
5563                 rtw_p2p_set_scan_result_type( dev, info, wrqu, &extra[10] );
5564         }
5565 #endif //CONFIG_WFD
5566
5567 #endif //CONFIG_P2P
5568
5569         return ret;
5570
5571 }
5572
5573 static int rtw_p2p_get(struct net_device *dev,
5574                                struct iw_request_info *info,
5575                                union iwreq_data *wrqu, char *extra)
5576 {
5577
5578         int ret = 0;
5579
5580 #ifdef CONFIG_P2P
5581
5582         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
5583         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5584         struct iw_point *pdata = &wrqu->data;
5585         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
5586         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5587
5588         if ( padapter->bShowGetP2PState )
5589         {
5590                 DBG_8723A( "[%s] extra = %s\n", __func__, (char*) wrqu->data.pointer );
5591         }
5592
5593         if (!memcmp(wrqu->data.pointer, "status", 6))
5594         {
5595                 rtw_p2p_get_status( dev, info, wrqu, extra );
5596         }
5597         else if (!memcmp(wrqu->data.pointer, "role", 4))
5598         {
5599                 rtw_p2p_get_role( dev, info, wrqu, extra);
5600         }
5601         else if (!memcmp(wrqu->data.pointer, "peer_ifa", 8))
5602         {
5603                 rtw_p2p_get_peer_ifaddr( dev, info, wrqu, extra);
5604         }
5605         else if (!memcmp(wrqu->data.pointer, "req_cm", 6))
5606         {
5607                 rtw_p2p_get_req_cm( dev, info, wrqu, extra);
5608         }
5609         else if (!memcmp(wrqu->data.pointer, "peer_deva", 9))
5610         {
5611                 //      Get the P2P device address when receiving the provision discovery request frame.
5612                 rtw_p2p_get_peer_devaddr( dev, info, wrqu, extra);
5613         }
5614         else if (!memcmp(wrqu->data.pointer, "group_id", 8))
5615         {
5616                 rtw_p2p_get_groupid( dev, info, wrqu, extra);
5617         }
5618         else if (!memcmp(wrqu->data.pointer, "peer_deva_inv", 9))
5619         {
5620                 //      Get the P2P device address when receiving the P2P Invitation request frame.
5621                 rtw_p2p_get_peer_devaddr_by_invitation( dev, info, wrqu, extra);
5622         }
5623         else if (!memcmp(wrqu->data.pointer, "op_ch", 5))
5624         {
5625                 rtw_p2p_get_op_ch( dev, info, wrqu, extra);
5626         }
5627 #ifdef CONFIG_WFD
5628         else if (!memcmp(wrqu->data.pointer, "peer_port", 9))
5629         {
5630                 rtw_p2p_get_peer_wfd_port( dev, info, wrqu, extra );
5631         }
5632         else if (!memcmp(wrqu->data.pointer, "wfd_sa", 6))
5633         {
5634                 rtw_p2p_get_peer_wfd_session_available( dev, info, wrqu, extra );
5635         }
5636         else if (!memcmp( wrqu->data.pointer, "wfd_pc", 6))
5637         {
5638                 rtw_p2p_get_peer_wfd_preferred_connection( dev, info, wrqu, extra );
5639         }
5640 #endif // CONFIG_WFD
5641
5642 #endif //CONFIG_P2P
5643
5644         return ret;
5645
5646 }
5647
5648 static int rtw_p2p_get2(struct net_device *dev,
5649                         struct iw_request_info *info,
5650                         union iwreq_data *wrqu, char *extra)
5651 {
5652         int ret = 0;
5653
5654 #ifdef CONFIG_P2P
5655
5656         int length = wrqu->data.length;
5657         char *buffer = (u8 *)kmalloc(length, GFP_KERNEL);
5658
5659         if (buffer == NULL) {
5660                 ret = -ENOMEM;
5661                 goto exit;
5662         }
5663
5664         if (copy_from_user(buffer, wrqu->data.pointer, wrqu->data.length)) {
5665                 ret = -EFAULT;
5666                 goto bad;
5667         }
5668
5669         DBG_8723A("[%s] buffer = %s\n", __func__, buffer);
5670
5671         if (!memcmp(buffer, "wpsCM=", 6)) {
5672                 ret = rtw_p2p_get_wps_configmethod(dev, info, wrqu, extra, &buffer[6]);
5673         } else if (!memcmp(buffer, "devN=", 5)) {
5674                 ret = rtw_p2p_get_device_name(dev, info, wrqu, extra, &buffer[5]);
5675         } else if (!memcmp(buffer, "dev_type=", 9)) {
5676                 ret = rtw_p2p_get_device_type(dev, info, wrqu, extra, &buffer[9]);
5677         } else if (!memcmp(buffer, "go_devadd=", 10)) {
5678                 ret = rtw_p2p_get_go_device_address(dev, info, wrqu, extra, &buffer[10]);
5679         } else if (!memcmp(buffer, "InvProc=", 8)) {
5680                 ret = rtw_p2p_get_invitation_procedure(dev, info, wrqu, extra, &buffer[8]);
5681         } else {
5682                 snprintf(extra, sizeof("Command not found."), "Command not found.");
5683                 wrqu->data.length = strlen(extra);
5684         }
5685 bad:
5686         kfree(buffer);
5687 exit:
5688 #endif //CONFIG_P2P
5689
5690         return ret;
5691
5692 }
5693
5694 static int rtw_cta_test_start(struct net_device *dev,
5695                                                            struct iw_request_info *info,
5696                                                            union iwreq_data *wrqu, char *extra)
5697 {
5698         int ret = 0;
5699         struct rtw_adapter      *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
5700         DBG_8723A("%s %s\n", __func__, extra);
5701         if (!strcmp(extra, "1"))
5702                 padapter->in_cta_test = 1;
5703         else
5704                 padapter->in_cta_test = 0;
5705
5706         if(padapter->in_cta_test)
5707         {
5708                 u32 v = rtw_read32(padapter, REG_RCR);
5709                 v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN );//| RCR_ADF
5710                 rtw_write32(padapter, REG_RCR, v);
5711                 DBG_8723A("enable RCR_ADF\n");
5712         }
5713         else
5714         {
5715                 u32 v = rtw_read32(padapter, REG_RCR);
5716                 v |= RCR_CBSSID_DATA | RCR_CBSSID_BCN ;//| RCR_ADF
5717                 rtw_write32(padapter, REG_RCR, v);
5718                 DBG_8723A("disable RCR_ADF\n");
5719         }
5720         return ret;
5721 }
5722
5723
5724 extern int rtw_change_ifname(struct rtw_adapter *padapter, const char *ifname);
5725 static int rtw_rereg_nd_name(struct net_device *dev,
5726                                struct iw_request_info *info,
5727                                union iwreq_data *wrqu, char *extra)
5728 {
5729         int ret = 0;
5730         struct rtw_adapter *padapter = rtw_netdev_priv(dev);
5731         struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
5732         char new_ifname[IFNAMSIZ];
5733
5734         if(rereg_priv->old_ifname[0] == 0) {
5735                 char *reg_ifname;
5736 #ifdef CONFIG_CONCURRENT_MODE
5737                 if (padapter->isprimary)
5738                         reg_ifname = padapter->registrypriv.ifname;
5739                 else
5740 #endif
5741                 reg_ifname = padapter->registrypriv.if2name;
5742
5743                 strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
5744                 rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
5745         }
5746
5747         //DBG_8723A("%s wrqu->data.length:%d\n", __func__, wrqu->data.length);
5748         if(wrqu->data.length > IFNAMSIZ)
5749                 return -EFAULT;
5750
5751         if ( copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ) ) {
5752                 return -EFAULT;
5753         }
5754
5755         if( 0 == strcmp(rereg_priv->old_ifname, new_ifname) ) {
5756                 return ret;
5757         }
5758
5759         DBG_8723A("%s new_ifname:%s\n", __func__, new_ifname);
5760         if( 0 != (ret = rtw_change_ifname(padapter, new_ifname)) ) {
5761                 goto exit;
5762         }
5763
5764         if(!memcmp(rereg_priv->old_ifname, "disable%d", 9)) {
5765                 padapter->ledpriv.bRegUseLed= rereg_priv->old_bRegUseLed;
5766                 rtw_hal_sw_led_init(padapter);
5767                 rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
5768         }
5769
5770         strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
5771         rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
5772
5773         if(!memcmp(new_ifname, "disable%d", 9)) {
5774
5775                 DBG_8723A("%s disable\n", __func__);
5776                 // free network queue for Android's timming issue
5777                 rtw_free_network_queue(padapter, _TRUE);
5778
5779                 // close led
5780                 rtw_led_control(padapter, LED_CTL_POWER_OFF);
5781                 rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
5782                 padapter->ledpriv.bRegUseLed= _FALSE;
5783                 rtw_hal_sw_led_deinit(padapter);
5784
5785                 // the interface is being "disabled", we can do deeper IPS
5786                 rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv);
5787                 rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL);
5788         }
5789 exit:
5790         return ret;
5791
5792 }
5793
5794 static void mac_reg_dump(struct rtw_adapter *padapter)
5795 {
5796         int i,j=1;
5797         printk("\n======= MAC REG =======\n");
5798         for(i=0x0;i<0x300;i+=4)
5799         {
5800                 if(j%4==1)      printk("0x%02x",i);
5801                 printk(" 0x%08x ",rtw_read32(padapter,i));
5802                 if((j++)%4 == 0)        printk("\n");
5803         }
5804         for(i=0x400;i<0x800;i+=4)
5805         {
5806                 if(j%4==1)      printk("0x%02x",i);
5807                 printk(" 0x%08x ",rtw_read32(padapter,i));
5808                 if((j++)%4 == 0)        printk("\n");
5809         }
5810 }
5811 void bb_reg_dump(struct rtw_adapter *padapter)
5812 {
5813         int i,j=1;
5814         printk("\n======= BB REG =======\n");
5815         for(i=0x800;i<0x1000;i+=4)
5816         {
5817                 if(j%4==1) printk("0x%02x",i);
5818
5819                 printk(" 0x%08x ",rtw_read32(padapter,i));
5820                 if((j++)%4 == 0)        printk("\n");
5821         }
5822 }
5823 void rf_reg_dump(struct rtw_adapter *padapter)
5824 {
5825         int i,j=1,path;
5826         u32 value;
5827         u8 rf_type,path_nums = 0;
5828         rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
5829
5830         printk("\n======= RF REG =======\n");
5831         if((RF_1T2R == rf_type) ||(RF_1T1R ==rf_type ))
5832                 path_nums = 1;
5833         else
5834                 path_nums = 2;
5835
5836         for(path=0;path<path_nums;path++)
5837         {
5838                 printk("\nRF_Path(%x)\n",path);
5839                 for(i=0;i<0x100;i++)
5840                 {
5841                         //value = PHY_QueryRFReg(padapter, (RF_RADIO_PATH_E)path,i, bMaskDWord);
5842                         value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
5843                         if(j%4==1)      printk("0x%02x ",i);
5844                         printk(" 0x%08x ",value);
5845                         if((j++)%4==0)  printk("\n");
5846                 }
5847         }
5848 }
5849
5850 #ifdef CONFIG_IOL
5851 #include <rtw_iol.h>
5852 #endif
5853 static int rtw_dbg_port(struct net_device *dev,
5854                                struct iw_request_info *info,
5855                                union iwreq_data *wrqu, char *extra)
5856 {
5857         int ret = 0;
5858         u8 major_cmd, minor_cmd;
5859         u16 arg;
5860         u32 extra_arg, *pdata, val32;
5861         struct sta_info *psta;
5862         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
5863         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5864         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5865         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5866         struct security_priv *psecuritypriv = &padapter->securitypriv;
5867         struct wlan_network *cur_network = &(pmlmepriv->cur_network);
5868         struct sta_priv *pstapriv = &padapter->stapriv;
5869
5870
5871         pdata = (u32*)&wrqu->data;
5872
5873         val32 = *pdata;
5874         arg = (u16)(val32&0x0000ffff);
5875         major_cmd = (u8)(val32>>24);
5876         minor_cmd = (u8)((val32>>16)&0x00ff);
5877
5878         extra_arg = *(pdata+1);
5879
5880         switch(major_cmd)
5881         {
5882                 case 0x70://read_reg
5883                         switch(minor_cmd)
5884                         {
5885                                 case 1:
5886                                         DBG_8723A("rtw_read8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
5887                                         break;
5888                                 case 2:
5889                                         DBG_8723A("rtw_read16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
5890                                         break;
5891                                 case 4:
5892                                         DBG_8723A("rtw_read32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
5893                                         break;
5894                         }
5895                         break;
5896                 case 0x71://write_reg
5897                         switch(minor_cmd)
5898                         {
5899                                 case 1:
5900                                         rtw_write8(padapter, arg, extra_arg);
5901                                         DBG_8723A("rtw_write8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
5902                                         break;
5903                                 case 2:
5904                                         rtw_write16(padapter, arg, extra_arg);
5905                                         DBG_8723A("rtw_write16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
5906                                         break;
5907                                 case 4:
5908                                         rtw_write32(padapter, arg, extra_arg);
5909                                         DBG_8723A("rtw_write32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
5910                                         break;
5911                         }
5912                         break;
5913                 case 0x72://read_bb
5914                         DBG_8723A("read_bbreg(0x%x)=0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
5915                         break;
5916                 case 0x73://write_bb
5917                         rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
5918                         DBG_8723A("write_bbreg(0x%x)=0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
5919                         break;
5920                 case 0x74://read_rf
5921                         DBG_8723A("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));
5922                         break;
5923                 case 0x75://write_rf
5924                         rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
5925                         DBG_8723A("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));
5926                         break;
5927
5928                 case 0x76:
5929                         switch(minor_cmd) {
5930                         case 0x00: //normal mode,
5931                                 padapter->recvpriv.is_signal_dbg = 0;
5932                                 break;
5933                         case 0x01: //dbg mode
5934                                 padapter->recvpriv.is_signal_dbg = 1;
5935                                 extra_arg = extra_arg > 100 ? 100 : extra_arg;
5936                                 padapter->recvpriv.signal_strength_dbg = extra_arg;
5937                                 break;
5938                         }
5939                         break;
5940                 case 0x78: //IOL test
5941                         #ifdef CONFIG_IOL
5942                         switch(minor_cmd) {
5943                         case 0x04: //LLT table initialization test
5944                         {
5945                                 u8 page_boundary = 0xf9;
5946                                 {
5947                                         struct xmit_frame       *xmit_frame;
5948
5949                                         if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
5950                                                 ret = -ENOMEM;
5951                                                 break;
5952                                         }
5953
5954                                         rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
5955
5956
5957                                         if(_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500,0) )
5958                                                 ret = -EPERM;
5959                                 }
5960                         }
5961                                 break;
5962                         case 0x05: //blink LED test
5963                         {
5964                                 u16 reg = 0x4c;
5965                                 u32 blink_num = 50;
5966                                 u32 blink_delay_ms = 200;
5967                                 int i;
5968
5969                                 {
5970                                         struct xmit_frame       *xmit_frame;
5971
5972                                         if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
5973                                                 ret = -ENOMEM;
5974                                                 break;
5975                                         }
5976
5977                                         for(i=0;i<blink_num;i++){
5978                                                 #ifdef CONFIG_IOL_NEW_GENERATION
5979                                                 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00,0xff);
5980                                                 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
5981                                                 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08,0xff);
5982                                                 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
5983                                                 #else
5984                                                 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00);
5985                                                 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
5986                                                 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08);
5987                                                 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
5988                                                 #endif
5989                                         }
5990                                         if(_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms*blink_num*2)+200,0) )
5991                                                 ret = -EPERM;
5992                                 }
5993                         }
5994                                 break;
5995
5996                         case 0x06: //continuous write byte test
5997                         {
5998                                 u16 reg = arg;
5999                                 u16 start_value = 0;
6000                                 u32 write_num = extra_arg;
6001                                 int i;
6002                                 u8 final;
6003
6004                                 {
6005                                         struct xmit_frame       *xmit_frame;
6006
6007                                         if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
6008                                                 ret = -ENOMEM;
6009                                                 break;
6010                                         }
6011
6012                                         for(i=0;i<write_num;i++){
6013                                                 #ifdef CONFIG_IOL_NEW_GENERATION
6014                                                 rtw_IOL_append_WB_cmd(xmit_frame, reg, i+start_value,0xFF);
6015                                                 #else
6016                                                 rtw_IOL_append_WB_cmd(xmit_frame, reg, i+start_value);
6017                                                 #endif
6018                                         }
6019                                         if(_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000,0))
6020                                                 ret = -EPERM;
6021                                 }
6022
6023                                 if(start_value+write_num-1 == (final=rtw_read8(padapter, reg)) ) {
6024                                         DBG_8723A("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
6025                                 } else {
6026                                         DBG_8723A("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
6027                                 }
6028                         }
6029                                 break;
6030
6031                         case 0x07: //continuous write word test
6032                         {
6033                                 u16 reg = arg;
6034                                 u16 start_value = 200;
6035                                 u32 write_num = extra_arg;
6036
6037                                 int i;
6038                                 u16 final;
6039
6040                                 {
6041                                         struct xmit_frame       *xmit_frame;
6042
6043                                         if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
6044                                                 ret = -ENOMEM;
6045                                                 break;
6046                                         }
6047
6048                                         for(i=0;i<write_num;i++){
6049                                                 #ifdef CONFIG_IOL_NEW_GENERATION
6050                                                 rtw_IOL_append_WW_cmd(xmit_frame, reg, i+start_value,0xFFFF);
6051                                                 #else
6052                                                 rtw_IOL_append_WW_cmd(xmit_frame, reg, i+start_value);
6053                                                 #endif
6054                                         }
6055                                         if(_SUCCESS !=rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000,0))
6056                                                 ret = -EPERM;
6057                                 }
6058
6059                                 if(start_value+write_num-1 == (final=rtw_read16(padapter, reg)) ) {
6060                                         DBG_8723A("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
6061                                 } else {
6062                                         DBG_8723A("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
6063                                 }
6064                         }
6065                                 break;
6066
6067                         case 0x08: //continuous write dword test
6068                         {
6069                                 u16 reg = arg;
6070                                 u32 start_value = 0x110000c7;
6071                                 u32 write_num = extra_arg;
6072
6073                                 int i;
6074                                 u32 final;
6075                                 struct xmit_frame       *xmit_frame;
6076
6077                                 if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
6078                                         ret = -ENOMEM;
6079                                         break;
6080                                 }
6081
6082                                 for(i=0;i<write_num;i++){
6083                                         #ifdef CONFIG_IOL_NEW_GENERATION
6084                                         rtw_IOL_append_WD_cmd(xmit_frame, reg, i+start_value,0xFFFFFFFF);
6085                                         #else
6086                                         rtw_IOL_append_WD_cmd(xmit_frame, reg, i+start_value);
6087                                         #endif
6088                                 }
6089                                 if(_SUCCESS !=rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000,0))
6090                                         ret = -EPERM;
6091
6092
6093                                 if(start_value+write_num-1 == (final=rtw_read32(padapter, reg)) ) {
6094                                         DBG_8723A("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
6095                                 } else {
6096                                         DBG_8723A("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
6097                                 }
6098                         }
6099                                 break;
6100                         #endif //CONFIG_IOL
6101                         break;
6102                 case 0x79:
6103                         {
6104                                 /*
6105                                 * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
6106                                 * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
6107                                 */
6108                                 u8 value =  extra_arg & 0x0f;
6109                                 u8 sign = minor_cmd;
6110                                 u16 write_value = 0;
6111
6112                                 DBG_8723A("%s set RESP_TXAGC to %s %u\n", __func__, sign?"minus":"plus", value);
6113
6114                                 if (sign)
6115                                         value = value | 0x10;
6116
6117                                 write_value = value | (value << 5);
6118                                 rtw_write16(padapter, 0x6d9, write_value);
6119                         }
6120                         break;
6121                 case 0x7a:
6122                         receive_disconnect(padapter, pmlmeinfo->network.MacAddress
6123                                 , WLAN_REASON_EXPIRATION_CHK);
6124                         break;
6125                 case 0x7F:
6126                         switch(minor_cmd)
6127                         {
6128                                 case 0x0:
6129                                         DBG_8723A("fwstate=0x%x\n", get_fwstate(pmlmepriv));
6130                                         break;
6131                                 case 0x01:
6132                                         DBG_8723A("auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n",
6133                                                 psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
6134                                                 psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
6135                                         break;
6136                                 case 0x02:
6137                                         DBG_8723A("pmlmeinfo->state=0x%x\n", pmlmeinfo->state);
6138                                         break;
6139                                 case 0x03:
6140                                         DBG_8723A("qos_option=%d\n", pmlmepriv->qospriv.qos_option);
6141 #ifdef CONFIG_80211N_HT
6142                                         DBG_8723A("ht_option=%d\n", pmlmepriv->htpriv.ht_option);
6143 #endif //CONFIG_80211N_HT
6144                                         break;
6145                                 case 0x04:
6146                                         DBG_8723A("cur_ch=%d\n", pmlmeext->cur_channel);
6147                                         DBG_8723A("cur_bw=%d\n", pmlmeext->cur_bwmode);
6148                                         DBG_8723A("cur_ch_off=%d\n", pmlmeext->cur_ch_offset);
6149                                         break;
6150                                 case 0x05:
6151                                         psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
6152                                         if(psta)
6153                                         {
6154                                                 int i;
6155                                                 struct recv_reorder_ctrl *preorder_ctrl;
6156
6157                                                 DBG_8723A("SSID=%s\n", cur_network->network.Ssid.Ssid);
6158                                                 DBG_8723A("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
6159                                                 DBG_8723A("cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
6160                                                 DBG_8723A("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
6161                                                 DBG_8723A("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
6162 #ifdef CONFIG_80211N_HT
6163                                                 DBG_8723A("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
6164                                                 DBG_8723A("bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
6165                                                 DBG_8723A("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
6166                                                 DBG_8723A("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
6167 #endif //CONFIG_80211N_HT
6168
6169                                                 for(i=0;i<16;i++)
6170                                                 {
6171                                                         preorder_ctrl = &psta->recvreorder_ctrl[i];
6172                                                         if(preorder_ctrl->enable)
6173                                                         {
6174                                                                 DBG_8723A("tid=%d, indicate_seq=%d\n", i, preorder_ctrl->indicate_seq);
6175                                                         }
6176                                                 }
6177
6178                                         }
6179                                         else
6180                                         {
6181                                                 DBG_8723A("can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress));
6182                                         }
6183                                         break;
6184                                 case 0x06:
6185                                         {
6186                                                 u32     ODMFlag;
6187                                                 rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8*)(&ODMFlag));
6188                                                 DBG_8723A("(B)DMFlag=0x%x, arg=0x%x\n", ODMFlag, arg);
6189                                                 ODMFlag = (u32)(0x0f&arg);
6190                                                 DBG_8723A("(A)DMFlag=0x%x\n", ODMFlag);
6191                                                 rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
6192                                         }
6193                                         break;
6194                                 case 0x07:
6195                                         DBG_8723A("bSurpriseRemoved=%d, bDriverStopped=%d\n",
6196                                                 padapter->bSurpriseRemoved, padapter->bDriverStopped);
6197                                         break;
6198                                 case 0x08:
6199                                         {
6200                                                 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6201                                                 struct recv_priv  *precvpriv = &padapter->recvpriv;
6202
6203                                                 DBG_8723A("free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d"
6204                                                         ", free_xmit_extbuf_cnt=%d, free_xframe_ext_cnt=%d"
6205                                                         ", free_recvframe_cnt=%d\n",
6206                                                         pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt,
6207                                                         pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xframe_ext_cnt,
6208                                                         precvpriv->free_recvframe_cnt);
6209                                                 DBG_8723A("rx_urb_pending_cn=%d\n", precvpriv->rx_pending_cnt);
6210                                         }
6211                                         break;
6212                                 case 0x09:
6213                                         {
6214                                                 int i, j;
6215                                                 struct list_head *plist, *phead;
6216                                                 struct recv_reorder_ctrl *preorder_ctrl;
6217
6218 #ifdef CONFIG_AP_MODE
6219                                                 DBG_8723A("sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
6220 #endif
6221                                                 spin_lock_bh(&pstapriv->sta_hash_lock);
6222
6223                                                 for(i=0; i< NUM_STA; i++)
6224                                                 {
6225                                                         phead = &(pstapriv->sta_hash[i]);
6226                                                         plist = phead->next;
6227
6228                                                         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
6229                                                         {
6230                                                                 psta = container_of(plist, struct sta_info, hash_list);
6231
6232                                                                 plist = plist->next;
6233
6234                                                                 if(extra_arg == psta->aid)
6235                                                                 {
6236                                                                         DBG_8723A("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
6237                                                                         DBG_8723A("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
6238                                                                         DBG_8723A("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
6239 #ifdef CONFIG_80211N_HT
6240                                                                         DBG_8723A("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
6241                                                                         DBG_8723A("bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
6242                                                                         DBG_8723A("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
6243                                                                         DBG_8723A("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
6244 #endif //CONFIG_80211N_HT
6245
6246 #ifdef CONFIG_AP_MODE
6247                                                                         DBG_8723A("capability=0x%x\n", psta->capability);
6248                                                                         DBG_8723A("flags=0x%x\n", psta->flags);
6249                                                                         DBG_8723A("wpa_psk=0x%x\n", psta->wpa_psk);
6250                                                                         DBG_8723A("wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher);
6251                                                                         DBG_8723A("wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher);
6252                                                                         DBG_8723A("qos_info=0x%x\n", psta->qos_info);
6253 #endif
6254                                                                         DBG_8723A("dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy);
6255
6256
6257
6258                                                                         for(j=0;j<16;j++)
6259                                                                         {
6260                                                                                 preorder_ctrl = &psta->recvreorder_ctrl[j];
6261                                                                                 if(preorder_ctrl->enable)
6262                                                                                 {
6263                                                                                         DBG_8723A("tid=%d, indicate_seq=%d\n", j, preorder_ctrl->indicate_seq);
6264                                                                                 }
6265                                                                         }
6266
6267                                                                 }
6268
6269                                                         }
6270                                                 }
6271
6272                                                 spin_unlock_bh(&pstapriv->sta_hash_lock);
6273
6274                                         }
6275                                         break;
6276
6277                                 case 0x0c://dump rx/tx packet
6278                                         {
6279                                                 if(arg == 0){
6280                                                         DBG_8723A("dump rx packet (%d)\n",extra_arg);
6281                                                         //pHalData->bDumpRxPkt =extra_arg;
6282                                                         rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
6283                                                 }
6284                                                 else if(arg==1){
6285                                                         DBG_8723A("dump tx packet (%d)\n",extra_arg);
6286                                                         rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
6287                                                 }
6288                                         }
6289                                         break;
6290                 #ifdef DBG_CONFIG_ERROR_DETECT
6291                                 case 0x0f:
6292                                                 {
6293                                                         if(extra_arg == 0){
6294                                                                 DBG_8723A("###### silent reset test.......#####\n");
6295                                                                 rtw_hal_sreset_reset(padapter);
6296                                                         } else {
6297                                                                 HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
6298                                                                 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
6299                                                                 psrtpriv->dbg_trigger_point = extra_arg;
6300                                                         }
6301
6302                                                 }
6303                                 break;
6304                                 case 0x15:
6305                                         {
6306                                                 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
6307                                                 DBG_8723A("==>silent resete cnts:%d\n",pwrpriv->ips_enter_cnts);
6308                                         }
6309                                         break;
6310
6311                 #endif
6312
6313                                 case 0x10:// driver version display
6314                                         DBG_8723A("rtw driver version=%s\n", DRIVERVERSION);
6315                                         break;
6316                                 case 0x11:
6317                                         {
6318                                                 DBG_8723A("turn %s Rx RSSI display function\n",(extra_arg==1)?"on":"off");
6319                                                 padapter->bRxRSSIDisplay = extra_arg ;
6320                                                 rtw_hal_set_def_var(padapter, HW_DEF_FA_CNT_DUMP,&extra_arg);
6321                                         }
6322                                         break;
6323                                 case 0x12: //set rx_stbc
6324                                 {
6325                                         struct registry_priv    *pregpriv = &padapter->registrypriv;
6326                                         // 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g
6327                                         //default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ
6328                                         if( pregpriv && (extra_arg == 0 || extra_arg == 1|| extra_arg == 2 || extra_arg == 3))
6329                                         {
6330                                                 pregpriv->rx_stbc= extra_arg;
6331                                                 DBG_8723A("set rx_stbc=%d\n",pregpriv->rx_stbc);
6332                                         }
6333                                         else
6334                                                 DBG_8723A("get rx_stbc=%d\n",pregpriv->rx_stbc);
6335
6336                                 }
6337                                 break;
6338                                 case 0x13: //set ampdu_enable
6339                                 {
6340                                         struct registry_priv    *pregpriv = &padapter->registrypriv;
6341                                         // 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec)
6342                                         if( pregpriv && extra_arg >= 0 && extra_arg < 3 )
6343                                         {
6344                                                 pregpriv->ampdu_enable= extra_arg;
6345                                                 DBG_8723A("set ampdu_enable=%d\n",pregpriv->ampdu_enable);
6346                                         }
6347                                         else
6348                                                 DBG_8723A("get ampdu_enable=%d\n",pregpriv->ampdu_enable);
6349
6350                                 }
6351                                 break;
6352                                 case 0x14: //get wifi_spec
6353                                 {
6354                                         struct registry_priv    *pregpriv = &padapter->registrypriv;
6355                                         DBG_8723A("get wifi_spec=%d\n",pregpriv->wifi_spec);
6356
6357                                 }
6358                                 break;
6359                                 case 0x16:
6360                                 {
6361                                         if(arg == 0xff){
6362                                                 printk("ODM_COMP_DIG\t\tBIT0\n");
6363                                                 printk("ODM_COMP_RA_MASK\t\tBIT1\n");
6364                                                 printk("ODM_COMP_DYNAMIC_TXPWR\tBIT2\n");
6365                                                 printk("ODM_COMP_FA_CNT\t\tBIT3\n");
6366                                                 printk("ODM_COMP_RSSI_MONITOR\tBIT4\n");
6367                                                 printk("ODM_COMP_CCK_PD\t\tBIT5\n");
6368                                                 printk("ODM_COMP_ANT_DIV\t\tBIT6\n");
6369                                                 printk("ODM_COMP_PWR_SAVE\t\tBIT7\n");
6370                                                 printk("ODM_COMP_PWR_TRAIN\tBIT8\n");
6371                                                 printk("ODM_COMP_RATE_ADAPTIVE\tBIT9\n");
6372                                                 printk("ODM_COMP_PATH_DIV\t\tBIT10\n");
6373                                                 printk("ODM_COMP_PSD    \tBIT11\n");
6374                                                 printk("ODM_COMP_DYNAMIC_PRICCA\tBIT12\n");
6375                                                 printk("ODM_COMP_RXHP\t\tBIT13\n");
6376                                                 printk("ODM_COMP_EDCA_TURBO\tBIT16\n");
6377                                                 printk("ODM_COMP_EARLY_MODE\tBIT17\n");
6378                                                 printk("ODM_COMP_TX_PWR_TRACK\tBIT24\n");
6379                                                 printk("ODM_COMP_RX_GAIN_TRACK\tBIT25\n");
6380                                                 printk("ODM_COMP_CALIBRATION\tBIT26\n");
6381                                                 rtw_hal_get_def_var(padapter, HW_DEF_ODM_DBG_FLAG,&extra_arg);
6382                                         }
6383                                         else{
6384                                                 rtw_hal_set_def_var(padapter, HW_DEF_ODM_DBG_FLAG,&extra_arg);
6385                                         }
6386                                 }
6387                                         break;
6388 #ifdef DBG_FIXED_CHAN
6389                                 case 0x17:
6390                                         {
6391                                                 struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6392                                                 printk("===>  Fixed channel to %d \n",extra_arg);
6393                                                 pmlmeext->fixed_chan = extra_arg;
6394
6395                                         }
6396                                         break;
6397 #endif
6398                                 case 0x20:
6399                                         {
6400                                                 rtw_hal_get_hwreg(padapter, HW_VAR_READ_LLT_TAB,(u8 *)&extra_arg);
6401                                         }
6402                                         break;
6403                                 case 0x23:
6404                                         {
6405                                                 DBG_8723A("turn %s the bNotifyChannelChange Variable\n",(extra_arg==1)?"on":"off");
6406                                                 padapter->bNotifyChannelChange = extra_arg;
6407                                                 break;
6408                                         }
6409                                 case 0x24:
6410                                         {
6411 #ifdef CONFIG_P2P
6412                                                 DBG_8723A("turn %s the bShowGetP2PState Variable\n",(extra_arg==1)?"on":"off");
6413                                                 padapter->bShowGetP2PState = extra_arg;
6414 #endif // CONFIG_P2P
6415                                                 break;
6416                                         }
6417                                 case 0xaa:
6418                                         {
6419                                                 if(extra_arg> 0x13) extra_arg = 0xFF;
6420                                                 DBG_8723A("chang data rate to :0x%02x\n",extra_arg);
6421                                                 padapter->fix_rate = extra_arg;
6422                                         }
6423                                         break;
6424                                 case 0xdd://registers dump , 0 for mac reg,1 for bb reg, 2 for rf reg
6425                                         {
6426                                                 if(extra_arg==0){
6427                                                         mac_reg_dump(padapter);
6428                                                 }
6429                                                 else if(extra_arg==1){
6430                                                         bb_reg_dump(padapter);
6431                                                 }
6432                                                 else if(extra_arg==2){
6433                                                         rf_reg_dump(padapter);
6434                                                 }
6435
6436                                         }
6437                                         break;
6438
6439                                 case 0xee://turn on/off dynamic funcs
6440                                         {
6441                                                 u32 odm_flag;
6442
6443                                                 if(0xf==extra_arg){
6444                                                         rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC,&odm_flag);
6445                                                         DBG_8723A(" === DMFlag(0x%08x) === \n",odm_flag);
6446                                                         DBG_8723A("extra_arg = 0  - disable all dynamic func \n");
6447                                                         DBG_8723A("extra_arg = 1  - disable DIG- BIT(0)\n");
6448                                                         DBG_8723A("extra_arg = 2  - disable High power - BIT(1)\n");
6449                                                         DBG_8723A("extra_arg = 3  - disable tx power tracking - BIT(2)\n");
6450                                                         DBG_8723A("extra_arg = 4  - disable BT coexistence - BIT(3)\n");
6451                                                         DBG_8723A("extra_arg = 5  - disable antenna diversity - BIT(4)\n");
6452                                                         DBG_8723A("extra_arg = 6  - enable all dynamic func \n");
6453                                                 }
6454                                                 else{
6455                                                         /*      extra_arg = 0  - disable all dynamic func
6456                                                                 extra_arg = 1  - disable DIG
6457                                                                 extra_arg = 2  - disable tx power tracking
6458                                                                 extra_arg = 3  - turn on all dynamic func
6459                                                         */
6460                                                         rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
6461                                                         rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC,&odm_flag);
6462                                                         DBG_8723A(" === DMFlag(0x%08x) === \n",odm_flag);
6463                                                 }
6464                                         }
6465                                         break;
6466
6467                                 case 0xfd:
6468                                         rtw_write8(padapter, 0xc50, arg);
6469                                         DBG_8723A("wr(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
6470                                         rtw_write8(padapter, 0xc58, arg);
6471                                         DBG_8723A("wr(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
6472                                         break;
6473                                 case 0xfe:
6474                                         DBG_8723A("rd(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
6475                                         DBG_8723A("rd(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
6476                                         break;
6477                                 case 0xff:
6478                                         {
6479                                                 DBG_8723A("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
6480                                                 DBG_8723A("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
6481                                                 DBG_8723A("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
6482                                                 DBG_8723A("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
6483                                                 DBG_8723A("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
6484
6485                                                 DBG_8723A("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
6486
6487
6488                                                 DBG_8723A("\n");
6489
6490                                                 DBG_8723A("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
6491                                                 DBG_8723A("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
6492
6493                                                 DBG_8723A("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
6494
6495                                                 DBG_8723A("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
6496
6497                                                 DBG_8723A("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
6498                                                 DBG_8723A("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
6499
6500                                                 DBG_8723A("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
6501                                                 DBG_8723A("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
6502                                                 DBG_8723A("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
6503                                                 DBG_8723A("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
6504                                         }
6505                                         break;
6506                         }
6507                         break;
6508                 default:
6509                         DBG_8723A("error dbg cmd!\n");
6510                         break;
6511         }
6512
6513
6514         return ret;
6515
6516 }
6517
6518 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
6519 {
6520         uint ret=0;
6521         u32 flags;
6522         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
6523
6524         switch (name){
6525         case IEEE_PARAM_WPA_ENABLED:
6526
6527                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X; //802.1x
6528
6529                 //ret = ieee80211_wpa_enable(ieee, value);
6530
6531                 switch((value)&0xff)
6532                 {
6533                         case 1 : //WPA
6534                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; //WPA_PSK
6535                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
6536                                 break;
6537                         case 2: //WPA2
6538                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; //WPA2_PSK
6539                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
6540                                 break;
6541                 }
6542
6543                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("wpa_set_param:padapter->securitypriv.ndisauthtype=%d\n", padapter->securitypriv.ndisauthtype));
6544
6545                 break;
6546
6547         case IEEE_PARAM_TKIP_COUNTERMEASURES:
6548                 //ieee->tkip_countermeasures=value;
6549                 break;
6550
6551         case IEEE_PARAM_DROP_UNENCRYPTED:
6552         {
6553                 /* HACK:
6554                  *
6555                  * wpa_supplicant calls set_wpa_enabled when the driver
6556                  * is loaded and unloaded, regardless of if WPA is being
6557                  * used.  No other calls are made which can be used to
6558                  * determine if encryption will be used or not prior to
6559                  * association being expected.  If encryption is not being
6560                  * used, drop_unencrypted is set to false, else true -- we
6561                  * can use this to determine if the CAP_PRIVACY_ON bit should
6562                  * be set.
6563                  */
6564
6565                 break;
6566         }
6567         case IEEE_PARAM_PRIVACY_INVOKED:
6568
6569                 //ieee->privacy_invoked=value;
6570
6571                 break;
6572
6573         case IEEE_PARAM_AUTH_ALGS:
6574
6575                 ret = wpa_set_auth_algs(dev, value);
6576
6577                 break;
6578
6579         case IEEE_PARAM_IEEE_802_1X:
6580
6581                 //ieee->ieee802_1x=value;
6582
6583                 break;
6584
6585         case IEEE_PARAM_WPAX_SELECT:
6586
6587                 // added for WPA2 mixed mode
6588                 //DBG_8723A(KERN_WARNING "------------------------>wpax value = %x\n", value);
6589                 /*
6590                 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
6591                 ieee->wpax_type_set = 1;
6592                 ieee->wpax_type_notify = value;
6593                 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
6594                 */
6595
6596                 break;
6597
6598         default:
6599
6600
6601
6602                 ret = -EOPNOTSUPP;
6603
6604
6605                 break;
6606
6607         }
6608
6609         return ret;
6610
6611 }
6612
6613 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
6614 {
6615         int ret = 0;
6616         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
6617
6618         switch (command)
6619         {
6620                 case IEEE_MLME_STA_DEAUTH:
6621
6622                         if(!rtw_set_802_11_disassociate(padapter))
6623                                 ret = -1;
6624
6625                         break;
6626
6627                 case IEEE_MLME_STA_DISASSOC:
6628
6629                         if(!rtw_set_802_11_disassociate(padapter))
6630                                 ret = -1;
6631
6632                         break;
6633
6634                 default:
6635                         ret = -EOPNOTSUPP;
6636                         break;
6637         }
6638
6639         return ret;
6640
6641 }
6642
6643 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
6644 {
6645         struct ieee_param *param;
6646         uint ret=0;
6647
6648         //down(&ieee->wx_sem);
6649
6650         if (p->length < sizeof(struct ieee_param) || !p->pointer){
6651                 ret = -EINVAL;
6652                 goto out;
6653         }
6654
6655         param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
6656         if (param == NULL)
6657         {
6658                 ret = -ENOMEM;
6659                 goto exit;
6660         }
6661
6662         if (copy_from_user(param, p->pointer, p->length))
6663         {
6664                 ret = -EFAULT;
6665                 goto out;
6666         }
6667
6668         switch (param->cmd) {
6669
6670         case IEEE_CMD_SET_WPA_PARAM:
6671                 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
6672                 break;
6673
6674         case IEEE_CMD_SET_WPA_IE:
6675                 //ret = wpa_set_wpa_ie(dev, param, p->length);
6676                 ret =  rtw_set_wpa_ie((struct rtw_adapter *)rtw_netdev_priv(dev), (char*)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
6677                 break;
6678
6679         case IEEE_CMD_SET_ENCRYPTION:
6680                 ret = wpa_set_encryption(dev, param, p->length);
6681                 break;
6682
6683         case IEEE_CMD_MLME:
6684                 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
6685                 break;
6686
6687         default:
6688                 DBG_8723A("Unknown WPA supplicant request: %d\n", param->cmd);
6689                 ret = -EOPNOTSUPP;
6690                 break;
6691
6692         }
6693
6694         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
6695                 ret = -EFAULT;
6696
6697 out:
6698         kfree(param);
6699 exit:
6700         //up(&ieee->wx_sem);
6701
6702         return ret;
6703
6704 }
6705
6706 #ifdef CONFIG_AP_MODE
6707 static u8 set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta)
6708 {
6709         struct cmd_obj*                 ph2c;
6710         struct set_stakey_parm  *psetstakey_para;
6711         struct cmd_priv                         *pcmdpriv=&padapter->cmdpriv;
6712         u8      res=_SUCCESS;
6713
6714         ph2c = (struct cmd_obj*)kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
6715         if ( ph2c == NULL){
6716                 res= _FAIL;
6717                 goto fail1;
6718         }
6719
6720         psetstakey_para = (struct set_stakey_parm*)kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
6721         if(psetstakey_para==NULL){
6722                 kfree((u8 *) ph2c);
6723                 res=_FAIL;
6724                 goto exit;
6725         }
6726
6727         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
6728
6729
6730         psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
6731
6732         memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
6733
6734         memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
6735
6736
6737         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
6738
6739         kfree(psetstakey_para);
6740 exit:
6741         kfree(ph2c);
6742 fail1:
6743         return res;
6744
6745 }
6746
6747 static int set_group_key(struct rtw_adapter *padapter, u8 *key, u8 alg, int keyid)
6748 {
6749         u8 keylen;
6750         struct cmd_obj* pcmd;
6751         struct setkey_parm *psetkeyparm;
6752         struct cmd_priv *pcmdpriv=&(padapter->cmdpriv);
6753         int res=_SUCCESS;
6754
6755         DBG_8723A("%s\n", __func__);
6756
6757         pcmd = (struct cmd_obj*)kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
6758         if (!pcmd) {
6759                 res= _FAIL;
6760                 goto fail;
6761         }
6762         psetkeyparm=(struct setkey_parm*)kzalloc(sizeof(struct setkey_parm),
6763                                                  GFP_KERNEL);
6764         if (!psetkeyparm) {
6765                 res= _FAIL;
6766                 goto exit;
6767         }
6768
6769         psetkeyparm->keyid=(u8)keyid;
6770         if (is_wep_enc(alg))
6771                 padapter->mlmepriv.key_mask |= BIT(psetkeyparm->keyid);
6772         psetkeyparm->algorithm = alg;
6773
6774         psetkeyparm->set_tx = 1;
6775
6776         switch(alg) {
6777         case _WEP40_:
6778                 keylen = 5;
6779                 break;
6780         case _WEP104_:
6781                 keylen = 13;
6782                 break;
6783         case _TKIP_:
6784         case _TKIP_WTMIC_:
6785         case _AES_:
6786         default:
6787                 keylen = 16;
6788         }
6789         memcpy(&(psetkeyparm->key[0]), key, keylen);
6790         pcmd->cmdcode = _SetKey_CMD_;
6791         pcmd->parmbuf = (u8 *)psetkeyparm;
6792         pcmd->cmdsz =  (sizeof(struct setkey_parm));
6793         pcmd->rsp = NULL;
6794         pcmd->rspsz = 0;
6795
6796         INIT_LIST_HEAD(&pcmd->list);
6797
6798         res = rtw_enqueue_cmd(pcmdpriv, pcmd);
6799
6800         kfree(psetkeyparm);
6801 exit:
6802         kfree(pcmd);
6803 fail:
6804         return res;
6805 }
6806
6807 static int set_wep_key(struct rtw_adapter *padapter, u8 *key, u8 keylen, int keyid)
6808 {
6809         u8 alg;
6810
6811         switch(keylen) {
6812         case 5:
6813                 alg =_WEP40_;
6814                 break;
6815         case 13:
6816                 alg =_WEP104_;
6817                 break;
6818         default:
6819                 alg =_NO_PRIVACY_;
6820         }
6821
6822         return set_group_key(padapter, key, alg, keyid);
6823 }
6824
6825
6826 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
6827 {
6828         int ret = 0;
6829         u32 wep_key_idx, wep_key_len,wep_total_len;
6830         NDIS_802_11_WEP  *pwep = NULL;
6831         struct sta_info *psta = NULL, *pbcmc_sta = NULL;
6832         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
6833         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
6834         struct security_priv* psecuritypriv=&(padapter->securitypriv);
6835         struct sta_priv *pstapriv = &padapter->stapriv;
6836
6837         DBG_8723A("%s\n", __func__);
6838
6839         param->u.crypt.err = 0;
6840         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
6841
6842         //sizeof(struct ieee_param) = 64 bytes;
6843         //if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len)
6844         if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len)
6845         {
6846                 ret =  -EINVAL;
6847                 goto exit;
6848         }
6849
6850         if (is_broadcast_ether_addr(param->sta_addr)) {
6851                 if (param->u.crypt.idx >= WEP_KEYS)
6852                 {
6853                         ret = -EINVAL;
6854                         goto exit;
6855                 }
6856         }
6857         else
6858         {
6859                 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
6860                 if(!psta)
6861                 {
6862                         //ret = -EINVAL;
6863                         DBG_8723A("rtw_set_encryption(), sta has already been removed or never been added\n");
6864                         goto exit;
6865                 }
6866         }
6867
6868         if (strcmp(param->u.crypt.alg, "none") == 0 && (psta==NULL))
6869         {
6870                 //todo:clear default encryption keys
6871
6872                 DBG_8723A("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);
6873
6874                 goto exit;
6875         }
6876
6877
6878         if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta==NULL))
6879         {
6880                 DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n");
6881
6882                 wep_key_idx = param->u.crypt.idx;
6883                 wep_key_len = param->u.crypt.key_len;
6884
6885                 DBG_8723A("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
6886
6887                 if((wep_key_idx >= WEP_KEYS) || (wep_key_len<=0))
6888                 {
6889                         ret = -EINVAL;
6890                         goto exit;
6891                 }
6892
6893
6894                 if (wep_key_len > 0)
6895                 {
6896                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
6897                         wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
6898                         pwep = (NDIS_802_11_WEP *)kzalloc(wep_total_len,
6899                                                           GFP_KERNEL);
6900                         if(pwep == NULL){
6901                                 DBG_8723A(" r871x_set_encryption: pwep allocate fail !!!\n");
6902                                 goto exit;
6903                         }
6904
6905                         pwep->KeyLength = wep_key_len;
6906                         pwep->Length = wep_total_len;
6907
6908                 }
6909
6910                 pwep->KeyIndex = wep_key_idx;
6911
6912                 memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
6913
6914                 if(param->u.crypt.set_tx)
6915                 {
6916                         DBG_8723A("wep, set_tx=1\n");
6917
6918                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
6919                         psecuritypriv->dot11PrivacyAlgrthm=_WEP40_;
6920                         psecuritypriv->dot118021XGrpPrivacy=_WEP40_;
6921
6922                         if(pwep->KeyLength==13)
6923                         {
6924                                 psecuritypriv->dot11PrivacyAlgrthm=_WEP104_;
6925                                 psecuritypriv->dot118021XGrpPrivacy=_WEP104_;
6926                         }
6927
6928
6929                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
6930
6931                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
6932
6933                         psecuritypriv->dot11DefKeylen[wep_key_idx]=pwep->KeyLength;
6934
6935                         set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
6936
6937
6938                 }
6939                 else
6940                 {
6941                         DBG_8723A("wep, set_tx=0\n");
6942
6943                         //don't update "psecuritypriv->dot11PrivacyAlgrthm" and
6944                         //"psecuritypriv->dot11PrivacyKeyIndex=keyid", but can rtw_set_key to cam
6945
6946                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
6947
6948                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
6949
6950                         set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
6951
6952                 }
6953
6954                 goto exit;
6955
6956         }
6957
6958
6959         if(!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) // //group key
6960         {
6961                 if(param->u.crypt.set_tx ==1)
6962                 {
6963                         if(strcmp(param->u.crypt.alg, "WEP") == 0)
6964                         {
6965                                 DBG_8723A("%s, set group_key, WEP\n", __func__);
6966
6967                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
6968
6969                                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
6970                                 if(param->u.crypt.key_len==13)
6971                                 {
6972                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
6973                                 }
6974
6975                         }
6976                         else if(strcmp(param->u.crypt.alg, "TKIP") == 0)
6977                         {
6978                                 DBG_8723A("%s, set group_key, TKIP\n", __func__);
6979
6980                                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
6981
6982                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
6983
6984                                 //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);
6985                                 //set mic key
6986                                 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
6987                                 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
6988
6989                                 psecuritypriv->busetkipkey = _TRUE;
6990
6991                         }
6992                         else if(strcmp(param->u.crypt.alg, "CCMP") == 0)
6993                         {
6994                                 DBG_8723A("%s, set group_key, CCMP\n", __func__);
6995
6996                                 psecuritypriv->dot118021XGrpPrivacy = _AES_;
6997
6998                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
6999                         }
7000                         else
7001                         {
7002                                 DBG_8723A("%s, set group_key, none\n", __func__);
7003
7004                                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
7005                         }
7006
7007                         psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
7008
7009                         psecuritypriv->binstallGrpkey = _TRUE;
7010
7011                         psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;//!!!
7012
7013                         set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
7014
7015                         pbcmc_sta=rtw_get_bcmc_stainfo(padapter);
7016                         if(pbcmc_sta)
7017                         {
7018                                 pbcmc_sta->ieee8021x_blocked = _FALSE;
7019                                 pbcmc_sta->dot118021XPrivacy= psecuritypriv->dot118021XGrpPrivacy;//rx will use bmc_sta's dot118021XPrivacy
7020                         }
7021
7022                 }
7023
7024                 goto exit;
7025
7026         }
7027
7028         if(psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) // psk/802_1x
7029         {
7030                 if(check_fwstate(pmlmepriv, WIFI_AP_STATE))
7031                 {
7032                         if(param->u.crypt.set_tx ==1)
7033                         {
7034                                 memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
7035
7036                                 if(strcmp(param->u.crypt.alg, "WEP") == 0)
7037                                 {
7038                                         DBG_8723A("%s, set pairwise key, WEP\n", __func__);
7039
7040                                         psta->dot118021XPrivacy = _WEP40_;
7041                                         if(param->u.crypt.key_len==13)
7042                                         {
7043                                                 psta->dot118021XPrivacy = _WEP104_;
7044                                         }
7045                                 }
7046                                 else if(strcmp(param->u.crypt.alg, "TKIP") == 0)
7047                                 {
7048                                         DBG_8723A("%s, set pairwise key, TKIP\n", __func__);
7049
7050                                         psta->dot118021XPrivacy = _TKIP_;
7051
7052                                         //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);
7053                                         //set mic key
7054                                         memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
7055                                         memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
7056
7057                                         psecuritypriv->busetkipkey = _TRUE;
7058
7059                                 }
7060                                 else if(strcmp(param->u.crypt.alg, "CCMP") == 0)
7061                                 {
7062
7063                                         DBG_8723A("%s, set pairwise key, CCMP\n", __func__);
7064
7065                                         psta->dot118021XPrivacy = _AES_;
7066                                 }
7067                                 else
7068                                 {
7069                                         DBG_8723A("%s, set pairwise key, none\n", __func__);
7070
7071                                         psta->dot118021XPrivacy = _NO_PRIVACY_;
7072                                 }
7073
7074                                 set_pairwise_key(padapter, psta);
7075
7076                                 psta->ieee8021x_blocked = _FALSE;
7077
7078                         }
7079                         else//group key???
7080                         {
7081                                 if(strcmp(param->u.crypt.alg, "WEP") == 0)
7082                                 {
7083                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
7084
7085                                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
7086                                         if(param->u.crypt.key_len==13)
7087                                         {
7088                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
7089                                         }
7090                                 }
7091                                 else if(strcmp(param->u.crypt.alg, "TKIP") == 0)
7092                                 {
7093                                         psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
7094
7095                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
7096
7097                                         //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);
7098                                         //set mic key
7099                                         memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
7100                                         memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
7101
7102                                         psecuritypriv->busetkipkey = _TRUE;
7103
7104                                 }
7105                                 else if(strcmp(param->u.crypt.alg, "CCMP") == 0)
7106                                 {
7107                                         psecuritypriv->dot118021XGrpPrivacy = _AES_;
7108
7109                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
7110                                 }
7111                                 else
7112                                 {
7113                                         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
7114                                 }
7115
7116                                 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
7117
7118                                 psecuritypriv->binstallGrpkey = _TRUE;
7119
7120                                 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;//!!!
7121
7122                                 set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
7123
7124                                 pbcmc_sta=rtw_get_bcmc_stainfo(padapter);
7125                                 if(pbcmc_sta)
7126                                 {
7127                                         pbcmc_sta->ieee8021x_blocked = _FALSE;
7128                                         pbcmc_sta->dot118021XPrivacy= psecuritypriv->dot118021XGrpPrivacy;//rx will use bmc_sta's dot118021XPrivacy
7129                                 }
7130
7131                         }
7132
7133                 }
7134
7135         }
7136
7137 exit:
7138
7139         if(pwep) {
7140                 kfree(pwep);
7141         }
7142
7143         return ret;
7144
7145 }
7146
7147 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
7148 {
7149         int ret=0;
7150         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7151         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7152         struct sta_priv *pstapriv = &padapter->stapriv;
7153         unsigned char *pbuf = param->u.bcn_ie.buf;
7154
7155
7156         DBG_8723A("%s, len=%d\n", __func__, len);
7157
7158         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7159                 return -EINVAL;
7160
7161         memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
7162
7163         if((pstapriv->max_num_sta>NUM_STA) || (pstapriv->max_num_sta<=0))
7164                 pstapriv->max_num_sta = NUM_STA;
7165
7166
7167         if(rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)// 12 = param header, 2:no packed
7168                 ret = 0;
7169         else
7170                 ret = -EINVAL;
7171
7172
7173         return ret;
7174
7175 }
7176
7177 static int rtw_hostapd_sta_flush(struct net_device *dev)
7178 {
7179         //struct list_head      *phead, *plist;
7180         int ret=0;
7181         //struct sta_info *psta = NULL;
7182         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7183         //struct sta_priv *pstapriv = &padapter->stapriv;
7184
7185         DBG_8723A("%s\n", __func__);
7186
7187         flush_all_cam_entry(padapter);  //clear CAM
7188
7189         ret = rtw_sta_flush(padapter);
7190
7191         return ret;
7192
7193 }
7194
7195 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
7196 {
7197         int ret=0;
7198         struct sta_info *psta = NULL;
7199         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7200         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7201         struct sta_priv *pstapriv = &padapter->stapriv;
7202
7203         DBG_8723A("rtw_add_sta(aid=%d)=" MAC_FMT "\n", param->u.add_sta.aid, MAC_ARG(param->sta_addr));
7204
7205         if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)
7206         {
7207                 return -EINVAL;
7208         }
7209
7210         if (is_broadcast_ether_addr(param->sta_addr))
7211                 return -EINVAL;
7212
7213 /*
7214         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7215         if(psta)
7216         {
7217                 DBG_8723A("rtw_add_sta(), free has been added psta=%p\n", psta);
7218                 spin_lock_bh(&(pstapriv->sta_hash_lock));
7219                 rtw_free_stainfo(padapter,  psta);
7220                 spin_unlock_bh(&(pstapriv->sta_hash_lock));
7221
7222                 psta = NULL;
7223         }
7224 */
7225         //psta = rtw_alloc_stainfo(pstapriv, param->sta_addr);
7226         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7227         if(psta)
7228         {
7229                 int flags = param->u.add_sta.flags;
7230
7231                 //DBG_8723A("rtw_add_sta(), init sta's variables, psta=%p\n", psta);
7232
7233                 psta->aid = param->u.add_sta.aid;//aid=1~2007
7234
7235                 memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
7236
7237
7238                 //check wmm cap.
7239                 if(WLAN_STA_WME&flags)
7240                         psta->qos_option = 1;
7241                 else
7242                         psta->qos_option = 0;
7243
7244                 if(pmlmepriv->qospriv.qos_option == 0)
7245                         psta->qos_option = 0;
7246
7247
7248 #ifdef CONFIG_80211N_HT
7249                 //chec 802.11n ht cap.
7250                 if(WLAN_STA_HT&flags)
7251                 {
7252                         psta->htpriv.ht_option = _TRUE;
7253                         psta->qos_option = 1;
7254                         memcpy((void*)&psta->htpriv.ht_cap, (void*)&param->u.add_sta.ht_cap, sizeof(struct ieee80211_ht_cap));
7255                 }
7256                 else
7257                 {
7258                         psta->htpriv.ht_option = _FALSE;
7259                 }
7260
7261                 if(pmlmepriv->htpriv.ht_option == _FALSE)
7262                         psta->htpriv.ht_option = _FALSE;
7263 #endif
7264
7265
7266                 update_sta_info_apmode(padapter, psta);
7267
7268
7269         }
7270         else
7271         {
7272                 ret = -ENOMEM;
7273         }
7274
7275         return ret;
7276
7277 }
7278
7279 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
7280 {
7281         int ret=0;
7282         struct sta_info *psta = NULL;
7283         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7284         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7285         struct sta_priv *pstapriv = &padapter->stapriv;
7286
7287         DBG_8723A("rtw_del_sta=" MAC_FMT "\n", MAC_ARG(param->sta_addr));
7288
7289         if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)
7290         {
7291                 return -EINVAL;
7292         }
7293
7294         if (is_broadcast_ether_addr(param->sta_addr))
7295                 return -EINVAL;
7296
7297         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7298         if(psta)
7299         {
7300                 u8 updated;
7301
7302                 //DBG_8723A("free psta=%p, aid=%d\n", psta, psta->aid);
7303
7304                 spin_lock_bh(&pstapriv->asoc_list_lock);
7305                 if (!list_empty(&psta->asoc_list)) {
7306                         list_del_init(&psta->asoc_list);
7307                         pstapriv->asoc_list_cnt--;
7308                         updated = ap_free_sta(padapter, psta, _TRUE,
7309                                               WLAN_REASON_DEAUTH_LEAVING);
7310                 }
7311                 spin_unlock_bh(&pstapriv->asoc_list_lock);
7312
7313                 associated_clients_update(padapter, updated);
7314
7315                 psta = NULL;
7316
7317         }
7318         else
7319         {
7320                 DBG_8723A("rtw_del_sta(), sta has already been removed or never been added\n");
7321
7322                 //ret = -1;
7323         }
7324
7325
7326         return ret;
7327
7328 }
7329
7330 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
7331 {
7332         int ret=0;
7333         struct sta_info *psta = NULL;
7334         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7335         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7336         struct sta_priv *pstapriv = &padapter->stapriv;
7337         struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
7338         struct sta_data *psta_data = (struct sta_data *)param_ex->data;
7339
7340         DBG_8723A("rtw_ioctl_get_sta_info, sta_addr: " MAC_FMT "\n", MAC_ARG(param_ex->sta_addr));
7341
7342         if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)
7343         {
7344                 return -EINVAL;
7345         }
7346
7347         if (is_broadcast_ether_addr(param_ex->sta_addr))
7348                 return -EINVAL;
7349
7350         psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
7351         if(psta)
7352         {
7353                 psta_data->aid = (u16)psta->aid;
7354                 psta_data->capability = psta->capability;
7355                 psta_data->flags = psta->flags;
7356
7357 /*
7358                 nonerp_set : BIT(0)
7359                 no_short_slot_time_set : BIT(1)
7360                 no_short_preamble_set : BIT(2)
7361                 no_ht_gf_set : BIT(3)
7362                 no_ht_set : BIT(4)
7363                 ht_20mhz_set : BIT(5)
7364 */
7365
7366                 psta_data->sta_set =((psta->nonerp_set) |
7367                                                         (psta->no_short_slot_time_set <<1) |
7368                                                         (psta->no_short_preamble_set <<2) |
7369                                                         (psta->no_ht_gf_set <<3) |
7370                                                         (psta->no_ht_set <<4) |
7371                                                         (psta->ht_20mhz_set <<5));
7372
7373                 psta_data->tx_supp_rates_len =  psta->bssratelen;
7374                 memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
7375 #ifdef CONFIG_80211N_HT
7376                 memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct ieee80211_ht_cap));
7377 #endif //CONFIG_80211N_HT
7378                 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
7379                 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
7380                 psta_data->rx_drops = psta->sta_stats.rx_drops;
7381
7382                 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
7383                 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
7384                 psta_data->tx_drops = psta->sta_stats.tx_drops;
7385
7386
7387         }
7388         else
7389         {
7390                 ret = -1;
7391         }
7392
7393         return ret;
7394
7395 }
7396
7397 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
7398 {
7399         int ret=0;
7400         struct sta_info *psta = NULL;
7401         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7402         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7403         struct sta_priv *pstapriv = &padapter->stapriv;
7404
7405         DBG_8723A("rtw_get_sta_wpaie, sta_addr: " MAC_FMT "\n", MAC_ARG(param->sta_addr));
7406
7407         if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)
7408         {
7409                 return -EINVAL;
7410         }
7411
7412         if (is_broadcast_ether_addr(param->sta_addr))
7413                 return -EINVAL;
7414
7415         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7416         if(psta)
7417         {
7418                 if((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC))
7419                 {
7420                         int wpa_ie_len;
7421                         int copy_len;
7422
7423                         wpa_ie_len = psta->wpa_ie[1];
7424
7425                         copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)):(wpa_ie_len+2);
7426
7427                         param->u.wpa_ie.len = copy_len;
7428
7429                         memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
7430                 }
7431                 else
7432                 {
7433                         //ret = -1;
7434                         DBG_8723A("sta's wpa_ie is NONE\n");
7435                 }
7436         }
7437         else
7438         {
7439                 ret = -1;
7440         }
7441
7442         return ret;
7443
7444 }
7445
7446 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
7447 {
7448         int ret=0;
7449         unsigned char wps_oui[4]={0x0,0x50,0xf2,0x04};
7450         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7451         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7452         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7453         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7454         int ie_len;
7455
7456         DBG_8723A("%s, len=%d\n", __func__, len);
7457
7458         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7459                 return -EINVAL;
7460
7461         ie_len = len-12-2;// 12 = param header, 2:no packed
7462
7463
7464         if(pmlmepriv->wps_beacon_ie)
7465         {
7466                 kfree(pmlmepriv->wps_beacon_ie);
7467                 pmlmepriv->wps_beacon_ie = NULL;
7468         }
7469
7470         if(ie_len>0)
7471         {
7472                 pmlmepriv->wps_beacon_ie = kmalloc(ie_len, GFP_KERNEL);
7473                 pmlmepriv->wps_beacon_ie_len = ie_len;
7474                 if ( pmlmepriv->wps_beacon_ie == NULL) {
7475                         DBG_8723A("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
7476                         return -EINVAL;
7477                 }
7478
7479                 memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
7480
7481                 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, _TRUE);
7482
7483                 pmlmeext->bstart_bss = _TRUE;
7484         }
7485
7486         return ret;
7487 }
7488
7489 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
7490 {
7491         int ret=0;
7492         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7493         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7494         int ie_len;
7495
7496         DBG_8723A("%s, len=%d\n", __func__, len);
7497
7498         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7499                 return -EINVAL;
7500
7501         ie_len = len-12-2;// 12 = param header, 2:no packed
7502
7503
7504         if(pmlmepriv->wps_probe_resp_ie)
7505         {
7506                 kfree(pmlmepriv->wps_probe_resp_ie);
7507                 pmlmepriv->wps_probe_resp_ie = NULL;
7508         }
7509
7510         if(ie_len>0)
7511         {
7512                 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
7513                 pmlmepriv->wps_probe_resp_ie_len = ie_len;
7514                 if ( pmlmepriv->wps_probe_resp_ie == NULL) {
7515                         DBG_8723A("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
7516                         return -EINVAL;
7517                 }
7518                 memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
7519         }
7520
7521
7522         return ret;
7523
7524 }
7525
7526 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
7527 {
7528         int ret=0;
7529         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7530         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7531         int ie_len;
7532
7533         DBG_8723A("%s, len=%d\n", __func__, len);
7534
7535         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7536                 return -EINVAL;
7537
7538         ie_len = len-12-2;// 12 = param header, 2:no packed
7539
7540
7541         if(pmlmepriv->wps_assoc_resp_ie)
7542         {
7543                 kfree(pmlmepriv->wps_assoc_resp_ie);
7544                 pmlmepriv->wps_assoc_resp_ie = NULL;
7545         }
7546
7547         if(ie_len>0)
7548         {
7549                 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
7550                 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
7551                 if ( pmlmepriv->wps_assoc_resp_ie == NULL) {
7552                         DBG_8723A("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
7553                         return -EINVAL;
7554                 }
7555
7556                 memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
7557         }
7558
7559
7560         return ret;
7561
7562 }
7563
7564 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
7565 {
7566         int ret=0;
7567         struct rtw_adapter *adapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7568         struct mlme_priv *mlmepriv = &(adapter->mlmepriv);
7569         struct mlme_ext_priv    *mlmeext = &(adapter->mlmeextpriv);
7570         struct mlme_ext_info    *mlmeinfo = &(mlmeext->mlmext_info);
7571         int ie_len;
7572         u8 *ssid_ie;
7573         char ssid[NDIS_802_11_LENGTH_SSID + 1];
7574         int ssid_len;
7575         u8 ignore_broadcast_ssid;
7576
7577         if(check_fwstate(mlmepriv, WIFI_AP_STATE) != _TRUE)
7578                 return -EPERM;
7579
7580         if (param->u.bcn_ie.reserved[0] != 0xea)
7581                 return -EINVAL;
7582
7583         mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
7584
7585         ie_len = len-12-2;// 12 = param header, 2:no packed
7586         ssid_ie = rtw_get_ie(param->u.bcn_ie.buf,  WLAN_EID_SSID, &ssid_len, ie_len);
7587
7588         if (ssid_ie && ssid_len) {
7589                 WLAN_BSSID_EX *pbss_network = &mlmepriv->cur_network.network;
7590                 WLAN_BSSID_EX *pbss_network_ext = &mlmeinfo->network;
7591
7592                 memcpy(ssid, ssid_ie+2, ssid_len);
7593                 ssid[ssid_len>NDIS_802_11_LENGTH_SSID?NDIS_802_11_LENGTH_SSID:ssid_len] = 0x0;
7594
7595                 if(0)
7596                 DBG_8723A(FUNC_ADPT_FMT" ssid:(%s,%d), from ie:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
7597                         ssid, ssid_len,
7598                         pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
7599                         pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
7600
7601                 memcpy(pbss_network->Ssid.Ssid, (void *)ssid, ssid_len);
7602                 pbss_network->Ssid.SsidLength = ssid_len;
7603                 memcpy(pbss_network_ext->Ssid.Ssid, (void *)ssid, ssid_len);
7604                 pbss_network_ext->Ssid.SsidLength = ssid_len;
7605
7606                 if(0)
7607                 DBG_8723A(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
7608                         pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
7609                         pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
7610         }
7611
7612         DBG_8723A(FUNC_ADPT_FMT" ignore_broadcast_ssid:%d, %s,%d\n", FUNC_ADPT_ARG(adapter),
7613                 ignore_broadcast_ssid, ssid, ssid_len);
7614
7615         return ret;
7616 }
7617
7618 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
7619 {
7620         int ret=0;
7621         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7622         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7623
7624         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7625                 return -EINVAL;
7626
7627         if (is_broadcast_ether_addr(param->sta_addr))
7628                 return -EINVAL;
7629
7630         ret = rtw_acl_remove_sta(padapter, param->sta_addr);
7631
7632         return ret;
7633 }
7634
7635 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
7636 {
7637         int ret=0;
7638         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7639         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7640
7641         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7642                 return -EINVAL;
7643
7644         if (is_broadcast_ether_addr(param->sta_addr))
7645                 return -EINVAL;
7646
7647         ret = rtw_acl_add_sta(padapter, param->sta_addr);
7648
7649         return ret;
7650
7651 }
7652
7653 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
7654 {
7655         int ret=0;
7656         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7657         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7658
7659         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7660                 return -EINVAL;
7661
7662         rtw_set_macaddr_acl(padapter, param->u.mlme.command);
7663
7664         return ret;
7665 }
7666
7667 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
7668 {
7669         struct ieee_param *param;
7670         int ret = 0;
7671         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7672
7673         //DBG_8723A("%s\n", __func__);
7674
7675         /*
7676         * this function is expect to call in master mode, which allows no power saving
7677         * so, we just check hw_init_completed
7678         */
7679
7680         if (padapter->hw_init_completed==_FALSE){
7681                 ret = -EPERM;
7682                 goto fail;
7683         }
7684
7685
7686         //if (p->length < sizeof(struct ieee_param) || !p->pointer){
7687         if(!p->pointer){
7688                 ret = -EINVAL;
7689                 goto fail;
7690         }
7691
7692         param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
7693         if (param == NULL)
7694         {
7695                 ret = -ENOMEM;
7696                 goto fail;
7697         }
7698
7699         if (copy_from_user(param, p->pointer, p->length))
7700         {
7701                 ret = -EFAULT;
7702                 goto out;
7703         }
7704
7705         //DBG_8723A("%s, cmd=%d\n", __func__, param->cmd);
7706
7707         switch (param->cmd)
7708         {
7709                 case RTL871X_HOSTAPD_FLUSH:
7710
7711                         ret = rtw_hostapd_sta_flush(dev);
7712
7713                         break;
7714
7715                 case RTL871X_HOSTAPD_ADD_STA:
7716
7717                         ret = rtw_add_sta(dev, param);
7718
7719                         break;
7720
7721                 case RTL871X_HOSTAPD_REMOVE_STA:
7722
7723                         ret = rtw_del_sta(dev, param);
7724
7725                         break;
7726
7727                 case RTL871X_HOSTAPD_SET_BEACON:
7728
7729                         ret = rtw_set_beacon(dev, param, p->length);
7730
7731                         break;
7732
7733                 case RTL871X_SET_ENCRYPTION:
7734
7735                         ret = rtw_set_encryption(dev, param, p->length);
7736
7737                         break;
7738
7739                 case RTL871X_HOSTAPD_GET_WPAIE_STA:
7740
7741                         ret = rtw_get_sta_wpaie(dev, param);
7742
7743                         break;
7744
7745                 case RTL871X_HOSTAPD_SET_WPS_BEACON:
7746
7747                         ret = rtw_set_wps_beacon(dev, param, p->length);
7748
7749                         break;
7750
7751                 case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
7752
7753                         ret = rtw_set_wps_probe_resp(dev, param, p->length);
7754
7755                         break;
7756
7757                 case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
7758
7759                         ret = rtw_set_wps_assoc_resp(dev, param, p->length);
7760
7761                         break;
7762
7763                 case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
7764
7765                         ret = rtw_set_hidden_ssid(dev, param, p->length);
7766
7767                         break;
7768
7769                 case RTL871X_HOSTAPD_GET_INFO_STA:
7770
7771                         ret = rtw_ioctl_get_sta_data(dev, param, p->length);
7772
7773                         break;
7774
7775                 case RTL871X_HOSTAPD_SET_MACADDR_ACL:
7776
7777                         ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
7778
7779                         break;
7780
7781                 case RTL871X_HOSTAPD_ACL_ADD_STA:
7782
7783                         ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
7784
7785                         break;
7786
7787                 case RTL871X_HOSTAPD_ACL_REMOVE_STA:
7788
7789                         ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
7790
7791                         break;
7792
7793                 default:
7794                         DBG_8723A("Unknown hostapd request: %d\n", param->cmd);
7795                         ret = -EOPNOTSUPP;
7796                         break;
7797
7798         }
7799
7800         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
7801                 ret = -EFAULT;
7802
7803
7804 out:
7805         kfree((u8 *)param);
7806 fail:
7807         return ret;
7808 }
7809 #endif
7810
7811 #include <rtw_android.h>
7812 static int rtw_wx_set_priv(struct net_device *dev,
7813                                 struct iw_request_info *info,
7814                                 union iwreq_data *awrq,
7815                                 char *extra)
7816 {
7817
7818 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
7819         char *ext_dbg;
7820 #endif
7821
7822         int ret = 0;
7823         int len = 0;
7824         char *ext;
7825         int i;
7826
7827         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
7828         struct iw_point *dwrq = (struct iw_point*)awrq;
7829
7830         //RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, ("+rtw_wx_set_priv\n"));
7831         if(dwrq->length == 0)
7832                 return -EFAULT;
7833
7834         len = dwrq->length;
7835         if (!(ext = rtw_vmalloc(len)))
7836                 return -ENOMEM;
7837
7838         if (copy_from_user(ext, dwrq->pointer, len)) {
7839                 rtw_vmfree(ext, len);
7840                 return -EFAULT;
7841         }
7842
7843
7844         //RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_,
7845         //       ("rtw_wx_set_priv: %s req=%s\n",
7846         //        dev->name, ext));
7847
7848         #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
7849         if (!(ext_dbg = rtw_vmalloc(len)))
7850         {
7851                 rtw_vmfree(ext, len);
7852                 return -ENOMEM;
7853         }
7854
7855         memcpy(ext_dbg, ext, len);
7856         #endif
7857
7858         //added for wps2.0 @20110524
7859         if(dwrq->flags == 0x8766 && len > 8)
7860         {
7861                 u32 cp_sz;
7862                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7863                 u8 *probereq_wpsie = ext;
7864                 int probereq_wpsie_len = len;
7865                 u8 wps_oui[4]={0x0,0x50,0xf2,0x04};
7866
7867                 if((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
7868                         (!memcmp(&probereq_wpsie[2], wps_oui, 4)))
7869                 {
7870                         cp_sz = probereq_wpsie_len>MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN:probereq_wpsie_len;
7871
7872                         //memcpy(pmlmepriv->probereq_wpsie, probereq_wpsie, cp_sz);
7873                         //pmlmepriv->probereq_wpsie_len = cp_sz;
7874                         if(pmlmepriv->wps_probe_req_ie)
7875                         {
7876                                 u32 free_len = pmlmepriv->wps_probe_req_ie_len;
7877                                 pmlmepriv->wps_probe_req_ie_len = 0;
7878                                 kfree(pmlmepriv->wps_probe_req_ie);
7879                                 pmlmepriv->wps_probe_req_ie = NULL;
7880                         }
7881
7882                         pmlmepriv->wps_probe_req_ie = kmalloc(cp_sz,
7883                                                               GFP_KERNEL);
7884                         if ( pmlmepriv->wps_probe_req_ie == NULL) {
7885                                 printk("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
7886                                 ret =  -EINVAL;
7887                                 goto FREE_EXT;
7888
7889                         }
7890
7891                         memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
7892                         pmlmepriv->wps_probe_req_ie_len = cp_sz;
7893
7894                 }
7895
7896                 goto FREE_EXT;
7897
7898         }
7899
7900         if (len >= WEXT_CSCAN_HEADER_SIZE &&
7901             !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
7902                 ret = rtw_wx_set_scan(dev, info, awrq, ext);
7903                 goto FREE_EXT;
7904         }
7905
7906 #ifdef CONFIG_ANDROID
7907         //DBG_8723A("rtw_wx_set_priv: %s req=%s\n", dev->name, ext);
7908
7909         i = rtw_android_cmdstr_to_num(ext);
7910
7911         switch(i) {
7912                 case ANDROID_WIFI_CMD_START :
7913                         indicate_wx_custom_event(padapter, "START");
7914                         break;
7915                 case ANDROID_WIFI_CMD_STOP :
7916                         indicate_wx_custom_event(padapter, "STOP");
7917                         break;
7918                 case ANDROID_WIFI_CMD_RSSI :
7919                         {
7920                                 struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
7921                                 struct  wlan_network    *pcur_network = &pmlmepriv->cur_network;
7922
7923                                 if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
7924                                         sprintf(ext, "%s rssi %d", pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
7925                                 } else {
7926                                         sprintf(ext, "OK");
7927                                 }
7928                         }
7929                         break;
7930                 case ANDROID_WIFI_CMD_LINKSPEED :
7931                         {
7932                                 u16 mbps = rtw_get_cur_max_rate(padapter)/10;
7933                                 sprintf(ext, "LINKSPEED %d", mbps);
7934                         }
7935                         break;
7936                 case ANDROID_WIFI_CMD_MACADDR :
7937                         sprintf(ext, "MACADDR = " MAC_FMT, MAC_ARG(dev->dev_addr));
7938                         break;
7939                 case ANDROID_WIFI_CMD_SCAN_ACTIVE :
7940                         {
7941                                 //rtw_set_scan_mode(padapter, SCAN_ACTIVE);
7942                                 sprintf(ext, "OK");
7943                         }
7944                         break;
7945                 case ANDROID_WIFI_CMD_SCAN_PASSIVE :
7946                         {
7947                                 //rtw_set_scan_mode(padapter, SCAN_PASSIVE);
7948                                 sprintf(ext, "OK");
7949                         }
7950                         break;
7951
7952                 case ANDROID_WIFI_CMD_COUNTRY :
7953                         {
7954                                 char country_code[10];
7955                                 sscanf(ext, "%*s %s", country_code);
7956                                 rtw_set_country(padapter, country_code);
7957                                 sprintf(ext, "OK");
7958                         }
7959                         break;
7960                 default :
7961                         #ifdef  CONFIG_DEBUG_RTW_WX_SET_PRIV
7962                         DBG_8723A("%s: %s unknowned req=%s\n", __func__,
7963                                 dev->name, ext_dbg);
7964                         #endif
7965
7966                         sprintf(ext, "OK");
7967
7968         }
7969
7970         if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (u16)(strlen(ext)+1)) ) )
7971                 ret = -EFAULT;
7972
7973         #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
7974         DBG_8723A("%s: %s req=%s rep=%s dwrq->length=%d, strlen(ext)+1=%d\n", __func__,
7975                 dev->name, ext_dbg ,ext, dwrq->length, (u16)(strlen(ext)+1));
7976         #endif
7977 #endif //end of CONFIG_ANDROID
7978
7979
7980 FREE_EXT:
7981
7982         rtw_vmfree(ext, len);
7983         #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
7984         rtw_vmfree(ext_dbg, len);
7985         #endif
7986
7987         //DBG_8723A("rtw_wx_set_priv: (SIOCSIWPRIV) %s ret=%d\n",
7988         //              dev->name, ret);
7989
7990         return ret;
7991 }
7992
7993 static int rtw_pm_set(struct net_device *dev,
7994                                struct iw_request_info *info,
7995                                union iwreq_data *wrqu, char *extra)
7996 {
7997         int ret = 0;
7998         unsigned        mode = 0;
7999         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8000
8001         DBG_8723A( "[%s] extra = %s\n", __func__, extra );
8002
8003         if (!memcmp(extra, "lps=", 4))
8004         {
8005                 sscanf(extra+4, "%u", &mode);
8006                 ret = rtw_pm_set_lps(padapter,mode);
8007         }
8008         else if (!memcmp(extra, "ips=", 4))
8009         {
8010                 sscanf(extra+4, "%u", &mode);
8011                 ret = rtw_pm_set_ips(padapter,mode);
8012         }
8013         else{
8014                 ret = -EINVAL;
8015         }
8016
8017         return ret;
8018 }
8019
8020
8021 static int rtw_wfd_tdls_enable(struct net_device *dev,
8022                                 struct iw_request_info *info,
8023                                 union iwreq_data *wrqu, char *extra)
8024 {
8025         int ret = 0;
8026
8027 #ifdef CONFIG_TDLS
8028 #ifdef CONFIG_WFD
8029
8030         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8031
8032         printk( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
8033
8034         if ( extra[ 0 ] == '0' )
8035         {
8036                 padapter->wdinfo.wfd_tdls_enable = 0;
8037         }
8038         else
8039         {
8040                 padapter->wdinfo.wfd_tdls_enable = 1;
8041         }
8042
8043 #endif //CONFIG_WFD
8044 #endif //CONFIG_TDLS
8045
8046         return ret;
8047 }
8048
8049 static int rtw_tdls_weaksec(struct net_device *dev,
8050                                 struct iw_request_info *info,
8051                                 union iwreq_data *wrqu, char *extra)
8052 {
8053         int ret = 0;
8054
8055 #ifdef CONFIG_TDLS
8056
8057         u8 i, j;
8058         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8059
8060         DBG_8723A( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
8061
8062         if ( extra[ 0 ] == '0' )
8063         {
8064                 padapter->wdinfo.wfd_tdls_weaksec = 0;
8065         }
8066         else
8067         {
8068                 padapter->wdinfo.wfd_tdls_weaksec = 1;
8069         }
8070 #endif
8071
8072         return ret;
8073 }
8074
8075
8076 static int rtw_tdls_enable(struct net_device *dev,
8077                                 struct iw_request_info *info,
8078                                 union iwreq_data *wrqu, char *extra)
8079 {
8080         int ret = 0;
8081
8082 #ifdef CONFIG_TDLS
8083
8084         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8085         struct tdls_info        *ptdlsinfo = &padapter->tdlsinfo;
8086         struct list_head        *plist, *phead;
8087         s32     index;
8088         struct sta_info *psta = NULL;
8089         struct  sta_priv *pstapriv = &padapter->stapriv;
8090         u8 tdls_sta[NUM_STA][ETH_ALEN];
8091         u8 empty_hwaddr[ETH_ALEN] = { 0x00 };
8092
8093         printk( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
8094
8095         memset(tdls_sta, 0x00, sizeof(tdls_sta));
8096
8097         if ( extra[ 0 ] == '0' )
8098         {
8099                 ptdlsinfo->enable = 0;
8100
8101                 if(pstapriv->asoc_sta_count==1)
8102                         return ret;
8103
8104                 spin_lock_bh(&pstapriv->sta_hash_lock);
8105                 for(index=0; index< NUM_STA; index++)
8106                 {
8107                         phead = &(pstapriv->sta_hash[index]);
8108                         plist = phead->next;
8109
8110                         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
8111                         {
8112                                 psta = container_of(plist, struct sta_info ,hash_list);
8113
8114                                 plist = plist->next;
8115
8116                                 if(psta->tdls_sta_state != TDLS_STATE_NONE)
8117                                 {
8118                                         memcpy(tdls_sta[index], psta->hwaddr, ETH_ALEN);
8119                                 }
8120                         }
8121                 }
8122                 spin_unlock_bh(&pstapriv->sta_hash_lock);
8123
8124                 for (index=0; index< NUM_STA; index++)
8125                 {
8126                         if (memcmp(tdls_sta[index], empty_hwaddr, ETH_ALEN))
8127                         {
8128                                 printk("issue tear down to "MAC_FMT"\n", MAC_ARG(tdls_sta[index]));
8129                                 issue_tdls_teardown(padapter, tdls_sta[index]);
8130                         }
8131                 }
8132                 rtw_tdls_cmd(padapter, myid(&(padapter->eeprompriv)), TDLS_RS_RCR);
8133                 rtw_reset_tdls_info(padapter);
8134         }
8135         else if ( extra[ 0 ] == '1' )
8136         {
8137                 ptdlsinfo->enable = 1;
8138         }
8139 #endif //CONFIG_TDLS
8140
8141         return ret;
8142 }
8143
8144 static int rtw_tdls_setup(struct net_device *dev,
8145                                 struct iw_request_info *info,
8146                                 union iwreq_data *wrqu, char *extra)
8147 {
8148         int ret = 0;
8149
8150 #ifdef CONFIG_TDLS
8151
8152         u8 i, j;
8153         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8154         u8 mac_addr[ETH_ALEN];
8155
8156 #ifdef CONFIG_WFD
8157         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
8158 #endif // CONFIG_WFD
8159
8160         printk( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
8161
8162         for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
8163                 mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
8164         }
8165
8166 #ifdef CONFIG_WFD
8167         if ( _AES_ != padapter->securitypriv.dot11PrivacyAlgrthm )
8168         {
8169                 //      Weak Security situation with AP.
8170                 if ( 0 == pwdinfo->wfd_tdls_weaksec )
8171                 {
8172                         //      Can't send the tdls setup request out!!
8173                         DBG_8723A( "[%s] Current link is not AES, SKIP sending the tdls setup request!!\n", __func__ );
8174                 }
8175                 else
8176                 {
8177                         issue_tdls_setup_req(padapter, mac_addr);
8178                 }
8179         }
8180         else
8181 #endif // CONFIG_WFD
8182         {
8183                 issue_tdls_setup_req(padapter, mac_addr);
8184         }
8185 #endif
8186
8187         return ret;
8188 }
8189
8190 static int rtw_tdls_teardown(struct net_device *dev,
8191                                 struct iw_request_info *info,
8192                                 union iwreq_data *wrqu, char *extra)
8193 {
8194         int ret = 0;
8195
8196 #ifdef CONFIG_TDLS
8197
8198         u8 i,j;
8199         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8200         struct sta_info *ptdls_sta = NULL;
8201         u8 mac_addr[ETH_ALEN];
8202
8203         DBG_8723A( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
8204
8205         for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
8206                 mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
8207         }
8208
8209         ptdls_sta = rtw_get_stainfo( &(padapter->stapriv), mac_addr);
8210
8211         if(ptdls_sta != NULL)
8212         {
8213                 ptdls_sta->stat_code = _RSON_TDLS_TEAR_UN_RSN_;
8214                 issue_tdls_teardown(padapter, mac_addr);
8215         }
8216
8217 #endif //CONFIG_TDLS
8218
8219         return ret;
8220 }
8221
8222 static int rtw_tdls_discovery(struct net_device *dev,
8223                                 struct iw_request_info *info,
8224                                 union iwreq_data *wrqu, char *extra)
8225 {
8226         int ret = 0;
8227
8228 #ifdef CONFIG_TDLS
8229
8230         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8231         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8232         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8233
8234         DBG_8723A( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
8235
8236         issue_tdls_dis_req(padapter, NULL);
8237
8238 #endif //CONFIG_TDLS
8239
8240         return ret;
8241 }
8242
8243 static int rtw_tdls_ch_switch(struct net_device *dev,
8244                                 struct iw_request_info *info,
8245                                 union iwreq_data *wrqu, char *extra)
8246 {
8247         int ret = 0;
8248
8249 #ifdef CONFIG_TDLS
8250
8251         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8252         struct tdls_info        *ptdlsinfo = &padapter->tdlsinfo;
8253         u8 i, j, mac_addr[ETH_ALEN];
8254         struct sta_info *ptdls_sta = NULL;
8255
8256         DBG_8723A( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
8257
8258         for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
8259                 mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
8260         }
8261
8262         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
8263         if( ptdls_sta == NULL )
8264                 return ret;
8265         ptdlsinfo->ch_sensing=1;
8266
8267         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_INIT_CH_SEN);
8268
8269 #endif //CONFIG_TDLS
8270
8271                 return ret;
8272 }
8273
8274 static int rtw_tdls_pson(struct net_device *dev,
8275                                 struct iw_request_info *info,
8276                                 union iwreq_data *wrqu, char *extra)
8277 {
8278         int ret = 0;
8279
8280 #ifdef CONFIG_TDLS
8281
8282         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8283         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8284         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8285         u8 i, j, mac_addr[ETH_ALEN];
8286         struct sta_info *ptdls_sta = NULL;
8287
8288         DBG_8723A( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
8289
8290         for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
8291                 mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
8292         }
8293
8294         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
8295
8296         issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta, 1);
8297
8298 #endif //CONFIG_TDLS
8299
8300                 return ret;
8301 }
8302
8303 static int rtw_tdls_psoff(struct net_device *dev,
8304                                 struct iw_request_info *info,
8305                                 union iwreq_data *wrqu, char *extra)
8306 {
8307         int ret = 0;
8308
8309 #ifdef CONFIG_TDLS
8310
8311         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8312         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8313         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8314         u8 i, j, mac_addr[ETH_ALEN];
8315         struct sta_info *ptdls_sta = NULL;
8316
8317         DBG_8723A( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
8318
8319         for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
8320                 mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
8321         }
8322
8323         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
8324
8325         issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta, 0);
8326
8327 #endif //CONFIG_TDLS
8328
8329         return ret;
8330 }
8331
8332 static int rtw_tdls_setip(struct net_device *dev,
8333                                 struct iw_request_info *info,
8334                                 union iwreq_data *wrqu, char *extra)
8335 {
8336         int ret = 0;
8337
8338 #ifdef CONFIG_TDLS
8339 #ifdef CONFIG_WFD
8340
8341         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8342         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
8343         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
8344         u8 i=0, j=0, k=0, tag=0, ip[3] = { 0xff }, *ptr = extra;
8345
8346         printk( "[%s] %s %d\n", __func__, extra, wrqu->data.length - 1  );
8347
8348
8349         while( i < 4 )
8350         {
8351                 for( j=0; j < 4; j++)
8352                 {
8353                         if( *( extra + j + tag ) == '.' || *( extra + j + tag ) == '\0' )
8354                         {
8355                                 if( j == 1 )
8356                                         pwfd_info->ip_address[i]=convert_ip_addr( '0', '0', *(extra+(j-1)+tag));
8357                                 if( j == 2 )
8358                                         pwfd_info->ip_address[i]=convert_ip_addr( '0', *(extra+(j-2)+tag), *(extra+(j-1)+tag));
8359                                 if( j == 3 )
8360                                         pwfd_info->ip_address[i]=convert_ip_addr( *(extra+(j-3)+tag), *(extra+(j-2)+tag), *(extra+(j-1)+tag));
8361
8362                                 tag += j + 1;
8363                                 break;
8364                         }
8365                 }
8366                 i++;
8367         }
8368
8369         printk( "[%s] Set IP = %u.%u.%u.%u \n", __func__,
8370                 ptdlsinfo->wfd_info->ip_address[0], ptdlsinfo->wfd_info->ip_address[1],
8371                 ptdlsinfo->wfd_info->ip_address[2], ptdlsinfo->wfd_info->ip_address[3]
8372         );
8373
8374 #endif //CONFIG_WFD
8375 #endif //CONFIG_TDLS
8376
8377         return ret;
8378 }
8379
8380 static int rtw_tdls_getip(struct net_device *dev,
8381                                 struct iw_request_info *info,
8382                                 union iwreq_data *wrqu, char *extra)
8383 {
8384         int ret = 0;
8385
8386 #ifdef CONFIG_TDLS
8387 #ifdef CONFIG_WFD
8388
8389         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8390         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
8391         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
8392
8393         printk( "[%s]\n", __func__);
8394
8395         sprintf( extra, "\n\n%u.%u.%u.%u\n",
8396                 pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1],
8397                 pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]
8398                 );
8399
8400         printk( "[%s] IP=%u.%u.%u.%u\n", __func__,
8401                 pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1],
8402                 pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]
8403                 );
8404
8405         wrqu->data.length = strlen( extra );
8406
8407 #endif //CONFIG_WFD
8408 #endif //CONFIG_TDLS
8409
8410         return ret;
8411 }
8412
8413 static int rtw_tdls_getport(struct net_device *dev,
8414                                struct iw_request_info *info,
8415                                union iwreq_data *wrqu, char *extra)
8416 {
8417
8418         int ret = 0;
8419
8420 #ifdef CONFIG_TDLS
8421 #ifdef CONFIG_WFD
8422
8423         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8424         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
8425         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
8426
8427         printk( "[%s]\n", __func__);
8428
8429         sprintf( extra, "\n\n%d\n", pwfd_info->peer_rtsp_ctrlport );
8430         printk( "[%s] remote port = %d\n", __func__, pwfd_info->peer_rtsp_ctrlport );
8431
8432         wrqu->data.length = strlen( extra );
8433
8434 #endif //CONFIG_WFD
8435 #endif //CONFIG_TDLS
8436
8437         return ret;
8438
8439 }
8440
8441 //WFDTDLS, for sigma test
8442 static int rtw_tdls_dis_result(struct net_device *dev,
8443                                struct iw_request_info *info,
8444                                union iwreq_data *wrqu, char *extra)
8445 {
8446
8447         int ret = 0;
8448
8449 #ifdef CONFIG_TDLS
8450 #ifdef CONFIG_WFD
8451
8452         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8453         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
8454         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
8455
8456         printk( "[%s]\n", __func__);
8457
8458         if(ptdlsinfo->dev_discovered == 1 )
8459         {
8460                 sprintf( extra, "\n\nDis=1\n" );
8461                 ptdlsinfo->dev_discovered = 0;
8462         }
8463
8464         wrqu->data.length = strlen( extra );
8465
8466 #endif //CONFIG_WFD
8467 #endif //CONFIG_TDLS
8468
8469         return ret;
8470
8471 }
8472
8473 //WFDTDLS, for sigma test
8474 static int rtw_wfd_tdls_status(struct net_device *dev,
8475                                struct iw_request_info *info,
8476                                union iwreq_data *wrqu, char *extra)
8477 {
8478
8479         int ret = 0;
8480
8481 #ifdef CONFIG_TDLS
8482 #ifdef CONFIG_WFD
8483
8484         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8485         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
8486         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
8487
8488         printk( "[%s]\n", __func__);
8489
8490         if(ptdlsinfo->setup_state == TDLS_LINKED_STATE )
8491         {
8492                 sprintf( extra, "\n\nStatus=1\n" );
8493         }
8494         else
8495         {
8496                 sprintf( extra, "\n\nStatus=0\n" );
8497         }
8498
8499         wrqu->data.length = strlen( extra );
8500
8501 #endif //CONFIG_WFD
8502 #endif //CONFIG_TDLS
8503
8504         return ret;
8505
8506 }
8507
8508 static int rtw_tdls_ch_switch_off(struct net_device *dev,
8509                                 struct iw_request_info *info,
8510                                 union iwreq_data *wrqu, char *extra)
8511 {
8512         int ret = 0;
8513
8514 #ifdef CONFIG_TDLS
8515
8516         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8517         u8 i, j, mac_addr[ETH_ALEN];
8518         struct sta_info *ptdls_sta = NULL;
8519
8520         DBG_8723A( "[%s] %s %d\n", __func__, extra, wrqu->data.length -1  );
8521
8522         for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
8523                 mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
8524         }
8525
8526         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
8527
8528         ptdls_sta->tdls_sta_state |= TDLS_SW_OFF_STATE;
8529 /*
8530         if((ptdls_sta->tdls_sta_state & TDLS_AT_OFF_CH_STATE) && (ptdls_sta->tdls_sta_state & TDLS_PEER_AT_OFF_STATE)){
8531                 pmlmeinfo->tdls_candidate_ch= pmlmeext->cur_channel;
8532                 issue_tdls_ch_switch_req(padapter, mac_addr);
8533                 DBG_8723A("issue tdls ch switch req back to base channel\n");
8534         }
8535 */
8536
8537 #endif //CONFIG_TDLS
8538
8539         return ret;
8540 }
8541
8542 static int rtw_tdls(struct net_device *dev,
8543                                 struct iw_request_info *info,
8544                                 union iwreq_data *wrqu, char *extra)
8545 {
8546         int ret = 0;
8547
8548 #ifdef CONFIG_TDLS
8549         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
8550
8551         DBG_8723A( "[%s] extra = %s\n", __func__, extra );
8552         //      WFD Sigma will use the tdls enable command to let the driver know we want to test the tdls now!
8553         if (!memcmp(extra, "wfdenable=", 10))
8554         {
8555                 wrqu->data.length -=10;
8556                 rtw_wfd_tdls_enable( dev, info, wrqu, &extra[10] );
8557                 return ret;
8558         }
8559         else if (!memcmp(extra, "weaksec=", 8))
8560         {
8561                 wrqu->data.length -=8;
8562                 rtw_tdls_weaksec( dev, info, wrqu, &extra[8] );
8563                 return ret;
8564         }
8565         else if (!memcmp(extra, "tdlsenable=", 11))
8566         {
8567                 wrqu->data.length -=11;
8568                 rtw_tdls_enable( dev, info, wrqu, &extra[11] );
8569                 return ret;
8570         }
8571
8572         if( padapter->tdlsinfo.enable == 0 )
8573         {
8574                 printk("tdls haven't enabled\n");
8575                 return 0;
8576         }
8577
8578         if (!memcmp(extra, "setup=", 6))
8579         {
8580                 wrqu->data.length -=6;
8581                 rtw_tdls_setup( dev, info, wrqu, &extra[6] );
8582         }
8583         else if (!memcmp(extra, "tear=", 5))
8584         {
8585                 wrqu->data.length -= 5;
8586                 rtw_tdls_teardown( dev, info, wrqu, &extra[5] );
8587         }
8588         else if (!memcmp(extra, "dis=", 4))
8589         {
8590                 wrqu->data.length -= 4;
8591                 rtw_tdls_discovery( dev, info, wrqu, &extra[4] );
8592         }
8593         else if (!memcmp(extra, "sw=", 3))
8594         {
8595                 wrqu->data.length -= 3;
8596                 rtw_tdls_ch_switch( dev, info, wrqu, &extra[3] );
8597         }
8598         else if (!memcmp(extra, "swoff=", 6))
8599         {
8600                 wrqu->data.length -= 6;
8601                 rtw_tdls_ch_switch_off( dev, info, wrqu, &extra[6] );
8602         }
8603         else if (!memcmp(extra, "pson=", 5))
8604         {
8605                 wrqu->data.length -= 5;
8606                 rtw_tdls_pson( dev, info, wrqu, &extra[5] );
8607         }
8608         else if (!memcmp(extra, "psoff=", 6))
8609         {
8610                 wrqu->data.length -= 6;
8611                 rtw_tdls_psoff( dev, info, wrqu, &extra[6] );
8612         }
8613 #ifdef CONFIG_WFD
8614         else if (!memcmp(extra, "setip=", 6))
8615         {
8616                 wrqu->data.length -= 6;
8617                 rtw_tdls_setip( dev, info, wrqu, &extra[6] );
8618         }
8619         else if (!memcmp(extra, "tprobe=", 6))
8620         {
8621                 issue_tunneled_probe_req((struct rtw_adapter *)rtw_netdev_priv(dev));
8622         }
8623 #endif //CONFIG_WFD
8624
8625 #endif //CONFIG_TDLS
8626
8627         return ret;
8628 }
8629
8630
8631 static int rtw_tdls_get(struct net_device *dev,
8632                                 struct iw_request_info *info,
8633                                 union iwreq_data *wrqu, char *extra)
8634 {
8635         int ret = 0;
8636
8637 #ifdef CONFIG_WFD
8638
8639         DBG_8723A( "[%s] extra = %s\n", __func__, (char*) wrqu->data.pointer );
8640
8641         if (!memcmp(wrqu->data.pointer, "ip", 2))
8642         {
8643                 rtw_tdls_getip( dev, info, wrqu, extra );
8644         }
8645         if (!memcmp(wrqu->data.pointer, "port", 4))
8646         {
8647                 rtw_tdls_getport( dev, info, wrqu, extra );
8648         }
8649         //WFDTDLS, for sigma test
8650         if (!memcmp(wrqu->data.pointer, "dis", 3))
8651         {
8652                 rtw_tdls_dis_result( dev, info, wrqu, extra );
8653         }
8654         if (!memcmp(wrqu->data.pointer, "status", 6))
8655         {
8656                 rtw_wfd_tdls_status( dev, info, wrqu, extra );
8657         }
8658
8659 #endif //CONFIG_WFD
8660
8661         return ret;
8662 }
8663
8664
8665
8666
8667
8668 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
8669
8670 extern void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc);
8671 #define cal_txdesc_chksum rtl8723a_cal_txdesc_chksum
8672 extern void rtl8723a_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
8673 #define fill_default_txdesc rtl8723a_fill_default_txdesc
8674
8675 static s32 initLoopback(struct rtw_adapter *padapter)
8676 {
8677         PLOOPBACKDATA ploopback;
8678
8679         if (padapter->ploopback == NULL) {
8680                 ploopback = (PLOOPBACKDATA)kzalloc(sizeof(LOOPBACKDATA),
8681                                                    GFP_KERNEL);
8682                 if (ploopback == NULL)
8683                         return -ENOMEM;
8684
8685                 sema_init(&ploopback->sema, 0);
8686                 ploopback->bstop = _TRUE;
8687                 ploopback->cnt = 0;
8688                 ploopback->size = 300;
8689                 memset(ploopback->msg, 0, sizeof(ploopback->msg));
8690
8691                 padapter->ploopback = ploopback;
8692         }
8693         return 0;
8694 }
8695
8696 static void freeLoopback(struct rtw_adapter *padapter)
8697 {
8698         PLOOPBACKDATA ploopback;
8699
8700         ploopback = padapter->ploopback;
8701         if (ploopback) {
8702                 padapter->ploopback = NULL;
8703                 kfree((u8*)ploopback);
8704         }
8705 }
8706
8707 static s32 initpseudoadhoc(struct rtw_adapter *padapter)
8708 {
8709         NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
8710         s32 err;
8711
8712         networkType = Ndis802_11IBSS;
8713         err = rtw_set_802_11_infrastructure_mode(padapter, networkType);
8714         if (err == _FALSE) return _FAIL;
8715
8716         err = rtw_setopmode_cmd(padapter, networkType);
8717         if (err == _FAIL) return _FAIL;
8718
8719         return _SUCCESS;
8720 }
8721
8722 static s32 createpseudoadhoc(struct rtw_adapter *padapter)
8723 {
8724         NDIS_802_11_AUTHENTICATION_MODE authmode;
8725         struct mlme_priv *pmlmepriv;
8726         NDIS_802_11_SSID *passoc_ssid;
8727         WLAN_BSSID_EX *pdev_network;
8728         u8 *pibss;
8729         u8 ssid[] = "pseduo_ad-hoc";
8730         s32 err;
8731
8732         pmlmepriv = &padapter->mlmepriv;
8733
8734         authmode = Ndis802_11AuthModeOpen;
8735         err = rtw_set_802_11_authentication_mode(padapter, authmode);
8736         if (err == _FALSE) return _FAIL;
8737
8738         passoc_ssid = &pmlmepriv->assoc_ssid;
8739         memset(passoc_ssid, 0, sizeof(NDIS_802_11_SSID));
8740         passoc_ssid->SsidLength = sizeof(ssid) - 1;
8741         memcpy(passoc_ssid->Ssid, ssid, passoc_ssid->SsidLength);
8742
8743         pdev_network = &padapter->registrypriv.dev_network;
8744         pibss = padapter->registrypriv.dev_network.MacAddress;
8745         memcpy(&pdev_network->Ssid, passoc_ssid, sizeof(NDIS_802_11_SSID));
8746
8747         rtw_update_registrypriv_dev_network(padapter);
8748         rtw_generate_random_ibss(pibss);
8749
8750         spin_lock_bh(&pmlmepriv->lock);
8751         pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
8752         spin_unlock_bh(&pmlmepriv->lock);
8753
8754 {
8755         struct wlan_network *pcur_network;
8756         struct sta_info *psta;
8757
8758         //3  create a new psta
8759         pcur_network = &pmlmepriv->cur_network;
8760
8761         //clear psta in the cur_network, if any
8762         psta = rtw_get_stainfo(&padapter->stapriv, pcur_network->network.MacAddress);
8763         if (psta) rtw_free_stainfo(padapter, psta);
8764
8765         psta = rtw_alloc_stainfo(&padapter->stapriv, pibss);
8766         if (psta == NULL) return _FAIL;
8767
8768         //3  join psudo AdHoc
8769         pcur_network->join_res = 1;
8770         pcur_network->aid = psta->aid = 1;
8771         memcpy(&pcur_network->network, pdev_network, get_WLAN_BSSID_EX_sz(pdev_network));
8772
8773         // set msr to WIFI_FW_ADHOC_STATE
8774         {
8775                 u8 val8;
8776
8777                 val8 = rtw_read8(padapter, MSR);
8778                 val8 &= 0xFC; // clear NETYPE0
8779                 val8 |= WIFI_FW_ADHOC_STATE & 0x3;
8780                 rtw_write8(padapter, MSR, val8);
8781         }
8782 }
8783         return _SUCCESS;
8784 }
8785
8786 static struct xmit_frame* createloopbackpkt(struct rtw_adapter *padapter, u32 size)
8787 {
8788         struct xmit_priv *pxmitpriv;
8789         struct xmit_frame *pframe;
8790         struct xmit_buf *pxmitbuf;
8791         struct pkt_attrib *pattrib;
8792         struct tx_desc *desc;
8793         u8 *pkt_start, *pkt_end, *ptr;
8794         struct rtw_ieee80211_hdr *hdr;
8795         s32 bmcast;
8796
8797
8798         if ((TXDESC_SIZE + WLANHDR_OFFSET + size) > MAX_XMITBUF_SZ) return NULL;
8799
8800         pxmitpriv = &padapter->xmitpriv;
8801         pframe = NULL;
8802
8803         //2 1. allocate xmit frame
8804         pframe = rtw_alloc_xmitframe(pxmitpriv);
8805         if (pframe == NULL) return NULL;
8806         pframe->padapter = padapter;
8807
8808         //2 2. allocate xmit buffer
8809         spin_lock_bh(&pxmitpriv->lock);
8810         pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
8811         spin_unlock_bh(&pxmitpriv->lock);
8812         if (pxmitbuf == NULL) {
8813                 rtw_free_xmitframe(pxmitpriv, pframe);
8814                 return NULL;
8815         }
8816
8817         pframe->pxmitbuf = pxmitbuf;
8818         pframe->buf_addr = pxmitbuf->pbuf;
8819         pxmitbuf->priv_data = pframe;
8820
8821         //2 3. update_attrib()
8822         pattrib = &pframe->attrib;
8823
8824         // init xmitframe attribute
8825         memset(pattrib, 0, sizeof(struct pkt_attrib));
8826
8827         pattrib->ether_type = 0x8723;
8828         memcpy(pattrib->src, padapter->eeprompriv.mac_addr, ETH_ALEN);
8829         memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
8830         memset(pattrib->dst, 0xFF, ETH_ALEN);
8831         memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
8832 //      pattrib->pctrl = 0;
8833 //      pattrib->dhcp_pkt = 0;
8834 //      pattrib->pktlen = 0;
8835         pattrib->ack_policy = 0;
8836 //      pattrib->pkt_hdrlen = ETH_HLEN;
8837         pattrib->hdrlen = WLAN_HDR_A3_LEN;
8838         pattrib->subtype = WIFI_DATA;
8839         pattrib->priority = 0;
8840         pattrib->qsel = pattrib->priority;
8841 //      do_queue_select(padapter, pattrib);
8842         pattrib->nr_frags = 1;
8843         pattrib->encrypt = 0;
8844         pattrib->bswenc = _FALSE;
8845         pattrib->qos_en = _FALSE;
8846
8847         bmcast = is_multicast_ether_addr(pattrib->ra);
8848         if (bmcast) {
8849                 pattrib->mac_id = 1;
8850                 pattrib->psta = rtw_get_bcmc_stainfo(padapter);
8851         } else {
8852                 pattrib->mac_id = 0;
8853                 pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
8854         }
8855
8856         pattrib->pktlen = size;
8857         pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;
8858
8859         //2 4. fill TX descriptor
8860         desc = (struct tx_desc*)pframe->buf_addr;
8861         memset(desc, 0, TXDESC_SIZE);
8862
8863         fill_default_txdesc(pframe, (u8*)desc);
8864
8865         // Hw set sequence number
8866         ((PTXDESC)desc)->hwseq_en = 0; // HWSEQ_EN, 0:disable, 1:enable
8867 //      ((PTXDESC)desc)->hwseq_sel = 0; // HWSEQ_SEL
8868
8869         ((PTXDESC)desc)->disdatafb = 1;
8870
8871         // convert to little endian
8872         desc->txdw0 = cpu_to_le32(desc->txdw0);
8873         desc->txdw1 = cpu_to_le32(desc->txdw1);
8874         desc->txdw2 = cpu_to_le32(desc->txdw2);
8875         desc->txdw3 = cpu_to_le32(desc->txdw3);
8876         desc->txdw4 = cpu_to_le32(desc->txdw4);
8877         desc->txdw5 = cpu_to_le32(desc->txdw5);
8878         desc->txdw6 = cpu_to_le32(desc->txdw6);
8879         desc->txdw7 = cpu_to_le32(desc->txdw7);
8880
8881         cal_txdesc_chksum(desc);
8882
8883         //2 5. coalesce
8884         pkt_start = pframe->buf_addr + TXDESC_SIZE;
8885         pkt_end = pkt_start + pattrib->last_txcmdsz;
8886
8887         //3 5.1. make wlan header, make_wlanhdr()
8888         hdr = (struct rtw_ieee80211_hdr *)pkt_start;
8889         SetFrameSubType(&hdr->frame_ctl, pattrib->subtype);
8890         memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); // DA
8891         memcpy(hdr->addr2, pattrib->src, ETH_ALEN); // SA
8892         memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); // RA, BSSID
8893
8894         //3 5.2. make payload
8895         ptr = pkt_start + pattrib->hdrlen;
8896         get_random_bytes(ptr, pkt_end - ptr);
8897
8898         pxmitbuf->len = TXDESC_SIZE + pattrib->last_txcmdsz;
8899         pxmitbuf->ptail += pxmitbuf->len;
8900
8901         return pframe;
8902 }
8903
8904 static void freeloopbackpkt(struct rtw_adapter *padapter, struct xmit_frame *pframe)
8905 {
8906         struct xmit_priv *pxmitpriv;
8907         struct xmit_buf *pxmitbuf;
8908
8909
8910         pxmitpriv = &padapter->xmitpriv;
8911         pxmitbuf = pframe->pxmitbuf;
8912
8913         rtw_free_xmitframe(pxmitpriv, pframe);
8914         rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
8915 }
8916
8917 static void printdata(u8 *pbuf, u32 len)
8918 {
8919         u32 i, val;
8920
8921
8922         for (i = 0; (i+4) <= len; i+=4) {
8923                 printk("%08X", *(u32*)(pbuf + i));
8924                 if ((i+4) & 0x1F) printk(" ");
8925                 else printk("\n");
8926         }
8927
8928         if (i < len)
8929         {
8930 #ifdef __BIG_ENDIAN
8931                 for (; i < len, i++)
8932                         printk("%02X", pbuf+i);
8933 #else // __LITTLE_ENDIAN
8934                 u8 str[9];
8935                 u8 n;
8936                 val = 0;
8937                 n = len - i;
8938                 memcpy(&val, pbuf+i, n);
8939                 sprintf(str, "%08X", val);
8940                 n = (4 - n) * 2;
8941                 printk("%8s", str+n);
8942 #endif // __LITTLE_ENDIAN
8943         }
8944         printk("\n");
8945 }
8946
8947 static u8 pktcmp(struct rtw_adapter *padapter, u8 *txbuf, u32 txsz, u8 *rxbuf, u32 rxsz)
8948 {
8949         PHAL_DATA_TYPE phal;
8950         struct recv_stat *prxstat;
8951         struct recv_stat report;
8952         PRXREPORT prxreport;
8953         u32 drvinfosize;
8954         u32 rxpktsize;
8955         u8 fcssize;
8956         u8 ret = _FALSE;
8957
8958         prxstat = (struct recv_stat*)rxbuf;
8959         report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
8960         report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
8961         report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
8962         report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
8963         report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
8964         report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
8965
8966         prxreport = (PRXREPORT)&report;
8967         drvinfosize = prxreport->drvinfosize << 3;
8968         rxpktsize = prxreport->pktlen;
8969
8970         phal = GET_HAL_DATA(padapter);
8971         if (phal->ReceiveConfig & RCR_APPFCS)
8972                 fcssize = IEEE80211_FCS_LEN;
8973         else
8974                 fcssize = 0;
8975
8976         if ((txsz - TXDESC_SIZE) != (rxpktsize - fcssize)) {
8977                 DBG_8723A("%s: ERROR! size not match tx/rx=%d/%d !\n",
8978                         __func__, txsz - TXDESC_SIZE, rxpktsize - fcssize);
8979                 ret = _FALSE;
8980         } else {
8981                 if (!memcmp(txbuf + TXDESC_SIZE,
8982                             rxbuf + RXDESC_SIZE + drvinfosize,
8983                             txsz - TXDESC_SIZE)) {
8984                         ret = _TRUE;
8985                 } else {
8986                         ret = _FALSE;
8987                         DBG_8723A("%s: ERROR! pkt content mismatch!\n",
8988                                   __func__);
8989                 }
8990         }
8991
8992         if (ret == _FALSE)
8993         {
8994                 DBG_8723A("\n%s: TX PKT total=%d, desc=%d, content=%d\n",
8995                         __func__, txsz, TXDESC_SIZE, txsz - TXDESC_SIZE);
8996                 DBG_8723A("%s: TX DESC size=%d\n", __func__, TXDESC_SIZE);
8997                 printdata(txbuf, TXDESC_SIZE);
8998                 DBG_8723A("%s: TX content size=%d\n", __func__, txsz - TXDESC_SIZE);
8999                 printdata(txbuf + TXDESC_SIZE, txsz - TXDESC_SIZE);
9000
9001                 DBG_8723A("\n%s: RX PKT read=%d offset=%d(%d,%d) content=%d\n",
9002                         __func__, rxsz, RXDESC_SIZE + drvinfosize, RXDESC_SIZE, drvinfosize, rxpktsize);
9003                 if (rxpktsize != 0)
9004                 {
9005                         DBG_8723A("%s: RX DESC size=%d\n", __func__, RXDESC_SIZE);
9006                         printdata(rxbuf, RXDESC_SIZE);
9007                         DBG_8723A("%s: RX drvinfo size=%d\n", __func__, drvinfosize);
9008                         printdata(rxbuf + RXDESC_SIZE, drvinfosize);
9009                         DBG_8723A("%s: RX content size=%d\n", __func__, rxpktsize);
9010                         printdata(rxbuf + RXDESC_SIZE + drvinfosize, rxpktsize);
9011                 } else {
9012                         DBG_8723A("%s: RX data size=%d\n", __func__, rxsz);
9013                         printdata(rxbuf, rxsz);
9014                 }
9015         }
9016
9017         return ret;
9018 }
9019
9020 int lbk_thread(void *context)
9021 {
9022         s32 err;
9023         struct rtw_adapter *padapter;
9024         PLOOPBACKDATA ploopback;
9025         struct xmit_frame *pxmitframe;
9026         u32 cnt, ok, fail, headerlen;
9027         u32 pktsize;
9028         u32 ff_hwaddr;
9029
9030
9031         padapter = (struct rtw_adapter *)context;
9032         ploopback = padapter->ploopback;
9033         if (ploopback == NULL) return -1;
9034         cnt = 0;
9035         ok = 0;
9036         fail = 0;
9037
9038         daemonize("%s", "RTW_LBK_THREAD");
9039         allow_signal(SIGTERM);
9040
9041         do {
9042                 if (ploopback->size == 0) {
9043                         get_random_bytes(&pktsize, 4);
9044                         pktsize = (pktsize % 1535) + 1; // 1~1535
9045                 } else
9046                         pktsize = ploopback->size;
9047
9048                 pxmitframe = createloopbackpkt(padapter, pktsize);
9049                 if (pxmitframe == NULL) {
9050                         sprintf(ploopback->msg, "loopback FAIL! 3. create Packet FAIL!");
9051                         break;
9052                 }
9053
9054                 ploopback->txsize = TXDESC_SIZE + pxmitframe->attrib.last_txcmdsz;
9055                 memcpy(ploopback->txbuf, pxmitframe->buf_addr, ploopback->txsize);
9056                 ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
9057                 cnt++;
9058                 DBG_8723A("%s: write port cnt=%d size=%d\n", __func__, cnt, ploopback->txsize);
9059                 pxmitframe->pxmitbuf->pdata = ploopback->txbuf;
9060                 rtw_write_port(padapter, ff_hwaddr, ploopback->txsize, (u8 *)pxmitframe->pxmitbuf);
9061
9062                 // wait for rx pkt
9063                 down(&ploopback->sema)
9064
9065                 err = pktcmp(padapter, ploopback->txbuf, ploopback->txsize, ploopback->rxbuf, ploopback->rxsize);
9066                 if (err == _TRUE)
9067                         ok++;
9068                 else
9069                         fail++;
9070
9071                 ploopback->txsize = 0;
9072                 memset(ploopback->txbuf, 0, 0x8000);
9073                 ploopback->rxsize = 0;
9074                 memset(ploopback->rxbuf, 0, 0x8000);
9075
9076                 freeloopbackpkt(padapter, pxmitframe);
9077                 pxmitframe = NULL;
9078
9079                 if (signal_pending(current)) {
9080                         flush_signals(current);
9081                 }
9082
9083                 if ((ploopback->bstop == _TRUE) ||
9084                         ((ploopback->cnt != 0) && (ploopback->cnt == cnt)))
9085                 {
9086                         u32 ok_rate, fail_rate, all;
9087                         all = cnt;
9088                         ok_rate = (ok*100)/all;
9089                         fail_rate = (fail*100)/all;
9090                         sprintf(ploopback->msg,\
9091                                         "loopback result: ok=%d%%(%d/%d),error=%d%%(%d/%d)",\
9092                                         ok_rate, ok, all, fail_rate, fail, all);
9093                         break;
9094                 }
9095         } while (1);
9096
9097         ploopback->bstop = _TRUE;
9098
9099         thread_exit();
9100 }
9101
9102 static void loopbackTest(struct rtw_adapter *padapter, u32 cnt, u32 size, u8* pmsg)
9103 {
9104         PLOOPBACKDATA ploopback;
9105         u32 len;
9106         s32 err;
9107
9108
9109         ploopback = padapter->ploopback;
9110
9111         if (ploopback)
9112         {
9113                 if (ploopback->bstop == _FALSE) {
9114                         ploopback->bstop = _TRUE;
9115                         up(&ploopback->sema);
9116                 }
9117                 len = 0;
9118                 do {
9119                         len = strlen(ploopback->msg);
9120                         if (len) break;
9121                         msleep(1);
9122                 } while (1);
9123                 memcpy(pmsg, ploopback->msg, len+1);
9124                 freeLoopback(padapter);
9125
9126                 return;
9127         }
9128
9129         // disable dynamic algorithm
9130         {
9131         u32 DMFlag = DYNAMIC_FUNC_DISABLE;
9132         rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8*)&DMFlag);
9133         }
9134
9135         // create pseudo ad-hoc connection
9136         err = initpseudoadhoc(padapter);
9137         if (err == _FAIL) {
9138                 sprintf(pmsg, "loopback FAIL! 1.1 init ad-hoc FAIL!");
9139                 return;
9140         }
9141
9142         err = createpseudoadhoc(padapter);
9143         if (err == _FAIL) {
9144                 sprintf(pmsg, "loopback FAIL! 1.2 create ad-hoc master FAIL!");
9145                 return;
9146         }
9147
9148         err = initLoopback(padapter);
9149         if (err) {
9150                 sprintf(pmsg, "loopback FAIL! 2. init FAIL! error code=%d", err);
9151                 return;
9152         }
9153
9154         ploopback = padapter->ploopback;
9155
9156         ploopback->bstop = _FALSE;
9157         ploopback->cnt = cnt;
9158         ploopback->size = size;
9159         ploopback->lbkthread = kthread_run(lbk_thread, padapter, "RTW_LBK_THREAD");
9160         if (IS_ERR(padapter->lbkthread))
9161         {
9162                 freeLoopback(padapter);
9163                 sprintf(pmsg, "loopback start FAIL! cnt=%d", cnt);
9164                 return;
9165         }
9166
9167         sprintf(pmsg, "loopback start! cnt=%d", cnt);
9168 }
9169 #endif // CONFIG_MAC_LOOPBACK_DRIVER
9170
9171 static int rtw_test(
9172         struct net_device *dev,
9173         struct iw_request_info *info,
9174         union iwreq_data *wrqu, char *extra)
9175 {
9176         u32 len;
9177         u8 *pbuf, *pch;
9178         char *ptmp;
9179         u8 *delim = ",";
9180         int ret = 0;
9181         struct rtw_adapter *padapter = rtw_netdev_priv(dev);
9182
9183
9184         DBG_8723A("+%s\n", __func__);
9185         len = wrqu->data.length;
9186
9187         pbuf = (u8*)kzalloc(len, GFP_KERNEL);
9188         if (pbuf == NULL) {
9189                 DBG_8723A("%s: no memory!\n", __func__);
9190                 return -ENOMEM;
9191         }
9192
9193         if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
9194                 DBG_8723A("%s: copy from user fail!\n", __func__);
9195                 ret = -EFAULT;
9196                 goto out;
9197         }
9198         DBG_8723A("%s: string=\"%s\"\n", __func__, pbuf);
9199
9200         ptmp = (char*)pbuf;
9201         pch = strsep(&ptmp, delim);
9202         if ((pch == NULL) || (strlen(pch) == 0)) {
9203                 DBG_8723A("%s: parameter error(level 1)!\n", __func__);
9204                 ret = -EFAULT;
9205                 goto out;
9206         }
9207
9208 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
9209         if (strcmp(pch, "loopback") == 0)
9210         {
9211                 s32 cnt = 0;
9212                 u32 size = 64;
9213
9214                 pch = strsep(&ptmp, delim);
9215                 if ((pch == NULL) || (strlen(pch) == 0)) {
9216                         DBG_8723A("%s: parameter error(level 2)!\n", __func__);
9217                         ret = -EFAULT;
9218                         goto out;
9219                 }
9220
9221                 sscanf(pch, "%d", &cnt);
9222                 DBG_8723A("%s: loopback cnt=%d\n", __func__, cnt);
9223
9224                 pch = strsep(&ptmp, delim);
9225                 if ((pch == NULL) || (strlen(pch) == 0)) {
9226                         DBG_8723A("%s: parameter error(level 2)!\n", __func__);
9227                         ret = -EFAULT;
9228                         goto out;
9229                 }
9230
9231                 sscanf(pch, "%d", &size);
9232                 DBG_8723A("%s: loopback size=%d\n", __func__, size);
9233
9234                 loopbackTest(padapter, cnt, size, extra);
9235                 wrqu->data.length = strlen(extra) + 1;
9236
9237                 kfree(pbuf);
9238                 return ret;
9239         }
9240 #endif
9241
9242 #ifdef CONFIG_BT_COEXIST
9243 #define GET_BT_INFO(padapter)   (&GET_HAL_DATA(padapter)->BtInfo)
9244
9245         if (strcmp(pch, "btdbg") == 0)
9246         {
9247                 DBG_8723A("===== BT debug information Start =====\n");
9248                 DBG_8723A("WIFI status=\n");
9249                 DBG_8723A("BT status=\n");
9250                 DBG_8723A("BT profile=\n");
9251                 DBG_8723A("WIFI RSSI=%d\n", GET_HAL_DATA(padapter)->dmpriv.UndecoratedSmoothedPWDB);
9252                 DBG_8723A("BT RSSI=\n");
9253                 DBG_8723A("coex mechanism=\n");
9254                 DBG_8723A("BT counter TX/RX=/\n");
9255                 DBG_8723A("0x880=0x%08x\n", rtw_read32(padapter, 0x880));
9256                 DBG_8723A("0x6c0=0x%08x\n", rtw_read32(padapter, 0x6c0));
9257                 DBG_8723A("0x6c4=0x%08x\n", rtw_read32(padapter, 0x6c4));
9258                 DBG_8723A("0x6c8=0x%08x\n", rtw_read32(padapter, 0x6c8));
9259                 DBG_8723A("0x6cc=0x%08x\n", rtw_read32(padapter, 0x6cc));
9260                 DBG_8723A("0x778=0x%08x\n", rtw_read32(padapter, 0x778));
9261                 DBG_8723A("0xc50=0x%08x\n", rtw_read32(padapter, 0xc50));
9262                 BT_DisplayBtCoexInfo(padapter);
9263                 DBG_8723A("===== BT debug information End =====\n");
9264         }
9265
9266         if (strcmp(pch, "bton") == 0)
9267         {
9268                 PBT30Info               pBTInfo = GET_BT_INFO(padapter);
9269                 PBT_MGNT                pBtMgnt = &pBTInfo->BtMgnt;
9270
9271                 pBtMgnt->ExtConfig.bManualControl = _FALSE;
9272         }
9273
9274         if (strcmp(pch, "btoff") == 0)
9275         {
9276                 PBT30Info               pBTInfo = GET_BT_INFO(padapter);
9277                 PBT_MGNT                pBtMgnt = &pBTInfo->BtMgnt;
9278
9279                 pBtMgnt->ExtConfig.bManualControl = _TRUE;
9280         }
9281 #endif // CONFIG_BT_COEXIST
9282
9283         if (strcmp(pch, "h2c") == 0)
9284         {
9285                 u8 param[6];
9286                 u8 count = 0;
9287                 u32 tmp;
9288                 u8 i;
9289                 u32 pos;
9290                 s32 ret;
9291
9292
9293                 do {
9294                         pch = strsep(&ptmp, delim);
9295                         if ((pch == NULL) || (strlen(pch) == 0))
9296                                 break;
9297
9298                         sscanf(pch, "%x", &tmp);
9299                         param[count++] = (u8)tmp;
9300                 } while (count < 6);
9301
9302                 if (count == 0) {
9303                         kfree(pbuf);
9304                         DBG_8723A("%s: parameter error(level 2)!\n", __func__);
9305                         return -EFAULT;
9306                 }
9307
9308                 ret = FillH2CCmd(padapter, param[0], count-1, &param[1]);
9309
9310                 pos = sprintf(extra, "H2C ID=%x content=", param[0]);
9311                 for (i=0; i<count; i++) {
9312                         pos += sprintf(extra+pos, "%x,", param[i]);
9313                 }
9314                 extra[pos] = 0;
9315                 pos--;
9316                 pos += sprintf(extra+pos, " %s", ret==_FAIL?"FAIL":"OK");
9317
9318                 wrqu->data.length = strlen(extra) + 1;
9319         }
9320 out:
9321         kfree(pbuf);
9322         return 0;
9323 }
9324
9325 static iw_handler rtw_handlers[] =
9326 {
9327         NULL,                                   /* SIOCSIWCOMMIT */
9328         rtw_wx_get_name,                /* SIOCGIWNAME */
9329         dummy,                                  /* SIOCSIWNWID */
9330         dummy,                                  /* SIOCGIWNWID */
9331         rtw_wx_set_freq,                /* SIOCSIWFREQ */
9332         rtw_wx_get_freq,                /* SIOCGIWFREQ */
9333         rtw_wx_set_mode,                /* SIOCSIWMODE */
9334         rtw_wx_get_mode,                /* SIOCGIWMODE */
9335         dummy,                                  /* SIOCSIWSENS */
9336         rtw_wx_get_sens,                /* SIOCGIWSENS */
9337         NULL,                                   /* SIOCSIWRANGE */
9338         rtw_wx_get_range,               /* SIOCGIWRANGE */
9339         rtw_wx_set_priv,                /* SIOCSIWPRIV */
9340         NULL,                                   /* SIOCGIWPRIV */
9341         NULL,                                   /* SIOCSIWSTATS */
9342         NULL,                                   /* SIOCGIWSTATS */
9343         dummy,                                  /* SIOCSIWSPY */
9344         dummy,                                  /* SIOCGIWSPY */
9345         NULL,                                   /* SIOCGIWTHRSPY */
9346         NULL,                                   /* SIOCWIWTHRSPY */
9347         rtw_wx_set_wap,         /* SIOCSIWAP */
9348         rtw_wx_get_wap,         /* SIOCGIWAP */
9349         rtw_wx_set_mlme,                /* request MLME operation; uses struct iw_mlme */
9350         dummy,                                  /* SIOCGIWAPLIST -- depricated */
9351         rtw_wx_set_scan,                /* SIOCSIWSCAN */
9352         rtw_wx_get_scan,                /* SIOCGIWSCAN */
9353         rtw_wx_set_essid,               /* SIOCSIWESSID */
9354         rtw_wx_get_essid,               /* SIOCGIWESSID */
9355         dummy,                                  /* SIOCSIWNICKN */
9356         rtw_wx_get_nick,                /* SIOCGIWNICKN */
9357         NULL,                                   /* -- hole -- */
9358         NULL,                                   /* -- hole -- */
9359         rtw_wx_set_rate,                /* SIOCSIWRATE */
9360         rtw_wx_get_rate,                /* SIOCGIWRATE */
9361         rtw_wx_set_rts,                 /* SIOCSIWRTS */
9362         rtw_wx_get_rts,                 /* SIOCGIWRTS */
9363         rtw_wx_set_frag,                /* SIOCSIWFRAG */
9364         rtw_wx_get_frag,                /* SIOCGIWFRAG */
9365         dummy,                                  /* SIOCSIWTXPOW */
9366         dummy,                                  /* SIOCGIWTXPOW */
9367         dummy,                                  /* SIOCSIWRETRY */
9368         rtw_wx_get_retry,               /* SIOCGIWRETRY */
9369         rtw_wx_set_enc,                 /* SIOCSIWENCODE */
9370         rtw_wx_get_enc,                 /* SIOCGIWENCODE */
9371         dummy,                                  /* SIOCSIWPOWER */
9372         rtw_wx_get_power,               /* SIOCGIWPOWER */
9373         NULL,                                   /*---hole---*/
9374         NULL,                                   /*---hole---*/
9375         rtw_wx_set_gen_ie,              /* SIOCSIWGENIE */
9376         NULL,                                   /* SIOCGWGENIE */
9377         rtw_wx_set_auth,                /* SIOCSIWAUTH */
9378         NULL,                                   /* SIOCGIWAUTH */
9379         rtw_wx_set_enc_ext,             /* SIOCSIWENCODEEXT */
9380         NULL,                                   /* SIOCGIWENCODEEXT */
9381         rtw_wx_set_pmkid,               /* SIOCSIWPMKSA */
9382         NULL,                                   /*---hole---*/
9383 };
9384
9385
9386 static const struct iw_priv_args rtw_private_args[] = {
9387         {
9388                 SIOCIWFIRSTPRIV + 0x0,
9389                 IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
9390         },
9391         {
9392                 SIOCIWFIRSTPRIV + 0x1,
9393                 IW_PRIV_TYPE_CHAR | 0x7FF,
9394                 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
9395         },
9396         {
9397                 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
9398         },
9399         {
9400                 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
9401         },
9402         {
9403                 SIOCIWFIRSTPRIV + 0x4,
9404                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
9405         },
9406         {
9407                 SIOCIWFIRSTPRIV + 0x5,
9408                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
9409         },
9410         {
9411                 SIOCIWFIRSTPRIV + 0x6,
9412                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
9413         },
9414 //for PLATFORM_MT53XX
9415         {
9416                 SIOCIWFIRSTPRIV + 0x7,
9417                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
9418         },
9419         {
9420                 SIOCIWFIRSTPRIV + 0x8,
9421                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
9422         },
9423         {
9424                 SIOCIWFIRSTPRIV + 0x9,
9425                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
9426         },
9427
9428 //for RTK_DMP_PLATFORM
9429         {
9430                 SIOCIWFIRSTPRIV + 0xA,
9431                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
9432         },
9433
9434         {
9435                 SIOCIWFIRSTPRIV + 0xB,
9436                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
9437         },
9438         {
9439                 SIOCIWFIRSTPRIV + 0xC,
9440                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
9441         },
9442         {
9443                 SIOCIWFIRSTPRIV + 0xD,
9444                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
9445         },
9446         {
9447                 SIOCIWFIRSTPRIV + 0x10,
9448                 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "p2p_set"
9449         },
9450         {
9451                 SIOCIWFIRSTPRIV + 0x11,
9452                 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN , "p2p_get"
9453         },
9454         {
9455                 SIOCIWFIRSTPRIV + 0x12, 0, 0, "NULL"
9456         },
9457         {
9458                 SIOCIWFIRSTPRIV + 0x13,
9459                 IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64 , "p2p_get2"
9460         },
9461         {
9462                 SIOCIWFIRSTPRIV + 0x14,
9463                 IW_PRIV_TYPE_CHAR  | 64, 0, "tdls"
9464         },
9465         {
9466                 SIOCIWFIRSTPRIV + 0x15,
9467                 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN , "tdls_get"
9468         },
9469         {
9470                 SIOCIWFIRSTPRIV + 0x16,
9471                 IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
9472         },
9473
9474         {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ , 0 , "rereg_nd_name"},
9475
9476         {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
9477         {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
9478         {
9479                 SIOCIWFIRSTPRIV + 0x1D,
9480                 IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
9481         },
9482 };
9483
9484 static iw_handler rtw_private_handler[] =
9485 {
9486         rtw_wx_write32,                                 //0x00
9487         rtw_wx_read32,                                  //0x01
9488         rtw_drvext_hdl,                                 //0x02
9489         NULL,                                           //0x03
9490
9491 // for MM DTV platform
9492         rtw_get_ap_info,                                        //0x04
9493
9494         rtw_set_pid,                                            //0x05
9495         rtw_wps_start,                                  //0x06
9496
9497 // for PLATFORM_MT53XX
9498         rtw_wx_get_sensitivity,                 //0x07
9499         rtw_wx_set_mtk_wps_probe_ie,    //0x08
9500         rtw_wx_set_mtk_wps_ie,                  //0x09
9501
9502 // for RTK_DMP_PLATFORM
9503 // Set Channel depend on the country code
9504         rtw_wx_set_channel_plan,                //0x0A
9505
9506         rtw_dbg_port,                                   //0x0B
9507         rtw_wx_write_rf,                                        //0x0C
9508         rtw_wx_read_rf,                                 //0x0D
9509
9510         rtw_wx_priv_null,                               //0x0E
9511         rtw_wx_priv_null,                               //0x0F
9512
9513         rtw_p2p_set,                                    //0x10
9514         rtw_p2p_get,                                    //0x11
9515         NULL,                                                   //0x12
9516         rtw_p2p_get2,                                   //0x13
9517
9518         rtw_tdls,                                               //0x14
9519         rtw_tdls_get,                                   //0x15
9520
9521         rtw_pm_set,                                             //0x16
9522         rtw_wx_priv_null,                               //0x17
9523         rtw_rereg_nd_name,                              //0x18
9524         rtw_wx_priv_null,                               //0x19
9525
9526         NULL /*rtw_mp_efuse_set*/,                      //0x1A
9527         NULL /*rtw_mp_efuse_get*/,                      //0x1B
9528         NULL,                                                   // 0x1C is reserved for hostapd
9529         rtw_test,                                               // 0x1D
9530 };
9531
9532 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
9533 {
9534         struct rtw_adapter *padapter = (struct rtw_adapter *)rtw_netdev_priv(dev);
9535         struct iw_statistics *piwstats = &padapter->iwstats;
9536         int tmp_level = 0;
9537         int tmp_qual = 0;
9538         int tmp_noise = 0;
9539
9540         if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != _TRUE)
9541         {
9542                 piwstats->qual.qual = 0;
9543                 piwstats->qual.level = 0;
9544                 piwstats->qual.noise = 0;
9545                 //DBG_8723A("No link  level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
9546         }
9547         else{
9548                 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
9549                 tmp_level = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);
9550                 #else
9551                 tmp_level = padapter->recvpriv.signal_strength;
9552                 #ifdef CONFIG_BT_COEXIST
9553                 {
9554                         u8 signal = (u8)tmp_level;
9555                         BT_SignalCompensation(padapter, &signal, NULL);
9556                         tmp_level= signal;
9557                 }
9558                 #endif // CONFIG_BT_COEXIST
9559                 #endif
9560
9561                 tmp_qual = padapter->recvpriv.signal_qual;
9562                 tmp_noise =padapter->recvpriv.noise;
9563                 //DBG_8723A("level:%d, qual:%d, noise:%d, rssi (%d)\n", tmp_level, tmp_qual, tmp_noise,padapter->recvpriv.rssi);
9564
9565                 piwstats->qual.level = tmp_level;
9566                 piwstats->qual.qual = tmp_qual;
9567                 piwstats->qual.noise = tmp_noise;
9568         }
9569         piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;//|IW_QUAL_DBM;
9570
9571         #ifdef CONFIG_SIGNAL_DISPLAY_DBM
9572         piwstats->qual.updated = piwstats->qual.updated | IW_QUAL_DBM;
9573         #endif
9574
9575         return &padapter->iwstats;
9576 }
9577
9578 #ifdef CONFIG_WIRELESS_EXT
9579 struct iw_handler_def rtw_handlers_def =
9580 {
9581         .standard = rtw_handlers,
9582         .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
9583 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) || defined(CONFIG_WEXT_PRIV)
9584         .private = rtw_private_handler,
9585         .private_args = (struct iw_priv_args *)rtw_private_args,
9586         .num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
9587         .num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
9588 #endif
9589         .get_wireless_stats = rtw_get_wireless_stats,
9590 };
9591 #endif
9592
9593 // copy from net/wireless/wext.c start
9594 /* ---------------------------------------------------------------- */
9595 /*
9596  * Calculate size of private arguments
9597  */
9598 static const char iw_priv_type_size[] = {
9599         0,                              /* IW_PRIV_TYPE_NONE */
9600         1,                              /* IW_PRIV_TYPE_BYTE */
9601         1,                              /* IW_PRIV_TYPE_CHAR */
9602         0,                              /* Not defined */
9603         sizeof(__u32),                  /* IW_PRIV_TYPE_INT */
9604         sizeof(struct iw_freq),         /* IW_PRIV_TYPE_FLOAT */
9605         sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
9606         0,                              /* Not defined */
9607 };
9608
9609 static int get_priv_size(__u16 args)
9610 {
9611         int num = args & IW_PRIV_SIZE_MASK;
9612         int type = (args & IW_PRIV_TYPE_MASK) >> 12;
9613
9614         return num * iw_priv_type_size[type];
9615 }
9616 // copy from net/wireless/wext.c end
9617
9618 static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
9619 {
9620         int err = 0;
9621         u8 *input = NULL;
9622         u32 input_len = 0;
9623         const char delim[] = " ";
9624         u8 *output = NULL;
9625         u32 output_len = 0;
9626         u32 count = 0;
9627         u8 *buffer= NULL;
9628         u32 buffer_len = 0;
9629         char *ptr = NULL;
9630         u8 cmdname[17] = {0}; // IFNAMSIZ+1
9631         u32 cmdlen;
9632         s32 len;
9633         u8 *extra = NULL;
9634         u32 extra_size = 0;
9635
9636         s32 k;
9637         const iw_handler *priv;         /* Private ioctl */
9638         const struct iw_priv_args *priv_args;   /* Private ioctl description */
9639         u32 num_priv;                           /* Number of ioctl */
9640         u32 num_priv_args;                      /* Number of descriptions */
9641         iw_handler handler;
9642         int temp;
9643         int subcmd = 0;                         /* sub-ioctl index */
9644         int offset = 0;                         /* Space for sub-ioctl index */
9645
9646         union iwreq_data wdata;
9647
9648
9649         memcpy(&wdata, wrq_data, sizeof(wdata));
9650
9651         input_len = wdata.data.length;
9652         input = kzalloc(input_len, GFP_KERNEL);
9653         if (NULL == input)
9654                 return -ENOMEM;
9655         if (copy_from_user(input, wdata.data.pointer, input_len)) {
9656                 err = -EFAULT;
9657                 goto exit;
9658         }
9659         ptr = input;
9660         len = input_len;
9661
9662         sscanf(ptr, "%16s", cmdname);
9663         cmdlen = strlen(cmdname);
9664         DBG_8723A("%s: cmd=%s\n", __func__, cmdname);
9665
9666         // skip command string
9667         if (cmdlen > 0)
9668                 cmdlen += 1; // skip one space
9669         ptr += cmdlen;
9670         len -= cmdlen;
9671         DBG_8723A("%s: parameters=%s\n", __func__, ptr);
9672
9673         priv = rtw_private_handler;
9674         priv_args = rtw_private_args;
9675         num_priv = sizeof(rtw_private_handler) / sizeof(iw_handler);
9676         num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args);
9677
9678         if (num_priv_args == 0) {
9679                 err = -EOPNOTSUPP;
9680                 goto exit;
9681         }
9682
9683         /* Search the correct ioctl */
9684         k = -1;
9685         while((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname));
9686
9687         /* If not found... */
9688         if (k == num_priv_args) {
9689                 err = -EOPNOTSUPP;
9690                 goto exit;
9691         }
9692
9693         /* Watch out for sub-ioctls ! */
9694         if (priv_args[k].cmd < SIOCDEVPRIVATE)
9695         {
9696                 int j = -1;
9697
9698                 /* Find the matching *real* ioctl */
9699                 while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
9700                         (priv_args[j].set_args != priv_args[k].set_args) ||
9701                         (priv_args[j].get_args != priv_args[k].get_args)));
9702
9703                 /* If not found... */
9704                 if (j == num_priv_args) {
9705                         err = -EINVAL;
9706                         goto exit;
9707                 }
9708
9709                 /* Save sub-ioctl number */
9710                 subcmd = priv_args[k].cmd;
9711                 /* Reserve one int (simplify alignment issues) */
9712                 offset = sizeof(__u32);
9713                 /* Use real ioctl definition from now on */
9714                 k = j;
9715         }
9716
9717         buffer = kzalloc(4096, GFP_KERNEL);
9718         if (NULL == buffer) {
9719                 err = -ENOMEM;
9720                 goto exit;
9721         }
9722
9723         /* If we have to set some data */
9724         if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
9725                 (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
9726         {
9727                 u8 *str;
9728
9729                 switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK)
9730                 {
9731                         case IW_PRIV_TYPE_BYTE:
9732                                 /* Fetch args */
9733                                 count = 0;
9734                                 do {
9735                                         str = strsep(&ptr, delim);
9736                                         if (NULL == str) break;
9737                                         sscanf(str, "%i", &temp);
9738                                         buffer[count++] = (u8)temp;
9739                                 } while (1);
9740                                 buffer_len = count;
9741
9742                                 /* Number of args to fetch */
9743                                 wdata.data.length = count;
9744                                 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
9745                                         wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
9746
9747                                 break;
9748
9749                         case IW_PRIV_TYPE_INT:
9750                                 /* Fetch args */
9751                                 count = 0;
9752                                 do {
9753                                         str = strsep(&ptr, delim);
9754                                         if (NULL == str) break;
9755                                         sscanf(str, "%i", &temp);
9756                                         ((s32*)buffer)[count++] = (s32)temp;
9757                                 } while (1);
9758                                 buffer_len = count * sizeof(s32);
9759
9760                                 /* Number of args to fetch */
9761                                 wdata.data.length = count;
9762                                 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
9763                                         wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
9764
9765                                 break;
9766
9767                         case IW_PRIV_TYPE_CHAR:
9768                                 if (len > 0)
9769                                 {
9770                                         /* Size of the string to fetch */
9771                                         wdata.data.length = len;
9772                                         if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
9773                                                 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
9774
9775                                         /* Fetch string */
9776                                         memcpy(buffer, ptr, wdata.data.length);
9777                                 }
9778                                 else
9779                                 {
9780                                         wdata.data.length = 1;
9781                                         buffer[0] = '\0';
9782                                 }
9783                                 buffer_len = wdata.data.length;
9784                                 break;
9785
9786                         default:
9787                                 DBG_8723A("%s: Not yet implemented...\n", __func__);
9788                                 err = -1;
9789                                 goto exit;
9790                 }
9791
9792                 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
9793                         (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK)))
9794                 {
9795                         DBG_8723A("%s: The command %s needs exactly %d argument(s)...\n",
9796                                         __func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
9797                         err = -EINVAL;
9798                         goto exit;
9799                 }
9800         }   /* if args to set */
9801         else
9802         {
9803                 wdata.data.length = 0L;
9804         }
9805
9806         /* Those two tests are important. They define how the driver
9807         * will have to handle the data */
9808         if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
9809                 ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ))
9810         {
9811                 /* First case : all SET args fit within wrq */
9812                 if (offset)
9813                         wdata.mode = subcmd;
9814                 memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
9815         }
9816         else
9817         {
9818                 if ((priv_args[k].set_args == 0) &&
9819                         (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
9820                         (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
9821                 {
9822                         /* Second case : no SET args, GET args fit within wrq */
9823                         if (offset)
9824                                 wdata.mode = subcmd;
9825                 }
9826                 else
9827                 {
9828                         /* Third case : args won't fit in wrq, or variable number of args */
9829                         if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
9830                                 err = -EFAULT;
9831                                 goto exit;
9832                         }
9833                         wdata.data.flags = subcmd;
9834                 }
9835         }
9836
9837         kfree(input);
9838         input = NULL;
9839
9840         extra_size = 0;
9841         if (IW_IS_SET(priv_args[k].cmd))
9842         {
9843                 /* Size of set arguments */
9844                 extra_size = get_priv_size(priv_args[k].set_args);
9845
9846                 /* Does it fits in iwr ? */
9847                 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
9848                         ((extra_size + offset) <= IFNAMSIZ))
9849                         extra_size = 0;
9850         } else {
9851                 /* Size of get arguments */
9852                 extra_size = get_priv_size(priv_args[k].get_args);
9853
9854                 /* Does it fits in iwr ? */
9855                 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
9856                         (extra_size <= IFNAMSIZ))
9857                         extra_size = 0;
9858         }
9859
9860         if (extra_size == 0) {
9861                 extra = (u8*)&wdata;
9862                 kfree(buffer);
9863                 buffer = NULL;
9864         } else
9865                 extra = buffer;
9866
9867         handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
9868         err = handler(dev, NULL, &wdata, extra);
9869
9870         /* If we have to get some data */
9871         if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
9872                 (priv_args[k].get_args & IW_PRIV_SIZE_MASK))
9873         {
9874                 int j;
9875                 int n = 0;      /* number of args */
9876                 u8 str[20] = {0};
9877
9878                 /* Check where is the returned data */
9879                 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
9880                         (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
9881                         n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
9882                 else
9883                         n = wdata.data.length;
9884
9885                 output = kmalloc(4096, GFP_KERNEL);
9886                 if (NULL == output) {
9887                         err =  -ENOMEM;
9888                         goto exit;
9889                 }
9890
9891                 switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK)
9892                 {
9893                         case IW_PRIV_TYPE_BYTE:
9894                                 /* Display args */
9895                                 for (j = 0; j < n; j++)
9896                                 {
9897                                         sprintf(str, "%d  ", extra[j]);
9898                                         len = strlen(str);
9899                                         output_len = strlen(output);
9900                                         if ((output_len + len + 1) > 4096) {
9901                                                 err = -E2BIG;
9902                                                 goto exit;
9903                                         }
9904                                         memcpy(output+output_len, str, len);
9905                                 }
9906                                 break;
9907
9908                         case IW_PRIV_TYPE_INT:
9909                                 /* Display args */
9910                                 for (j = 0; j < n; j++)
9911                                 {
9912                                         sprintf(str, "%d  ", ((__s32*)extra)[j]);
9913                                         len = strlen(str);
9914                                         output_len = strlen(output);
9915                                         if ((output_len + len + 1) > 4096) {
9916                                                 err = -E2BIG;
9917                                                 goto exit;
9918                                         }
9919                                         memcpy(output+output_len, str, len);
9920                                 }
9921                                 break;
9922
9923                         case IW_PRIV_TYPE_CHAR:
9924                                 /* Display args */
9925                                 memcpy(output, extra, n);
9926                                 break;
9927
9928                         default:
9929                                 DBG_8723A("%s: Not yet implemented...\n", __func__);
9930                                 err = -1;
9931                                 goto exit;
9932                 }
9933
9934                 output_len = strlen(output) + 1;
9935                 wrq_data->data.length = output_len;
9936                 if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
9937                         err = -EFAULT;
9938                         goto exit;
9939                 }
9940         }   /* if args to set */
9941         else
9942         {
9943                 wrq_data->data.length = 0;
9944         }
9945
9946 exit:
9947         if (input)
9948                 kfree(input);
9949         if (buffer)
9950                 kfree(buffer);
9951         if (output)
9952                 kfree(output);
9953
9954         return err;
9955 }
9956
9957 #include <rtw_android.h>
9958 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
9959 {
9960         struct iwreq *wrq = (struct iwreq *)rq;
9961         int ret=0;
9962
9963         switch (cmd)
9964         {
9965                 case RTL_IOCTL_WPA_SUPPLICANT:
9966                         ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
9967                         break;
9968 #ifdef CONFIG_AP_MODE
9969                 case RTL_IOCTL_HOSTAPD:
9970                         ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
9971                         break;
9972 #ifdef CONFIG_NO_WIRELESS_HANDLERS
9973                 case SIOCSIWMODE:
9974                         ret = rtw_wx_set_mode(dev, NULL, &wrq->u, NULL);
9975                         break;
9976 #endif
9977 #endif // CONFIG_AP_MODE
9978                 case SIOCDEVPRIVATE:
9979                         ret = rtw_ioctl_wext_private(dev, &wrq->u);
9980                         break;
9981                 default:
9982                         ret = -EOPNOTSUPP;
9983                         break;
9984         }
9985
9986         return ret;
9987 }