8723BU: Update 8723BU wifi driver to version v4.3.16_14189.20150519_BTCOEX2015119...
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bu / os_dep / linux / ioctl_cfg80211.c
1 /******************************************************************************\r
2  *\r
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.\r
4  *                                        \r
5  * This program is free software; you can redistribute it and/or modify it\r
6  * under the terms of version 2 of the GNU General Public License as\r
7  * published by the Free Software Foundation.\r
8  *\r
9  * This program is distributed in the hope that it will be useful, but WITHOUT\r
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
12  * more details.\r
13  *\r
14  * You should have received a copy of the GNU General Public License along with\r
15  * this program; if not, write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA\r
17  *\r
18  *\r
19  ******************************************************************************/\r
20 #define  _IOCTL_CFG80211_C_\r
21 \r
22 #include <drv_types.h>\r
23 \r
24 #ifdef CONFIG_IOCTL_CFG80211\r
25 \r
26 #include <rtw_wifi_regd.h>\r
27 \r
28 #define RTW_MAX_MGMT_TX_CNT (8)\r
29 #define RTW_MAX_MGMT_TX_MS_GAS (500)\r
30 \r
31 #define RTW_SCAN_IE_LEN_MAX      2304\r
32 #define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 5000 //ms\r
33 #define RTW_MAX_NUM_PMKIDS 4\r
34 \r
35 #define RTW_CH_MAX_2G_CHANNEL               14      /* Max channel in 2G band */\r
36 \r
37 #ifdef CONFIG_WAPI_SUPPORT\r
38 \r
39 #ifndef WLAN_CIPHER_SUITE_SMS4\r
40 #define WLAN_CIPHER_SUITE_SMS4          0x00147201\r
41 #endif\r
42 \r
43 #ifndef WLAN_AKM_SUITE_WAPI_PSK\r
44 #define WLAN_AKM_SUITE_WAPI_PSK         0x000FAC04\r
45 #endif\r
46 \r
47 #ifndef WLAN_AKM_SUITE_WAPI_CERT\r
48 #define WLAN_AKM_SUITE_WAPI_CERT        0x000FAC12\r
49 #endif\r
50 \r
51 #ifndef NL80211_WAPI_VERSION_1\r
52 #define NL80211_WAPI_VERSION_1          (1 << 2)\r
53 #endif\r
54 \r
55 #endif\r
56 \r
57 #ifdef CONFIG_PLATFORM_ARM_SUN8I\r
58 #define BUSY_TRAFFIC_SCAN_DENY_PERIOD   8000\r
59 #else\r
60 #define BUSY_TRAFFIC_SCAN_DENY_PERIOD   12000\r
61 #endif\r
62 \r
63 static const u32 rtw_cipher_suites[] = {\r
64         WLAN_CIPHER_SUITE_WEP40,\r
65         WLAN_CIPHER_SUITE_WEP104,\r
66         WLAN_CIPHER_SUITE_TKIP,\r
67         WLAN_CIPHER_SUITE_CCMP,\r
68 #ifdef CONFIG_WAPI_SUPPORT\r
69         WLAN_CIPHER_SUITE_SMS4,\r
70 #endif // CONFIG_WAPI_SUPPORT\r
71 #ifdef CONFIG_IEEE80211W\r
72         WLAN_CIPHER_SUITE_AES_CMAC,\r
73 #endif //CONFIG_IEEE80211W\r
74 };\r
75 \r
76 #define RATETAB_ENT(_rate, _rateid, _flags) \\r
77         {                                                               \\r
78                 .bitrate        = (_rate),                              \\r
79                 .hw_value       = (_rateid),                            \\r
80                 .flags          = (_flags),                             \\r
81         }\r
82 \r
83 #define CHAN2G(_channel, _freq, _flags) {                       \\r
84         .band                   = IEEE80211_BAND_2GHZ,          \\r
85         .center_freq            = (_freq),                      \\r
86         .hw_value               = (_channel),                   \\r
87         .flags                  = (_flags),                     \\r
88         .max_antenna_gain       = 0,                            \\r
89         .max_power              = 30,                           \\r
90 }\r
91 \r
92 #define CHAN5G(_channel, _flags) {                              \\r
93         .band                   = IEEE80211_BAND_5GHZ,          \\r
94         .center_freq            = 5000 + (5 * (_channel)),      \\r
95         .hw_value               = (_channel),                   \\r
96         .flags                  = (_flags),                     \\r
97         .max_antenna_gain       = 0,                            \\r
98         .max_power              = 30,                           \\r
99 }\r
100 \r
101 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
102 /* if wowlan is not supported, kernel generate a disconnect at each suspend\r
103  * cf: /net/wireless/sysfs.c, so register a stub wowlan.\r
104  * Moreover wowlan has to be enabled via a the nl80211_set_wowlan callback.\r
105  * (from user space, e.g. iw phy0 wowlan enable)\r
106  */\r
107 static const struct wiphy_wowlan_support wowlan_stub = {\r
108         .flags = WIPHY_WOWLAN_ANY,\r
109         .n_patterns = 0,\r
110         .pattern_max_len = 0,\r
111         .pattern_min_len = 0,\r
112 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))\r
113         .max_pkt_offset = 0,\r
114 #endif\r
115 };\r
116 #endif\r
117 \r
118 static struct ieee80211_rate rtw_rates[] = {\r
119         RATETAB_ENT(10,  0x1,   0),\r
120         RATETAB_ENT(20,  0x2,   0),\r
121         RATETAB_ENT(55,  0x4,   0),\r
122         RATETAB_ENT(110, 0x8,   0),\r
123         RATETAB_ENT(60,  0x10,  0),\r
124         RATETAB_ENT(90,  0x20,  0),\r
125         RATETAB_ENT(120, 0x40,  0),\r
126         RATETAB_ENT(180, 0x80,  0),\r
127         RATETAB_ENT(240, 0x100, 0),\r
128         RATETAB_ENT(360, 0x200, 0),\r
129         RATETAB_ENT(480, 0x400, 0),\r
130         RATETAB_ENT(540, 0x800, 0),\r
131 };\r
132 \r
133 #define rtw_a_rates             (rtw_rates + 4)\r
134 #define RTW_A_RATES_NUM 8\r
135 #define rtw_g_rates             (rtw_rates + 0)\r
136 #define RTW_G_RATES_NUM 12\r
137 \r
138 #define RTW_2G_CHANNELS_NUM 14\r
139 #define RTW_5G_CHANNELS_NUM 37\r
140 \r
141 static struct ieee80211_channel rtw_2ghz_channels[] = {\r
142         CHAN2G(1, 2412, 0),\r
143         CHAN2G(2, 2417, 0),\r
144         CHAN2G(3, 2422, 0),\r
145         CHAN2G(4, 2427, 0),\r
146         CHAN2G(5, 2432, 0),\r
147         CHAN2G(6, 2437, 0),\r
148         CHAN2G(7, 2442, 0),\r
149         CHAN2G(8, 2447, 0),\r
150         CHAN2G(9, 2452, 0),\r
151         CHAN2G(10, 2457, 0),\r
152         CHAN2G(11, 2462, 0),\r
153         CHAN2G(12, 2467, 0),\r
154         CHAN2G(13, 2472, 0),\r
155         CHAN2G(14, 2484, 0),\r
156 };\r
157 \r
158 static struct ieee80211_channel rtw_5ghz_a_channels[] = {\r
159         CHAN5G(34, 0),          CHAN5G(36, 0),\r
160         CHAN5G(38, 0),          CHAN5G(40, 0),\r
161         CHAN5G(42, 0),          CHAN5G(44, 0),\r
162         CHAN5G(46, 0),          CHAN5G(48, 0),\r
163         CHAN5G(52, 0),          CHAN5G(56, 0),\r
164         CHAN5G(60, 0),          CHAN5G(64, 0),\r
165         CHAN5G(100, 0),         CHAN5G(104, 0),\r
166         CHAN5G(108, 0),         CHAN5G(112, 0),\r
167         CHAN5G(116, 0),         CHAN5G(120, 0),\r
168         CHAN5G(124, 0),         CHAN5G(128, 0),\r
169         CHAN5G(132, 0),         CHAN5G(136, 0),\r
170         CHAN5G(140, 0),         CHAN5G(149, 0),\r
171         CHAN5G(153, 0),         CHAN5G(157, 0),\r
172         CHAN5G(161, 0),         CHAN5G(165, 0),\r
173         CHAN5G(184, 0),         CHAN5G(188, 0),\r
174         CHAN5G(192, 0),         CHAN5G(196, 0),\r
175         CHAN5G(200, 0),         CHAN5G(204, 0),\r
176         CHAN5G(208, 0),         CHAN5G(212, 0),\r
177         CHAN5G(216, 0),\r
178 };\r
179 \r
180 \r
181 void rtw_2g_channels_init(struct ieee80211_channel *channels)\r
182 {\r
183         _rtw_memcpy((void*)channels, (void*)rtw_2ghz_channels,\r
184                 sizeof(struct ieee80211_channel)*RTW_2G_CHANNELS_NUM\r
185         );\r
186 }\r
187 \r
188 void rtw_5g_channels_init(struct ieee80211_channel *channels)\r
189 {\r
190         _rtw_memcpy((void*)channels, (void*)rtw_5ghz_a_channels,\r
191                 sizeof(struct ieee80211_channel)*RTW_5G_CHANNELS_NUM\r
192         );\r
193 }\r
194 \r
195 void rtw_2g_rates_init(struct ieee80211_rate *rates)\r
196 {\r
197         _rtw_memcpy(rates, rtw_g_rates,\r
198                 sizeof(struct ieee80211_rate)*RTW_G_RATES_NUM\r
199         );\r
200 }\r
201 \r
202 void rtw_5g_rates_init(struct ieee80211_rate *rates)\r
203 {\r
204         _rtw_memcpy(rates, rtw_a_rates,\r
205                 sizeof(struct ieee80211_rate)*RTW_A_RATES_NUM\r
206         );\r
207 }\r
208 \r
209 struct ieee80211_supported_band *rtw_spt_band_alloc(\r
210         enum ieee80211_band band\r
211         )\r
212 {\r
213         struct ieee80211_supported_band *spt_band = NULL;\r
214         int n_channels, n_bitrates;\r
215 \r
216         if(band == IEEE80211_BAND_2GHZ)\r
217         {\r
218                 n_channels = RTW_2G_CHANNELS_NUM;\r
219                 n_bitrates = RTW_G_RATES_NUM;\r
220         }\r
221         else if(band == IEEE80211_BAND_5GHZ)\r
222         {\r
223                 n_channels = RTW_5G_CHANNELS_NUM;\r
224                 n_bitrates = RTW_A_RATES_NUM;\r
225         }\r
226         else\r
227         {\r
228                 goto exit;\r
229         }\r
230 \r
231         spt_band = (struct ieee80211_supported_band *)rtw_zmalloc(\r
232                 sizeof(struct ieee80211_supported_band)\r
233                 + sizeof(struct ieee80211_channel)*n_channels\r
234                 + sizeof(struct ieee80211_rate)*n_bitrates\r
235         );\r
236         if(!spt_band)\r
237                 goto exit;\r
238 \r
239         spt_band->channels = (struct ieee80211_channel*)(((u8*)spt_band)+sizeof(struct ieee80211_supported_band));\r
240         spt_band->bitrates= (struct ieee80211_rate*)(((u8*)spt_band->channels)+sizeof(struct ieee80211_channel)*n_channels);\r
241         spt_band->band = band;\r
242         spt_band->n_channels = n_channels;\r
243         spt_band->n_bitrates = n_bitrates;\r
244 \r
245         if(band == IEEE80211_BAND_2GHZ)\r
246         {\r
247                 rtw_2g_channels_init(spt_band->channels);\r
248                 rtw_2g_rates_init(spt_band->bitrates);\r
249         }\r
250         else if(band == IEEE80211_BAND_5GHZ)\r
251         {\r
252                 rtw_5g_channels_init(spt_band->channels);\r
253                 rtw_5g_rates_init(spt_band->bitrates);\r
254         }\r
255 \r
256         //spt_band.ht_cap\r
257         \r
258 exit:\r
259 \r
260         return spt_band;\r
261 }\r
262 \r
263 void rtw_spt_band_free(struct ieee80211_supported_band *spt_band)\r
264 {\r
265         u32 size = 0;\r
266 \r
267         if(!spt_band)\r
268                 return;\r
269         \r
270         if(spt_band->band == IEEE80211_BAND_2GHZ)\r
271         {\r
272                 size = sizeof(struct ieee80211_supported_band)\r
273                         + sizeof(struct ieee80211_channel)*RTW_2G_CHANNELS_NUM\r
274                         + sizeof(struct ieee80211_rate)*RTW_G_RATES_NUM;\r
275         }\r
276         else if(spt_band->band == IEEE80211_BAND_5GHZ)\r
277         {\r
278                 size = sizeof(struct ieee80211_supported_band)\r
279                         + sizeof(struct ieee80211_channel)*RTW_5G_CHANNELS_NUM\r
280                         + sizeof(struct ieee80211_rate)*RTW_A_RATES_NUM;                \r
281         }\r
282         else\r
283         {\r
284                 \r
285         }\r
286         rtw_mfree((u8*)spt_band, size);\r
287 }\r
288 \r
289 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
290 static const struct ieee80211_txrx_stypes\r
291 rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {\r
292         [NL80211_IFTYPE_ADHOC] = {\r
293                 .tx = 0xffff,\r
294                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)\r
295         },\r
296         [NL80211_IFTYPE_STATION] = {\r
297                 .tx = 0xffff,\r
298                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |\r
299                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)\r
300         },\r
301         [NL80211_IFTYPE_AP] = {\r
302                 .tx = 0xffff,\r
303                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |\r
304                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |\r
305                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |\r
306                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |\r
307                 BIT(IEEE80211_STYPE_AUTH >> 4) |\r
308                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |\r
309                 BIT(IEEE80211_STYPE_ACTION >> 4)\r
310         },\r
311         [NL80211_IFTYPE_AP_VLAN] = {\r
312                 /* copy AP */\r
313                 .tx = 0xffff,\r
314                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |\r
315                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |\r
316                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |\r
317                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |\r
318                 BIT(IEEE80211_STYPE_AUTH >> 4) |\r
319                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |\r
320                 BIT(IEEE80211_STYPE_ACTION >> 4)\r
321         },\r
322         [NL80211_IFTYPE_P2P_CLIENT] = {\r
323                 .tx = 0xffff,\r
324                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |\r
325                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)\r
326         },\r
327         [NL80211_IFTYPE_P2P_GO] = {\r
328                 .tx = 0xffff,\r
329                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |\r
330                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |\r
331                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |\r
332                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |\r
333                 BIT(IEEE80211_STYPE_AUTH >> 4) |\r
334                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |\r
335                 BIT(IEEE80211_STYPE_ACTION >> 4)\r
336         },\r
337 };\r
338 #endif\r
339 \r
340 static int rtw_ieee80211_channel_to_frequency(int chan, int band)\r
341 {\r
342         /* see 802.11 17.3.8.3.2 and Annex J\r
343         * there are overlapping channel numbers in 5GHz and 2GHz bands */\r
344            \r
345         if (band == IEEE80211_BAND_5GHZ) {\r
346         if (chan >= 182 && chan <= 196)\r
347                         return 4000 + chan * 5;\r
348              else\r
349                     return 5000 + chan * 5;\r
350        } else { /* IEEE80211_BAND_2GHZ */\r
351                 if (chan == 14)\r
352                         return 2484;\r
353              else if (chan < 14)\r
354                         return 2407 + chan * 5;\r
355              else\r
356                         return 0; /* not supported */\r
357         }\r
358 }\r
359 \r
360 static u64 rtw_get_systime_us(void)\r
361 {\r
362 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))\r
363         struct timespec ts;\r
364         get_monotonic_boottime(&ts);\r
365         return ((u64)ts.tv_sec*1000000) + ts.tv_nsec / 1000;\r
366 #else\r
367         struct timeval tv;\r
368         do_gettimeofday(&tv);\r
369         return ((u64)tv.tv_sec*1000000) + tv.tv_usec;\r
370 #endif\r
371 }\r
372 \r
373 #define MAX_BSSINFO_LEN 1000\r
374 struct cfg80211_bss *rtw_cfg80211_inform_bss(_adapter *padapter, struct wlan_network *pnetwork)\r
375 {\r
376         struct ieee80211_channel *notify_channel;\r
377         struct cfg80211_bss *bss = NULL;\r
378         //struct ieee80211_supported_band *band;       \r
379         u16 channel;\r
380         u32 freq;\r
381         u64 notify_timestamp;\r
382         u16 notify_capability;\r
383         u16 notify_interval;\r
384         u8 *notify_ie;\r
385         size_t notify_ielen;\r
386         s32 notify_signal;\r
387         //u8 buf[MAX_BSSINFO_LEN];\r
388 \r
389         u8 *pbuf;\r
390         size_t buf_size = MAX_BSSINFO_LEN;\r
391         size_t len,bssinf_len=0;\r
392         struct rtw_ieee80211_hdr *pwlanhdr;\r
393         unsigned short *fctrl;\r
394         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
395                 \r
396         struct wireless_dev *wdev = padapter->rtw_wdev;\r
397         struct wiphy *wiphy = wdev->wiphy;\r
398         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
399 \r
400         pbuf = rtw_zmalloc(buf_size);\r
401         if(pbuf == NULL){\r
402                 DBG_871X("%s pbuf allocate failed  !! \n",__FUNCTION__);\r
403                 return bss;\r
404         }\r
405                 \r
406         //DBG_8192C("%s\n", __func__);\r
407 \r
408         bssinf_len = pnetwork->network.IELength+sizeof (struct rtw_ieee80211_hdr_3addr);\r
409         if(bssinf_len > buf_size){\r
410                 DBG_871X("%s IE Length too long > %zu byte \n",__FUNCTION__,buf_size);\r
411                 goto exit;\r
412         }\r
413 \r
414 #ifndef CONFIG_WAPI_SUPPORT\r
415         {\r
416                 u16 wapi_len = 0;\r
417         \r
418                 if(rtw_get_wapi_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &wapi_len)>0)\r
419                 {\r
420                         if(wapi_len > 0)\r
421                         {\r
422                                 DBG_871X("%s, no support wapi!\n",__FUNCTION__);\r
423                                 goto exit;\r
424                         }       \r
425                 }               \r
426         }       \r
427 #endif //!CONFIG_WAPI_SUPPORT\r
428 \r
429         //To reduce PBC Overlap rate\r
430         //_enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);\r
431         if(adapter_wdev_data(padapter)->scan_request != NULL)\r
432         {\r
433                 u8 *psr=NULL, sr = 0;\r
434                 NDIS_802_11_SSID *pssid = &pnetwork->network.Ssid;\r
435                 struct cfg80211_scan_request *request = adapter_wdev_data(padapter)->scan_request;\r
436                 struct cfg80211_ssid *ssids = request->ssids;\r
437                 u32 wpsielen=0;\r
438                 u8 *wpsie=NULL; \r
439                 \r
440                 wpsie = rtw_get_wps_ie(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wpsielen);\r
441                 \r
442                 if(wpsie && wpsielen>0)\r
443                         psr = rtw_get_wps_attr_content(wpsie,  wpsielen, WPS_ATTR_SELECTED_REGISTRAR, (u8*)(&sr), NULL);\r
444                 \r
445                 if (sr != 0)\r
446                 {                       \r
447                         if(request->n_ssids == 1 && request->n_channels == 1) // it means under processing WPS\r
448                         {\r
449                                 DBG_8192C("ssid=%s, len=%d\n", pssid->Ssid, pssid->SsidLength);\r
450 \r
451                                 if (ssids[0].ssid_len == 0) {\r
452                                 }\r
453                                 else if(pssid->SsidLength == ssids[0].ssid_len &&\r
454                                         _rtw_memcmp(pssid->Ssid, ssids[0].ssid, ssids[0].ssid_len))\r
455                                 {\r
456                                         DBG_871X("%s, got sr and ssid match!\n", __func__);\r
457                                 }\r
458                                 else\r
459                                 {\r
460                                         if(psr !=NULL)\r
461                                                 *psr = 0; //clear sr\r
462                                 \r
463 #if 0                   \r
464                                         WLAN_BSSID_EX  *pselect_network = &pnetwork->network;\r
465                                         struct cfg80211_bss *pselect_bss = NULL;\r
466                                         struct ieee80211_channel *notify_channel = NULL;\r
467                                         u32 freq;\r
468 \r
469                                         DBG_871X("%s, got sr, but ssid mismatch, to remove this bss\n", __func__);\r
470 \r
471                                         if (pselect_network->Configuration.DSConfig <= RTW_CH_MAX_2G_CHANNEL)\r
472                                                 freq = rtw_ieee80211_channel_to_frequency(pselect_network->Configuration.DSConfig, IEEE80211_BAND_2GHZ);\r
473                                         else\r
474                                                 freq = rtw_ieee80211_channel_to_frequency(pselect_network->Configuration.DSConfig, IEEE80211_BAND_5GHZ);\r
475 \r
476                                         notify_channel = ieee80211_get_channel(wiphy, freq);\r
477                                         pselect_bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/,\r
478                                                                 pselect_network->MacAddress, pselect_network->Ssid.Ssid,\r
479                                                                 pselect_network->Ssid.SsidLength, 0/*WLAN_CAPABILITY_ESS*/, \r
480                                                                 0/*WLAN_CAPABILITY_ESS*/);\r
481 \r
482                                         if(pselect_bss)\r
483                                         {\r
484                                                 DBG_871X("%s, got bss for cfg80211 for unlinking bss\n", __func__);\r
485 \r
486                                                 cfg80211_unlink_bss(wiphy, pselect_bss);\r
487 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)\r
488                                                 cfg80211_put_bss(wiphy, pselect_bss);\r
489 #else\r
490                                                 cfg80211_put_bss(pselect_bss);\r
491 #endif\r
492                                                 \r
493                                         }\r
494                                         \r
495                                         goto exit;\r
496 #endif                                  \r
497                                 }                       \r
498                         }                       \r
499                 }               \r
500         }\r
501         //_exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);\r
502         \r
503 \r
504         channel = pnetwork->network.Configuration.DSConfig;\r
505         if (channel <= RTW_CH_MAX_2G_CHANNEL)\r
506                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);\r
507         else\r
508                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);\r
509         \r
510         notify_channel = ieee80211_get_channel(wiphy, freq);\r
511 \r
512         if (0)\r
513                 notify_timestamp = le64_to_cpu(*(u64*)rtw_get_timestampe_from_ie(pnetwork->network.IEs));\r
514         else\r
515                 notify_timestamp = rtw_get_systime_us();\r
516 \r
517         notify_interval = le16_to_cpu(*(u16*)rtw_get_beacon_interval_from_ie(pnetwork->network.IEs));\r
518         notify_capability = le16_to_cpu(*(u16*)rtw_get_capability_from_ie(pnetwork->network.IEs));              \r
519 \r
520         notify_ie = pnetwork->network.IEs+_FIXED_IE_LENGTH_;\r
521         notify_ielen = pnetwork->network.IELength-_FIXED_IE_LENGTH_;\r
522 \r
523         //We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM: signal strength in mBm (100*dBm)\r
524         if ( check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE &&\r
525                 is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {\r
526                 notify_signal = 100*translate_percentage_to_dbm(padapter->recvpriv.signal_strength);//dbm\r
527         } else {\r
528                 notify_signal = 100*translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);//dbm\r
529         }\r
530                 \r
531         #if 0\r
532         DBG_8192C("bssid: "MAC_FMT"\n", MAC_ARG(pnetwork->network.MacAddress));\r
533         DBG_8192C("Channel: %d(%d)\n", channel, freq);\r
534         DBG_8192C("Capability: %X\n", notify_capability);\r
535         DBG_8192C("Beacon interval: %d\n", notify_interval);\r
536         DBG_8192C("Signal: %d\n", notify_signal);\r
537         DBG_8192C("notify_timestamp: %llu\n", notify_timestamp);\r
538         #endif\r
539 \r
540         //pbuf = buf;\r
541         \r
542         pwlanhdr = (struct rtw_ieee80211_hdr *)pbuf;    \r
543         fctrl = &(pwlanhdr->frame_ctl);\r
544         *(fctrl) = 0;   \r
545 \r
546         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);\r
547         //pmlmeext->mgnt_seq++;\r
548 \r
549         if (pnetwork->network.Reserved[0] == 1) { // WIFI_BEACON\r
550                 _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);                \r
551                 SetFrameSubType(pbuf, WIFI_BEACON);\r
552         } else {\r
553                 _rtw_memcpy(pwlanhdr->addr1, adapter_mac_addr(padapter), ETH_ALEN);\r
554                 SetFrameSubType(pbuf, WIFI_PROBERSP);\r
555         }\r
556 \r
557         _rtw_memcpy(pwlanhdr->addr2, pnetwork->network.MacAddress, ETH_ALEN);\r
558         _rtw_memcpy(pwlanhdr->addr3, pnetwork->network.MacAddress, ETH_ALEN);\r
559 \r
560 \r
561         //pbuf += sizeof(struct rtw_ieee80211_hdr_3addr);\r
562         len = sizeof (struct rtw_ieee80211_hdr_3addr);\r
563         _rtw_memcpy((pbuf+len), pnetwork->network.IEs, pnetwork->network.IELength);\r
564         *((u64*)(pbuf+len)) = cpu_to_le64(notify_timestamp);\r
565         \r
566         len += pnetwork->network.IELength;      \r
567 \r
568         //#ifdef CONFIG_P2P\r
569         //if(rtw_get_p2p_ie(pnetwork->network.IEs+12, pnetwork->network.IELength-12, NULL, NULL))\r
570         //{\r
571         //      DBG_8192C("%s, got p2p_ie\n", __func__);\r
572         //}\r
573         //#endif\r
574 \r
575 #if 1   \r
576         bss = cfg80211_inform_bss_frame(wiphy, notify_channel, (struct ieee80211_mgmt *)pbuf,\r
577                 len, notify_signal, GFP_ATOMIC);\r
578 #else                    \r
579                         \r
580         bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)pnetwork->network.MacAddress,\r
581                 notify_timestamp, notify_capability, notify_interval, notify_ie,\r
582                 notify_ielen, notify_signal, GFP_ATOMIC/*GFP_KERNEL*/);\r
583 #endif\r
584 \r
585         if (unlikely(!bss)) {\r
586                 DBG_8192C(FUNC_ADPT_FMT" bss NULL\n", FUNC_ADPT_ARG(padapter));\r
587                 goto exit;\r
588         }\r
589 \r
590 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))\r
591 #ifndef COMPAT_KERNEL_RELEASE\r
592         //patch for cfg80211, update beacon ies to information_elements\r
593         if (pnetwork->network.Reserved[0] == 1) { // WIFI_BEACON\r
594         \r
595                  if(bss->len_information_elements != bss->len_beacon_ies)\r
596                  {\r
597                         bss->information_elements = bss->beacon_ies;                    \r
598                         bss->len_information_elements =  bss->len_beacon_ies;\r
599                  }              \r
600         }\r
601 #endif //COMPAT_KERNEL_RELEASE\r
602 #endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)\r
603 \r
604 /*      \r
605         {\r
606                 if( bss->information_elements == bss->proberesp_ies) \r
607                 {\r
608                         if( bss->len_information_elements !=  bss->len_proberesp_ies)\r
609                         {\r
610                                 DBG_8192C("error!, len_information_elements !=  bss->len_proberesp_ies\n");\r
611                         }\r
612                                                         \r
613                 }\r
614                 else if(bss->len_information_elements <  bss->len_beacon_ies)\r
615                 {\r
616                         bss->information_elements = bss->beacon_ies;                    \r
617                         bss->len_information_elements =  bss->len_beacon_ies;\r
618                 }\r
619         }\r
620 */\r
621 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)\r
622         cfg80211_put_bss(wiphy, bss);\r
623 #else\r
624         cfg80211_put_bss(bss);\r
625 #endif\r
626         \r
627 exit:\r
628         if(pbuf)\r
629                 rtw_mfree(pbuf, buf_size);      \r
630         return bss;\r
631         \r
632 }\r
633 \r
634 /*\r
635         Check the given bss is valid by kernel API cfg80211_get_bss()\r
636         @padapter : the given adapter\r
637         \r
638         return _TRUE if bss is valid,  _FALSE for not found.\r
639 */\r
640 int rtw_cfg80211_check_bss(_adapter *padapter)\r
641 {\r
642         WLAN_BSSID_EX  *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);\r
643         struct cfg80211_bss *bss = NULL;\r
644         struct ieee80211_channel *notify_channel = NULL;\r
645         u32 freq;\r
646 \r
647         if (!(pnetwork) || !(padapter->rtw_wdev))\r
648                 return _FALSE;\r
649 \r
650         if (pnetwork->Configuration.DSConfig <= RTW_CH_MAX_2G_CHANNEL)\r
651                 freq = rtw_ieee80211_channel_to_frequency(pnetwork->Configuration.DSConfig, IEEE80211_BAND_2GHZ);\r
652         else\r
653                 freq = rtw_ieee80211_channel_to_frequency(pnetwork->Configuration.DSConfig, IEEE80211_BAND_5GHZ);\r
654 \r
655         notify_channel = ieee80211_get_channel(padapter->rtw_wdev->wiphy, freq);\r
656         bss = cfg80211_get_bss(padapter->rtw_wdev->wiphy, notify_channel,\r
657                         pnetwork->MacAddress, pnetwork->Ssid.Ssid,\r
658                         pnetwork->Ssid.SsidLength,\r
659                         WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);\r
660 \r
661 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)\r
662         cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss);\r
663 #else\r
664         cfg80211_put_bss(bss);\r
665 #endif\r
666 \r
667         return  (bss!=NULL);\r
668 }\r
669 \r
670 void rtw_cfg80211_ibss_indicate_connect(_adapter *padapter)\r
671 {\r
672         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;\r
673         struct wlan_network  *cur_network = &(pmlmepriv->cur_network);\r
674         struct wireless_dev *pwdev = padapter->rtw_wdev;\r
675         struct cfg80211_bss *bss = NULL;\r
676 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))\r
677         struct wiphy *wiphy = pwdev->wiphy;\r
678         int freq = 2412;\r
679         struct ieee80211_channel *notify_channel;\r
680 #endif\r
681 \r
682         DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));\r
683 \r
684 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))    \r
685         if (cur_network->network.Configuration.DSConfig <= RTW_CH_MAX_2G_CHANNEL)\r
686                 freq = rtw_ieee80211_channel_to_frequency(cur_network->network.Configuration.DSConfig, IEEE80211_BAND_2GHZ);\r
687         else\r
688                 freq = rtw_ieee80211_channel_to_frequency(cur_network->network.Configuration.DSConfig, IEEE80211_BAND_5GHZ);\r
689         \r
690         if (0)\r
691                 DBG_871X("chan: %d, freq: %d\n", cur_network->network.Configuration.DSConfig, freq);\r
692 #endif\r
693 \r
694         if (pwdev->iftype != NL80211_IFTYPE_ADHOC) \r
695         {\r
696                 return;\r
697         }\r
698 \r
699         if (!rtw_cfg80211_check_bss(padapter)) {\r
700                 WLAN_BSSID_EX  *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);\r
701                 struct wlan_network *scanned = pmlmepriv->cur_network_scanned;\r
702 \r
703                 if(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)==_TRUE)\r
704                 {\r
705                         \r
706                         _rtw_memcpy(&cur_network->network, pnetwork, sizeof(WLAN_BSSID_EX));\r
707                         if(cur_network)\r
708                         {\r
709                                 if (!rtw_cfg80211_inform_bss(padapter,cur_network))\r
710                                         DBG_871X(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));\r
711                                 else\r
712                                         DBG_871X(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter));\r
713                         }\r
714                         else\r
715                         {\r
716                                 DBG_871X("cur_network is not exist!!!\n");\r
717                                 return ;\r
718                         }\r
719                 }\r
720                 else\r
721                 {\r
722                         if(scanned == NULL)\r
723                                 rtw_warn_on(1);\r
724 \r
725                         if (_rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE\r
726                                 && _rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE\r
727                         ) {\r
728                                 if (!rtw_cfg80211_inform_bss(padapter,scanned)) {\r
729                                         DBG_871X(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));\r
730                                 } else {\r
731                                         //DBG_871X(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter));\r
732                                 }\r
733                         } else {\r
734                                 DBG_871X("scanned & pnetwork compare fail\n");\r
735                                 rtw_warn_on(1);\r
736                         }\r
737                 }\r
738 \r
739                 if (!rtw_cfg80211_check_bss(padapter))\r
740                         DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" BSS not found !!\n", FUNC_ADPT_ARG(padapter));\r
741         }\r
742         //notify cfg80211 that device joined an IBSS\r
743 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))\r
744         notify_channel = ieee80211_get_channel(wiphy, freq);\r
745         cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, notify_channel, GFP_ATOMIC);\r
746 #else\r
747         cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, GFP_ATOMIC);\r
748 #endif\r
749 }\r
750 \r
751 void rtw_cfg80211_indicate_connect(_adapter *padapter)\r
752 {\r
753         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;\r
754         struct wlan_network  *cur_network = &(pmlmepriv->cur_network);\r
755         struct wireless_dev *pwdev = padapter->rtw_wdev;\r
756 #ifdef CONFIG_P2P\r
757         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);\r
758 #endif\r
759         struct cfg80211_bss *bss = NULL;\r
760 \r
761         DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));\r
762         if (pwdev->iftype != NL80211_IFTYPE_STATION\r
763                 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
764                 && pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT\r
765                 #endif\r
766         ) {\r
767                 return;\r
768         }\r
769 \r
770         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)\r
771                 return;\r
772 \r
773 #ifdef CONFIG_P2P\r
774         if(pwdinfo->driver_interface == DRIVER_CFG80211 )\r
775         {\r
776                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))\r
777                 {\r
778                         rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));\r
779                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);\r
780                         rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);\r
781                         DBG_8192C("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));\r
782                 }\r
783         }\r
784 #endif //CONFIG_P2P\r
785 \r
786         {\r
787                 WLAN_BSSID_EX  *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);\r
788                 struct wlan_network *scanned = pmlmepriv->cur_network_scanned;\r
789 \r
790                 //DBG_871X(FUNC_ADPT_FMT" BSS not found\n", FUNC_ADPT_ARG(padapter));\r
791 \r
792                 if(scanned == NULL) {\r
793                         rtw_warn_on(1);\r
794                         goto check_bss;\r
795                 }\r
796 \r
797                 if (_rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE\r
798                         && _rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE\r
799                 ) {\r
800                         if (!rtw_cfg80211_inform_bss(padapter,scanned)) {\r
801                                 DBG_871X(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));\r
802                         } else {\r
803                                 //DBG_871X(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter));\r
804                         }\r
805                 } else {\r
806                         DBG_871X("scanned: %s("MAC_FMT"), cur: %s("MAC_FMT")\n",\r
807                                 scanned->network.Ssid.Ssid, MAC_ARG(scanned->network.MacAddress),\r
808                                 pnetwork->Ssid.Ssid, MAC_ARG(pnetwork->MacAddress)\r
809                         );\r
810                         rtw_warn_on(1);\r
811                 }\r
812         }\r
813 \r
814 check_bss:\r
815         if (!rtw_cfg80211_check_bss(padapter))\r
816                 DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" BSS not found !!\n", FUNC_ADPT_ARG(padapter));\r
817 \r
818         if (rtw_to_roam(padapter) > 0) {\r
819                 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE)\r
820                 struct wiphy *wiphy = pwdev->wiphy;\r
821                 struct ieee80211_channel *notify_channel;\r
822                 u32 freq;\r
823                 u16 channel = cur_network->network.Configuration.DSConfig;\r
824 \r
825                 if (channel <= RTW_CH_MAX_2G_CHANNEL)\r
826                         freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);\r
827                 else\r
828                         freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);\r
829 \r
830                 notify_channel = ieee80211_get_channel(wiphy, freq);\r
831                 #endif\r
832 \r
833                 DBG_871X(FUNC_ADPT_FMT" call cfg80211_roamed\n", FUNC_ADPT_ARG(padapter));\r
834                 cfg80211_roamed(padapter->pnetdev\r
835                         #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE)\r
836                         , notify_channel\r
837                         #endif\r
838                         , cur_network->network.MacAddress\r
839                         , pmlmepriv->assoc_req+sizeof(struct rtw_ieee80211_hdr_3addr)+2\r
840                         , pmlmepriv->assoc_req_len-sizeof(struct rtw_ieee80211_hdr_3addr)-2\r
841                         , pmlmepriv->assoc_rsp+sizeof(struct rtw_ieee80211_hdr_3addr)+6\r
842                         , pmlmepriv->assoc_rsp_len-sizeof(struct rtw_ieee80211_hdr_3addr)-6\r
843                         , GFP_ATOMIC);\r
844         }\r
845         else\r
846         {\r
847         #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)     \r
848                 DBG_8192C("pwdev->sme_state(b)=%d\n", pwdev->sme_state);\r
849         #endif\r
850                 cfg80211_connect_result(padapter->pnetdev, cur_network->network.MacAddress\r
851                         , pmlmepriv->assoc_req+sizeof(struct rtw_ieee80211_hdr_3addr)+2\r
852                         , pmlmepriv->assoc_req_len-sizeof(struct rtw_ieee80211_hdr_3addr)-2\r
853                         , pmlmepriv->assoc_rsp+sizeof(struct rtw_ieee80211_hdr_3addr)+6\r
854                         , pmlmepriv->assoc_rsp_len-sizeof(struct rtw_ieee80211_hdr_3addr)-6\r
855                         , WLAN_STATUS_SUCCESS, GFP_ATOMIC);\r
856         #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)     \r
857                 DBG_8192C("pwdev->sme_state(a)=%d\n", pwdev->sme_state);\r
858         #endif\r
859         }\r
860 }\r
861 \r
862 void rtw_cfg80211_indicate_disconnect(_adapter *padapter)\r
863 {\r
864         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;\r
865         struct wireless_dev *pwdev = padapter->rtw_wdev;\r
866 #ifdef CONFIG_P2P\r
867         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);\r
868 #endif\r
869 \r
870         DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));\r
871 \r
872         if (pwdev->iftype != NL80211_IFTYPE_STATION \r
873                 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
874                 && pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT\r
875                 #endif\r
876         ) {\r
877                 return;\r
878         }\r
879 \r
880         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)\r
881                 return;\r
882 \r
883 #ifdef CONFIG_P2P       \r
884         if( pwdinfo->driver_interface == DRIVER_CFG80211 )\r
885         {\r
886                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))\r
887                 {\r
888                         rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));\r
889                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);\r
890 \r
891                         DBG_8192C("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));\r
892                 }\r
893         }\r
894 #endif //CONFIG_P2P\r
895 \r
896         if (!padapter->mlmepriv.not_indic_disco) {\r
897                 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)                     \r
898                 DBG_8192C("pwdev->sme_state(b)=%d\n", pwdev->sme_state);\r
899 \r
900                 if(pwdev->sme_state==CFG80211_SME_CONNECTING)\r
901                         cfg80211_connect_result(padapter->pnetdev, NULL, NULL, 0, NULL, 0, \r
902                                 WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC/*GFP_KERNEL*/);\r
903                 else if(pwdev->sme_state==CFG80211_SME_CONNECTED)\r
904                         cfg80211_disconnected(padapter->pnetdev, 0, NULL, 0, GFP_ATOMIC);\r
905                 //else\r
906                         //DBG_8192C("pwdev->sme_state=%d\n", pwdev->sme_state);\r
907 \r
908                 DBG_8192C("pwdev->sme_state(a)=%d\n", pwdev->sme_state);\r
909                 #else\r
910 \r
911                 if(check_fwstate(&padapter->mlmepriv, _FW_LINKED))              \r
912                         cfg80211_disconnected(padapter->pnetdev, 0, NULL, 0, GFP_ATOMIC);\r
913                 else\r
914                         cfg80211_connect_result(padapter->pnetdev, NULL, NULL, 0, NULL, 0, \r
915                                 WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC/*GFP_KERNEL*/);\r
916                 #endif\r
917         }\r
918 }\r
919         \r
920 \r
921 #ifdef CONFIG_AP_MODE\r
922 static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)\r
923 {\r
924         int ret = 0;\r
925         u32 wep_key_idx, wep_key_len,wep_total_len;\r
926         struct sta_info *psta = NULL, *pbcmc_sta = NULL;        \r
927         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);\r
928         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
929         struct security_priv* psecuritypriv=&(padapter->securitypriv);\r
930         struct sta_priv *pstapriv = &padapter->stapriv;\r
931 \r
932         DBG_8192C("%s\n", __FUNCTION__);\r
933 \r
934         param->u.crypt.err = 0;\r
935         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';\r
936 \r
937         //sizeof(struct ieee_param) = 64 bytes;\r
938         //if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len)\r
939         if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len)\r
940         {\r
941                 ret =  -EINVAL;\r
942                 goto exit;\r
943         }\r
944 \r
945         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&\r
946             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&\r
947             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) \r
948         {\r
949                 if (param->u.crypt.idx >= WEP_KEYS)\r
950                 {\r
951                         ret = -EINVAL;\r
952                         goto exit;\r
953                 }       \r
954         }\r
955         else \r
956         {               \r
957                 psta = rtw_get_stainfo(pstapriv, param->sta_addr);\r
958                 if(!psta)\r
959                 {\r
960                         //ret = -EINVAL;\r
961                         DBG_8192C("rtw_set_encryption(), sta has already been removed or never been added\n");\r
962                         goto exit;\r
963                 }                       \r
964         }\r
965 \r
966         if (strcmp(param->u.crypt.alg, "none") == 0 && (psta==NULL))\r
967         {\r
968                 //todo:clear default encryption keys\r
969 \r
970                 DBG_8192C("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);\r
971                 \r
972                 goto exit;\r
973         }\r
974 \r
975 \r
976         if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta==NULL))\r
977         {               \r
978                 DBG_8192C("r871x_set_encryption, crypt.alg = WEP\n");\r
979                 \r
980                 wep_key_idx = param->u.crypt.idx;\r
981                 wep_key_len = param->u.crypt.key_len;\r
982                                         \r
983                 DBG_8192C("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);\r
984 \r
985                 if((wep_key_idx >= WEP_KEYS) || (wep_key_len<=0))\r
986                 {\r
987                         ret = -EINVAL;\r
988                         goto exit;\r
989                 }\r
990                         \r
991                 if (wep_key_len > 0) \r
992                 {                       \r
993                         wep_key_len = wep_key_len <= 5 ? 5 : 13;\r
994                 }\r
995                 \r
996                 if (psecuritypriv->bWepDefaultKeyIdxSet == 0)\r
997                 {\r
998                         //wep default key has not been set, so use this key index as default key.\r
999 \r
1000                         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;\r
1001                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;\r
1002                         psecuritypriv->dot11PrivacyAlgrthm=_WEP40_;\r
1003                         psecuritypriv->dot118021XGrpPrivacy=_WEP40_;\r
1004                         \r
1005                         if(wep_key_len == 13)\r
1006                         {\r
1007                                 psecuritypriv->dot11PrivacyAlgrthm=_WEP104_;\r
1008                                 psecuritypriv->dot118021XGrpPrivacy=_WEP104_;\r
1009                         }\r
1010 \r
1011                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;\r
1012                 }\r
1013                         \r
1014                 _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);\r
1015                                         \r
1016                 psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;\r
1017 \r
1018                 rtw_ap_set_wep_key(padapter, param->u.crypt.key, wep_key_len, wep_key_idx, 1);\r
1019 \r
1020                 goto exit;\r
1021                 \r
1022         }\r
1023 \r
1024         \r
1025         if(!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) // //group key\r
1026         {\r
1027                 if(param->u.crypt.set_tx == 0) //group key\r
1028                 {\r
1029                         if(strcmp(param->u.crypt.alg, "WEP") == 0)\r
1030                         {\r
1031                                 DBG_8192C("%s, set group_key, WEP\n", __FUNCTION__);\r
1032                                 \r
1033                                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));\r
1034                                         \r
1035                                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;\r
1036                                 if(param->u.crypt.key_len==13)\r
1037                                 {                                               \r
1038                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;\r
1039                                 }\r
1040                                 \r
1041                         }\r
1042                         else if(strcmp(param->u.crypt.alg, "TKIP") == 0)\r
1043                         {                                               \r
1044                                 DBG_8192C("%s, set group_key, TKIP\n", __FUNCTION__);\r
1045                                 \r
1046                                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;\r
1047 \r
1048                                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));\r
1049                                 \r
1050                                 //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);\r
1051                                 //set mic key\r
1052                                 _rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);\r
1053                                 _rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);\r
1054 \r
1055                                 psecuritypriv->busetkipkey = _TRUE;\r
1056                                                                                         \r
1057                         }\r
1058                         else if(strcmp(param->u.crypt.alg, "CCMP") == 0)\r
1059                         {\r
1060                                 DBG_8192C("%s, set group_key, CCMP\n", __FUNCTION__);\r
1061                         \r
1062                                 psecuritypriv->dot118021XGrpPrivacy = _AES_;\r
1063 \r
1064                                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));\r
1065                         }\r
1066                         else\r
1067                         {\r
1068                                 DBG_8192C("%s, set group_key, none\n", __FUNCTION__);\r
1069                                 \r
1070                                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;\r
1071                         }\r
1072 \r
1073                         psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;\r
1074 \r
1075                         psecuritypriv->binstallGrpkey = _TRUE;\r
1076 \r
1077                         psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;//!!!\r
1078                                                                 \r
1079                         rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);\r
1080                         \r
1081                         pbcmc_sta=rtw_get_bcmc_stainfo(padapter);\r
1082                         if(pbcmc_sta)\r
1083                         {\r
1084                                 pbcmc_sta->ieee8021x_blocked = _FALSE;\r
1085                                 pbcmc_sta->dot118021XPrivacy= psecuritypriv->dot118021XGrpPrivacy;//rx will use bmc_sta's dot118021XPrivacy                     \r
1086                         }       \r
1087                                                 \r
1088                 }\r
1089 \r
1090                 goto exit;\r
1091                 \r
1092         }       \r
1093 \r
1094         if(psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) // psk/802_1x\r
1095         {\r
1096                 if(check_fwstate(pmlmepriv, WIFI_AP_STATE))\r
1097                 {\r
1098                         if(param->u.crypt.set_tx ==1) //pairwise key\r
1099                         { \r
1100                                 _rtw_memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));\r
1101                                 \r
1102                                 if(strcmp(param->u.crypt.alg, "WEP") == 0)\r
1103                                 {\r
1104                                         DBG_8192C("%s, set pairwise key, WEP\n", __FUNCTION__);\r
1105                                         \r
1106                                         psta->dot118021XPrivacy = _WEP40_;\r
1107                                         if(param->u.crypt.key_len==13)\r
1108                                         {                                               \r
1109                                                 psta->dot118021XPrivacy = _WEP104_;\r
1110                                         }\r
1111                                 }\r
1112                                 else if(strcmp(param->u.crypt.alg, "TKIP") == 0)\r
1113                                 {                                               \r
1114                                         DBG_8192C("%s, set pairwise key, TKIP\n", __FUNCTION__);\r
1115                                         \r
1116                                         psta->dot118021XPrivacy = _TKIP_;\r
1117                                 \r
1118                                         //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);\r
1119                                         //set mic key\r
1120                                         _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);\r
1121                                         _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);\r
1122 \r
1123                                         psecuritypriv->busetkipkey = _TRUE;\r
1124                                                                                         \r
1125                                 }\r
1126                                 else if(strcmp(param->u.crypt.alg, "CCMP") == 0)\r
1127                                 {\r
1128 \r
1129                                         DBG_8192C("%s, set pairwise key, CCMP\n", __FUNCTION__);\r
1130                                         \r
1131                                         psta->dot118021XPrivacy = _AES_;\r
1132                                 }\r
1133                                 else\r
1134                                 {\r
1135                                         DBG_8192C("%s, set pairwise key, none\n", __FUNCTION__);\r
1136                                         \r
1137                                         psta->dot118021XPrivacy = _NO_PRIVACY_;\r
1138                                 }\r
1139                                                 \r
1140                                 rtw_ap_set_pairwise_key(padapter, psta);\r
1141                                         \r
1142                                 psta->ieee8021x_blocked = _FALSE;\r
1143                                         \r
1144                                 psta->bpairwise_key_installed = _TRUE;\r
1145                                         \r
1146                         }                       \r
1147                         else//group key???\r
1148                         { \r
1149                                 if(strcmp(param->u.crypt.alg, "WEP") == 0)\r
1150                                 {\r
1151                                         _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));\r
1152                                         \r
1153                                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;\r
1154                                         if(param->u.crypt.key_len==13)\r
1155                                         {                                               \r
1156                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;\r
1157                                         }\r
1158                                 }\r
1159                                 else if(strcmp(param->u.crypt.alg, "TKIP") == 0)\r
1160                                 {                                               \r
1161                                         psecuritypriv->dot118021XGrpPrivacy = _TKIP_;\r
1162 \r
1163                                         _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));\r
1164                                 \r
1165                                         //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);\r
1166                                         //set mic key\r
1167                                         _rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);\r
1168                                         _rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);\r
1169 \r
1170                                         psecuritypriv->busetkipkey = _TRUE;\r
1171                                                                                         \r
1172                                 }\r
1173                                 else if(strcmp(param->u.crypt.alg, "CCMP") == 0)\r
1174                                 {\r
1175                                         psecuritypriv->dot118021XGrpPrivacy = _AES_;\r
1176 \r
1177                                         _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));\r
1178                                 }\r
1179                                 else\r
1180                                 {\r
1181                                         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;\r
1182                                 }\r
1183 \r
1184                                 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;\r
1185 \r
1186                                 psecuritypriv->binstallGrpkey = _TRUE;  \r
1187                                                                 \r
1188                                 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;//!!!\r
1189                                                                 \r
1190                                 rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);\r
1191                         \r
1192                                 pbcmc_sta=rtw_get_bcmc_stainfo(padapter);\r
1193                                 if(pbcmc_sta)\r
1194                                 {\r
1195                                         pbcmc_sta->ieee8021x_blocked = _FALSE;\r
1196                                         pbcmc_sta->dot118021XPrivacy= psecuritypriv->dot118021XGrpPrivacy;//rx will use bmc_sta's dot118021XPrivacy                     \r
1197                                 }                                       \r
1198 \r
1199                         }\r
1200                         \r
1201                 }\r
1202                                 \r
1203         }\r
1204 \r
1205 exit:\r
1206 \r
1207         return ret;\r
1208         \r
1209 }\r
1210 #endif\r
1211 \r
1212 static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)\r
1213 {\r
1214         int ret = 0;\r
1215         u32 wep_key_idx, wep_key_len,wep_total_len;\r
1216         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);\r
1217         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;               \r
1218         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
1219 #ifdef CONFIG_P2P\r
1220         struct wifidirect_info* pwdinfo = &padapter->wdinfo;\r
1221 #endif //CONFIG_P2P\r
1222 \r
1223 _func_enter_;\r
1224 \r
1225         DBG_8192C("%s\n", __func__);\r
1226 \r
1227         param->u.crypt.err = 0;\r
1228         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';\r
1229 \r
1230         if (param_len < (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len)\r
1231         {\r
1232                 ret =  -EINVAL;         \r
1233                 goto exit;\r
1234         }\r
1235 \r
1236         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&\r
1237             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&\r
1238             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) \r
1239         {\r
1240                 if (param->u.crypt.idx >= WEP_KEYS\r
1241 #ifdef CONFIG_IEEE80211W\r
1242                         && param->u.crypt.idx > BIP_MAX_KEYID\r
1243 #endif //CONFIG_IEEE80211W\r
1244                 )\r
1245                 {\r
1246                         ret = -EINVAL;\r
1247                         goto exit;\r
1248                 }\r
1249         } else {\r
1250 #ifdef CONFIG_WAPI_SUPPORT\r
1251                 if (strcmp(param->u.crypt.alg, "SMS4"))\r
1252 #endif\r
1253                 {\r
1254                 ret = -EINVAL;\r
1255                 goto exit;\r
1256         }\r
1257         }\r
1258 \r
1259         if (strcmp(param->u.crypt.alg, "WEP") == 0)\r
1260         {\r
1261                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("wpa_set_encryption, crypt.alg = WEP\n"));\r
1262                 DBG_8192C("wpa_set_encryption, crypt.alg = WEP\n");\r
1263 \r
1264                 wep_key_idx = param->u.crypt.idx;\r
1265                 wep_key_len = param->u.crypt.key_len;\r
1266 \r
1267                 if ((wep_key_idx > WEP_KEYS) || (wep_key_len <= 0))\r
1268                 {\r
1269                         ret = -EINVAL;\r
1270                         goto exit;\r
1271                 }\r
1272 \r
1273                 if (psecuritypriv->bWepDefaultKeyIdxSet == 0)\r
1274                 {\r
1275                         //wep default key has not been set, so use this key index as default key.\r
1276 \r
1277                         wep_key_len = wep_key_len <= 5 ? 5 : 13;\r
1278 \r
1279                 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;\r
1280                         psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;\r
1281                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;\r
1282 \r
1283                         if(wep_key_len==13)\r
1284                         {\r
1285                                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;\r
1286                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;\r
1287                         }\r
1288 \r
1289                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;\r
1290                 }\r
1291                         \r
1292                 _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);\r
1293                         \r
1294                 psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;\r
1295                         \r
1296                 rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, _TRUE);\r
1297 \r
1298                 goto exit;              \r
1299         }\r
1300 \r
1301         if(padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) // 802_1x\r
1302         {\r
1303                 struct sta_info * psta,*pbcmc_sta;\r
1304                 struct sta_priv * pstapriv = &padapter->stapriv;\r
1305 \r
1306                 //DBG_8192C("%s, : dot11AuthAlgrthm == dot11AuthAlgrthm_8021X \n", __func__);\r
1307 \r
1308                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == _TRUE) //sta mode\r
1309                 {\r
1310                         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));                 \r
1311                         if (psta == NULL) {\r
1312                                 //DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail \n"));\r
1313                                 DBG_8192C("%s, : Obtain Sta_info fail \n", __func__);\r
1314                         }\r
1315                         else\r
1316                         {\r
1317                                 //Jeff: don't disable ieee8021x_blocked while clearing key\r
1318                                 if (strcmp(param->u.crypt.alg, "none") != 0) \r
1319                                         psta->ieee8021x_blocked = _FALSE;\r
1320 \r
1321                                 \r
1322                                 if((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)||\r
1323                                                 (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))\r
1324                                 {\r
1325                                         psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;\r
1326                                 }               \r
1327 \r
1328                                 if(param->u.crypt.set_tx ==1)//pairwise key\r
1329                                 { \r
1330 \r
1331                                         DBG_8192C("%s, : param->u.crypt.set_tx ==1 \n", __func__);\r
1332                                         \r
1333                                         _rtw_memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));\r
1334                                         \r
1335                                         if(strcmp(param->u.crypt.alg, "TKIP") == 0)//set mic key\r
1336                                         {                                               \r
1337                                                 //DEBUG_ERR(("\nset key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len));\r
1338                                                 _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);\r
1339                                                 _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);\r
1340 \r
1341                                                 padapter->securitypriv.busetkipkey=_FALSE;\r
1342                                                 //_set_timer(&padapter->securitypriv.tkip_timer, 50);                                           \r
1343                                         }\r
1344 \r
1345                                         //DEBUG_ERR((" param->u.crypt.key_len=%d\n",param->u.crypt.key_len));\r
1346                                         DBG_871X(" ~~~~set sta key:unicastkey\n");\r
1347                                         \r
1348                                         rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _TRUE);\r
1349                                 }\r
1350                                 else//group key\r
1351                                 {\r
1352                                         if(strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0)\r
1353                                         {\r
1354                                                 _rtw_memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key,(param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));\r
1355                                                 _rtw_memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[16]),8);\r
1356                                                 _rtw_memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[24]),8);\r
1357                                                 padapter->securitypriv.binstallGrpkey = _TRUE;  \r
1358                                                 //DEBUG_ERR((" param->u.crypt.key_len=%d\n", param->u.crypt.key_len));\r
1359                                                 DBG_871X(" ~~~~set sta key:groupkey\n");\r
1360         \r
1361                                                 padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;\r
1362                                                 rtw_set_key(padapter,&padapter->securitypriv,param->u.crypt.idx, 1, _TRUE);\r
1363                                         }\r
1364 #ifdef CONFIG_IEEE80211W\r
1365                                         else if(strcmp(param->u.crypt.alg, "BIP") == 0)\r
1366                                         {\r
1367                                                 int no;\r
1368                                                 //DBG_871X("BIP key_len=%d , index=%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx);\r
1369                                                 //save the IGTK key, length 16 bytes\r
1370                                                 _rtw_memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey,  param->u.crypt.key,(param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));\r
1371                                                 /*DBG_871X("IGTK key below:\n");\r
1372                                                 for(no=0;no<16;no++)\r
1373                                                         printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);\r
1374                                                 DBG_871X("\n");*/\r
1375                                                 padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;\r
1376                                                 padapter->securitypriv.binstallBIPkey = _TRUE;\r
1377                                                 DBG_871X(" ~~~~set sta key:IGKT\n");\r
1378                                         }\r
1379 #endif //CONFIG_IEEE80211W\r
1380                                         \r
1381 #ifdef CONFIG_P2P\r
1382                                         if(pwdinfo->driver_interface == DRIVER_CFG80211 )\r
1383                                         {\r
1384                                                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))\r
1385                                                 {\r
1386                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);\r
1387                                                 }\r
1388                                         }\r
1389 #endif //CONFIG_P2P\r
1390                                         \r
1391                                 }                                               \r
1392                         }\r
1393 \r
1394                         pbcmc_sta=rtw_get_bcmc_stainfo(padapter);\r
1395                         if(pbcmc_sta==NULL)\r
1396                         {\r
1397                                 //DEBUG_ERR( ("Set OID_802_11_ADD_KEY: bcmc stainfo is null \n"));\r
1398                         }\r
1399                         else\r
1400                         {\r
1401                                 //Jeff: don't disable ieee8021x_blocked while clearing key\r
1402                                 if (strcmp(param->u.crypt.alg, "none") != 0) \r
1403                                         pbcmc_sta->ieee8021x_blocked = _FALSE;\r
1404                                 \r
1405                                 if((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)||\r
1406                                                 (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))\r
1407                                 {                                                       \r
1408                                         pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;\r
1409                                 }                                       \r
1410                         }                               \r
1411                 }\r
1412                 else if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) //adhoc mode\r
1413                 {               \r
1414                 }                       \r
1415         }\r
1416 \r
1417 #ifdef CONFIG_WAPI_SUPPORT\r
1418         if (strcmp(param->u.crypt.alg, "SMS4") == 0)\r
1419         {\r
1420                 PRT_WAPI_T                      pWapiInfo = &padapter->wapiInfo;\r
1421                 PRT_WAPI_STA_INFO       pWapiSta;\r
1422                 u8                                      WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;\r
1423                 u8                                      WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;\r
1424                 u8                                      WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;\r
1425 \r
1426                 if(param->u.crypt.set_tx == 1)\r
1427                 {\r
1428                         list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {\r
1429                                 if(_rtw_memcmp(pWapiSta->PeerMacAddr,param->sta_addr,6))\r
1430                                 {\r
1431                                         _rtw_memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);\r
1432 \r
1433                                         pWapiSta->wapiUsk.bSet = true;\r
1434                                         _rtw_memcpy(pWapiSta->wapiUsk.dataKey,param->u.crypt.key,16);\r
1435                                         _rtw_memcpy(pWapiSta->wapiUsk.micKey,param->u.crypt.key+16,16);\r
1436                                         pWapiSta->wapiUsk.keyId = param->u.crypt.idx ;\r
1437                                         pWapiSta->wapiUsk.bTxEnable = true;\r
1438 \r
1439                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiAEPNInitialValueSrc,16);\r
1440                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiAEPNInitialValueSrc,16);\r
1441                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiAEPNInitialValueSrc,16);\r
1442                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiAEPNInitialValueSrc,16);\r
1443                                         _rtw_memcpy(pWapiSta->lastRxUnicastPN,WapiAEPNInitialValueSrc,16);\r
1444                                         pWapiSta->wapiUskUpdate.bTxEnable = false;\r
1445                                         pWapiSta->wapiUskUpdate.bSet = false;\r
1446 \r
1447                                         if (psecuritypriv->sw_encrypt== false || psecuritypriv->sw_decrypt == false)\r
1448                                         {\r
1449                                                 //set unicast key for ASUE\r
1450                                                 rtw_wapi_set_key(padapter, &pWapiSta->wapiUsk, pWapiSta, false, false);\r
1451                                         }\r
1452                                 }\r
1453                         }\r
1454                 }\r
1455                 else\r
1456                 {\r
1457                         list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {\r
1458                                 if(_rtw_memcmp(pWapiSta->PeerMacAddr,get_bssid(pmlmepriv),6))\r
1459                                 {\r
1460                                         pWapiSta->wapiMsk.bSet = true;\r
1461                                         _rtw_memcpy(pWapiSta->wapiMsk.dataKey,param->u.crypt.key,16);\r
1462                                         _rtw_memcpy(pWapiSta->wapiMsk.micKey,param->u.crypt.key+16,16);\r
1463                                         pWapiSta->wapiMsk.keyId = param->u.crypt.idx ;\r
1464                                         pWapiSta->wapiMsk.bTxEnable = false;\r
1465                                         if(!pWapiSta->bSetkeyOk)\r
1466                                                 pWapiSta->bSetkeyOk = true;\r
1467                                         pWapiSta->bAuthenticateInProgress = false;\r
1468 \r
1469                                         _rtw_memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16);\r
1470 \r
1471                                         if (psecuritypriv->sw_decrypt == false)\r
1472                                         {\r
1473                                                 //set rx broadcast key for ASUE\r
1474                                                 rtw_wapi_set_key(padapter, &pWapiSta->wapiMsk, pWapiSta, true, false);\r
1475                                         }\r
1476                                 }\r
1477 \r
1478                         }\r
1479                 }\r
1480         }\r
1481 #endif\r
1482 \r
1483 \r
1484 exit:\r
1485 \r
1486         DBG_8192C("%s, ret=%d\n", __func__, ret);\r
1487         \r
1488         _func_exit_;\r
1489         \r
1490         return ret;     \r
1491 }\r
1492 \r
1493 static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,\r
1494 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
1495                                 u8 key_index, bool pairwise, const u8 *mac_addr,\r
1496 #else   // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))\r
1497                                 u8 key_index, const u8 *mac_addr,\r
1498 #endif  // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))\r
1499                                 struct key_params *params)\r
1500 {\r
1501         char *alg_name;\r
1502         u32 param_len;\r
1503         struct ieee_param *param = NULL;        \r
1504         int ret=0;\r
1505         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
1506         struct wireless_dev *rtw_wdev = padapter->rtw_wdev;\r
1507         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;\r
1508 #ifdef CONFIG_TDLS\r
1509         struct sta_info *ptdls_sta;\r
1510 #endif /* CONFIG_TDLS */\r
1511         \r
1512         DBG_871X(FUNC_NDEV_FMT" adding key for %pM\n", FUNC_NDEV_ARG(ndev), mac_addr);\r
1513         DBG_871X("cipher=0x%x\n", params->cipher);\r
1514         DBG_871X("key_len=0x%x\n", params->key_len);\r
1515         DBG_871X("seq_len=0x%x\n", params->seq_len);\r
1516         DBG_871X("key_index=%d\n", key_index);\r
1517 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
1518         DBG_871X("pairwise=%d\n", pairwise);\r
1519 #endif  // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))\r
1520 \r
1521         param_len = sizeof(struct ieee_param) + params->key_len;\r
1522         param = (struct ieee_param *)rtw_malloc(param_len);\r
1523         if (param == NULL)\r
1524                 return -1;\r
1525         \r
1526         _rtw_memset(param, 0, param_len);\r
1527 \r
1528         param->cmd = IEEE_CMD_SET_ENCRYPTION;\r
1529         _rtw_memset(param->sta_addr, 0xff, ETH_ALEN);\r
1530 \r
1531         switch (params->cipher) {\r
1532         case IW_AUTH_CIPHER_NONE:\r
1533                 //todo: remove key \r
1534                 //remove = 1;   \r
1535                 alg_name = "none";\r
1536                 break;\r
1537         case WLAN_CIPHER_SUITE_WEP40:\r
1538         case WLAN_CIPHER_SUITE_WEP104:\r
1539                 alg_name = "WEP";\r
1540                 break;\r
1541         case WLAN_CIPHER_SUITE_TKIP:\r
1542                 alg_name = "TKIP";\r
1543                 break;\r
1544         case WLAN_CIPHER_SUITE_CCMP:\r
1545                 alg_name = "CCMP";\r
1546                 break;\r
1547 #ifdef CONFIG_IEEE80211W\r
1548         case WLAN_CIPHER_SUITE_AES_CMAC:\r
1549                 alg_name = "BIP";\r
1550                 break;\r
1551 #endif //CONFIG_IEEE80211W\r
1552 #ifdef CONFIG_WAPI_SUPPORT\r
1553         case WLAN_CIPHER_SUITE_SMS4:\r
1554                 alg_name= "SMS4";\r
1555                 if(pairwise == NL80211_KEYTYPE_PAIRWISE) {\r
1556                         if (key_index != 0 && key_index != 1) {\r
1557                                 ret = -ENOTSUPP;\r
1558                                 goto addkey_end;\r
1559                         }\r
1560                         _rtw_memcpy((void*)param->sta_addr, (void*)mac_addr, ETH_ALEN);\r
1561                 } else {\r
1562                         DBG_871X("mac_addr is null \n");\r
1563                 }\r
1564                 DBG_871X("rtw_wx_set_enc_ext: SMS4 case \n");\r
1565                 break;\r
1566 #endif\r
1567 \r
1568         default:        \r
1569                 ret = -ENOTSUPP;\r
1570                 goto addkey_end;\r
1571         }\r
1572         \r
1573         strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);\r
1574         \r
1575 \r
1576         if (!mac_addr || is_broadcast_ether_addr(mac_addr))\r
1577         {\r
1578                 param->u.crypt.set_tx = 0; //for wpa/wpa2 group key\r
1579         } else {\r
1580                 param->u.crypt.set_tx = 1; //for wpa/wpa2 pairwise key\r
1581         }\r
1582         \r
1583         \r
1584         //param->u.crypt.idx = key_index - 1;\r
1585         param->u.crypt.idx = key_index;\r
1586         \r
1587         if (params->seq_len && params->seq) \r
1588         {       \r
1589                 _rtw_memcpy(param->u.crypt.seq, (u8 *)params->seq, params->seq_len);\r
1590         }\r
1591 \r
1592         if(params->key_len && params->key)\r
1593         {\r
1594                 param->u.crypt.key_len = params->key_len;               \r
1595                 _rtw_memcpy(param->u.crypt.key, (u8 *)params->key, params->key_len);\r
1596         }       \r
1597 \r
1598         if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)\r
1599         {\r
1600 #ifdef CONFIG_TDLS\r
1601                 if (rtw_tdls_is_driver_setup(padapter) == _FALSE && mac_addr) {\r
1602                         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, (void *)mac_addr);\r
1603                         if (ptdls_sta != NULL && ptdls_sta->tdls_sta_state) {\r
1604                                 _rtw_memcpy(ptdls_sta->tpk.tk, params->key, params->key_len);\r
1605                                 rtw_tdls_set_key(padapter, ptdls_sta);\r
1606                                 goto addkey_end;\r
1607                         }\r
1608                 }\r
1609 #endif /* CONFIG_TDLS */\r
1610 \r
1611                 ret =  rtw_cfg80211_set_encryption(ndev, param, param_len);     \r
1612         }\r
1613         else if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)\r
1614         {\r
1615 #ifdef CONFIG_AP_MODE\r
1616                 if(mac_addr)\r
1617                         _rtw_memcpy(param->sta_addr, (void*)mac_addr, ETH_ALEN);\r
1618         \r
1619                 ret = rtw_cfg80211_ap_set_encryption(ndev, param, param_len);\r
1620 #endif\r
1621         }\r
1622         else if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE\r
1623                 || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)\r
1624         {\r
1625                 //DBG_8192C("@@@@@@@@@@ fw_state=0x%x, iftype=%d\n", pmlmepriv->fw_state, rtw_wdev->iftype);\r
1626                 ret =  rtw_cfg80211_set_encryption(ndev, param, param_len);\r
1627         }\r
1628         else\r
1629         {\r
1630                 DBG_8192C("error! fw_state=0x%x, iftype=%d\n", pmlmepriv->fw_state, rtw_wdev->iftype);\r
1631                 \r
1632         }\r
1633 \r
1634 addkey_end:\r
1635         if(param)\r
1636         {\r
1637                 rtw_mfree((u8*)param, param_len);\r
1638         }\r
1639 \r
1640         return ret;\r
1641 \r
1642 }\r
1643 \r
1644 static int cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,\r
1645 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
1646                                 u8 key_index, bool pairwise, const u8 *mac_addr,\r
1647 #else   // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))\r
1648                                 u8 key_index, const u8 *mac_addr,\r
1649 #endif  // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))\r
1650                                 void *cookie,\r
1651                                 void (*callback)(void *cookie,\r
1652                                                  struct key_params*))\r
1653 {\r
1654 #if 0\r
1655         struct iwm_priv *iwm = ndev_to_iwm(ndev);\r
1656         struct iwm_key *key = &iwm->keys[key_index];\r
1657         struct key_params params;\r
1658 \r
1659         IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);\r
1660 \r
1661         memset(&params, 0, sizeof(params));\r
1662 \r
1663         params.cipher = key->cipher;\r
1664         params.key_len = key->key_len;\r
1665         params.seq_len = key->seq_len;\r
1666         params.seq = key->seq;\r
1667         params.key = key->key;\r
1668 \r
1669         callback(cookie, &params);\r
1670 \r
1671         return key->key_len ? 0 : -ENOENT;\r
1672 #endif\r
1673         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
1674         return 0;\r
1675 }\r
1676 \r
1677 static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,\r
1678 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
1679                                 u8 key_index, bool pairwise, const u8 *mac_addr)\r
1680 #else   // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))\r
1681                                 u8 key_index, const u8 *mac_addr)\r
1682 #endif  // (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))\r
1683 {\r
1684         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);         \r
1685         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
1686 \r
1687         DBG_871X(FUNC_NDEV_FMT" key_index=%d\n", FUNC_NDEV_ARG(ndev), key_index);\r
1688 \r
1689         if (key_index == psecuritypriv->dot11PrivacyKeyIndex)\r
1690         {\r
1691                 //clear the flag of wep default key set.\r
1692                 psecuritypriv->bWepDefaultKeyIdxSet = 0;\r
1693         }\r
1694 \r
1695         return 0;\r
1696 }\r
1697 \r
1698 static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,\r
1699         struct net_device *ndev, u8 key_index\r
1700         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)\r
1701         , bool unicast, bool multicast\r
1702         #endif\r
1703         )\r
1704 {\r
1705         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);         \r
1706         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
1707 \r
1708 #define SET_DEF_KEY_PARAM_FMT " key_index=%d"\r
1709 #define SET_DEF_KEY_PARAM_ARG , key_index\r
1710 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)\r
1711         #define SET_DEF_KEY_PARAM_FMT_2_6_38 ", unicast=%d, multicast=%d"\r
1712         #define SET_DEF_KEY_PARAM_ARG_2_6_38 , unicast, multicast\r
1713 #else\r
1714         #define SET_DEF_KEY_PARAM_FMT_2_6_38 ""\r
1715         #define SET_DEF_KEY_PARAM_ARG_2_6_38\r
1716 #endif\r
1717 \r
1718         DBG_871X(FUNC_NDEV_FMT\r
1719                 SET_DEF_KEY_PARAM_FMT\r
1720                 SET_DEF_KEY_PARAM_FMT_2_6_38\r
1721                 "\n", FUNC_NDEV_ARG(ndev)\r
1722                 SET_DEF_KEY_PARAM_ARG\r
1723                 SET_DEF_KEY_PARAM_ARG_2_6_38\r
1724         );\r
1725 \r
1726         if ((key_index < WEP_KEYS) && ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) || (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_))) //set wep default key\r
1727         {\r
1728                 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;\r
1729 \r
1730                 psecuritypriv->dot11PrivacyKeyIndex = key_index;\r
1731 \r
1732                 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;\r
1733                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;\r
1734                 if (psecuritypriv->dot11DefKeylen[key_index] == 13)\r
1735                 {\r
1736                         psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;\r
1737                         psecuritypriv->dot118021XGrpPrivacy = _WEP104_;\r
1738                 }\r
1739 \r
1740                 psecuritypriv->bWepDefaultKeyIdxSet = 1; //set the flag to represent that wep default key has been set\r
1741         }\r
1742 \r
1743         return 0;\r
1744 \r
1745 }\r
1746 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))\r
1747 static int cfg80211_rtw_set_rekey_data(struct wiphy *wiphy,\r
1748         struct net_device *ndev,\r
1749         struct cfg80211_gtk_rekey_data *data)\r
1750 {\r
1751         /*int i;*/\r
1752         struct sta_info *psta;\r
1753         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
1754         struct mlme_priv   *pmlmepriv = &padapter->mlmepriv;\r
1755         struct sta_priv *pstapriv = &padapter->stapriv;\r
1756         struct security_priv *psecuritypriv = &(padapter->securitypriv);\r
1757 \r
1758         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));\r
1759         if (psta == NULL) {\r
1760                 DBG_871X("%s, : Obtain Sta_info fail\n", __func__);\r
1761                 return -1;\r
1762         }\r
1763 \r
1764         _rtw_memcpy(psta->kek, data->kek, NL80211_KEK_LEN);\r
1765         /*printk("\ncfg80211_rtw_set_rekey_data KEK:");\r
1766         for(i=0;i<NL80211_KEK_LEN; i++)\r
1767                 printk(" %02x ", psta->kek[i]);*/\r
1768         _rtw_memcpy(psta->kck, data->kck, NL80211_KCK_LEN);\r
1769         /*printk("\ncfg80211_rtw_set_rekey_data KCK:");\r
1770         for(i=0;i<NL80211_KCK_LEN; i++)\r
1771                 printk(" %02x ", psta->kck[i]);*/\r
1772         _rtw_memcpy(psta->replay_ctr, data->replay_ctr, NL80211_REPLAY_CTR_LEN);\r
1773         psecuritypriv->binstallKCK_KEK = _TRUE;\r
1774         /*printk("\nREPLAY_CTR: ");\r
1775         for(i=0;i<RTW_REPLAY_CTR_LEN; i++)\r
1776                 printk(" %02x ", psta->replay_ctr[i]);*/\r
1777 \r
1778         return 0;\r
1779 }\r
1780 #endif /*CONFIG_GTK_OL*/\r
1781 static int cfg80211_rtw_get_station(struct wiphy *wiphy,\r
1782                                 struct net_device *ndev,\r
1783 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0))\r
1784                                 u8 *mac, \r
1785 #else\r
1786                                 const u8 *mac,\r
1787 #endif\r
1788                                 struct station_info *sinfo)\r
1789 {\r
1790         int ret = 0;\r
1791         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
1792         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;\r
1793         struct sta_info *psta = NULL;\r
1794         struct sta_priv *pstapriv = &padapter->stapriv;\r
1795 \r
1796         sinfo->filled = 0;\r
1797 \r
1798         if (!mac) {\r
1799                 DBG_871X(FUNC_NDEV_FMT" mac==%p\n", FUNC_NDEV_ARG(ndev), mac);\r
1800                 ret = -ENOENT;\r
1801                 goto exit;\r
1802         }\r
1803 \r
1804         psta = rtw_get_stainfo(pstapriv, (u8 *)mac);\r
1805         if (psta == NULL) {\r
1806                 DBG_8192C("%s, sta_info is null\n", __func__);\r
1807                 ret = -ENOENT;\r
1808                 goto exit;\r
1809         }\r
1810 \r
1811 #ifdef CONFIG_DEBUG_CFG80211\r
1812         DBG_871X(FUNC_NDEV_FMT" mac="MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(mac));\r
1813 #endif\r
1814 \r
1815         //for infra./P2PClient mode\r
1816         if(     check_fwstate(pmlmepriv, WIFI_STATION_STATE)\r
1817                 && check_fwstate(pmlmepriv, _FW_LINKED)\r
1818         )\r
1819         {\r
1820                 struct wlan_network  *cur_network = &(pmlmepriv->cur_network);\r
1821 \r
1822                 if (_rtw_memcmp((u8 *)mac, cur_network->network.MacAddress, ETH_ALEN) == _FALSE) {\r
1823                         DBG_871X("%s, mismatch bssid="MAC_FMT"\n", __func__, MAC_ARG(cur_network->network.MacAddress));\r
1824                         ret = -ENOENT;\r
1825                         goto exit;\r
1826                 }\r
1827 \r
1828                 sinfo->filled |= STATION_INFO_SIGNAL;\r
1829                 sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);\r
1830 \r
1831                 sinfo->filled |= STATION_INFO_TX_BITRATE;\r
1832                 sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);\r
1833 \r
1834                 sinfo->filled |= STATION_INFO_RX_PACKETS;\r
1835                 sinfo->rx_packets = sta_rx_data_pkts(psta);\r
1836 \r
1837                 sinfo->filled |= STATION_INFO_TX_PACKETS;\r
1838                 sinfo->tx_packets = psta->sta_stats.tx_pkts;\r
1839 \r
1840         }\r
1841 \r
1842         //for Ad-Hoc/AP mode\r
1843         if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)\r
1844                         ||check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)\r
1845                         ||check_fwstate(pmlmepriv, WIFI_AP_STATE))\r
1846                 && check_fwstate(pmlmepriv, _FW_LINKED)\r
1847         )\r
1848         {\r
1849                 //TODO: should acquire station info...\r
1850         }\r
1851 \r
1852 exit:\r
1853         return ret;\r
1854 }\r
1855 \r
1856 extern int netdev_open(struct net_device *pnetdev);\r
1857 #ifdef CONFIG_CONCURRENT_MODE\r
1858 extern int netdev_if2_open(struct net_device *pnetdev);\r
1859 #endif\r
1860 \r
1861 /*\r
1862 enum nl80211_iftype {\r
1863         NL80211_IFTYPE_UNSPECIFIED,\r
1864        NL80211_IFTYPE_ADHOC, //1\r
1865        NL80211_IFTYPE_STATION, //2\r
1866        NL80211_IFTYPE_AP, //3\r
1867        NL80211_IFTYPE_AP_VLAN,\r
1868        NL80211_IFTYPE_WDS,\r
1869        NL80211_IFTYPE_MONITOR, //6\r
1870        NL80211_IFTYPE_MESH_POINT,\r
1871        NL80211_IFTYPE_P2P_CLIENT, //8\r
1872         NL80211_IFTYPE_P2P_GO, //9\r
1873        //keep last \r
1874        NUM_NL80211_IFTYPES,\r
1875        NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1\r
1876 };\r
1877 */\r
1878 static int cfg80211_rtw_change_iface(struct wiphy *wiphy,\r
1879                                      struct net_device *ndev,\r
1880                                      enum nl80211_iftype type, u32 *flags,\r
1881                                      struct vif_params *params)\r
1882 {\r
1883         enum nl80211_iftype old_type;\r
1884         NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;\r
1885         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
1886         struct wireless_dev *rtw_wdev = padapter->rtw_wdev;\r
1887         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
1888 #ifdef CONFIG_P2P\r
1889         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);\r
1890 #endif\r
1891         int ret = 0;\r
1892         u8 change = _FALSE;\r
1893 \r
1894         DBG_871X(FUNC_NDEV_FMT" type=%d\n", FUNC_NDEV_ARG(ndev), type);\r
1895 \r
1896         if(adapter_to_dvobj(padapter)->processing_dev_remove == _TRUE)\r
1897         {\r
1898                 ret= -EPERM;\r
1899                 goto exit;\r
1900         }               \r
1901         \r
1902 #ifdef CONFIG_CONCURRENT_MODE\r
1903         if(padapter->adapter_type == SECONDARY_ADAPTER)\r
1904         {\r
1905                 DBG_871X(FUNC_NDEV_FMT" call netdev_if2_open\n", FUNC_NDEV_ARG(ndev));\r
1906                 if(netdev_if2_open(ndev) != 0) {\r
1907                         DBG_871X(FUNC_NDEV_FMT" call netdev_if2_open fail\n", FUNC_NDEV_ARG(ndev));\r
1908                         ret= -EPERM;\r
1909                         goto exit;\r
1910                 }\r
1911         }\r
1912         else if(padapter->adapter_type == PRIMARY_ADAPTER)\r
1913 #endif //CONFIG_CONCURRENT_MODE\r
1914         {\r
1915                 DBG_871X(FUNC_NDEV_FMT" call netdev_open\n", FUNC_NDEV_ARG(ndev));\r
1916                 if(netdev_open(ndev) != 0) {\r
1917                         DBG_871X(FUNC_NDEV_FMT" call netdev_open fail\n", FUNC_NDEV_ARG(ndev));\r
1918                         ret= -EPERM;\r
1919                         goto exit;\r
1920                 }\r
1921         }\r
1922 \r
1923         if(_FAIL == rtw_pwr_wakeup(padapter)) {\r
1924                 DBG_871X(FUNC_NDEV_FMT" call rtw_pwr_wakeup fail\n", FUNC_NDEV_ARG(ndev));\r
1925                 ret= -EPERM;\r
1926                 goto exit;\r
1927         }\r
1928 \r
1929         old_type = rtw_wdev->iftype;\r
1930         DBG_871X(FUNC_NDEV_FMT" old_iftype=%d, new_iftype=%d\n",\r
1931                 FUNC_NDEV_ARG(ndev), old_type, type);\r
1932 \r
1933         if(old_type != type)\r
1934         {\r
1935                 change = _TRUE;\r
1936                 pmlmeext->action_public_rxseq = 0xffff;\r
1937                 pmlmeext->action_public_dialog_token = 0xff;\r
1938         }       \r
1939 \r
1940         /* initial default type */\r
1941         ndev->type = ARPHRD_ETHER;\r
1942 \r
1943         switch (type) {\r
1944         case NL80211_IFTYPE_ADHOC:\r
1945                 networkType = Ndis802_11IBSS;\r
1946                 break;\r
1947 #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE))\r
1948         case NL80211_IFTYPE_P2P_CLIENT:\r
1949 #endif\r
1950         case NL80211_IFTYPE_STATION:\r
1951                 networkType = Ndis802_11Infrastructure;\r
1952                 #ifdef CONFIG_P2P\r
1953                 if(pwdinfo->driver_interface == DRIVER_CFG80211 )\r
1954                 {\r
1955                         if(change && rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))\r
1956                         {\r
1957                                 //it means remove GO and change mode from AP(GO) to station(P2P DEVICE)\r
1958                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);\r
1959                                 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));\r
1960 \r
1961                                 DBG_8192C("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));\r
1962                         }\r
1963                 }\r
1964                 #endif //CONFIG_P2P\r
1965                 break;\r
1966 #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE))\r
1967         case NL80211_IFTYPE_P2P_GO:\r
1968 #endif\r
1969         case NL80211_IFTYPE_AP:\r
1970                 networkType = Ndis802_11APMode;\r
1971                 #ifdef CONFIG_P2P\r
1972                 if(pwdinfo->driver_interface == DRIVER_CFG80211 )\r
1973                 {\r
1974                         if(change && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))\r
1975                         {\r
1976                                 //it means P2P Group created, we will be GO and change mode from  P2P DEVICE to AP(GO)\r
1977                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);\r
1978                         }\r
1979                 }\r
1980                 #endif //CONFIG_P2P\r
1981                 break;\r
1982         case NL80211_IFTYPE_MONITOR:\r
1983                 networkType = Ndis802_11Monitor;\r
1984 #if 0\r
1985                 ndev->type = ARPHRD_IEEE80211; /* IEEE 802.11 : 801 */\r
1986 #endif\r
1987                 ndev->type = ARPHRD_IEEE80211_RADIOTAP; /* IEEE 802.11 + radiotap header : 803 */\r
1988                 break;\r
1989         default:\r
1990                 ret = -EOPNOTSUPP;\r
1991                 goto exit;\r
1992         }\r
1993 \r
1994         rtw_wdev->iftype = type;\r
1995         \r
1996         if (rtw_set_802_11_infrastructure_mode(padapter, networkType) ==_FALSE)\r
1997         {\r
1998                 rtw_wdev->iftype = old_type;\r
1999                 ret = -EPERM;\r
2000                 goto exit;\r
2001         }\r
2002 \r
2003         rtw_setopmode_cmd(padapter, networkType, _TRUE);\r
2004         \r
2005 exit:\r
2006 \r
2007         DBG_871X(FUNC_NDEV_FMT" ret:%d\n", FUNC_NDEV_ARG(ndev), ret);\r
2008         return ret;\r
2009 }\r
2010 \r
2011 void rtw_cfg80211_indicate_scan_done(_adapter *adapter, bool aborted)\r
2012 {\r
2013         struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);\r
2014         _irqL   irqL;\r
2015 \r
2016         _enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);\r
2017         if (pwdev_priv->scan_request != NULL) {\r
2018                 #ifdef CONFIG_DEBUG_CFG80211\r
2019                 DBG_871X("%s with scan req\n", __FUNCTION__);\r
2020                 #endif\r
2021 \r
2022                 /* avoid WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); */\r
2023                 if(pwdev_priv->scan_request->wiphy != pwdev_priv->rtw_wdev->wiphy)\r
2024                 {\r
2025                         DBG_8192C("error wiphy compare\n");\r
2026                 }\r
2027                 else\r
2028                 {\r
2029                         cfg80211_scan_done(pwdev_priv->scan_request, aborted);\r
2030                 }\r
2031 \r
2032                 pwdev_priv->scan_request = NULL;\r
2033         } else {\r
2034                 #ifdef CONFIG_DEBUG_CFG80211\r
2035                 DBG_871X("%s without scan req\n", __FUNCTION__);\r
2036                 #endif\r
2037         }\r
2038         _exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);\r
2039 }\r
2040 \r
2041 void rtw_cfg80211_unlink_bss(_adapter *padapter, struct wlan_network *pnetwork)\r
2042 {\r
2043         struct wireless_dev *pwdev = padapter->rtw_wdev;\r
2044         struct wiphy *wiphy = pwdev->wiphy;\r
2045         struct cfg80211_bss *bss = NULL;\r
2046         WLAN_BSSID_EX select_network = pnetwork->network;\r
2047         \r
2048         bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/,\r
2049                 select_network.MacAddress, select_network.Ssid.Ssid,\r
2050                 select_network.Ssid.SsidLength, 0/*WLAN_CAPABILITY_ESS*/, \r
2051                 0/*WLAN_CAPABILITY_ESS*/);\r
2052         \r
2053         if (bss) {\r
2054                 cfg80211_unlink_bss(wiphy, bss);\r
2055                 DBG_8192C("%s(): cfg80211_unlink %s!! () ",__func__,select_network.Ssid.Ssid );\r
2056 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)\r
2057                 cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss);\r
2058 #else\r
2059                 cfg80211_put_bss(bss);\r
2060 #endif\r
2061         }\r
2062         return;\r
2063 }\r
2064 \r
2065 void rtw_cfg80211_surveydone_event_callback(_adapter *padapter)\r
2066 {\r
2067         _irqL   irqL;\r
2068         _list                                   *plist, *phead; \r
2069         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);     \r
2070         _queue                          *queue  = &(pmlmepriv->scanned_queue);  \r
2071         struct  wlan_network    *pnetwork = NULL;\r
2072         u32 cnt=0;\r
2073         u32 wait_for_surveydone;\r
2074         sint wait_status;\r
2075 #ifdef CONFIG_P2P\r
2076         struct  wifidirect_info*        pwdinfo = &padapter->wdinfo;\r
2077 #endif //CONFIG_P2P\r
2078         struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);\r
2079 \r
2080 #ifdef CONFIG_DEBUG_CFG80211\r
2081         DBG_8192C("%s\n", __func__);\r
2082 #endif\r
2083 \r
2084         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);\r
2085 \r
2086         phead = get_list_head(queue);\r
2087         plist = get_next(phead);\r
2088        \r
2089         while(1)\r
2090         {\r
2091                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)\r
2092                         break;\r
2093 \r
2094                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);\r
2095 \r
2096                 //report network only if the current channel set contains the channel to which this network belongs\r
2097                 if(rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0\r
2098                         && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == _TRUE\r
2099                         && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))\r
2100                 )\r
2101                 {               \r
2102                         //ev=translate_scan(padapter, a, pnetwork, ev, stop);\r
2103                         rtw_cfg80211_inform_bss(padapter, pnetwork);            \r
2104                 }\r
2105                 /* //check ralink testbed RSN IE length\r
2106                 {\r
2107                         if(_rtw_memcmp(pnetwork->network.Ssid.Ssid, "Ralink_11n_AP",13))\r
2108                         {\r
2109                                 uint ie_len=0;\r
2110                                 u8 *p=NULL;\r
2111                                 p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pnetwork->network.IELength - _BEACON_IE_OFFSET_));\r
2112                                 DBG_871X("ie_len=%d\n", ie_len);\r
2113                         }\r
2114                 }*/\r
2115                 plist = get_next(plist);\r
2116         \r
2117         }\r
2118         \r
2119         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);\r
2120 }\r
2121 \r
2122 static int rtw_cfg80211_set_probe_req_wpsp2pie(_adapter *padapter, char *buf, int len)\r
2123 {\r
2124         int ret = 0;\r
2125         uint wps_ielen = 0;\r
2126         u8 *wps_ie;\r
2127         u32     p2p_ielen = 0;  \r
2128         u8 *p2p_ie;\r
2129         u32     wfd_ielen = 0;  \r
2130         u8 *wfd_ie;\r
2131         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);    \r
2132 \r
2133 #ifdef CONFIG_DEBUG_CFG80211\r
2134         DBG_8192C("%s, ielen=%d\n", __func__, len);\r
2135 #endif\r
2136         \r
2137         if(len>0)\r
2138         {\r
2139                 if((wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen)))\r
2140                 {\r
2141                         #ifdef CONFIG_DEBUG_CFG80211\r
2142                         DBG_8192C("probe_req_wps_ielen=%d\n", wps_ielen);\r
2143                         #endif\r
2144                         \r
2145                         if(pmlmepriv->wps_probe_req_ie)\r
2146                         {\r
2147                                 u32 free_len = pmlmepriv->wps_probe_req_ie_len;\r
2148                                 pmlmepriv->wps_probe_req_ie_len = 0;\r
2149                                 rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);\r
2150                                 pmlmepriv->wps_probe_req_ie = NULL;                     \r
2151                         }       \r
2152 \r
2153                         pmlmepriv->wps_probe_req_ie = rtw_malloc(wps_ielen);\r
2154                         if ( pmlmepriv->wps_probe_req_ie == NULL) {\r
2155                                 DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
2156                                 return -EINVAL;\r
2157                         \r
2158                         }\r
2159                         _rtw_memcpy(pmlmepriv->wps_probe_req_ie, wps_ie, wps_ielen);\r
2160                         pmlmepriv->wps_probe_req_ie_len = wps_ielen;\r
2161                 }\r
2162 \r
2163                 //buf += wps_ielen;\r
2164                 //len -= wps_ielen;\r
2165 \r
2166                 #ifdef CONFIG_P2P\r
2167                 if((p2p_ie=rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen))) \r
2168                 {\r
2169                         struct wifidirect_info *wdinfo = &padapter->wdinfo;\r
2170                         u32 attr_contentlen = 0;\r
2171                         u8 listen_ch_attr[5];\r
2172 \r
2173                         #ifdef CONFIG_DEBUG_CFG80211\r
2174                         DBG_8192C("probe_req_p2p_ielen=%d\n", p2p_ielen);\r
2175                         #endif\r
2176                         \r
2177                         if(pmlmepriv->p2p_probe_req_ie)\r
2178                         {\r
2179                                 u32 free_len = pmlmepriv->p2p_probe_req_ie_len;\r
2180                                 pmlmepriv->p2p_probe_req_ie_len = 0;\r
2181                                 rtw_mfree(pmlmepriv->p2p_probe_req_ie, free_len);\r
2182                                 pmlmepriv->p2p_probe_req_ie = NULL;\r
2183                         }       \r
2184 \r
2185                         pmlmepriv->p2p_probe_req_ie = rtw_malloc(p2p_ielen);\r
2186                         if ( pmlmepriv->p2p_probe_req_ie == NULL) {\r
2187                                 DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
2188                                 return -EINVAL;\r
2189                         \r
2190                         }\r
2191                         _rtw_memcpy(pmlmepriv->p2p_probe_req_ie, p2p_ie, p2p_ielen);\r
2192                         pmlmepriv->p2p_probe_req_ie_len = p2p_ielen;\r
2193 \r
2194                         if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, (u8*)listen_ch_attr, (uint*) &attr_contentlen)\r
2195                                 && attr_contentlen == 5)\r
2196                         {\r
2197                                 if (wdinfo->listen_channel !=  listen_ch_attr[4]) {\r
2198                                         DBG_871X(FUNC_ADPT_FMT" listen channel - country:%c%c%c, class:%u, ch:%u\n",\r
2199                                                 FUNC_ADPT_ARG(padapter), listen_ch_attr[0], listen_ch_attr[1], listen_ch_attr[2],\r
2200                                                 listen_ch_attr[3], listen_ch_attr[4]);\r
2201                                         wdinfo->listen_channel = listen_ch_attr[4];\r
2202                                 }\r
2203                         }\r
2204                 }\r
2205                 #endif //CONFIG_P2P\r
2206                 \r
2207                 //buf += p2p_ielen;\r
2208                 //len -= p2p_ielen;\r
2209 \r
2210                 #ifdef CONFIG_WFD\r
2211                 if(rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) \r
2212                 {\r
2213                         #ifdef CONFIG_DEBUG_CFG80211\r
2214                         DBG_8192C("probe_req_wfd_ielen=%d\n", wfd_ielen);\r
2215                         #endif\r
2216                         \r
2217                         if(pmlmepriv->wfd_probe_req_ie)\r
2218                         {\r
2219                                 u32 free_len = pmlmepriv->wfd_probe_req_ie_len;\r
2220                                 pmlmepriv->wfd_probe_req_ie_len = 0;\r
2221                                 rtw_mfree(pmlmepriv->wfd_probe_req_ie, free_len);\r
2222                                 pmlmepriv->wfd_probe_req_ie = NULL;\r
2223                         }       \r
2224 \r
2225                         pmlmepriv->wfd_probe_req_ie = rtw_malloc(wfd_ielen);\r
2226                         if ( pmlmepriv->wfd_probe_req_ie == NULL) {\r
2227                                 DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
2228                                 return -EINVAL;\r
2229                         \r
2230                         }\r
2231                         rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_probe_req_ie, &pmlmepriv->wfd_probe_req_ie_len);                        \r
2232                 }\r
2233                 #endif //CONFIG_WFD\r
2234                 \r
2235         }\r
2236 \r
2237         return ret;\r
2238         \r
2239 }\r
2240 \r
2241 static int cfg80211_rtw_scan(struct wiphy *wiphy\r
2242         #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))\r
2243         , struct net_device *ndev\r
2244         #endif\r
2245         , struct cfg80211_scan_request *request)\r
2246 {\r
2247 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
2248         struct net_device *ndev = wdev_to_ndev(request->wdev);\r
2249 #endif\r
2250         int i;\r
2251         u8 _status = _FALSE;\r
2252         int ret = 0;    \r
2253         NDIS_802_11_SSID ssid[RTW_SSID_SCAN_AMOUNT];\r
2254         struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];\r
2255         _irqL   irqL;\r
2256         u8 *wps_ie=NULL;\r
2257         uint wps_ielen=0;       \r
2258         u8 *p2p_ie=NULL;\r
2259         uint p2p_ielen=0;\r
2260         u8 survey_times=3;\r
2261         u8 survey_times_for_one_ch=6;\r
2262         struct cfg80211_ssid *ssids = request->ssids;\r
2263         int social_channel = 0, j = 0;\r
2264         bool need_indicate_scan_done = _FALSE;\r
2265         bool ps_denied = _FALSE;\r
2266 \r
2267         _adapter *padapter;\r
2268         struct rtw_wdev_priv *pwdev_priv;\r
2269         struct mlme_priv *pmlmepriv;\r
2270 #ifdef CONFIG_P2P\r
2271         struct wifidirect_info *pwdinfo;\r
2272 #endif //CONFIG_P2P\r
2273 #ifdef CONFIG_CONCURRENT_MODE   \r
2274         PADAPTER pbuddy_adapter = NULL;\r
2275         struct mlme_priv *pbuddy_mlmepriv = NULL;\r
2276 #endif //CONFIG_CONCURRENT_MODE\r
2277 \r
2278         if (ndev == NULL) {\r
2279                 ret = -EINVAL;\r
2280                 goto exit;\r
2281         }\r
2282 \r
2283         padapter = (_adapter *)rtw_netdev_priv(ndev);\r
2284         pwdev_priv = adapter_wdev_data(padapter);\r
2285         pmlmepriv= &padapter->mlmepriv;\r
2286 #ifdef CONFIG_P2P\r
2287         pwdinfo= &(padapter->wdinfo);   \r
2288 #endif //CONFIG_P2P\r
2289 \r
2290 //#ifdef CONFIG_DEBUG_CFG80211\r
2291         DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));\r
2292 //#endif\r
2293 \r
2294 #ifdef CONFIG_CONCURRENT_MODE\r
2295         if (padapter->pbuddy_adapter) {\r
2296                 pbuddy_adapter = padapter->pbuddy_adapter;\r
2297                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);  \r
2298         }\r
2299 #endif //CONFIG_CONCURRENT_MODE\r
2300 \r
2301 #ifdef CONFIG_MP_INCLUDED\r
2302 if (padapter->registrypriv.mp_mode == 1)\r
2303 {\r
2304                 DBG_871X(FUNC_ADPT_FMT ": MP mode block Scan request\n", FUNC_ADPT_ARG(padapter));  \r
2305                 ret = -EPERM;\r
2306                 goto exit;\r
2307 }\r
2308 #ifdef CONFIG_CONCURRENT_MODE\r
2309         if (padapter->pbuddy_adapter) {\r
2310                 if (padapter->pbuddy_adapter->registrypriv.mp_mode == 1)\r
2311                 {\r
2312                         DBG_871X(FUNC_ADPT_FMT ": MP mode block Scan request\n", FUNC_ADPT_ARG(padapter->pbuddy_adapter));\r
2313                         ret = -EPERM;\r
2314                         goto exit;\r
2315                 }\r
2316         }\r
2317 #endif //CONFIG_CONCURRENT_MODE\r
2318 #endif\r
2319 \r
2320         _enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);\r
2321         pwdev_priv->scan_request = request;\r
2322         _exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);\r
2323 \r
2324         if (adapter_wdev_data(padapter)->block_scan == _TRUE) {\r
2325                 DBG_871X(FUNC_ADPT_FMT" wdev_priv.block_scan is set\n", FUNC_ADPT_ARG(padapter));\r
2326                 need_indicate_scan_done = _TRUE;\r
2327                 goto check_need_indicate_scan_done;\r
2328         }\r
2329 \r
2330         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)\r
2331         {\r
2332 #ifdef CONFIG_DEBUG_CFG80211\r
2333                 DBG_871X("%s under WIFI_AP_STATE\n", __FUNCTION__);\r
2334 #endif\r
2335 \r
2336                 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS|_FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)\r
2337                 {\r
2338                         DBG_8192C("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);\r
2339 \r
2340                         if(check_fwstate(pmlmepriv, WIFI_UNDER_WPS))\r
2341                         {\r
2342                                 DBG_8192C("AP mode process WPS \n");\r
2343                         }\r
2344                         \r
2345                         need_indicate_scan_done = _TRUE;\r
2346                         goto check_need_indicate_scan_done;\r
2347                 } \r
2348         }\r
2349 \r
2350         rtw_ps_deny(padapter, PS_DENY_SCAN);\r
2351         ps_denied = _TRUE;\r
2352         if(_FAIL == rtw_pwr_wakeup(padapter)) {\r
2353                 need_indicate_scan_done = _TRUE;\r
2354                 goto check_need_indicate_scan_done;\r
2355         }\r
2356 \r
2357         #ifdef CONFIG_P2P\r
2358         if( pwdinfo->driver_interface == DRIVER_CFG80211 )\r
2359         {\r
2360                 if(ssids->ssid != NULL\r
2361                         && _rtw_memcmp(ssids->ssid, "DIRECT-", 7)\r
2362                         && rtw_get_p2p_ie((u8 *)request->ie, request->ie_len, NULL, NULL)\r
2363                 )\r
2364                 {\r
2365                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))\r
2366                         {\r
2367                                 rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);\r
2368                                 adapter_wdev_data(padapter)->p2p_enabled = _TRUE;\r
2369                         }\r
2370                         else\r
2371                         {\r
2372                                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));\r
2373                                 #ifdef CONFIG_DEBUG_CFG80211\r
2374                                 DBG_8192C("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));\r
2375                                 #endif\r
2376                         }\r
2377                         rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);\r
2378                 \r
2379                         if(request->n_channels == 3 &&\r
2380                                 request->channels[0]->hw_value == 1 &&\r
2381                                 request->channels[1]->hw_value == 6 &&\r
2382                                 request->channels[2]->hw_value == 11\r
2383                         )\r
2384                         {\r
2385                                 social_channel = 1;\r
2386                         }\r
2387                 }\r
2388         }\r
2389         #endif //CONFIG_P2P\r
2390 \r
2391         if(request->ie && request->ie_len>0)\r
2392         {\r
2393                 rtw_cfg80211_set_probe_req_wpsp2pie(padapter, (u8 *)request->ie, request->ie_len );\r
2394         }\r
2395 \r
2396         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {\r
2397                 DBG_8192C("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);\r
2398                 need_indicate_scan_done = _TRUE;\r
2399                 goto check_need_indicate_scan_done;\r
2400         } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) {\r
2401                 DBG_8192C("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);\r
2402                 ret = -EBUSY;\r
2403                 goto check_need_indicate_scan_done;\r
2404         }\r
2405 \r
2406         if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE)\r
2407         {\r
2408 #if 1 // Miracast can't do AP scan\r
2409                 static u32 lastscantime = 0;\r
2410                 u32 passtime;\r
2411 \r
2412                 passtime = rtw_get_passing_time_ms(lastscantime);\r
2413                 lastscantime = rtw_get_current_time();\r
2414                 if (passtime > BUSY_TRAFFIC_SCAN_DENY_PERIOD)\r
2415 #endif\r
2416                 {\r
2417                         DBG_871X("%s: bBusyTraffic == _TRUE\n", __FUNCTION__);\r
2418                         need_indicate_scan_done = _TRUE;\r
2419                         goto check_need_indicate_scan_done;\r
2420                 }\r
2421         }\r
2422 \r
2423         if (rtw_is_scan_deny(padapter)){\r
2424                 DBG_871X(FUNC_ADPT_FMT  ": scan deny\n", FUNC_ADPT_ARG(padapter));\r
2425                 need_indicate_scan_done = _TRUE;\r
2426                 goto check_need_indicate_scan_done;\r
2427         }\r
2428 \r
2429 #ifdef CONFIG_CONCURRENT_MODE\r
2430         if(pbuddy_mlmepriv && (pbuddy_mlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE))  \r
2431         {\r
2432 #if 1 // Miracast can't do AP scan\r
2433                 static u32 buddylastscantime = 0;\r
2434                 u32 passtime;\r
2435 \r
2436                 passtime = rtw_get_passing_time_ms(buddylastscantime);\r
2437                 buddylastscantime = rtw_get_current_time();\r
2438                 if ((passtime > BUSY_TRAFFIC_SCAN_DENY_PERIOD)\r
2439 //#ifdef CONFIG_P2P\r
2440 //                      ||(!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE))\r
2441 //#endif //CONFIG_P2P\r
2442                 )\r
2443 #endif\r
2444                 {\r
2445                         DBG_871X("%s: bBusyTraffic == _TRUE at buddy_intf\n", __FUNCTION__);\r
2446                         need_indicate_scan_done = _TRUE;\r
2447                         goto check_need_indicate_scan_done;\r
2448                 }\r
2449         }\r
2450 \r
2451         if (check_buddy_fwstate(padapter, _FW_UNDER_LINKING|WIFI_UNDER_WPS) == _TRUE) {\r
2452                 DBG_871X("buddy_intf's mlme state:0x%x\n", pbuddy_mlmepriv->fw_state);\r
2453                 need_indicate_scan_done = _TRUE;\r
2454                 goto check_need_indicate_scan_done;\r
2455 \r
2456         } else if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY)) {\r
2457                 bool scan_via_buddy = _FALSE;\r
2458                 struct rtw_wdev_priv *buddy_wdev_priv = adapter_wdev_data(pbuddy_adapter);\r
2459 \r
2460                 _enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);\r
2461                 _enter_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);\r
2462                 if (buddy_wdev_priv->scan_request) {\r
2463                         DBG_871X("scan via buddy\n");\r
2464                         pmlmepriv->scanning_via_buddy_intf = _TRUE;\r
2465                         _enter_critical_bh(&pmlmepriv->lock, &irqL);\r
2466                         set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);\r
2467                         _exit_critical_bh(&pmlmepriv->lock, &irqL);\r
2468                         scan_via_buddy = _TRUE;\r
2469                 }\r
2470                 _exit_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);\r
2471                 _exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);\r
2472 \r
2473                 if (scan_via_buddy == _FALSE)\r
2474                         need_indicate_scan_done = _TRUE;\r
2475 \r
2476                 goto check_need_indicate_scan_done;\r
2477         }\r
2478 #endif /* CONFIG_CONCURRENT_MODE */\r
2479 \r
2480 #ifdef CONFIG_P2P\r
2481         if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))\r
2482         {\r
2483                 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);\r
2484                 rtw_free_network_queue(padapter, _TRUE);\r
2485 \r
2486                 if(social_channel == 0)\r
2487                         rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);\r
2488                 else\r
2489                         rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_SOCIAL_LAST);\r
2490         }\r
2491 #endif //CONFIG_P2P\r
2492 \r
2493 \r
2494         _rtw_memset(ssid, 0, sizeof(NDIS_802_11_SSID)*RTW_SSID_SCAN_AMOUNT);\r
2495         //parsing request ssids, n_ssids\r
2496         for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {\r
2497                 #ifdef CONFIG_DEBUG_CFG80211\r
2498                 DBG_8192C("ssid=%s, len=%d\n", ssids[i].ssid, ssids[i].ssid_len);\r
2499                 #endif\r
2500                 _rtw_memcpy(ssid[i].Ssid, ssids[i].ssid, ssids[i].ssid_len);\r
2501                 ssid[i].SsidLength = ssids[i].ssid_len; \r
2502         }\r
2503 \r
2504         /* parsing channels, n_channels */\r
2505         _rtw_memset(ch, 0, sizeof(struct rtw_ieee80211_channel)*RTW_CHANNEL_SCAN_AMOUNT);\r
2506         for (i=0;i<request->n_channels && i<RTW_CHANNEL_SCAN_AMOUNT;i++) {\r
2507                 #ifdef CONFIG_DEBUG_CFG80211\r
2508                 DBG_871X(FUNC_ADPT_FMT CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(request->channels[i]));\r
2509                 #endif\r
2510                 ch[i].hw_value = request->channels[i]->hw_value;\r
2511                 ch[i].flags = request->channels[i]->flags;\r
2512         }\r
2513 \r
2514         _enter_critical_bh(&pmlmepriv->lock, &irqL);\r
2515         if (request->n_channels == 1) {\r
2516                 for(i=1;i<survey_times_for_one_ch;i++)\r
2517                         _rtw_memcpy(&ch[i], &ch[0], sizeof(struct rtw_ieee80211_channel));\r
2518                 _status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, ch, survey_times_for_one_ch);\r
2519         } else if (request->n_channels <= 4) {\r
2520                 for(j=request->n_channels-1;j>=0;j--)\r
2521                         for(i=0;i<survey_times;i++)\r
2522                 {\r
2523                         _rtw_memcpy(&ch[j*survey_times+i], &ch[j], sizeof(struct rtw_ieee80211_channel));\r
2524                 }\r
2525                 _status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, ch, survey_times * request->n_channels);\r
2526         } else {\r
2527                 _status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, NULL, 0);\r
2528         }\r
2529         _exit_critical_bh(&pmlmepriv->lock, &irqL);\r
2530 \r
2531 \r
2532         if(_status == _FALSE)\r
2533         {\r
2534                 ret = -1;\r
2535         }\r
2536 \r
2537 check_need_indicate_scan_done:\r
2538         if (_TRUE == need_indicate_scan_done)\r
2539         {\r
2540                 rtw_cfg80211_surveydone_event_callback(padapter);\r
2541                 rtw_cfg80211_indicate_scan_done(padapter, _FALSE);\r
2542         }\r
2543 \r
2544 cancel_ps_deny:\r
2545         if (ps_denied == _TRUE)\r
2546                 rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);\r
2547 \r
2548 exit:\r
2549         return ret;\r
2550         \r
2551 }\r
2552 \r
2553 static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)\r
2554 {\r
2555 #if 0\r
2556         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);\r
2557 \r
2558         if (changed & WIPHY_PARAM_RTS_THRESHOLD &&\r
2559             (iwm->conf.rts_threshold != wiphy->rts_threshold)) {\r
2560                 int ret;\r
2561 \r
2562                 iwm->conf.rts_threshold = wiphy->rts_threshold;\r
2563 \r
2564                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,\r
2565                                              CFG_RTS_THRESHOLD,\r
2566                                              iwm->conf.rts_threshold);\r
2567                 if (ret < 0)\r
2568                         return ret;\r
2569         }\r
2570 \r
2571         if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&\r
2572             (iwm->conf.frag_threshold != wiphy->frag_threshold)) {\r
2573                 int ret;\r
2574 \r
2575                 iwm->conf.frag_threshold = wiphy->frag_threshold;\r
2576 \r
2577                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,\r
2578                                              CFG_FRAG_THRESHOLD,\r
2579                                              iwm->conf.frag_threshold);\r
2580                 if (ret < 0)\r
2581                         return ret;\r
2582         }\r
2583 #endif\r
2584         DBG_8192C("%s\n", __func__);\r
2585         return 0;\r
2586 }\r
2587 \r
2588 \r
2589 \r
2590 static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, u32 wpa_version)\r
2591 {       \r
2592         DBG_8192C("%s, wpa_version=%d\n", __func__, wpa_version);\r
2593         \r
2594         if (!wpa_version) {             \r
2595                 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;           \r
2596                 return 0;\r
2597         }\r
2598 \r
2599 \r
2600         if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))\r
2601         {               \r
2602                 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;         \r
2603         }\r
2604 \r
2605 /*\r
2606         if (wpa_version & NL80211_WPA_VERSION_2)\r
2607         {               \r
2608                 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;\r
2609         }\r
2610 */\r
2611 \r
2612         #ifdef CONFIG_WAPI_SUPPORT\r
2613         if (wpa_version & NL80211_WAPI_VERSION_1)\r
2614         {\r
2615                 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWAPI;\r
2616         }\r
2617         #endif\r
2618 \r
2619         return 0;\r
2620 \r
2621 }\r
2622 \r
2623 static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,\r
2624                              enum nl80211_auth_type sme_auth_type)\r
2625 {\r
2626         DBG_8192C("%s, nl80211_auth_type=%d\n", __func__, sme_auth_type);\r
2627 \r
2628 \r
2629         switch (sme_auth_type) {\r
2630         case NL80211_AUTHTYPE_AUTOMATIC:\r
2631 \r
2632                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;\r
2633 \r
2634                 break;\r
2635         case NL80211_AUTHTYPE_OPEN_SYSTEM:\r
2636         \r
2637                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;\r
2638 \r
2639                 if(psecuritypriv->ndisauthtype>Ndis802_11AuthModeWPA)\r
2640                         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;\r
2641                 \r
2642 #ifdef CONFIG_WAPI_SUPPORT\r
2643                 if(psecuritypriv->ndisauthtype == Ndis802_11AuthModeWAPI)\r
2644                         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;\r
2645 #endif\r
2646 \r
2647                 break;\r
2648         case NL80211_AUTHTYPE_SHARED_KEY:\r
2649 \r
2650                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;\r
2651 \r
2652                 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;\r
2653 \r
2654 \r
2655                 break;\r
2656         default:                \r
2657                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;\r
2658                 //return -ENOTSUPP;\r
2659         }\r
2660 \r
2661         return 0;\r
2662 \r
2663 }\r
2664 \r
2665 static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, u32 cipher, bool ucast)\r
2666 {\r
2667         u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;\r
2668 \r
2669         u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :\r
2670                 &psecuritypriv->dot118021XGrpPrivacy;\r
2671 \r
2672         DBG_8192C("%s, ucast=%d, cipher=0x%x\n", __func__, ucast, cipher);\r
2673 \r
2674 \r
2675         if (!cipher) {\r
2676                 *profile_cipher = _NO_PRIVACY_;\r
2677                 psecuritypriv->ndisencryptstatus = ndisencryptstatus;\r
2678                 return 0;\r
2679         }\r
2680         \r
2681         switch (cipher) {\r
2682         case IW_AUTH_CIPHER_NONE:\r
2683                 *profile_cipher = _NO_PRIVACY_;\r
2684                 ndisencryptstatus = Ndis802_11EncryptionDisabled;\r
2685 #ifdef CONFIG_WAPI_SUPPORT\r
2686                 if(psecuritypriv->dot11PrivacyAlgrthm ==_SMS4_ )\r
2687                 {\r
2688                         *profile_cipher = _SMS4_;\r
2689                 }\r
2690 #endif\r
2691                 break;\r
2692         case WLAN_CIPHER_SUITE_WEP40:\r
2693                 *profile_cipher = _WEP40_;\r
2694                 ndisencryptstatus = Ndis802_11Encryption1Enabled;\r
2695                 break;\r
2696         case WLAN_CIPHER_SUITE_WEP104:\r
2697                 *profile_cipher = _WEP104_;\r
2698                 ndisencryptstatus = Ndis802_11Encryption1Enabled;\r
2699                 break;\r
2700         case WLAN_CIPHER_SUITE_TKIP:\r
2701                 *profile_cipher = _TKIP_;\r
2702                 ndisencryptstatus = Ndis802_11Encryption2Enabled;\r
2703                 break;\r
2704         case WLAN_CIPHER_SUITE_CCMP:\r
2705                 *profile_cipher = _AES_;\r
2706                 ndisencryptstatus = Ndis802_11Encryption3Enabled;\r
2707                 break;\r
2708 #ifdef CONFIG_WAPI_SUPPORT\r
2709         case WLAN_CIPHER_SUITE_SMS4:\r
2710                 *profile_cipher = _SMS4_;\r
2711                 ndisencryptstatus = Ndis802_11_EncrypteionWAPI;\r
2712                 break;\r
2713 #endif\r
2714         default:\r
2715                 DBG_8192C("Unsupported cipher: 0x%x\n", cipher);\r
2716                 return -ENOTSUPP;\r
2717         }\r
2718 \r
2719         if(ucast)\r
2720         {\r
2721                 psecuritypriv->ndisencryptstatus = ndisencryptstatus;\r
2722                 \r
2723                 //if(psecuritypriv->dot11PrivacyAlgrthm >= _AES_)\r
2724                 //      psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;\r
2725         }       \r
2726 \r
2727         return 0;\r
2728 }\r
2729 \r
2730 static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv, u32 key_mgt)\r
2731 {\r
2732         DBG_8192C("%s, key_mgt=0x%x\n", __func__, key_mgt);\r
2733 \r
2734         if (key_mgt == WLAN_AKM_SUITE_8021X)\r
2735                 //*auth_type = UMAC_AUTH_TYPE_8021X;\r
2736                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;\r
2737         else if (key_mgt == WLAN_AKM_SUITE_PSK) {\r
2738                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;\r
2739         }\r
2740 #ifdef CONFIG_WAPI_SUPPORT\r
2741         else if(key_mgt ==WLAN_AKM_SUITE_WAPI_PSK){\r
2742                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;\r
2743         }\r
2744         else if(key_mgt ==WLAN_AKM_SUITE_WAPI_CERT){\r
2745                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;\r
2746         }\r
2747 #endif\r
2748 \r
2749 \r
2750         else {\r
2751                 DBG_8192C("Invalid key mgt: 0x%x\n", key_mgt);\r
2752                 //return -EINVAL;\r
2753         }\r
2754 \r
2755         return 0;\r
2756 }\r
2757 \r
2758 static int rtw_cfg80211_set_wpa_ie(_adapter *padapter, u8 *pie, size_t ielen)\r
2759 {\r
2760         u8 *buf=NULL, *pos=NULL;        \r
2761         u32 left;       \r
2762         int group_cipher = 0, pairwise_cipher = 0;\r
2763         int ret = 0;\r
2764         int wpa_ielen=0;\r
2765         int wpa2_ielen=0;\r
2766         u8 *pwpa, *pwpa2;\r
2767         u8 null_addr[]= {0,0,0,0,0,0};\r
2768 \r
2769         if (pie == NULL || !ielen) {\r
2770                 /* Treat this as normal case, but need to clear WIFI_UNDER_WPS */\r
2771                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);\r
2772                 goto exit;\r
2773         }\r
2774 \r
2775         if (ielen > MAX_WPA_IE_LEN+MAX_WPS_IE_LEN+MAX_P2P_IE_LEN) {\r
2776                 ret = -EINVAL;\r
2777                 goto exit;\r
2778         }\r
2779 \r
2780         buf = rtw_zmalloc(ielen);\r
2781         if (buf == NULL){\r
2782                 ret =  -ENOMEM;\r
2783                 goto exit;\r
2784         }\r
2785 \r
2786         _rtw_memcpy(buf, pie , ielen);\r
2787 \r
2788         //dump\r
2789         {\r
2790                 int i;\r
2791                 DBG_8192C("set wpa_ie(length:%zu):\n", ielen);\r
2792                 for(i=0;i<ielen;i=i+8)\r
2793                         DBG_8192C("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]);\r
2794         }\r
2795 \r
2796         pos = buf;\r
2797         if(ielen < RSN_HEADER_LEN){\r
2798                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("Ie len too short %d\n", ielen));\r
2799                 ret  = -1;\r
2800                 goto exit;\r
2801         }\r
2802 \r
2803         pwpa = rtw_get_wpa_ie(buf, &wpa_ielen, ielen);\r
2804         if(pwpa && wpa_ielen>0)\r
2805         {\r
2806                 if(rtw_parse_wpa_ie(pwpa, wpa_ielen+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)\r
2807                 {\r
2808                         padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;\r
2809                         padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPAPSK;\r
2810                         _rtw_memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0], wpa_ielen+2);\r
2811                         \r
2812                         DBG_8192C("got wpa_ie, wpa_ielen:%u\n", wpa_ielen);\r
2813                 }\r
2814         }\r
2815 \r
2816         pwpa2 = rtw_get_wpa2_ie(buf, &wpa2_ielen, ielen);\r
2817         if(pwpa2 && wpa2_ielen>0)\r
2818         {\r
2819                 if(rtw_parse_wpa2_ie(pwpa2, wpa2_ielen+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)\r
2820                 {\r
2821                         padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;\r
2822                         padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPA2PSK;  \r
2823                         _rtw_memcpy(padapter->securitypriv.supplicant_ie, &pwpa2[0], wpa2_ielen+2);\r
2824 \r
2825                         DBG_8192C("got wpa2_ie, wpa2_ielen:%u\n", wpa2_ielen);\r
2826                 }\r
2827         }\r
2828 \r
2829         if (group_cipher == 0)\r
2830         {\r
2831                 group_cipher = WPA_CIPHER_NONE;\r
2832         }\r
2833         if (pairwise_cipher == 0)\r
2834         {\r
2835                 pairwise_cipher = WPA_CIPHER_NONE;\r
2836         }\r
2837         \r
2838         switch(group_cipher)\r
2839         {\r
2840                 case WPA_CIPHER_NONE:\r
2841                         padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;\r
2842                         padapter->securitypriv.ndisencryptstatus=Ndis802_11EncryptionDisabled;\r
2843                         break;\r
2844                 case WPA_CIPHER_WEP40:\r
2845                         padapter->securitypriv.dot118021XGrpPrivacy=_WEP40_;\r
2846                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;\r
2847                         break;\r
2848                 case WPA_CIPHER_TKIP:\r
2849                         padapter->securitypriv.dot118021XGrpPrivacy=_TKIP_;\r
2850                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;\r
2851                         break;\r
2852                 case WPA_CIPHER_CCMP:\r
2853                         padapter->securitypriv.dot118021XGrpPrivacy=_AES_;\r
2854                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;\r
2855                         break;\r
2856                 case WPA_CIPHER_WEP104: \r
2857                         padapter->securitypriv.dot118021XGrpPrivacy=_WEP104_;\r
2858                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;\r
2859                         break;\r
2860         }\r
2861 \r
2862         switch(pairwise_cipher)\r
2863         {\r
2864                 case WPA_CIPHER_NONE:\r
2865                         padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;\r
2866                         padapter->securitypriv.ndisencryptstatus=Ndis802_11EncryptionDisabled;\r
2867                         break;\r
2868                 case WPA_CIPHER_WEP40:\r
2869                         padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;\r
2870                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;\r
2871                         break;\r
2872                 case WPA_CIPHER_TKIP:\r
2873                         padapter->securitypriv.dot11PrivacyAlgrthm=_TKIP_;\r
2874                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;\r
2875                         break;\r
2876                 case WPA_CIPHER_CCMP:\r
2877                         padapter->securitypriv.dot11PrivacyAlgrthm=_AES_;\r
2878                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;\r
2879                         break;\r
2880                 case WPA_CIPHER_WEP104: \r
2881                         padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;\r
2882                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;\r
2883                         break;\r
2884         }\r
2885         \r
2886         {/* handle wps_ie */\r
2887                 uint wps_ielen; \r
2888                 u8 *wps_ie;\r
2889 \r
2890                 wps_ie = rtw_get_wps_ie(buf, ielen, NULL, &wps_ielen);\r
2891                 if (wps_ie && wps_ielen > 0) {\r
2892                         DBG_8192C("got wps_ie, wps_ielen:%u\n", wps_ielen);\r
2893                         padapter->securitypriv.wps_ie_len = wps_ielen<MAX_WPS_IE_LEN?wps_ielen:MAX_WPS_IE_LEN;\r
2894                         _rtw_memcpy(padapter->securitypriv.wps_ie, wps_ie, padapter->securitypriv.wps_ie_len);\r
2895                         set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);\r
2896                 } else {\r
2897                         _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);\r
2898                 }\r
2899         }\r
2900 \r
2901         #ifdef CONFIG_P2P\r
2902         {//check p2p_ie for assoc req; \r
2903                 uint p2p_ielen=0;\r
2904                 u8 *p2p_ie;\r
2905                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2906 \r
2907                 if((p2p_ie=rtw_get_p2p_ie(buf, ielen, NULL, &p2p_ielen)))\r
2908                 {\r
2909                         #ifdef CONFIG_DEBUG_CFG80211\r
2910                         DBG_8192C("%s p2p_assoc_req_ielen=%d\n", __FUNCTION__, p2p_ielen);\r
2911                         #endif\r
2912 \r
2913                         if(pmlmepriv->p2p_assoc_req_ie)\r
2914                         {\r
2915                                 u32 free_len = pmlmepriv->p2p_assoc_req_ie_len;\r
2916                                 pmlmepriv->p2p_assoc_req_ie_len = 0;\r
2917                                 rtw_mfree(pmlmepriv->p2p_assoc_req_ie, free_len);\r
2918                                 pmlmepriv->p2p_assoc_req_ie = NULL;\r
2919                         }\r
2920 \r
2921                         pmlmepriv->p2p_assoc_req_ie = rtw_malloc(p2p_ielen);\r
2922                         if ( pmlmepriv->p2p_assoc_req_ie == NULL) {\r
2923                                 DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
2924                                 goto exit;\r
2925                         }\r
2926                         _rtw_memcpy(pmlmepriv->p2p_assoc_req_ie, p2p_ie, p2p_ielen);\r
2927                         pmlmepriv->p2p_assoc_req_ie_len = p2p_ielen;\r
2928                 }\r
2929         }\r
2930         #endif //CONFIG_P2P\r
2931 \r
2932         #ifdef CONFIG_WFD\r
2933         {//check wfd_ie for assoc req; \r
2934                 uint wfd_ielen=0;\r
2935                 u8 *wfd_ie;\r
2936                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2937 \r
2938                 if(rtw_get_wfd_ie(buf, ielen, NULL, &wfd_ielen))\r
2939                 {\r
2940                         #ifdef CONFIG_DEBUG_CFG80211\r
2941                         DBG_8192C("%s wfd_assoc_req_ielen=%d\n", __FUNCTION__, wfd_ielen);\r
2942                         #endif\r
2943 \r
2944                         if(pmlmepriv->wfd_assoc_req_ie)\r
2945                         {\r
2946                                 u32 free_len = pmlmepriv->wfd_assoc_req_ie_len;\r
2947                                 pmlmepriv->wfd_assoc_req_ie_len = 0;\r
2948                                 rtw_mfree(pmlmepriv->wfd_assoc_req_ie, free_len);\r
2949                                 pmlmepriv->wfd_assoc_req_ie = NULL;\r
2950                         }\r
2951 \r
2952                         pmlmepriv->wfd_assoc_req_ie = rtw_malloc(wfd_ielen);\r
2953                         if ( pmlmepriv->wfd_assoc_req_ie == NULL) {\r
2954                                 DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
2955                                 goto exit;\r
2956                         }\r
2957                         rtw_get_wfd_ie(buf, ielen, pmlmepriv->wfd_assoc_req_ie, &pmlmepriv->wfd_assoc_req_ie_len);                      \r
2958                 }\r
2959         }\r
2960         #endif //CONFIG_WFD\r
2961 \r
2962         //TKIP and AES disallow multicast packets until installing group key\r
2963         if(padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_\r
2964                 || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_\r
2965                 || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)\r
2966                 //WPS open need to enable multicast\r
2967                 //|| check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == _TRUE)\r
2968                 rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);\r
2969 \r
2970         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,\r
2971                 ("rtw_set_wpa_ie: pairwise_cipher=0x%08x padapter->securitypriv.ndisencryptstatus=%d padapter->securitypriv.ndisauthtype=%d\n",\r
2972                 pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));\r
2973 \r
2974 exit:\r
2975         if (buf)\r
2976                 rtw_mfree(buf, ielen);\r
2977         if (ret)\r
2978                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);\r
2979         return ret;\r
2980 }\r
2981 \r
2982 static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,\r
2983                                   struct cfg80211_ibss_params *params)\r
2984 {\r
2985         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
2986         NDIS_802_11_SSID ndis_ssid;\r
2987         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
2988         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;\r
2989         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
2990         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2991         WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));\r
2992 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))\r
2993         struct cfg80211_chan_def *pch_def;\r
2994 #endif\r
2995         struct ieee80211_channel *pch;\r
2996         int ret=0;\r
2997 \r
2998 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))\r
2999         pch_def = (struct cfg80211_chan_def *)(&params->chandef); \r
3000         pch = (struct ieee80211_channel *) pch_def->chan;\r
3001 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))\r
3002         pch = (struct ieee80211_channel *)(params->channel); \r
3003 #endif\r
3004         \r
3005         if(_FAIL == rtw_pwr_wakeup(padapter)) {\r
3006                 ret= -EPERM;\r
3007                 goto exit;\r
3008         }\r
3009 \r
3010         if(check_fwstate(pmlmepriv, WIFI_AP_STATE)) {\r
3011                 ret = -EPERM;\r
3012                 goto exit;\r
3013         }\r
3014 \r
3015 #ifdef CONFIG_CONCURRENT_MODE\r
3016         if (check_buddy_fwstate(padapter, _FW_UNDER_LINKING) == _TRUE) {\r
3017                 DBG_8192C("%s, but buddy_intf is under linking\n", __FUNCTION__);\r
3018                 ret = -EINVAL;\r
3019                 goto exit;\r
3020         }\r
3021         if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY) == _TRUE) {\r
3022                 rtw_scan_abort(padapter->pbuddy_adapter);\r
3023         }\r
3024 #endif //CONFIG_CONCURRENT_MODE\r
3025         \r
3026         if (!params->ssid || !params->ssid_len)\r
3027         {\r
3028                 ret = -EINVAL;\r
3029                 goto exit;\r
3030         }\r
3031 \r
3032         if (params->ssid_len > IW_ESSID_MAX_SIZE){\r
3033 \r
3034                 ret= -E2BIG;\r
3035                 goto exit;\r
3036         }\r
3037         \r
3038         _rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));                   \r
3039         ndis_ssid.SsidLength = params->ssid_len;\r
3040         _rtw_memcpy(ndis_ssid.Ssid, (u8 *)params->ssid, params->ssid_len);\r
3041 \r
3042         //DBG_8192C("ssid=%s, len=%zu\n", ndis_ssid.Ssid, params->ssid_len);\r
3043         \r
3044         psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;\r
3045         psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;\r
3046         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;\r
3047         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; //open system\r
3048         psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;\r
3049         \r
3050         ret = rtw_cfg80211_set_auth_type(psecuritypriv, NL80211_AUTHTYPE_OPEN_SYSTEM);\r
3051         rtw_set_802_11_authentication_mode(padapter, psecuritypriv->ndisauthtype);\r
3052 \r
3053         DBG_871X("%s: center_freq = %d\n", __func__, pch->center_freq);\r
3054         pmlmeext->cur_channel = rtw_freq2ch(pch->center_freq);\r
3055         \r
3056         if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == _FALSE) \r
3057         {\r
3058                 ret = -1;\r
3059                 goto exit;\r
3060         }       \r
3061         \r
3062 exit:\r
3063         return ret;\r
3064 }\r
3065 \r
3066 static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)\r
3067 {\r
3068         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
3069         struct wireless_dev *rtw_wdev = padapter->rtw_wdev;\r
3070         enum nl80211_iftype old_type;\r
3071         int ret = 0;\r
3072 \r
3073         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
3074 \r
3075         padapter->mlmepriv.not_indic_disco = _TRUE;\r
3076         \r
3077         old_type = rtw_wdev->iftype;\r
3078         \r
3079         rtw_set_to_roam(padapter, 0);\r
3080 \r
3081         if(check_fwstate(&padapter->mlmepriv, _FW_LINKED)) \r
3082         {\r
3083                 rtw_scan_abort(padapter);\r
3084                 LeaveAllPowerSaveMode(padapter);\r
3085                 \r
3086                 rtw_wdev->iftype = NL80211_IFTYPE_STATION;\r
3087                 \r
3088                 if (rtw_set_802_11_infrastructure_mode(padapter, Ndis802_11Infrastructure) ==_FALSE)\r
3089                 {\r
3090                         rtw_wdev->iftype = old_type;\r
3091                         ret = -EPERM;\r
3092                         goto leave_ibss;\r
3093                 }\r
3094                 rtw_setopmode_cmd(padapter, Ndis802_11Infrastructure,_TRUE);    \r
3095         }\r
3096 \r
3097 leave_ibss:\r
3098         padapter->mlmepriv.not_indic_disco = _FALSE;\r
3099 \r
3100         return 0;\r
3101 }\r
3102 \r
3103 static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,\r
3104                                  struct cfg80211_connect_params *sme)\r
3105 {\r
3106         int ret=0;\r
3107         _irqL irqL;     \r
3108         _list *phead;   \r
3109         struct wlan_network *pnetwork = NULL;\r
3110         NDIS_802_11_AUTHENTICATION_MODE authmode;       \r
3111         NDIS_802_11_SSID ndis_ssid;     \r
3112         u8 *dst_ssid, *src_ssid;\r
3113         u8 *dst_bssid, *src_bssid;\r
3114         //u8 matched_by_bssid=_FALSE;\r
3115         //u8 matched_by_ssid=_FALSE;\r
3116         u8 matched=_FALSE;\r
3117         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
3118         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;      \r
3119         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
3120         _queue *queue = &pmlmepriv->scanned_queue;      \r
3121 \r
3122         padapter->mlmepriv.not_indic_disco = _TRUE;\r
3123         \r
3124         DBG_871X("=>"FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
3125         DBG_871X("privacy=%d, key=%p, key_len=%d, key_idx=%d\n",\r
3126                 sme->privacy, sme->key, sme->key_len, sme->key_idx);\r
3127 \r
3128 \r
3129         if(adapter_wdev_data(padapter)->block == _TRUE)\r
3130         {\r
3131                 ret = -EBUSY;\r
3132                 DBG_871X("%s wdev_priv.block is set\n", __FUNCTION__);\r
3133                 goto exit;\r
3134         }\r
3135 \r
3136 #ifdef CONFIG_PLATFORM_MSTAR_SCAN_BEFORE_CONNECT\r
3137         printk("MStar Android!\n");\r
3138         if(adapter_wdev_data(padapter)->bandroid_scan == _FALSE)\r
3139         {\r
3140 #ifdef CONFIG_P2P\r
3141                 struct wifidirect_info *pwdinfo= &(padapter->wdinfo);   \r
3142                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))\r
3143 #endif //CONFIG_P2P\r
3144                 {\r
3145                         ret = -EBUSY;\r
3146                         printk("Android hasn't attached yet!\n");\r
3147                         goto exit;\r
3148                 }       \r
3149         }\r
3150 #endif\r
3151 \r
3152         rtw_ps_deny(padapter, PS_DENY_JOIN);\r
3153         if(_FAIL == rtw_pwr_wakeup(padapter)) {\r
3154                 ret= -EPERM;\r
3155                 goto exit;\r
3156         }\r
3157 \r
3158         if(check_fwstate(pmlmepriv, WIFI_AP_STATE)) {\r
3159                 ret = -EPERM;\r
3160                 goto exit;\r
3161         }\r
3162 \r
3163 #ifdef CONFIG_CONCURRENT_MODE\r
3164         if (check_buddy_fwstate(padapter, _FW_UNDER_LINKING) == _TRUE) {\r
3165                 DBG_8192C("%s, but buddy_intf is under linking\n", __FUNCTION__);\r
3166                 ret = -EINVAL;\r
3167                 goto exit;\r
3168         }\r
3169         if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY) == _TRUE) {\r
3170                 rtw_scan_abort(padapter->pbuddy_adapter);\r
3171         }\r
3172 #endif\r
3173 \r
3174         if (!sme->ssid || !sme->ssid_len)\r
3175         {\r
3176                 ret = -EINVAL;\r
3177                 goto exit;\r
3178         }\r
3179 \r
3180         if (sme->ssid_len > IW_ESSID_MAX_SIZE){\r
3181 \r
3182                 ret= -E2BIG;\r
3183                 goto exit;\r
3184         }\r
3185         \r
3186         _rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));                   \r
3187         ndis_ssid.SsidLength = sme->ssid_len;\r
3188         _rtw_memcpy(ndis_ssid.Ssid, (u8 *)sme->ssid, sme->ssid_len);\r
3189 \r
3190         DBG_8192C("ssid=%s, len=%zu\n", ndis_ssid.Ssid, sme->ssid_len);\r
3191         \r
3192 \r
3193         if (sme->bssid)\r
3194                 DBG_8192C("bssid="MAC_FMT"\n", MAC_ARG(sme->bssid));\r
3195 \r
3196 \r
3197         if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) {\r
3198                 ret = -EBUSY;\r
3199                 DBG_8192C("%s, fw_state=0x%x, goto exit\n", __FUNCTION__, pmlmepriv->fw_state);\r
3200                 goto exit;              \r
3201         }\r
3202         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {\r
3203                 rtw_scan_abort(padapter);\r
3204         }\r
3205 \r
3206         psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;\r
3207         psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;\r
3208         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;\r
3209         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; //open system\r
3210         psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;\r
3211 \r
3212 #ifdef CONFIG_WAPI_SUPPORT\r
3213          padapter->wapiInfo.bWapiEnable = false;\r
3214 #endif\r
3215 \r
3216         ret = rtw_cfg80211_set_wpa_version(psecuritypriv, sme->crypto.wpa_versions);\r
3217         if (ret < 0)\r
3218                 goto exit;\r
3219 \r
3220 #ifdef CONFIG_WAPI_SUPPORT\r
3221         if(sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1)\r
3222         {\r
3223                 padapter->wapiInfo.bWapiEnable = true;\r
3224                 padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;\r
3225                 padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;\r
3226         }\r
3227 #endif\r
3228 \r
3229         ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);\r
3230 \r
3231 #ifdef CONFIG_WAPI_SUPPORT\r
3232         if(psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_WAPI)\r
3233                 padapter->mlmeextpriv.mlmext_info.auth_algo = psecuritypriv->dot11AuthAlgrthm;\r
3234 #endif\r
3235 \r
3236 \r
3237         if (ret < 0)\r
3238                 goto exit;\r
3239 \r
3240         DBG_8192C("%s, ie_len=%zu\n", __func__, sme->ie_len);\r
3241                         \r
3242         ret = rtw_cfg80211_set_wpa_ie(padapter, (u8 *)sme->ie, sme->ie_len);\r
3243         if (ret < 0)\r
3244                 goto exit;\r
3245 \r
3246         if (sme->crypto.n_ciphers_pairwise) {           \r
3247                 ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.ciphers_pairwise[0], _TRUE);\r
3248                 if (ret < 0)\r
3249                         goto exit;\r
3250         }\r
3251 \r
3252         //For WEP Shared auth\r
3253         if((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared\r
3254                 || psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) && sme->key\r
3255         )\r
3256         {\r
3257                 u32 wep_key_idx, wep_key_len,wep_total_len;\r
3258                 NDIS_802_11_WEP  *pwep = NULL;\r
3259                 DBG_871X("%s(): Shared/Auto WEP\n",__FUNCTION__);\r
3260 \r
3261                 wep_key_idx = sme->key_idx;\r
3262                 wep_key_len = sme->key_len;\r
3263 \r
3264                 if (sme->key_idx > WEP_KEYS) {\r
3265                         ret = -EINVAL;\r
3266                         goto exit;\r
3267                 }\r
3268 \r
3269                 if (wep_key_len > 0) \r
3270                 {\r
3271                         wep_key_len = wep_key_len <= 5 ? 5 : 13;\r
3272                         wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);\r
3273                         pwep =(NDIS_802_11_WEP   *) rtw_malloc(wep_total_len);\r
3274                         if(pwep == NULL){\r
3275                                 DBG_871X(" wpa_set_encryption: pwep allocate fail !!!\n");\r
3276                                 ret = -ENOMEM;\r
3277                                 goto exit;\r
3278                         }\r
3279 \r
3280                         _rtw_memset(pwep, 0, wep_total_len);\r
3281 \r
3282                         pwep->KeyLength = wep_key_len;\r
3283                         pwep->Length = wep_total_len;\r
3284 \r
3285                         if(wep_key_len==13)\r
3286                         {\r
3287                                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;\r
3288                                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP104_;\r
3289                         }\r
3290                 }\r
3291                 else {          \r
3292                         ret = -EINVAL;\r
3293                         goto exit;\r
3294                 }\r
3295 \r
3296                 pwep->KeyIndex = wep_key_idx;\r
3297                 pwep->KeyIndex |= 0x80000000;\r
3298 \r
3299                 _rtw_memcpy(pwep->KeyMaterial,  (void *)sme->key, pwep->KeyLength);\r
3300 \r
3301                 if(rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)\r
3302                 {\r
3303                         ret = -EOPNOTSUPP ;\r
3304                 }\r
3305 \r
3306                 if (pwep) {\r
3307                         rtw_mfree((u8 *)pwep,wep_total_len);            \r
3308                 }\r
3309 \r
3310                 if(ret < 0)\r
3311                         goto exit;\r
3312         }\r
3313 \r
3314         ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.cipher_group, _FALSE);\r
3315         if (ret < 0)\r
3316                 return ret;\r
3317 \r
3318         if (sme->crypto.n_akm_suites) {\r
3319                 ret = rtw_cfg80211_set_key_mgt(psecuritypriv, sme->crypto.akm_suites[0]);\r
3320                 if (ret < 0)\r
3321                         goto exit;\r
3322         }\r
3323 \r
3324 #ifdef CONFIG_WAPI_SUPPORT\r
3325       if(sme->crypto.akm_suites[0] ==WLAN_AKM_SUITE_WAPI_PSK){\r
3326                 padapter->wapiInfo.bWapiPSK = true;\r
3327         }\r
3328         else if(sme->crypto.akm_suites[0] ==WLAN_AKM_SUITE_WAPI_CERT){\r
3329               padapter->wapiInfo.bWapiPSK = false;\r
3330         }\r
3331 #endif\r
3332 \r
3333         authmode = psecuritypriv->ndisauthtype;\r
3334         rtw_set_802_11_authentication_mode(padapter, authmode);\r
3335 \r
3336         //rtw_set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus);\r
3337 \r
3338         if (rtw_set_802_11_connect(padapter, (u8 *)sme->bssid, &ndis_ssid) == _FALSE) {\r
3339                 ret = -1;\r
3340                 goto exit;\r
3341         }\r
3342 \r
3343         DBG_8192C("set ssid:dot11AuthAlgrthm=%d, dot11PrivacyAlgrthm=%d, dot118021XGrpPrivacy=%d\n", psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm, psecuritypriv->dot118021XGrpPrivacy);\r
3344         \r
3345 exit:\r
3346 \r
3347         rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);\r
3348 \r
3349         DBG_8192C("<=%s, ret %d\n",__FUNCTION__, ret);\r
3350 \r
3351         padapter->mlmepriv.not_indic_disco = _FALSE;\r
3352 \r
3353         return ret;\r
3354 }\r
3355 \r
3356 static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,\r
3357                                    u16 reason_code)\r
3358 {\r
3359         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
3360 \r
3361         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
3362 \r
3363         padapter->mlmepriv.not_indic_disco = _TRUE;\r
3364 \r
3365         rtw_set_to_roam(padapter, 0);\r
3366 \r
3367         //if(check_fwstate(&padapter->mlmepriv, _FW_LINKED))\r
3368         {\r
3369                 rtw_scan_abort(padapter);\r
3370                 LeaveAllPowerSaveMode(padapter);\r
3371                 rtw_disassoc_cmd(padapter, 500, _FALSE);\r
3372                 \r
3373                 DBG_871X("%s...call rtw_indicate_disconnect\n", __FUNCTION__);\r
3374                 \r
3375                 rtw_indicate_disconnect(padapter);\r
3376                 \r
3377                 rtw_free_assoc_resources(padapter, 1);\r
3378                 rtw_pwr_wakeup(padapter);               \r
3379         }\r
3380 \r
3381         padapter->mlmepriv.not_indic_disco = _FALSE;\r
3382 \r
3383         DBG_871X(FUNC_NDEV_FMT" return 0\n", FUNC_NDEV_ARG(ndev));\r
3384         return 0;\r
3385 }\r
3386 \r
3387 static int cfg80211_rtw_set_txpower(struct wiphy *wiphy,\r
3388 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))\r
3389         struct wireless_dev *wdev,\r
3390 #endif\r
3391 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) || defined(COMPAT_KERNEL_RELEASE)\r
3392         enum nl80211_tx_power_setting type, int mbm)\r
3393 #else\r
3394         enum tx_power_setting type, int dbm)\r
3395 #endif\r
3396 {\r
3397 #if 0\r
3398         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);\r
3399         int ret;\r
3400 \r
3401         switch (type) {\r
3402         case NL80211_TX_POWER_AUTOMATIC:\r
3403                 return 0;\r
3404         case NL80211_TX_POWER_FIXED:\r
3405                 if (mbm < 0 || (mbm % 100))\r
3406                         return -EOPNOTSUPP;\r
3407 \r
3408                 if (!test_bit(IWM_STATUS_READY, &iwm->status))\r
3409                         return 0;\r
3410 \r
3411                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,\r
3412                                               CFG_TX_PWR_LIMIT_USR,\r
3413                                               MBM_TO_DBM(mbm) * 2);\r
3414                 if (ret < 0)\r
3415                         return ret;\r
3416 \r
3417                 return iwm_tx_power_trigger(iwm);\r
3418         default:\r
3419                 IWM_ERR(iwm, "Unsupported power type: %d\n", type);\r
3420                 return -EOPNOTSUPP;\r
3421         }\r
3422 #endif\r
3423         DBG_8192C("%s\n", __func__);\r
3424         return 0;\r
3425 }\r
3426 \r
3427 static int cfg80211_rtw_get_txpower(struct wiphy *wiphy,\r
3428 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))\r
3429         struct wireless_dev *wdev,\r
3430 #endif\r
3431         int *dbm)\r
3432 {\r
3433         DBG_8192C("%s\n", __func__);\r
3434 \r
3435         *dbm = (12);\r
3436         \r
3437         return 0;\r
3438 }\r
3439 \r
3440 inline bool rtw_cfg80211_pwr_mgmt(_adapter *adapter)\r
3441 {\r
3442         struct rtw_wdev_priv *rtw_wdev_priv = adapter_wdev_data(adapter);\r
3443         return rtw_wdev_priv->power_mgmt;\r
3444 }\r
3445 \r
3446 static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,\r
3447                                        struct net_device *ndev,\r
3448                                        bool enabled, int timeout)\r
3449 {\r
3450         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
3451         struct rtw_wdev_priv *rtw_wdev_priv = adapter_wdev_data(padapter);\r
3452         \r
3453         DBG_871X(FUNC_NDEV_FMT" enabled:%u, timeout:%d\n", FUNC_NDEV_ARG(ndev),\r
3454                 enabled, timeout);\r
3455 \r
3456         rtw_wdev_priv->power_mgmt = enabled;\r
3457 \r
3458         #ifdef CONFIG_LPS\r
3459         if (!enabled)\r
3460                 LPS_Leave(padapter, "CFG80211_PWRMGMT");\r
3461         #endif\r
3462 \r
3463         return 0;\r
3464 }\r
3465 \r
3466 static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,\r
3467                                   struct net_device *ndev,\r
3468                                   struct cfg80211_pmksa *pmksa)\r
3469 {\r
3470         u8      index,blInserted = _FALSE;\r
3471         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
3472         struct mlme_priv *mlme = &padapter->mlmepriv;\r
3473         struct security_priv    *psecuritypriv = &padapter->securitypriv;\r
3474         u8      strZeroMacAddress[ ETH_ALEN ] = { 0x00 };\r
3475 \r
3476         DBG_871X(FUNC_NDEV_FMT" "MAC_FMT" "KEY_FMT"\n", FUNC_NDEV_ARG(ndev)\r
3477                 , MAC_ARG(pmksa->bssid), KEY_ARG(pmksa->pmkid));\r
3478 \r
3479         if ( _rtw_memcmp((u8 *)pmksa->bssid, strZeroMacAddress, ETH_ALEN ) == _TRUE )\r
3480         {\r
3481                 return -EINVAL;\r
3482         }\r
3483 \r
3484         if (check_fwstate(mlme, _FW_LINKED) == _FALSE) {\r
3485                 DBG_871X(FUNC_NDEV_FMT" not set pmksa cause not in linked state\n", FUNC_NDEV_ARG(ndev));\r
3486                 return -EINVAL;\r
3487         }\r
3488 \r
3489         blInserted = _FALSE;\r
3490         \r
3491         //overwrite PMKID\r
3492         for(index=0 ; index<NUM_PMKID_CACHE; index++)\r
3493         {\r
3494                 if( _rtw_memcmp(psecuritypriv->PMKIDList[index].Bssid, (u8 *)pmksa->bssid, ETH_ALEN) ==_TRUE )\r
3495                 { // BSSID is matched, the same AP => rewrite with new PMKID.\r
3496                         DBG_871X(FUNC_NDEV_FMT" BSSID exists in the PMKList.\n", FUNC_NDEV_ARG(ndev));\r
3497 \r
3498                         _rtw_memcpy( psecuritypriv->PMKIDList[index].PMKID, (u8 *)pmksa->pmkid, WLAN_PMKID_LEN);\r
3499                         psecuritypriv->PMKIDList[index].bUsed = _TRUE;\r
3500                         psecuritypriv->PMKIDIndex = index+1;\r
3501                         blInserted = _TRUE;\r
3502                         break;\r
3503                 }       \r
3504         }\r
3505 \r
3506         if(!blInserted)\r
3507         {\r
3508                 // Find a new entry\r
3509                 DBG_871X(FUNC_NDEV_FMT" Use the new entry index = %d for this PMKID.\n",\r
3510                         FUNC_NDEV_ARG(ndev), psecuritypriv->PMKIDIndex );\r
3511 \r
3512                 _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, (u8 *)pmksa->bssid, ETH_ALEN);\r
3513                 _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, (u8 *)pmksa->pmkid, WLAN_PMKID_LEN);\r
3514 \r
3515                 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = _TRUE;\r
3516                 psecuritypriv->PMKIDIndex++ ;\r
3517                 if(psecuritypriv->PMKIDIndex==16)\r
3518                 {\r
3519                         psecuritypriv->PMKIDIndex =0;\r
3520                 } \r
3521         } \r
3522 \r
3523         return 0;\r
3524 }\r
3525 \r
3526 static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,\r
3527                                   struct net_device *ndev,\r
3528                                   struct cfg80211_pmksa *pmksa)\r
3529 {\r
3530         u8      index, bMatched = _FALSE;\r
3531         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
3532         struct security_priv    *psecuritypriv = &padapter->securitypriv;\r
3533 \r
3534         DBG_871X(FUNC_NDEV_FMT" "MAC_FMT" "KEY_FMT"\n", FUNC_NDEV_ARG(ndev)\r
3535                 , MAC_ARG(pmksa->bssid), KEY_ARG(pmksa->pmkid));\r
3536 \r
3537         for(index=0 ; index<NUM_PMKID_CACHE; index++)\r
3538         {\r
3539                 if( _rtw_memcmp(psecuritypriv->PMKIDList[index].Bssid, (u8 *)pmksa->bssid, ETH_ALEN) ==_TRUE )\r
3540                 { // BSSID is matched, the same AP => Remove this PMKID information and reset it. \r
3541                         _rtw_memset(psecuritypriv->PMKIDList[index].Bssid, 0x00, ETH_ALEN );\r
3542                         _rtw_memset(psecuritypriv->PMKIDList[index].PMKID, 0x00, WLAN_PMKID_LEN );\r
3543                         psecuritypriv->PMKIDList[index].bUsed = _FALSE;\r
3544                         bMatched = _TRUE;\r
3545                         DBG_871X(FUNC_NDEV_FMT" clear id:%hhu\n", FUNC_NDEV_ARG(ndev), index);          \r
3546                         break;\r
3547                 }       \r
3548         }\r
3549 \r
3550         if(_FALSE == bMatched)\r
3551         {\r
3552                 DBG_871X(FUNC_NDEV_FMT" do not have matched BSSID\n"\r
3553                         , FUNC_NDEV_ARG(ndev));\r
3554                 return -EINVAL;\r
3555         }\r
3556 \r
3557         return 0;\r
3558 }\r
3559 \r
3560 static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,\r
3561                                     struct net_device *ndev)\r
3562 {\r
3563         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
3564         struct security_priv    *psecuritypriv = &padapter->securitypriv;\r
3565 \r
3566         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
3567 \r
3568         _rtw_memset( &psecuritypriv->PMKIDList[ 0 ], 0x00, sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );\r
3569         psecuritypriv->PMKIDIndex = 0;\r
3570 \r
3571         return 0;\r
3572 }\r
3573 \r
3574 #ifdef CONFIG_AP_MODE\r
3575 void rtw_cfg80211_indicate_sta_assoc(_adapter *padapter, u8 *pmgmt_frame, uint frame_len)\r
3576 {\r
3577         s32 freq;\r
3578         int channel;\r
3579         struct wireless_dev *pwdev = padapter->rtw_wdev;\r
3580         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);      \r
3581         struct net_device *ndev = padapter->pnetdev;\r
3582 \r
3583         DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));\r
3584 \r
3585 #if defined(RTW_USE_CFG80211_STA_EVENT) || defined(COMPAT_KERNEL_RELEASE)\r
3586         {\r
3587                 struct station_info sinfo;\r
3588                 u8 ie_offset;\r
3589                 if (GetFrameSubType(pmgmt_frame) == WIFI_ASSOCREQ)\r
3590                         ie_offset = _ASOCREQ_IE_OFFSET_;\r
3591                 else // WIFI_REASSOCREQ\r
3592                         ie_offset = _REASOCREQ_IE_OFFSET_;\r
3593         \r
3594                 sinfo.filled = 0;\r
3595                 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;\r
3596                 sinfo.assoc_req_ies = pmgmt_frame + WLAN_HDR_A3_LEN + ie_offset;\r
3597                 sinfo.assoc_req_ies_len = frame_len - WLAN_HDR_A3_LEN - ie_offset;\r
3598                 cfg80211_new_sta(ndev, GetAddr2Ptr(pmgmt_frame), &sinfo, GFP_ATOMIC);\r
3599         }\r
3600 #else /* defined(RTW_USE_CFG80211_STA_EVENT) */\r
3601         channel = pmlmeext->cur_channel;\r
3602         if (channel <= RTW_CH_MAX_2G_CHANNEL)\r
3603                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);\r
3604         else\r
3605                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);\r
3606 \r
3607         #ifdef COMPAT_KERNEL_RELEASE\r
3608         rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);\r
3609         #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
3610         rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);\r
3611         #else //COMPAT_KERNEL_RELEASE\r
3612         {\r
3613                 //to avoid WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)  when calling cfg80211_send_rx_assoc()\r
3614                 #ifndef CONFIG_PLATFORM_MSTAR\r
3615                 pwdev->iftype = NL80211_IFTYPE_STATION;\r
3616                 #endif //CONFIG_PLATFORM_MSTAR\r
3617                 DBG_8192C("iftype=%d before call cfg80211_send_rx_assoc()\n", pwdev->iftype);\r
3618                 rtw_cfg80211_send_rx_assoc(padapter, NULL, pmgmt_frame, frame_len);\r
3619                 DBG_8192C("iftype=%d after call cfg80211_send_rx_assoc()\n", pwdev->iftype);\r
3620                 pwdev->iftype = NL80211_IFTYPE_AP;\r
3621                 //cfg80211_rx_action(padapter->pnetdev, freq, pmgmt_frame, frame_len, GFP_ATOMIC);\r
3622         }\r
3623         #endif //COMPAT_KERNEL_RELEASE\r
3624 #endif /* defined(RTW_USE_CFG80211_STA_EVENT) */\r
3625 \r
3626 }\r
3627 \r
3628 void rtw_cfg80211_indicate_sta_disassoc(_adapter *padapter, unsigned char *da, unsigned short reason)\r
3629 {\r
3630         s32 freq;\r
3631         int channel;\r
3632         u8 *pmgmt_frame;\r
3633         uint frame_len;\r
3634         struct rtw_ieee80211_hdr *pwlanhdr;\r
3635         unsigned short *fctrl;  \r
3636         u8 mgmt_buf[128] = {0};\r
3637         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
3638         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
3639         struct net_device *ndev = padapter->pnetdev;\r
3640         \r
3641         DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));\r
3642 \r
3643 #if defined(RTW_USE_CFG80211_STA_EVENT) || defined(COMPAT_KERNEL_RELEASE)\r
3644         cfg80211_del_sta(ndev, da, GFP_ATOMIC);\r
3645 #else /* defined(RTW_USE_CFG80211_STA_EVENT) */\r
3646         channel = pmlmeext->cur_channel;\r
3647         if (channel <= RTW_CH_MAX_2G_CHANNEL)\r
3648                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);\r
3649         else\r
3650                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);\r
3651 \r
3652         pmgmt_frame = mgmt_buf; \r
3653         pwlanhdr = (struct rtw_ieee80211_hdr *)pmgmt_frame;\r
3654 \r
3655         fctrl = &(pwlanhdr->frame_ctl);\r
3656         *(fctrl) = 0;\r
3657 \r
3658         _rtw_memcpy(pwlanhdr->addr1, adapter_mac_addr(padapter), ETH_ALEN);\r
3659         _rtw_memcpy(pwlanhdr->addr2, da, ETH_ALEN);     \r
3660         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
3661 \r
3662         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);\r
3663         pmlmeext->mgnt_seq++;\r
3664         SetFrameSubType(pmgmt_frame, WIFI_DEAUTH);\r
3665 \r
3666         pmgmt_frame += sizeof(struct rtw_ieee80211_hdr_3addr);\r
3667         frame_len = sizeof(struct rtw_ieee80211_hdr_3addr);\r
3668 \r
3669         reason = cpu_to_le16(reason);\r
3670         pmgmt_frame = rtw_set_fixed_ie(pmgmt_frame, _RSON_CODE_ , (unsigned char *)&reason, &frame_len);\r
3671 \r
3672         #ifdef COMPAT_KERNEL_RELEASE\r
3673         rtw_cfg80211_rx_mgmt(padapter, freq, 0, mgmt_buf, frame_len, GFP_ATOMIC);\r
3674         #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
3675         rtw_cfg80211_rx_mgmt(padapter, freq, 0, mgmt_buf, frame_len, GFP_ATOMIC);\r
3676         #else //COMPAT_KERNEL_RELEASE\r
3677         cfg80211_send_disassoc(padapter->pnetdev, mgmt_buf, frame_len); \r
3678         //cfg80211_rx_action(padapter->pnetdev, freq, mgmt_buf, frame_len, GFP_ATOMIC);\r
3679         #endif //COMPAT_KERNEL_RELEASE\r
3680 #endif /* defined(RTW_USE_CFG80211_STA_EVENT) */\r
3681 }\r
3682 \r
3683 static int rtw_cfg80211_monitor_if_open(struct net_device *ndev)\r
3684 {\r
3685         int ret = 0;\r
3686 \r
3687         DBG_8192C("%s\n", __func__);\r
3688         \r
3689         return ret;\r
3690 }\r
3691 \r
3692 static int rtw_cfg80211_monitor_if_close(struct net_device *ndev)\r
3693 {\r
3694         int ret = 0;\r
3695 \r
3696         DBG_8192C("%s\n", __func__);\r
3697         \r
3698         return ret;\r
3699 }\r
3700 \r
3701 static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struct net_device *ndev)\r
3702 {       \r
3703         int ret = 0;\r
3704         int rtap_len;\r
3705         int qos_len = 0;\r
3706         int dot11_hdr_len = 24;\r
3707         int snap_len = 6;\r
3708         unsigned char *pdata;\r
3709         u16 frame_ctl;\r
3710         unsigned char src_mac_addr[6];\r
3711         unsigned char dst_mac_addr[6];\r
3712         struct ieee80211_hdr *dot11_hdr;\r
3713         struct ieee80211_radiotap_header *rtap_hdr;\r
3714         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
3715         \r
3716         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
3717 \r
3718         if (skb)\r
3719                 rtw_mstat_update(MSTAT_TYPE_SKB, MSTAT_ALLOC_SUCCESS, skb->truesize);\r
3720 \r
3721         if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))\r
3722                 goto fail;\r
3723 \r
3724         rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;\r
3725         if (unlikely(rtap_hdr->it_version))\r
3726                 goto fail;\r
3727 \r
3728         rtap_len = ieee80211_get_radiotap_len(skb->data);\r
3729         if (unlikely(skb->len < rtap_len))\r
3730                 goto fail;\r
3731 \r
3732         if(rtap_len != 14)\r
3733         {\r
3734                 DBG_8192C("radiotap len (should be 14): %d\n", rtap_len);\r
3735                 goto fail;\r
3736         }       \r
3737 \r
3738         /* Skip the ratio tap header */\r
3739         skb_pull(skb, rtap_len);\r
3740 \r
3741         dot11_hdr = (struct ieee80211_hdr *)skb->data;\r
3742         frame_ctl = le16_to_cpu(dot11_hdr->frame_control);\r
3743         /* Check if the QoS bit is set */\r
3744         if ((frame_ctl & RTW_IEEE80211_FCTL_FTYPE) == RTW_IEEE80211_FTYPE_DATA) {\r
3745                 /* Check if this ia a Wireless Distribution System (WDS) frame\r
3746                  * which has 4 MAC addresses\r
3747                  */\r
3748                 if (dot11_hdr->frame_control & 0x0080)\r
3749                         qos_len = 2;\r
3750                 if ((dot11_hdr->frame_control & 0x0300) == 0x0300)\r
3751                         dot11_hdr_len += 6;\r
3752 \r
3753                 memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));\r
3754                 memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));\r
3755 \r
3756                 /* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for\r
3757                  * for two MAC addresses\r
3758                  */\r
3759                 skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2);\r
3760                 pdata = (unsigned char*)skb->data;\r
3761                 memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr));\r
3762                 memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr));\r
3763 \r
3764                 DBG_8192C("should be eapol packet\n");\r
3765 \r
3766                 /* Use the real net device to transmit the packet */\r
3767                 ret = _rtw_xmit_entry(skb, padapter->pnetdev);\r
3768 \r
3769                 return ret;\r
3770 \r
3771         }\r
3772         else if ((frame_ctl & (RTW_IEEE80211_FCTL_FTYPE|RTW_IEEE80211_FCTL_STYPE))\r
3773                 == (RTW_IEEE80211_FTYPE_MGMT|RTW_IEEE80211_STYPE_ACTION)\r
3774         ) \r
3775         {\r
3776                 //only for action frames\r
3777                 struct xmit_frame               *pmgntframe;\r
3778                 struct pkt_attrib       *pattrib;\r
3779                 unsigned char   *pframe;        \r
3780                 //u8 category, action, OUI_Subtype, dialogToken=0;\r
3781                 //unsigned char *frame_body;\r
3782                 struct rtw_ieee80211_hdr *pwlanhdr;     \r
3783                 struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);\r
3784                 struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
3785                 u8 *buf = skb->data;\r
3786                 u32 len = skb->len;\r
3787                 u8 category, action;\r
3788                 int type = -1;\r
3789 \r
3790                 if (rtw_action_frame_parse(buf, len, &category, &action) == _FALSE) {\r
3791                         DBG_8192C(FUNC_NDEV_FMT" frame_control:0x%x\n", FUNC_NDEV_ARG(ndev),\r
3792                                 le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl));\r
3793                         goto fail;\r
3794                 }\r
3795                 \r
3796                 DBG_8192C("RTW_Tx:da="MAC_FMT" via "FUNC_NDEV_FMT"\n",\r
3797                         MAC_ARG(GetAddr1Ptr(buf)), FUNC_NDEV_ARG(ndev));\r
3798                 #ifdef CONFIG_P2P\r
3799                 if((type = rtw_p2p_check_frames(padapter, buf, len, _TRUE)) >= 0)\r
3800                         goto dump;\r
3801                 #endif\r
3802                 if (category == RTW_WLAN_CATEGORY_PUBLIC)\r
3803                         DBG_871X("RTW_Tx:%s\n", action_public_str(action));\r
3804                 else\r
3805                         DBG_871X("RTW_Tx:category(%u), action(%u)\n", category, action);\r
3806 \r
3807 dump:\r
3808                 //starting alloc mgmt frame to dump it\r
3809                 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
3810                 {                       \r
3811                         goto fail;\r
3812                 }\r
3813 \r
3814                 //update attribute\r
3815                 pattrib = &pmgntframe->attrib;\r
3816                 update_mgntframe_attrib(padapter, pattrib);\r
3817                 pattrib->retry_ctrl = _FALSE;\r
3818 \r
3819                 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
3820 \r
3821                 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
3822 \r
3823                 _rtw_memcpy(pframe, (void*)buf, len);\r
3824                 #ifdef CONFIG_WFD\r
3825                 if (type >= 0)\r
3826                 {\r
3827                         struct wifi_display_info                *pwfd_info;\r
3828                         \r
3829                         pwfd_info = padapter->wdinfo.wfd_info;\r
3830                         \r
3831                         if ( _TRUE == pwfd_info->wfd_enable )\r
3832                         {\r
3833                                 rtw_append_wfd_ie( padapter, pframe, &len );\r
3834                         }\r
3835                 }\r
3836                 #endif // CONFIG_WFD\r
3837                 pattrib->pktlen = len;  \r
3838         \r
3839                 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
3840                 //update seq number\r
3841                 pmlmeext->mgnt_seq = GetSequence(pwlanhdr);\r
3842                 pattrib->seqnum = pmlmeext->mgnt_seq;\r
3843                 pmlmeext->mgnt_seq++;\r
3844 \r
3845         \r
3846                 pattrib->last_txcmdsz = pattrib->pktlen;\r
3847         \r
3848                 dump_mgntframe(padapter, pmgntframe);\r
3849                 \r
3850         }\r
3851         else\r
3852         {\r
3853                 DBG_8192C("frame_ctl=0x%x\n", frame_ctl & (RTW_IEEE80211_FCTL_FTYPE|RTW_IEEE80211_FCTL_STYPE));\r
3854         }\r
3855 \r
3856         \r
3857 fail:\r
3858         \r
3859         rtw_skb_free(skb);\r
3860 \r
3861         return 0;\r
3862         \r
3863 }\r
3864 \r
3865 static void rtw_cfg80211_monitor_if_set_multicast_list(struct net_device *ndev)\r
3866 {\r
3867         DBG_8192C("%s\n", __func__);\r
3868 }\r
3869 \r
3870 static int rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)\r
3871 {\r
3872         int ret = 0;\r
3873         \r
3874         DBG_8192C("%s\n", __func__);\r
3875         \r
3876         return ret;\r
3877 }\r
3878 \r
3879 #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))\r
3880 static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {\r
3881         .ndo_open = rtw_cfg80211_monitor_if_open,\r
3882        .ndo_stop = rtw_cfg80211_monitor_if_close,\r
3883        .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,\r
3884        #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))\r
3885        .ndo_set_multicast_list = rtw_cfg80211_monitor_if_set_multicast_list,\r
3886        #endif\r
3887        .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,       \r
3888 };\r
3889 #endif\r
3890 \r
3891 static int rtw_cfg80211_add_monitor_if(_adapter *padapter, char *name, struct net_device **ndev)\r
3892 {\r
3893         int ret = 0;\r
3894         struct net_device* mon_ndev = NULL;\r
3895         struct wireless_dev* mon_wdev = NULL;\r
3896         struct rtw_netdev_priv_indicator *pnpi;\r
3897         struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);\r
3898                 \r
3899         if (!name ) {\r
3900                 DBG_871X(FUNC_ADPT_FMT" without specific name\n", FUNC_ADPT_ARG(padapter));\r
3901                 ret = -EINVAL;\r
3902                 goto out;\r
3903         }\r
3904 \r
3905         if (pwdev_priv->pmon_ndev) {\r
3906                 DBG_871X(FUNC_ADPT_FMT" monitor interface exist: "NDEV_FMT"\n",\r
3907                         FUNC_ADPT_ARG(padapter), NDEV_ARG(pwdev_priv->pmon_ndev));\r
3908                 ret = -EBUSY;\r
3909                 goto out;\r
3910         }\r
3911 \r
3912         mon_ndev = alloc_etherdev(sizeof(struct rtw_netdev_priv_indicator));\r
3913         if (!mon_ndev) {\r
3914                 DBG_871X(FUNC_ADPT_FMT" allocate ndev fail\n", FUNC_ADPT_ARG(padapter));\r
3915                 ret = -ENOMEM;\r
3916                 goto out;\r
3917         }\r
3918 \r
3919         mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;\r
3920         strncpy(mon_ndev->name, name, IFNAMSIZ);\r
3921         mon_ndev->name[IFNAMSIZ - 1] = 0;\r
3922         mon_ndev->destructor = rtw_ndev_destructor;\r
3923         \r
3924 #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))\r
3925         mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;\r
3926 #else\r
3927         mon_ndev->open = rtw_cfg80211_monitor_if_open;\r
3928         mon_ndev->stop = rtw_cfg80211_monitor_if_close;\r
3929         mon_ndev->hard_start_xmit = rtw_cfg80211_monitor_if_xmit_entry;\r
3930         mon_ndev->set_mac_address = rtw_cfg80211_monitor_if_set_mac_address;\r
3931 #endif\r
3932 \r
3933         pnpi = netdev_priv(mon_ndev);\r
3934         pnpi->priv = padapter;\r
3935         pnpi->sizeof_priv = sizeof(_adapter);\r
3936 \r
3937         /*  wdev */\r
3938         mon_wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));\r
3939         if (!mon_wdev) {\r
3940                 DBG_871X(FUNC_ADPT_FMT" allocate mon_wdev fail\n", FUNC_ADPT_ARG(padapter));\r
3941                 ret = -ENOMEM;\r
3942                 goto out;\r
3943         }\r
3944 \r
3945         mon_wdev->wiphy = padapter->rtw_wdev->wiphy;\r
3946         mon_wdev->netdev = mon_ndev;\r
3947         mon_wdev->iftype = NL80211_IFTYPE_MONITOR;\r
3948         mon_ndev->ieee80211_ptr = mon_wdev;\r
3949 \r
3950         ret = register_netdevice(mon_ndev);\r
3951         if (ret) {\r
3952                 goto out;\r
3953         }\r
3954 \r
3955         *ndev = pwdev_priv->pmon_ndev = mon_ndev;\r
3956         _rtw_memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ+1);\r
3957 \r
3958 out:\r
3959         if (ret && mon_wdev) {\r
3960                 rtw_mfree((u8*)mon_wdev, sizeof(struct wireless_dev));\r
3961                 mon_wdev = NULL;\r
3962         }\r
3963 \r
3964         if (ret && mon_ndev) {\r
3965                 free_netdev(mon_ndev);\r
3966                 *ndev = mon_ndev = NULL;\r
3967         }\r
3968 \r
3969         return ret;\r
3970 }\r
3971 \r
3972 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
3973 static struct wireless_dev *\r
3974 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)\r
3975 static struct net_device *\r
3976 #else\r
3977 static int\r
3978 #endif\r
3979         cfg80211_rtw_add_virtual_intf(\r
3980                 struct wiphy *wiphy,\r
3981         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))\r
3982                 const char *name,\r
3983         #else\r
3984                 char *name,\r
3985         #endif\r
3986                 enum nl80211_iftype type, u32 *flags, struct vif_params *params)\r
3987 {\r
3988         int ret = 0;\r
3989         struct net_device* ndev = NULL;\r
3990         _adapter *padapter = wiphy_to_adapter(wiphy);\r
3991 \r
3992         DBG_871X(FUNC_ADPT_FMT " wiphy:%s, name:%s, type:%d\n",\r
3993                 FUNC_ADPT_ARG(padapter), wiphy_name(wiphy), name, type);\r
3994 \r
3995         switch (type) {\r
3996         case NL80211_IFTYPE_ADHOC:\r
3997         case NL80211_IFTYPE_AP_VLAN:\r
3998         case NL80211_IFTYPE_WDS:\r
3999         case NL80211_IFTYPE_MESH_POINT:\r
4000                 ret = -ENODEV;\r
4001                 break;\r
4002         case NL80211_IFTYPE_MONITOR:\r
4003                 ret = rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);\r
4004                 break;\r
4005 \r
4006 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
4007         case NL80211_IFTYPE_P2P_CLIENT:\r
4008 #endif\r
4009         case NL80211_IFTYPE_STATION:\r
4010                 ret = -ENODEV;\r
4011                 break;\r
4012 \r
4013 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
4014         case NL80211_IFTYPE_P2P_GO:\r
4015 #endif\r
4016         case NL80211_IFTYPE_AP:\r
4017                 ret = -ENODEV;\r
4018                 break;\r
4019         default:\r
4020                 ret = -ENODEV;\r
4021                 DBG_871X("Unsupported interface type\n");\r
4022                 break;\r
4023         }\r
4024 \r
4025         DBG_871X(FUNC_ADPT_FMT" ndev:%p, ret:%d\n", FUNC_ADPT_ARG(padapter), ndev, ret);\r
4026 \r
4027 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
4028         return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret);\r
4029 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)\r
4030         return ndev ? ndev : ERR_PTR(ret);\r
4031 #else\r
4032         return ret;\r
4033 #endif\r
4034 }\r
4035 \r
4036 static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,\r
4037 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
4038         struct wireless_dev *wdev\r
4039 #else\r
4040         struct net_device *ndev\r
4041 #endif\r
4042 )\r
4043 {\r
4044 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
4045         struct net_device *ndev = wdev_to_ndev(wdev);\r
4046 #endif\r
4047         int ret = 0;\r
4048         _adapter *adapter;\r
4049         struct rtw_wdev_priv *pwdev_priv;\r
4050 \r
4051         if (!ndev) {\r
4052                 ret = -EINVAL;\r
4053                 goto exit;\r
4054         }\r
4055 \r
4056         adapter = (_adapter *)rtw_netdev_priv(ndev);\r
4057         pwdev_priv = adapter_wdev_data(adapter);\r
4058 \r
4059         unregister_netdevice(ndev);\r
4060 \r
4061         if (ndev == pwdev_priv->pmon_ndev) {\r
4062                 pwdev_priv->pmon_ndev = NULL;\r
4063                 pwdev_priv->ifname_mon[0] = '\0';\r
4064                 DBG_871X(FUNC_NDEV_FMT" remove monitor interface\n", FUNC_NDEV_ARG(ndev));\r
4065         }\r
4066 \r
4067 exit:\r
4068         return ret;\r
4069 }\r
4070 \r
4071 static int rtw_add_beacon(_adapter *adapter, const u8 *head, size_t head_len, const u8 *tail, size_t tail_len)\r
4072 {\r
4073         int ret=0;\r
4074         u8 *pbuf = NULL;\r
4075         uint len, wps_ielen=0;  \r
4076         uint p2p_ielen=0;\r
4077         u8 *p2p_ie;\r
4078         u8 got_p2p_ie = _FALSE;\r
4079         struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);\r
4080         //struct sta_priv *pstapriv = &padapter->stapriv;\r
4081         \r
4082 \r
4083         DBG_8192C("%s beacon_head_len=%zu, beacon_tail_len=%zu\n", __FUNCTION__, head_len, tail_len);\r
4084 \r
4085         \r
4086         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)\r
4087                 return -EINVAL;\r
4088 \r
4089         if(head_len<24)\r
4090                 return -EINVAL;\r
4091         \r
4092 \r
4093         pbuf = rtw_zmalloc(head_len+tail_len);\r
4094         if(!pbuf)\r
4095                 return -ENOMEM;\r
4096         \r
4097 \r
4098         //_rtw_memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);\r
4099 \r
4100         //if((pstapriv->max_num_sta>NUM_STA) || (pstapriv->max_num_sta<=0))\r
4101         //      pstapriv->max_num_sta = NUM_STA;\r
4102 \r
4103         \r
4104         _rtw_memcpy(pbuf, (void *)head+24, head_len-24);// 24=beacon header len.\r
4105         _rtw_memcpy(pbuf+head_len-24, (void *)tail, tail_len);\r
4106 \r
4107         len = head_len+tail_len-24;\r
4108 \r
4109         //check wps ie if inclued\r
4110         if(rtw_get_wps_ie(pbuf+_FIXED_IE_LENGTH_, len-_FIXED_IE_LENGTH_, NULL, &wps_ielen))\r
4111                 DBG_8192C("add bcn, wps_ielen=%d\n", wps_ielen);\r
4112 \r
4113 #ifdef CONFIG_P2P\r
4114         if( adapter->wdinfo.driver_interface == DRIVER_CFG80211 )\r
4115         {\r
4116                 //check p2p if enable\r
4117                 if(rtw_get_p2p_ie(pbuf+_FIXED_IE_LENGTH_, len-_FIXED_IE_LENGTH_, NULL, &p2p_ielen))\r
4118                 {               \r
4119                         struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;\r
4120                         struct wifidirect_info *pwdinfo= &(adapter->wdinfo);\r
4121 \r
4122                         DBG_8192C("got p2p_ie, len=%d\n", p2p_ielen);\r
4123                         \r
4124                         got_p2p_ie = _TRUE;     \r
4125                 \r
4126                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))\r
4127                         {                       \r
4128                                 DBG_8192C("Enable P2P function for the first time\n");\r
4129                                 rtw_p2p_enable(adapter, P2P_ROLE_GO);\r
4130                                 adapter_wdev_data(adapter)->p2p_enabled = _TRUE;\r
4131                                 \r
4132                                 adapter->stapriv.expire_to = 3; // 3x2 = 6 sec in p2p mode\r
4133                         }\r
4134                         else\r
4135                         {\r
4136                                 DBG_8192C("enter GO Mode, p2p_ielen=%d\n", p2p_ielen);\r
4137 \r
4138                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);\r
4139                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);\r
4140                                 pwdinfo->intent = 15;           \r
4141                         }\r
4142                 }\r
4143         }\r
4144 #endif // CONFIG_P2P\r
4145 \r
4146         /* pbss_network->IEs will not include p2p_ie, wfd ie */\r
4147         rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, P2P_OUI, 4);\r
4148         rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, WFD_OUI, 4);\r
4149 \r
4150         if (rtw_check_beacon_data(adapter, pbuf,  len) == _SUCCESS) \r
4151         {\r
4152 #ifdef  CONFIG_P2P              \r
4153                 //check p2p if enable\r
4154                 if(got_p2p_ie == _TRUE)\r
4155                 {\r
4156                         struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;\r
4157                         struct wifidirect_info *pwdinfo= &(adapter->wdinfo);\r
4158                         pwdinfo->operating_channel = pmlmeext->cur_channel;                     \r
4159                 }\r
4160 #endif //CONFIG_P2P\r
4161                 ret = 0;\r
4162         }       \r
4163         else\r
4164         {\r
4165                 ret = -EINVAL;\r
4166         }       \r
4167         \r
4168 \r
4169         rtw_mfree(pbuf, head_len+tail_len);     \r
4170         \r
4171         return ret;     \r
4172 }\r
4173 \r
4174 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) && !defined(COMPAT_KERNEL_RELEASE)\r
4175 static int cfg80211_rtw_add_beacon(struct wiphy *wiphy, struct net_device *ndev,\r
4176                               struct beacon_parameters *info)\r
4177 {\r
4178         int ret=0;\r
4179         _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);\r
4180 \r
4181         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4182         ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);\r
4183 \r
4184         return ret;\r
4185 }\r
4186 \r
4187 static int cfg80211_rtw_set_beacon(struct wiphy *wiphy, struct net_device *ndev,\r
4188                               struct beacon_parameters *info)\r
4189 {\r
4190         _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);\r
4191         struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);\r
4192         \r
4193         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4194 \r
4195         pmlmeext->bstart_bss = _TRUE;\r
4196 \r
4197         cfg80211_rtw_add_beacon(wiphy, ndev, info);\r
4198         \r
4199         return 0;\r
4200 }\r
4201 \r
4202 static int      cfg80211_rtw_del_beacon(struct wiphy *wiphy, struct net_device *ndev)\r
4203 {\r
4204         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4205         \r
4206         return 0;\r
4207 }\r
4208 #else\r
4209 static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,\r
4210                                                                 struct cfg80211_ap_settings *settings)\r
4211 {\r
4212         int ret = 0;\r
4213         _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);\r
4214         \r
4215         DBG_871X(FUNC_NDEV_FMT" hidden_ssid:%d, auth_type:%d\n", FUNC_NDEV_ARG(ndev),\r
4216                 settings->hidden_ssid, settings->auth_type);\r
4217 \r
4218         ret = rtw_add_beacon(adapter, settings->beacon.head, settings->beacon.head_len,\r
4219                 settings->beacon.tail, settings->beacon.tail_len);\r
4220 \r
4221         adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode = settings->hidden_ssid;\r
4222         \r
4223         if (settings->ssid && settings->ssid_len) {\r
4224                 WLAN_BSSID_EX *pbss_network = &adapter->mlmepriv.cur_network.network;\r
4225                 WLAN_BSSID_EX *pbss_network_ext = &adapter->mlmeextpriv.mlmext_info.network;\r
4226 \r
4227                 if(0)\r
4228                         DBG_871X(FUNC_ADPT_FMT" ssid:(%s,%zu), from ie:(%s,%d)\n", FUNC_ADPT_ARG(adapter),\r
4229                                 settings->ssid, settings->ssid_len,\r
4230                                 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength);\r
4231 \r
4232                 _rtw_memcpy(pbss_network->Ssid.Ssid, (void *)settings->ssid, settings->ssid_len);\r
4233                 pbss_network->Ssid.SsidLength = settings->ssid_len;\r
4234                 _rtw_memcpy(pbss_network_ext->Ssid.Ssid, (void *)settings->ssid, settings->ssid_len);\r
4235                 pbss_network_ext->Ssid.SsidLength = settings->ssid_len;\r
4236 \r
4237                 if(0)\r
4238                         DBG_871X(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),\r
4239                                 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,\r
4240                                 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);\r
4241         }\r
4242 \r
4243         return ret;\r
4244 }\r
4245 \r
4246 static int cfg80211_rtw_change_beacon(struct wiphy *wiphy, struct net_device *ndev,\r
4247                                 struct cfg80211_beacon_data *info)\r
4248 {\r
4249         int ret = 0;\r
4250         _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);\r
4251 \r
4252         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4253 \r
4254         ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);\r
4255 \r
4256         return ret;\r
4257 }\r
4258 \r
4259 static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)\r
4260 {\r
4261         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4262         return 0;\r
4263 }\r
4264 \r
4265 #endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))\r
4266 \r
4267 static int      cfg80211_rtw_add_station(struct wiphy *wiphy, struct net_device *ndev,\r
4268 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0))\r
4269                                 u8 *mac, \r
4270 #else\r
4271                                 const u8 *mac,\r
4272 #endif\r
4273                                struct station_parameters *params)\r
4274 {\r
4275         int ret = 0;\r
4276 #ifdef CONFIG_TDLS\r
4277         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
4278         struct sta_priv *pstapriv = &padapter->stapriv;\r
4279         struct sta_info *psta;\r
4280 #endif /* CONFIG_TDLS */\r
4281         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4282         \r
4283 #ifdef CONFIG_TDLS\r
4284         psta = rtw_get_stainfo(pstapriv, mac);\r
4285         if (psta == NULL) {\r
4286                 psta = rtw_alloc_stainfo(pstapriv, mac);\r
4287                 if (psta ==NULL) {\r
4288                         DBG_871X("[%s] Alloc station for "MAC_FMT" fail\n", __FUNCTION__, MAC_ARG(mac));\r
4289                         ret =-EOPNOTSUPP;\r
4290                         goto exit;\r
4291                 }\r
4292         }\r
4293 #endif /* CONFIG_TDLS */\r
4294 \r
4295 exit:\r
4296         return ret;\r
4297 }\r
4298 \r
4299 static int      cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev,\r
4300 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0))\r
4301                                 u8 *mac\r
4302 #else\r
4303                                 const u8 *mac\r
4304 #endif\r
4305                                )\r
4306 {\r
4307         int ret=0;      \r
4308         _irqL irqL;\r
4309         _list   *phead, *plist;\r
4310         u8 updated = _FALSE;\r
4311         struct sta_info *psta = NULL;\r
4312         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
4313         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
4314         struct sta_priv *pstapriv = &padapter->stapriv;\r
4315 \r
4316         DBG_871X("+"FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4317 \r
4318         if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)               \r
4319         {\r
4320                 DBG_8192C("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n", __func__);\r
4321                 return -EINVAL;         \r
4322         }\r
4323 \r
4324 \r
4325         if(!mac)\r
4326         {\r
4327                 DBG_8192C("flush all sta, and cam_entry\n");\r
4328 \r
4329                 flush_all_cam_entry(padapter);  //clear CAM\r
4330 \r
4331                 ret = rtw_sta_flush(padapter);\r
4332                 \r
4333                 return ret;\r
4334         }       \r
4335 \r
4336 \r
4337         DBG_8192C("free sta macaddr =" MAC_FMT "\n", MAC_ARG(mac));\r
4338 \r
4339         if (mac[0] == 0xff && mac[1] == 0xff &&\r
4340             mac[2] == 0xff && mac[3] == 0xff &&\r
4341             mac[4] == 0xff && mac[5] == 0xff) \r
4342         {\r
4343                 return -EINVAL; \r
4344         }\r
4345 \r
4346 \r
4347         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
4348         \r
4349         phead = &pstapriv->asoc_list;\r
4350         plist = get_next(phead);\r
4351 \r
4352         //check asoc_queue\r
4353         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
4354         {\r
4355                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
4356                 \r
4357                 plist = get_next(plist);        \r
4358         \r
4359                 if(_rtw_memcmp((u8 *)mac, psta->hwaddr, ETH_ALEN))              \r
4360                 {\r
4361                         if(psta->dot8021xalg == 1 && psta->bpairwise_key_installed == _FALSE)\r
4362                         {\r
4363                                 DBG_8192C("%s, sta's dot8021xalg = 1 and key_installed = _FALSE\n", __func__);\r
4364                         }\r
4365                         else\r
4366                         {\r
4367                                 DBG_8192C("free psta=%p, aid=%d\n", psta, psta->aid);\r
4368 \r
4369                                 rtw_list_delete(&psta->asoc_list);\r
4370                                 pstapriv->asoc_list_cnt--;\r
4371 \r
4372                                 //_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
4373                                 if (check_fwstate(pmlmepriv, (WIFI_AP_STATE)) == _TRUE)\r
4374                                         updated = ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_PREV_AUTH_NOT_VALID);\r
4375                                 else\r
4376                                         updated = ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING);\r
4377                                 //_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
4378 \r
4379                                 psta = NULL;\r
4380 \r
4381                                 break;\r
4382                         }               \r
4383                                         \r
4384                 }\r
4385                 \r
4386         }\r
4387 \r
4388         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
4389 \r
4390         associated_clients_update(padapter, updated);\r
4391 \r
4392         DBG_871X("-"FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4393         \r
4394         return ret;     \r
4395 \r
4396 }\r
4397 \r
4398 static int      cfg80211_rtw_change_station(struct wiphy *wiphy, struct net_device *ndev,\r
4399 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0))\r
4400                                 u8 *mac, \r
4401 #else\r
4402                                 const u8 *mac,\r
4403 #endif\r
4404                                 struct station_parameters *params)\r
4405 {\r
4406         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4407         \r
4408         return 0;\r
4409 }\r
4410 \r
4411 struct sta_info *rtw_sta_info_get_by_idx(const int idx, struct sta_priv *pstapriv)\r
4412 \r
4413 {\r\r
4414         _list   *phead, *plist;\r
4415         struct sta_info *psta = NULL;\r
4416         int i = 0;\r
4417         \r
4418         phead = &pstapriv->asoc_list;\r
4419         plist = get_next(phead);\r
4420 \r
4421         //check asoc_queue\r
4422         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
4423         {\r
4424                 if(idx == i) psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
4425                 plist = get_next(plist);        \r
4426                 i++;\r
4427         }\r
4428         return psta;\r
4429 }\r
4430 \r
4431 static int      cfg80211_rtw_dump_station(struct wiphy *wiphy, struct net_device *ndev,\r
4432                                int idx, u8 *mac, struct station_info *sinfo)\r
4433 {\r
4434 \r
4435         int ret = 0;\r
4436         _irqL irqL;\r
4437         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
4438         struct sta_info *psta = NULL;\r
4439         struct sta_priv *pstapriv = &padapter->stapriv;\r
4440         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4441 \r
4442         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
4443         psta = rtw_sta_info_get_by_idx(idx, pstapriv);\r
4444         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
4445         if(NULL == psta)\r
4446         {\r
4447                 DBG_871X("Station is not found\n");\r
4448                 ret = -ENOENT;\r
4449                 goto exit;\r
4450         }\r
4451         _rtw_memcpy(mac, psta->hwaddr, ETH_ALEN);\r
4452         sinfo->filled = 0;\r
4453         sinfo->filled |= STATION_INFO_SIGNAL;\r
4454         sinfo->signal = psta->rssi;\r
4455         \r
4456 exit:\r
4457         return ret;\r
4458 }\r
4459 \r
4460 static int      cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,\r
4461                               struct bss_parameters *params)\r
4462 {\r
4463         u8 i;\r
4464 \r
4465         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4466 /*\r
4467         DBG_8192C("use_cts_prot=%d\n", params->use_cts_prot);\r
4468         DBG_8192C("use_short_preamble=%d\n", params->use_short_preamble);\r
4469         DBG_8192C("use_short_slot_time=%d\n", params->use_short_slot_time);\r
4470         DBG_8192C("ap_isolate=%d\n", params->ap_isolate);\r
4471 \r
4472         DBG_8192C("basic_rates_len=%d\n", params->basic_rates_len);\r
4473         for(i=0; i<params->basic_rates_len; i++)\r
4474         {               \r
4475                 DBG_8192C("basic_rates=%d\n", params->basic_rates[i]);\r
4476                 \r
4477         }       \r
4478 */      \r
4479         return 0;\r
4480         \r
4481 }\r
4482 \r
4483 static int      cfg80211_rtw_set_channel(struct wiphy *wiphy\r
4484         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))\r
4485         , struct net_device *ndev\r
4486         #endif\r
4487         , struct ieee80211_channel *chan, enum nl80211_channel_type channel_type)\r
4488 {\r
4489         int chan_target = (u8) ieee80211_frequency_to_channel(chan->center_freq);\r
4490         int chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
4491         int chan_width = CHANNEL_WIDTH_20;\r
4492         _adapter *padapter = wiphy_to_adapter(wiphy);\r
4493 \r
4494         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))\r
4495         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4496         #endif\r
4497 \r
4498         switch (channel_type) {\r
4499         case NL80211_CHAN_NO_HT:\r
4500         case NL80211_CHAN_HT20:\r
4501                 chan_width = CHANNEL_WIDTH_20;\r
4502                 chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
4503                 break;\r
4504         case NL80211_CHAN_HT40MINUS:\r
4505                 chan_width = CHANNEL_WIDTH_40;\r
4506                 chan_offset = HAL_PRIME_CHNL_OFFSET_UPPER;\r
4507                 break;\r
4508         case NL80211_CHAN_HT40PLUS:\r
4509                 chan_width = CHANNEL_WIDTH_40;\r
4510                 chan_offset = HAL_PRIME_CHNL_OFFSET_LOWER;\r
4511                 break;\r
4512         default:\r
4513                 chan_width = CHANNEL_WIDTH_20;\r
4514                 chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
4515                 break;\r
4516         }\r
4517 \r
4518         set_channel_bwmode(padapter, chan_target, chan_offset, chan_width);\r
4519 \r
4520         return 0;\r
4521 }\r
4522 \r
4523 static int      cfg80211_rtw_auth(struct wiphy *wiphy, struct net_device *ndev,\r
4524                         struct cfg80211_auth_request *req)\r
4525 {\r
4526         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4527         \r
4528         return 0;\r
4529 }\r
4530 \r
4531 static int      cfg80211_rtw_assoc(struct wiphy *wiphy, struct net_device *ndev,\r
4532                          struct cfg80211_assoc_request *req)\r
4533 {\r
4534         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));\r
4535         \r
4536         return 0;\r
4537 }\r
4538 #endif //CONFIG_AP_MODE\r
4539 \r
4540 void rtw_cfg80211_rx_action_p2p(_adapter *padapter, u8 *pmgmt_frame, uint frame_len)\r
4541 {\r
4542         int type;\r
4543         s32 freq;\r
4544         int channel;\r
4545         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);\r
4546         u8 category, action;\r
4547 \r
4548         channel = rtw_get_oper_ch(padapter);\r
4549 \r
4550         DBG_8192C("RTW_Rx:cur_ch=%d\n", channel);\r
4551         #ifdef CONFIG_P2P\r
4552         type = rtw_p2p_check_frames(padapter, pmgmt_frame, frame_len, _FALSE);\r
4553         if (type >= 0)\r
4554                 goto indicate;\r
4555         #endif\r
4556         rtw_action_frame_parse(pmgmt_frame, frame_len, &category, &action);\r
4557         DBG_871X("RTW_Rx:category(%u), action(%u)\n", category, action);\r
4558 \r
4559 indicate:\r
4560         if (channel <= RTW_CH_MAX_2G_CHANNEL)\r
4561                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);\r
4562         else\r
4563                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);\r
4564 \r
4565 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
4566         rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);\r
4567 #else\r
4568         cfg80211_rx_action(padapter->pnetdev, freq, pmgmt_frame, frame_len, GFP_ATOMIC);\r
4569 #endif\r
4570 }\r
4571 \r
4572 void rtw_cfg80211_rx_p2p_action_public(_adapter *padapter, u8 *pmgmt_frame, uint frame_len)\r
4573 {\r
4574         int type;\r
4575         s32 freq;\r
4576         int channel;\r
4577         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);\r
4578         u8 category, action;\r
4579 \r
4580         channel = rtw_get_oper_ch(padapter);\r
4581 \r
4582         DBG_8192C("RTW_Rx:cur_ch=%d\n", channel);\r
4583         #ifdef CONFIG_P2P\r
4584         type = rtw_p2p_check_frames(padapter, pmgmt_frame, frame_len, _FALSE);\r
4585         if (type >= 0) {\r
4586                 switch (type) {\r
4587                 case P2P_GO_NEGO_CONF:\r
4588                 case P2P_PROVISION_DISC_RESP:\r
4589                 case P2P_INVIT_RESP:\r
4590                         rtw_set_scan_deny(padapter, 2000);                      \r
4591                         rtw_clear_scan_deny(padapter);\r
4592                 }\r
4593                 goto indicate;\r
4594         }\r
4595         #endif\r
4596         rtw_action_frame_parse(pmgmt_frame, frame_len, &category, &action);\r
4597         DBG_871X("RTW_Rx:category(%u), action(%u)\n", category, action);\r
4598 \r
4599 indicate:\r
4600         if (channel <= RTW_CH_MAX_2G_CHANNEL)\r
4601                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);\r
4602         else\r
4603                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);\r
4604 \r
4605 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
4606         rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);\r
4607 #else\r
4608         cfg80211_rx_action(padapter->pnetdev, freq, pmgmt_frame, frame_len, GFP_ATOMIC);\r
4609 #endif\r
4610 }\r
4611 \r
4612 void rtw_cfg80211_rx_action(_adapter *adapter, u8 *frame, uint frame_len, const char*msg)\r
4613 {\r
4614         s32 freq;\r
4615         int channel;\r
4616         struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);       \r
4617         struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);\r
4618         u8 category, action;\r
4619 \r
4620         channel = rtw_get_oper_ch(adapter);\r
4621 \r
4622         rtw_action_frame_parse(frame, frame_len, &category, &action);\r
4623 \r
4624         if (action == ACT_PUBLIC_GAS_INITIAL_REQ) {\r
4625                 rtw_set_scan_deny(adapter, 200);\r
4626                 rtw_scan_abort_no_wait(adapter);\r
4627                 #ifdef CONFIG_CONCURRENT_MODE\r
4628                 if (rtw_buddy_adapter_up(adapter))\r
4629                         rtw_scan_abort_no_wait(adapter->pbuddy_adapter);\r
4630                 #endif\r
4631         }\r
4632 \r
4633         if (channel <= RTW_CH_MAX_2G_CHANNEL)\r
4634                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);\r
4635         else\r
4636                 freq = rtw_ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);\r
4637 \r
4638 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
4639         rtw_cfg80211_rx_mgmt(adapter, freq, 0, frame, frame_len, GFP_ATOMIC);\r
4640 #else\r
4641         cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);\r
4642 #endif\r
4643 \r
4644         DBG_8192C("RTW_Rx:cur_ch=%d\n", channel);\r
4645         if (msg)\r
4646                 DBG_871X("RTW_Rx:%s\n", msg);\r
4647         else\r
4648                 DBG_871X("RTW_Rx:category(%u), action(%u)\n", category, action);\r
4649 }\r
4650 \r
4651 #ifdef CONFIG_P2P\r
4652 void rtw_cfg80211_issue_p2p_provision_request(_adapter *padapter, const u8 *buf, size_t len)\r
4653 {\r
4654         u16     wps_devicepassword_id = 0x0000;\r
4655         uint    wps_devicepassword_id_len = 0;\r
4656         u8                      wpsie[ 255 ] = { 0x00 }, p2p_ie[ 255 ] = { 0x00 };\r
4657         uint                    p2p_ielen = 0;\r
4658         uint                    wpsielen = 0;\r
4659         u32     devinfo_contentlen = 0;\r
4660         u8      devinfo_content[64] = { 0x00 };\r
4661         u16     capability = 0;\r
4662         uint capability_len = 0;\r
4663         \r
4664         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;\r
4665         u8                      action = P2P_PUB_ACTION_ACTION;\r
4666         u8                      dialogToken = 1;\r
4667         u32                     p2poui = cpu_to_be32(P2POUI);\r
4668         u8                      oui_subtype = P2P_PROVISION_DISC_REQ;   \r
4669         u32                     p2pielen = 0;\r
4670 #ifdef CONFIG_WFD\r
4671         u32                                     wfdielen = 0;\r
4672 #endif //CONFIG_WFD             \r
4673         \r
4674         struct xmit_frame                       *pmgntframe;\r
4675         struct pkt_attrib                       *pattrib;\r
4676         unsigned char                                   *pframe;\r
4677         struct rtw_ieee80211_hdr        *pwlanhdr;\r
4678         unsigned short                          *fctrl;\r
4679         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);\r
4680         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
4681         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
4682         \r
4683         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);\r
4684         u8 *frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));\r
4685         size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);\r
4686 \r
4687 \r
4688         DBG_871X( "[%s] In\n", __FUNCTION__ );\r
4689 \r
4690         //prepare for building provision_request frame  \r
4691         _rtw_memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr1Ptr(buf), ETH_ALEN);\r
4692         _rtw_memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, GetAddr1Ptr(buf), ETH_ALEN);\r
4693         \r
4694         pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;\r
4695                 \r
4696         rtw_get_wps_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);\r
4697         rtw_get_wps_attr_content( wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);\r
4698         wps_devicepassword_id = be16_to_cpu( wps_devicepassword_id );\r
4699 \r
4700         switch(wps_devicepassword_id) \r
4701         {\r
4702                 case WPS_DPID_PIN:\r
4703                         pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;\r
4704                         break;\r
4705                 case WPS_DPID_USER_SPEC:\r
4706                         pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;\r
4707                         break;\r
4708                 case WPS_DPID_MACHINE_SPEC:\r
4709                         break;\r
4710                 case WPS_DPID_REKEY:\r
4711                         break;\r
4712                 case WPS_DPID_PBC:\r
4713                         pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;\r
4714                         break;\r
4715                 case WPS_DPID_REGISTRAR_SPEC:\r
4716                         pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;\r
4717                         break;\r
4718                 default:\r
4719                         break;\r
4720         }\r
4721 \r
4722 \r
4723         if ( rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, p2p_ie, &p2p_ielen ) )\r
4724         {       \r
4725 \r
4726                 rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, devinfo_content, &devinfo_contentlen);                                       \r
4727                 rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&capability, &capability_len);\r
4728                                                 \r
4729         }\r
4730 \r
4731 \r
4732         //start to build provision_request frame        \r
4733         _rtw_memset(wpsie, 0, sizeof(wpsie));\r
4734         _rtw_memset(p2p_ie, 0, sizeof(p2p_ie));\r
4735         p2p_ielen = 0;  \r
4736         \r
4737         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
4738         {\r
4739                 return;\r
4740         }\r
4741 \r
4742         \r
4743         //update attribute\r
4744         pattrib = &pmgntframe->attrib;\r
4745         update_mgntframe_attrib(padapter, pattrib);\r
4746 \r
4747         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
4748 \r
4749         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
4750         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
4751 \r
4752         fctrl = &(pwlanhdr->frame_ctl);\r
4753         *(fctrl) = 0;\r
4754 \r
4755         _rtw_memcpy(pwlanhdr->addr1, pwdinfo->tx_prov_disc_info.peerDevAddr, ETH_ALEN);\r
4756         _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);\r
4757         _rtw_memcpy(pwlanhdr->addr3, pwdinfo->tx_prov_disc_info.peerDevAddr, ETH_ALEN);\r
4758 \r
4759         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);\r
4760         pmlmeext->mgnt_seq++;\r
4761         SetFrameSubType(pframe, WIFI_ACTION);\r
4762 \r
4763         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);\r
4764         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);\r
4765 \r
4766         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
4767         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
4768         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));\r
4769         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       \r
4770         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));               \r
4771 \r
4772 \r
4773         //build_prov_disc_request_p2p_ie        \r
4774         //      P2P OUI\r
4775         p2pielen = 0;\r
4776         p2p_ie[ p2pielen++ ] = 0x50;\r
4777         p2p_ie[ p2pielen++ ] = 0x6F;\r
4778         p2p_ie[ p2pielen++ ] = 0x9A;\r
4779         p2p_ie[ p2pielen++ ] = 0x09;    //      WFA P2P v1.0\r
4780 \r
4781         //      Commented by Albert 20110301\r
4782         //      According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes\r
4783         //      1. P2P Capability\r
4784         //      2. Device Info\r
4785         //      3. Group ID ( When joining an operating P2P Group )\r
4786 \r
4787         //      P2P Capability ATTR\r
4788         //      Type:   \r
4789         p2p_ie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;\r
4790 \r
4791         //      Length:\r
4792         //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );\r
4793         RTW_PUT_LE16(p2p_ie + p2pielen, 0x0002);\r
4794         p2pielen += 2;\r
4795 \r
4796         //      Value:\r
4797         //      Device Capability Bitmap, 1 byte\r
4798         //      Group Capability Bitmap, 1 byte\r
4799         _rtw_memcpy(p2p_ie + p2pielen, &capability, 2);\r
4800         p2pielen += 2;\r
4801         \r
4802 \r
4803         //      Device Info ATTR\r
4804         //      Type:\r
4805         p2p_ie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;\r
4806 \r
4807         //      Length:\r
4808         //      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) \r
4809         //      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)\r
4810         //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );\r
4811         RTW_PUT_LE16(p2p_ie + p2pielen, devinfo_contentlen);\r
4812         p2pielen += 2;\r
4813 \r
4814         //      Value:\r
4815         _rtw_memcpy(p2p_ie + p2pielen, devinfo_content, devinfo_contentlen);\r
4816         p2pielen += devinfo_contentlen;\r
4817 \r
4818 \r
4819         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2p_ie, &p2p_ielen);                      \r
4820         //p2pielen = build_prov_disc_request_p2p_ie( pwdinfo, pframe, NULL, 0, pwdinfo->tx_prov_disc_info.peerDevAddr);\r
4821         //pframe += p2pielen;\r
4822         pattrib->pktlen += p2p_ielen;\r
4823 \r
4824         wpsielen = 0;\r
4825         //      WPS OUI\r
4826         *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );\r
4827         wpsielen += 4;\r
4828 \r
4829         //      WPS version\r
4830         //      Type:\r
4831         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );\r
4832         wpsielen += 2;\r
4833 \r
4834         //      Length:\r
4835         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );\r
4836         wpsielen += 2;\r
4837 \r
4838         //      Value:\r
4839         wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0\r
4840 \r
4841         //      Config Method\r
4842         //      Type:\r
4843         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );\r
4844         wpsielen += 2;\r
4845 \r
4846         //      Length:\r
4847         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );\r
4848         wpsielen += 2;\r
4849 \r
4850         //      Value:\r
4851         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->tx_prov_disc_info.wps_config_method_request );\r
4852         wpsielen += 2;\r
4853 \r
4854         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );\r
4855 \r
4856 \r
4857 #ifdef CONFIG_WFD\r
4858         wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);\r
4859         pframe += wfdielen;\r
4860         pattrib->pktlen += wfdielen;\r
4861 #endif //CONFIG_WFD\r
4862 \r
4863         pattrib->last_txcmdsz = pattrib->pktlen;\r
4864 \r
4865         //dump_mgntframe(padapter, pmgntframe);\r
4866         if (dump_mgntframe_and_wait_ack(padapter, pmgntframe) != _SUCCESS)\r
4867                 DBG_8192C("%s, ack to\n", __func__);\r
4868 \r
4869         //if(wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)\r
4870         //{\r
4871         //      DBG_8192C("waiting for p2p peer key-in PIN CODE\n");\r
4872         //      rtw_msleep_os(15000); // 15 sec for key in PIN CODE, workaround for GS2 before issuing Nego Req.\r
4873         //}     \r
4874 \r
4875 }\r
4876 \r
4877 static s32 cfg80211_rtw_remain_on_channel(struct wiphy *wiphy,\r
4878 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
4879         struct wireless_dev *wdev,\r
4880 #else\r
4881         struct net_device *ndev,\r
4882 #endif\r
4883         struct ieee80211_channel * channel,\r
4884 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))\r
4885         enum nl80211_channel_type channel_type,\r
4886 #endif\r
4887         unsigned int duration, u64 *cookie)\r
4888 {\r
4889 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
4890         struct net_device *ndev = wdev_to_ndev(wdev);\r
4891 #endif\r
4892         s32 err = 0;\r
4893         u8 remain_ch = (u8) ieee80211_frequency_to_channel(channel->center_freq);\r
4894         u8 ready_on_channel = _FALSE;\r
4895         _adapter *padapter;\r
4896         struct rtw_wdev_priv *pwdev_priv;\r
4897         struct mlme_ext_priv *pmlmeext;\r
4898         struct wifidirect_info *pwdinfo;\r
4899         struct cfg80211_wifidirect_info *pcfg80211_wdinfo;\r
4900         u8 is_p2p_find = _FALSE;\r
4901 \r
4902 #ifndef CONFIG_RADIO_WORK\r
4903         #define RTW_ROCH_DURATION_ENLARGE\r
4904         #define RTW_ROCH_BACK_OP\r
4905 #endif\r
4906 \r
4907         if (ndev == NULL) {\r
4908                 return  -EINVAL;\r
4909         }\r
4910 \r
4911         padapter = (_adapter *)rtw_netdev_priv(ndev);\r
4912         pwdev_priv = adapter_wdev_data(padapter);\r
4913         pmlmeext = &padapter->mlmeextpriv;\r
4914         pwdinfo = &padapter->wdinfo;\r
4915         pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;\r
4916         #ifdef CONFIG_CONCURRENT_MODE\r
4917         is_p2p_find=(duration < (pwdinfo->ext_listen_interval))? _TRUE : _FALSE;\r
4918         #endif\r
4919 \r
4920         *cookie = ATOMIC_INC_RETURN(&pcfg80211_wdinfo->ro_ch_cookie_gen);\r
4921         \r
4922         DBG_871X(FUNC_ADPT_FMT" ch:%u duration:%d, cookie:0x%llx\n", FUNC_ADPT_ARG(padapter), remain_ch, duration, *cookie);\r
4923 \r
4924         if(pcfg80211_wdinfo->is_ro_ch == _TRUE)\r
4925         {\r
4926                 DBG_8192C("%s, cancel ro ch timer\n", __func__);\r
4927                 _cancel_timer_ex(&padapter->cfg80211_wdinfo.remain_on_ch_timer);\r
4928                 #ifdef CONFIG_CONCURRENT_MODE\r
4929                 ATOMIC_SET(&pwdev_priv->ro_ch_to, 1);\r
4930                 #endif //CONFIG_CONCURRENT_MODE\r
4931                 p2p_protocol_wk_hdl(padapter, P2P_RO_CH_WK);\r
4932         }\r
4933 \r
4934         pcfg80211_wdinfo->is_ro_ch = _TRUE;\r
4935         pcfg80211_wdinfo->last_ro_ch_time = rtw_get_current_time();\r
4936 \r
4937         if(_FAIL == rtw_pwr_wakeup(padapter)) {\r
4938                 err = -EFAULT;\r
4939                 goto exit;\r
4940         }\r
4941 \r
4942         _rtw_memcpy(&pcfg80211_wdinfo->remain_on_ch_channel, channel, sizeof(struct ieee80211_channel));\r
4943         #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))\r
4944         pcfg80211_wdinfo->remain_on_ch_type= channel_type;\r
4945         #endif\r
4946         pcfg80211_wdinfo->remain_on_ch_cookie= *cookie;\r
4947 \r
4948         rtw_scan_abort(padapter);\r
4949 #ifdef CONFIG_CONCURRENT_MODE           \r
4950         if ((rtw_buddy_adapter_up(padapter)) && is_p2p_find)            //don't scan_abort during p2p_listen.\r
4951                 rtw_scan_abort(padapter->pbuddy_adapter);                       \r
4952 #endif //CONFIG_CONCURRENT_MODE\r
4953 \r
4954         if (check_fwstate(&padapter->mlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS) == _TRUE)\r
4955         {\r
4956                 DBG_871X("mlme state:0x%x\n", get_fwstate(&padapter->mlmepriv));\r
4957                 remain_ch = padapter->mlmeextpriv.cur_channel;\r
4958         }\r
4959 #ifdef CONFIG_CONCURRENT_MODE\r
4960         if (check_buddy_fwstate(padapter, _FW_UNDER_LINKING|WIFI_UNDER_WPS) == _TRUE)\r
4961         {\r
4962                 DBG_871X("buddy_intf's mlme state:0x%x\n", get_fwstate(&(padapter->pbuddy_adapter->mlmepriv)));\r
4963                 remain_ch = padapter->pbuddy_adapter->mlmeextpriv.cur_channel;\r
4964         }\r
4965 #endif /* CONFIG_CONCURRENT_MODE */\r
4966 \r
4967         //if(!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) && !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))\r
4968         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))\r
4969         {\r
4970                 rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);\r
4971                 adapter_wdev_data(padapter)->p2p_enabled = _TRUE;\r
4972                 padapter->wdinfo.listen_channel = remain_ch;\r
4973         }\r
4974         else\r
4975         {\r
4976                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));\r
4977 #ifdef CONFIG_DEBUG_CFG80211            \r
4978                 DBG_8192C("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));\r
4979 #endif\r
4980         }\r
4981 \r
4982 \r
4983         rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);\r
4984 \r
4985         #ifdef RTW_ROCH_DURATION_ENLARGE\r
4986         if (duration < 400)\r
4987                 duration = duration * 3; /* extend from exper */\r
4988         #endif\r
4989 \r
4990 #ifdef RTW_ROCH_BACK_OP\r
4991 #ifdef CONFIG_CONCURRENT_MODE\r
4992         if (check_buddy_fwstate(padapter, _FW_LINKED)) {\r
4993                 if (is_p2p_find) /* p2p_find , duration<1000 */\r
4994                         duration = duration + pwdinfo->ext_listen_interval;\r
4995                 else /* p2p_listen, duration=5000 */\r
4996                         duration = pwdinfo->ext_listen_interval + (pwdinfo->ext_listen_interval / 4);\r
4997         }\r
4998 #endif\r
4999 #endif /* RTW_ROCH_BACK_OP */\r
5000 \r
5001         pcfg80211_wdinfo->restore_channel = rtw_get_oper_ch(padapter);\r
5002 \r
5003         if(rtw_ch_set_search_ch(pmlmeext->channel_set, remain_ch) >= 0) {\r
5004 #ifdef  CONFIG_CONCURRENT_MODE\r
5005                 if ( check_buddy_fwstate(padapter, _FW_LINKED) )\r
5006                 {\r
5007                         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;                     \r
5008                         struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;    \r
5009 \r
5010                         if((remain_ch != pbuddy_mlmeext->cur_channel) && !check_fwstate(&padapter->mlmepriv, _FW_LINKED))\r
5011                         {       \r
5012                                 if(ATOMIC_READ(&pwdev_priv->switch_ch_to)==1 ||\r
5013                                         (remain_ch != pmlmeext->cur_channel))\r
5014                                 {\r
5015                                         if (check_buddy_fwstate(padapter, WIFI_FW_STATION_STATE)) {\r
5016                                                 DBG_8192C("%s, issue nulldata pwrbit=1\n", __func__);\r
5017                                                 issue_nulldata(padapter->pbuddy_adapter, NULL, 1, 3, 500);\r
5018                                         }\r
5019 \r
5020                                         ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);\r
5021 \r
5022                                         #ifdef RTW_ROCH_BACK_OP\r
5023                                         DBG_8192C("%s, set switch ch timer, duration=%d\n", __func__, duration-pwdinfo->ext_listen_interval);\r
5024                                         _set_timer(&pwdinfo->ap_p2p_switch_timer, duration-pwdinfo->ext_listen_interval);\r
5025                                         #endif\r
5026                                 }                       \r
5027                         }\r
5028                 \r
5029                         ready_on_channel = _TRUE;\r
5030                         //pmlmeext->cur_channel = remain_ch;                    \r
5031                         //set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);\r
5032                 }else \r
5033 #endif //CONFIG_CONCURRENT_MODE\r
5034                 if(remain_ch != rtw_get_oper_ch(padapter) )\r
5035                 {\r
5036                         ready_on_channel = _TRUE;\r
5037                         //pmlmeext->cur_channel = remain_ch;                    \r
5038                         //set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);\r
5039                 }\r
5040         } else {\r
5041                 DBG_871X("%s remain_ch:%u not in channel plan!!!!\n", __FUNCTION__, remain_ch);\r
5042         }\r
5043         \r
5044 \r
5045         //call this after other things have been done\r
5046 #ifdef  CONFIG_CONCURRENT_MODE  \r
5047         if(ATOMIC_READ(&pwdev_priv->ro_ch_to)==1 ||\r
5048                 (remain_ch != rtw_get_oper_ch(padapter)))\r
5049         {\r
5050                 u8 co_channel = 0xff;\r
5051                 ATOMIC_SET(&pwdev_priv->ro_ch_to, 0);\r
5052 #endif\r
5053 \r
5054                 if(ready_on_channel == _TRUE)\r
5055                 {                       \r
5056                         if ( !check_fwstate(&padapter->mlmepriv, _FW_LINKED ) )\r
5057                         {\r
5058                                 pmlmeext->cur_channel = remain_ch;\r
5059                         \r
5060 #ifdef  CONFIG_CONCURRENT_MODE\r
5061                                 co_channel = rtw_get_oper_ch(padapter);\r
5062 \r
5063                                 if(co_channel !=remain_ch)\r
5064 #endif\r
5065                                 {\r
5066                                         //if (!padapter->mlmepriv.LinkDetectInfo.bBusyTraffic)\r
5067                                         set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);\r
5068                                 }\r
5069                         }\r
5070                 }\r
5071                 DBG_8192C("%s, set ro ch timer, duration=%d\n", __func__, duration);\r
5072                 _set_timer( &pcfg80211_wdinfo->remain_on_ch_timer, duration);\r
5073 \r
5074 #ifdef  CONFIG_CONCURRENT_MODE\r
5075         }\r
5076 #endif\r
5077 \r
5078         rtw_cfg80211_ready_on_channel(padapter, *cookie, channel, channel_type, duration, GFP_KERNEL);\r
5079 \r
5080 exit:\r
5081         if (err) {\r
5082                 pcfg80211_wdinfo->is_ro_ch = _FALSE;\r
5083                 pcfg80211_wdinfo->last_ro_ch_time = rtw_get_current_time();\r
5084         }\r
5085 \r
5086         return err;\r
5087 }\r
5088 \r
5089 static s32 cfg80211_rtw_cancel_remain_on_channel(struct wiphy *wiphy,\r
5090 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
5091         struct wireless_dev *wdev,\r
5092 #else\r
5093         struct net_device *ndev,\r
5094 #endif\r
5095         u64 cookie)\r
5096 {\r
5097 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
5098         struct net_device *ndev = wdev_to_ndev(wdev);\r
5099 #endif\r
5100         s32 err = 0;\r
5101         _adapter *padapter;\r
5102         struct rtw_wdev_priv *pwdev_priv;\r
5103         struct wifidirect_info *pwdinfo;\r
5104         struct cfg80211_wifidirect_info *pcfg80211_wdinfo;\r
5105 \r
5106         if (ndev == NULL) {\r
5107                 err = -EINVAL;\r
5108                 goto exit;\r
5109         }\r
5110 \r
5111         padapter = (_adapter *)rtw_netdev_priv(ndev);\r
5112         pwdev_priv = adapter_wdev_data(padapter);\r
5113         pwdinfo = &padapter->wdinfo;\r
5114         pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;\r
5115 \r
5116         DBG_871X(FUNC_ADPT_FMT" cookie:0x%llx\n", FUNC_ADPT_ARG(padapter), cookie);\r
5117 \r
5118         if (pcfg80211_wdinfo->is_ro_ch == _TRUE) {\r
5119                 DBG_8192C("%s, cancel ro ch timer\n", __func__);\r
5120                 _cancel_timer_ex(&padapter->cfg80211_wdinfo.remain_on_ch_timer);\r
5121                 #ifdef CONFIG_CONCURRENT_MODE\r
5122                 ATOMIC_SET(&pwdev_priv->ro_ch_to, 1);\r
5123                 #endif\r
5124                 p2p_protocol_wk_hdl(padapter, P2P_RO_CH_WK);\r
5125         }\r
5126 \r
5127         #if 0\r
5128         //      Disable P2P Listen State\r
5129         if(!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) && !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))\r
5130         {\r
5131                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))\r
5132                 {\r
5133                         rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);\r
5134                         _rtw_memset(pwdinfo, 0x00, sizeof(struct wifidirect_info));\r
5135                 }\r
5136         }\r
5137         else\r
5138         #endif\r
5139         {\r
5140                 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));\r
5141 #ifdef CONFIG_DEBUG_CFG80211             \r
5142                 DBG_8192C("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));\r
5143 #endif\r
5144         }\r
5145 \r
5146         pcfg80211_wdinfo->is_ro_ch = _FALSE;\r
5147         pcfg80211_wdinfo->last_ro_ch_time = rtw_get_current_time();\r
5148 \r
5149 exit:\r
5150         return err;\r
5151 }\r
5152 \r
5153 #endif //CONFIG_P2P\r
5154 \r
5155 static int _cfg80211_rtw_mgmt_tx(_adapter *padapter, u8 tx_ch, const u8 *buf, size_t len)\r
5156 {\r
5157         struct xmit_frame       *pmgntframe;\r
5158         struct pkt_attrib       *pattrib;\r
5159         unsigned char   *pframe;\r
5160         int ret = _FAIL;\r
5161         bool ack = _TRUE;\r
5162         struct rtw_ieee80211_hdr *pwlanhdr;\r
5163         struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);\r
5164         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);\r
5165         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);    \r
5166         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
5167 #ifdef  CONFIG_P2P\r
5168         struct wifidirect_info *pwdinfo = &padapter->wdinfo;\r
5169 #endif //CONFIG_P2P\r
5170         //struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;\r
5171 \r
5172         rtw_set_scan_deny(padapter, 1000);\r
5173 \r
5174         rtw_scan_abort(padapter);\r
5175         #ifdef CONFIG_CONCURRENT_MODE           \r
5176         if(rtw_buddy_adapter_up(padapter))      \r
5177                 rtw_scan_abort(padapter->pbuddy_adapter);\r
5178         #endif /* CONFIG_CONCURRENT_MODE */\r
5179 #ifdef CONFIG_P2P\r
5180         if (padapter->cfg80211_wdinfo.is_ro_ch == _TRUE) {\r
5181                 //DBG_8192C("%s, cancel ro ch timer\n", __func__);\r
5182                 //_cancel_timer_ex(&padapter->cfg80211_wdinfo.remain_on_ch_timer);\r
5183                 //padapter->cfg80211_wdinfo.is_ro_ch = _FALSE;\r
5184                 #ifdef CONFIG_CONCURRENT_MODE                   \r
5185                 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED ))\r
5186                 {\r
5187                         DBG_8192C("%s, extend ro ch time\n", __func__);\r
5188                         _set_timer( &padapter->cfg80211_wdinfo.remain_on_ch_timer, pwdinfo->ext_listen_period);\r
5189                 }       \r
5190                 #endif //CONFIG_CONCURRENT_MODE                 \r
5191         }\r
5192 #endif //CONFIG_P2P\r
5193 #ifdef CONFIG_CONCURRENT_MODE\r
5194         if (check_buddy_fwstate(padapter, _FW_LINKED )) {\r
5195                 u8 co_channel=0xff;\r
5196                 PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;                     \r
5197                 struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;    \r
5198 \r
5199                 co_channel = rtw_get_oper_ch(padapter);\r
5200 \r
5201                 if (tx_ch != pbuddy_mlmeext->cur_channel) {\r
5202 \r
5203                         u16 ext_listen_period;\r
5204                         \r
5205                         if (ATOMIC_READ(&pwdev_priv->switch_ch_to)==1) {\r
5206                                 if (check_buddy_fwstate(padapter, WIFI_FW_STATION_STATE)) {\r
5207                                         DBG_8192C("%s, issue nulldata pwrbit=1\n", __func__);\r
5208                                         issue_nulldata(padapter->pbuddy_adapter, NULL, 1, 3, 500);\r
5209                                 }\r
5210 \r
5211                                 ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);\r
5212 \r
5213                                 //DBG_8192C("%s, set switch ch timer, period=%d\n", __func__, pwdinfo->ext_listen_period);\r
5214                                 //_set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period);\r
5215                         }\r
5216 \r
5217                         if (check_fwstate(&padapter->mlmepriv, _FW_LINKED ))\r
5218                         {\r
5219                                 ext_listen_period = 500;// 500ms\r
5220                         }       \r
5221                         else\r
5222                         {                               \r
5223                                 ext_listen_period = pwdinfo->ext_listen_period;\r
5224                         }\r
5225 \r
5226                         DBG_8192C("%s, set switch ch timer, period=%d\n", __func__, ext_listen_period);\r
5227                         _set_timer(&pwdinfo->ap_p2p_switch_timer, ext_listen_period);   \r
5228                         \r
5229                 }\r
5230 \r
5231                 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED ))\r
5232                         pmlmeext->cur_channel = tx_ch;\r
5233 \r
5234                 if (tx_ch != co_channel)\r
5235                         set_channel_bwmode(padapter, tx_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);\r
5236         }else \r
5237 #endif //CONFIG_CONCURRENT_MODE\r
5238         //if (tx_ch != pmlmeext->cur_channel) {\r
5239         if(tx_ch != rtw_get_oper_ch(padapter)) {\r
5240                 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED ))\r
5241                         pmlmeext->cur_channel = tx_ch;\r
5242                 set_channel_bwmode(padapter, tx_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);\r
5243         }\r
5244 \r
5245         //starting alloc mgmt frame to dump it\r
5246         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
5247         {\r
5248                 //ret = -ENOMEM;\r
5249                 ret = _FAIL;\r
5250                 goto exit;\r
5251         }\r
5252 \r
5253         //update attribute\r
5254         pattrib = &pmgntframe->attrib;\r
5255         update_mgntframe_attrib(padapter, pattrib);\r
5256         pattrib->retry_ctrl = _FALSE;\r
5257 \r
5258         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
5259 \r
5260         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
5261 \r
5262         _rtw_memcpy(pframe, (void*)buf, len);\r
5263         pattrib->pktlen = len;  \r
5264         \r
5265         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
5266         //update seq number\r
5267         pmlmeext->mgnt_seq = GetSequence(pwlanhdr);\r
5268         pattrib->seqnum = pmlmeext->mgnt_seq;\r
5269         pmlmeext->mgnt_seq++;\r
5270 \r
5271 #ifdef CONFIG_WFD\r
5272         {\r
5273                 struct wifi_display_info        *pwfd_info;\r
5274                         \r
5275                 pwfd_info = padapter->wdinfo.wfd_info;\r
5276                         \r
5277                 if ( _TRUE == pwfd_info->wfd_enable )\r
5278                 {\r
5279                         rtw_append_wfd_ie( padapter, pframe, &pattrib->pktlen );\r
5280                 }\r
5281         }\r
5282 #endif // CONFIG_WFD\r
5283         \r
5284         pattrib->last_txcmdsz = pattrib->pktlen;\r
5285 \r
5286         if (dump_mgntframe_and_wait_ack(padapter, pmgntframe) != _SUCCESS) \r
5287         {\r
5288                 ack = _FALSE;\r
5289                 ret = _FAIL;\r
5290 \r
5291                 #ifdef CONFIG_DEBUG_CFG80211\r
5292                 DBG_8192C("%s, ack == _FAIL\n", __func__);\r
5293                 #endif\r
5294         }\r
5295         else \r
5296         {\r
5297 \r
5298 #ifdef CONFIG_XMIT_ACK\r
5299                 rtw_msleep_os(50);\r
5300 #endif  \r
5301                 #ifdef CONFIG_DEBUG_CFG80211\r
5302                 DBG_8192C("%s, ack=%d, ok!\n", __func__, ack);\r
5303                 #endif\r
5304                 ret = _SUCCESS;\r
5305         }\r
5306         \r
5307 exit:\r
5308 \r
5309         #ifdef CONFIG_DEBUG_CFG80211\r
5310         DBG_8192C("%s, ret=%d\n", __func__, ret);\r
5311         #endif\r
5312         \r
5313         return ret;             \r
5314         \r
5315 }\r
5316 \r
5317 static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy,\r
5318 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
5319         struct wireless_dev *wdev,\r
5320 #else\r
5321         struct net_device *ndev,\r
5322 #endif\r
5323 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)) || defined(COMPAT_KERNEL_RELEASE)\r
5324         struct ieee80211_channel *chan,\r
5325         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)\r
5326         bool offchan,\r
5327         #endif\r
5328         #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))\r
5329         enum nl80211_channel_type channel_type,\r
5330         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
5331         bool channel_type_valid,\r
5332         #endif\r
5333         #endif\r
5334         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)\r
5335         unsigned int wait,\r
5336         #endif\r
5337         const u8 *buf, size_t len,\r
5338         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0))\r
5339         bool no_cck,\r
5340         #endif\r
5341         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))\r
5342         bool dont_wait_for_ack,\r
5343         #endif\r
5344 #else\r
5345         struct cfg80211_mgmt_tx_params *params,\r
5346 #endif\r
5347         u64 *cookie)\r
5348 {\r
5349 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
5350         struct net_device *ndev = wdev_to_ndev(wdev);\r
5351 #endif\r
5352 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(COMPAT_KERNEL_RELEASE)\r
5353         struct ieee80211_channel *chan = params->chan;\r
5354         bool offchan = params->offchan;\r
5355         unsigned int wait = params->wait;\r
5356         const u8 *buf = params->buf;\r
5357         size_t len = params->len;\r
5358         bool no_cck = params->no_cck;\r
5359         bool dont_wait_for_ack = params->dont_wait_for_ack;\r
5360 #endif\r
5361         int ret = 0;\r
5362         int tx_ret;\r
5363         u32 dump_limit = RTW_MAX_MGMT_TX_CNT;\r
5364         u32 dump_cnt = 0;\r
5365         bool ack = _TRUE;\r
5366         u8 tx_ch = (u8)ieee80211_frequency_to_channel(chan->center_freq);\r
5367         u8 category, action;\r
5368         int type = (-1);\r
5369         u32 start = rtw_get_current_time();\r
5370         _adapter *padapter;\r
5371         struct rtw_wdev_priv *pwdev_priv;\r
5372 \r
5373         if (ndev == NULL) {\r
5374                 ret = -EINVAL;\r
5375                 goto exit;\r
5376         }\r
5377 \r
5378         padapter = (_adapter *)rtw_netdev_priv(ndev);\r
5379         pwdev_priv = adapter_wdev_data(padapter);\r
5380 \r
5381         /* cookie generation */\r
5382         *cookie = (unsigned long) buf;\r
5383 \r
5384 #ifdef CONFIG_DEBUG_CFG80211\r
5385         DBG_871X(FUNC_ADPT_FMT" len=%zu, ch=%d"\r
5386         #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))\r
5387                 ", ch_type=%d"\r
5388                 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)    \r
5389                 ", channel_type_valid=%d"\r
5390                 #endif\r
5391         #endif\r
5392                 "\n", FUNC_ADPT_ARG(padapter),\r
5393                 len, tx_ch\r
5394         #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))\r
5395                 , channel_type\r
5396                 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)    \r
5397                 , channel_type_valid\r
5398                 #endif\r
5399         #endif\r
5400         );\r
5401 #endif /* CONFIG_DEBUG_CFG80211 */\r
5402 \r
5403         /* indicate ack before issue frame to avoid racing with rsp frame */\r
5404 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
5405         rtw_cfg80211_mgmt_tx_status(padapter, *cookie, buf, len, ack, GFP_KERNEL);\r
5406 #elif  (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,34) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,35))\r
5407         cfg80211_action_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL);\r
5408 #endif\r
5409 \r
5410         if (rtw_action_frame_parse(buf, len, &category, &action) == _FALSE) {\r
5411                 DBG_8192C(FUNC_ADPT_FMT" frame_control:0x%x\n", FUNC_ADPT_ARG(padapter),\r
5412                         le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl));\r
5413                 goto exit;\r
5414         }\r
5415 \r
5416         DBG_8192C("RTW_Tx:tx_ch=%d, da="MAC_FMT"\n", tx_ch, MAC_ARG(GetAddr1Ptr(buf)));\r
5417         #ifdef CONFIG_P2P\r
5418         if((type = rtw_p2p_check_frames(padapter, buf, len, _TRUE)) >= 0) {\r
5419                 goto dump;\r
5420         }\r
5421         #endif\r
5422         if (category == RTW_WLAN_CATEGORY_PUBLIC)\r
5423                 DBG_871X("RTW_Tx:%s\n", action_public_str(action));\r
5424         else\r
5425                 DBG_871X("RTW_Tx:category(%u), action(%u)\n", category, action);\r
5426 \r
5427 dump:\r
5428 \r
5429         rtw_ps_deny(padapter, PS_DENY_MGNT_TX);\r
5430         if(_FAIL == rtw_pwr_wakeup(padapter)) {\r
5431                 ret = -EFAULT;\r
5432                 goto cancel_ps_deny;\r
5433         }\r
5434 \r
5435         while (1) {\r
5436                 u32 sleep_ms = 0;\r
5437                 u32 retry_guarantee_ms = 0;\r
5438 \r
5439                 dump_cnt++;\r
5440                 tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len);\r
5441 \r
5442                 switch (action) {\r
5443                 case ACT_PUBLIC_GAS_INITIAL_REQ:\r
5444                 case ACT_PUBLIC_GAS_INITIAL_RSP:\r
5445                         sleep_ms = 50;\r
5446                         retry_guarantee_ms = RTW_MAX_MGMT_TX_MS_GAS;\r
5447                 }\r
5448 \r
5449                 if (tx_ret == _SUCCESS\r
5450                         || (dump_cnt >= dump_limit && rtw_get_passing_time_ms(start) >= retry_guarantee_ms))\r
5451                                 break;\r
5452 \r
5453                 if (sleep_ms > 0)\r
5454                         rtw_msleep_os(sleep_ms);\r
5455         }\r
5456 \r
5457         if (tx_ret != _SUCCESS || dump_cnt > 1) {\r
5458                 DBG_871X(FUNC_ADPT_FMT" %s (%d/%d) in %d ms\n", FUNC_ADPT_ARG(padapter),\r
5459                         tx_ret==_SUCCESS?"OK":"FAIL", dump_cnt, dump_limit, rtw_get_passing_time_ms(start));\r
5460         }\r
5461 \r
5462         switch (type) {\r
5463         case P2P_GO_NEGO_CONF:\r
5464                 rtw_clear_scan_deny(padapter);\r
5465                 break;\r
5466         case P2P_INVIT_RESP:\r
5467                 if (pwdev_priv->invit_info.flags & BIT(0)\r
5468                         && pwdev_priv->invit_info.status == 0) \r
5469                 {\r
5470                         DBG_871X(FUNC_ADPT_FMT" agree with invitation of persistent group\n",\r
5471                                 FUNC_ADPT_ARG(padapter));\r
5472                         rtw_set_scan_deny(padapter, 5000);\r
5473                         rtw_pwr_wakeup_ex(padapter, 5000);\r
5474                         rtw_clear_scan_deny(padapter);\r
5475                 }\r
5476                 break;\r
5477         }       \r
5478 \r
5479 cancel_ps_deny:\r
5480         rtw_ps_deny_cancel(padapter, PS_DENY_MGNT_TX);\r
5481 exit:\r
5482         return ret;\r
5483 }\r
5484 \r
5485 static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,\r
5486 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))\r
5487         struct wireless_dev *wdev,\r
5488 #else\r
5489         struct net_device *ndev,\r
5490 #endif\r
5491         u16 frame_type, bool reg)\r
5492 {\r
5493 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))\r
5494         struct net_device *ndev = wdev_to_ndev(wdev);\r
5495 #endif\r
5496         _adapter *adapter;\r
5497 \r
5498         if (ndev == NULL)\r
5499                 goto exit;\r
5500 \r
5501         adapter = (_adapter *)rtw_netdev_priv(ndev);\r
5502 \r
5503 #ifdef CONFIG_DEBUG_CFG80211\r
5504         DBG_871X(FUNC_ADPT_FMT" frame_type:%x, reg:%d\n", FUNC_ADPT_ARG(adapter),\r
5505                 frame_type, reg);\r
5506 #endif\r
5507 \r
5508         if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))\r
5509                 return;\r
5510 exit:\r
5511         return;\r
5512 }\r
5513 \r
5514 #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0))\r
5515 static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy,\r
5516         struct net_device *ndev,\r
5517         u8 *peer,\r
5518         u8 action_code,\r
5519         u8 dialog_token,\r
5520         u16 status_code,\r
5521         const u8 *buf,\r
5522         size_t len)\r
5523 {\r
5524         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
5525         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;\r
5526         struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;\r
5527         int ret = 0;\r
5528         struct tdls_txmgmt txmgmt;\r
5529 \r
5530         if (rtw_tdls_is_driver_setup(padapter)) {\r
5531                 DBG_871X("Discard tdls action:%d, let driver to set up direct link\n", action_code);\r
5532                 goto discard;\r
5533         }\r
5534 \r
5535         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
5536         _rtw_memcpy(txmgmt.peer, peer, ETH_ALEN);\r
5537         txmgmt.action_code = action_code;\r
5538         txmgmt.dialog_token= dialog_token;\r
5539         txmgmt.status_code = status_code;\r
5540         txmgmt.len = len;\r
5541         txmgmt.buf = (u8 *)rtw_malloc(txmgmt.len);\r
5542         if (txmgmt.buf == NULL) {\r
5543                 ret = -ENOMEM;\r
5544                 goto bad;\r
5545         }\r
5546         _rtw_memcpy(txmgmt.buf, (void*)buf, txmgmt.len);\r
5547 \r
5548 /* Debug purpose */\r
5549 #if 1\r
5550         DBG_871X("%s %d\n", __FUNCTION__, __LINE__);\r
5551         DBG_871X("peer:"MAC_FMT", action code:%d, dialog:%d, status code:%d\n",\r
5552                                 MAC_ARG(txmgmt.peer), txmgmt.action_code, \r
5553                                 txmgmt.dialog_token, txmgmt.status_code);\r
5554         if (txmgmt.len > 0) {\r
5555                 int i=0;\r
5556                 for(;i < len; i++)\r
5557                         printk("%02x ", *(txmgmt.buf+i));\r
5558                         DBG_871X("len:%d\n", txmgmt.len);\r
5559         }\r
5560 #endif\r
5561 \r
5562         switch (txmgmt.action_code) {\r
5563         case TDLS_SETUP_REQUEST:\r
5564                 issue_tdls_setup_req(padapter, &txmgmt, _TRUE);\r
5565                 break;\r
5566         case TDLS_SETUP_RESPONSE:\r
5567                 issue_tdls_setup_rsp(padapter, &txmgmt);\r
5568                 break;\r
5569         case TDLS_SETUP_CONFIRM:\r
5570                 issue_tdls_setup_cfm(padapter, &txmgmt);\r
5571                 break;\r
5572         case TDLS_TEARDOWN:\r
5573                 issue_tdls_teardown(padapter, &txmgmt, _TRUE);\r
5574                 break;\r
5575         case TDLS_DISCOVERY_REQUEST:\r
5576                 issue_tdls_dis_req(padapter, &txmgmt);\r
5577                 break;\r
5578         case TDLS_DISCOVERY_RESPONSE:\r
5579                 issue_tdls_dis_rsp(padapter, &txmgmt, pmlmeinfo->enc_algo? _TRUE : _FALSE);\r
5580                 break;\r
5581         }\r
5582 \r
5583 bad:\r
5584         if (txmgmt.buf)\r
5585                 rtw_mfree(txmgmt.buf, txmgmt.len);\r
5586 \r
5587 discard:\r
5588         return ret;\r
5589 }\r
5590 \r
5591 static int cfg80211_rtw_tdls_oper(struct wiphy *wiphy,\r
5592         struct net_device *ndev,\r
5593         u8 *peer,\r
5594         enum nl80211_tdls_operation oper)\r
5595 {\r
5596         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
5597         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;\r
5598         struct tdls_txmgmt      txmgmt;\r
5599         struct sta_info *ptdls_sta = NULL;\r
5600 \r
5601         DBG_871X(FUNC_NDEV_FMT", nl80211_tdls_operation:%d\n", FUNC_NDEV_ARG(ndev), oper);\r
5602 \r
5603 #ifdef CONFIG_LPS\r
5604         rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1);\r
5605 #endif //CONFIG_LPS\r
5606 \r
5607         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
5608         if (peer)\r
5609                 _rtw_memcpy(txmgmt.peer, peer, ETH_ALEN);\r
5610 \r
5611         if (rtw_tdls_is_driver_setup(padapter)) {\r
5612                 /* these two cases are done by driver itself */\r
5613                 if (oper == NL80211_TDLS_ENABLE_LINK || oper == NL80211_TDLS_DISABLE_LINK)\r
5614                         return 0;\r
5615         }\r
5616 \r
5617         switch (oper) {\r
5618         case NL80211_TDLS_DISCOVERY_REQ:\r
5619                 issue_tdls_dis_req(padapter, &txmgmt);\r
5620                 break;\r
5621         case NL80211_TDLS_SETUP:\r
5622 #ifdef CONFIG_WFD\r
5623                 if ( _AES_ != padapter->securitypriv.dot11PrivacyAlgrthm ) {\r
5624                         if ( padapter->wdinfo.wfd_tdls_weaksec == _TRUE)\r
5625                                 issue_tdls_setup_req(padapter, &txmgmt, _TRUE);\r
5626                         else\r
5627                                 DBG_871X( "[%s] Current link is not AES, SKIP sending the tdls setup request!!\n", __FUNCTION__ );\r
5628                 } else\r
5629 #endif // CONFIG_WFD\r
5630                 {\r
5631                         issue_tdls_setup_req(padapter, &txmgmt, _TRUE);\r
5632                 }\r
5633                 break;\r
5634         case NL80211_TDLS_TEARDOWN:\r
5635                 ptdls_sta = rtw_get_stainfo( &(padapter->stapriv), txmgmt.peer);\r
5636                 if (ptdls_sta != NULL) {\r
5637                         txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;\r
5638                         issue_tdls_teardown(padapter, &txmgmt, _TRUE);\r
5639                 }else {\r
5640                         DBG_871X( "TDLS peer not found\n");\r
5641                 }\r
5642                 break;\r
5643         case NL80211_TDLS_ENABLE_LINK:\r
5644                 DBG_871X(FUNC_NDEV_FMT", NL80211_TDLS_ENABLE_LINK;mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(peer));\r
5645                 ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), peer);\r
5646                 if (ptdls_sta != NULL) {\r
5647                         ptdlsinfo->link_established = _TRUE;\r
5648                         ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;\r
5649                         ptdls_sta->state |= _FW_LINKED;\r
5650                         rtw_tdls_cmd(padapter, txmgmt.peer, TDLS_ESTABLISHED);\r
5651                 }\r
5652                 break;\r
5653         case NL80211_TDLS_DISABLE_LINK:\r
5654                 DBG_871X(FUNC_NDEV_FMT", NL80211_TDLS_DISABLE_LINK;mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(peer));\r
5655                 ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), peer);\r
5656                 if (ptdls_sta != NULL) {\r
5657                         rtw_tdls_cmd(padapter, peer, TDLS_TEAR_STA );\r
5658                 }\r
5659                 break;\r
5660         }\r
5661         return 0;\r
5662 }\r
5663 #endif /* CONFIG_TDLS */\r
5664 \r
5665 #if defined(CONFIG_PNO_SUPPORT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))\r
5666 static int cfg80211_rtw_sched_scan_start(struct wiphy *wiphy,\r
5667                 struct net_device *dev,\r
5668                 struct cfg80211_sched_scan_request *request) {\r
5669 \r
5670         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);\r
5671         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);\r
5672         u8 ret;\r
5673 \r
5674         if (padapter->bup == _FALSE) {\r
5675                 DBG_871X("%s: net device is down.\n", __func__);\r
5676                 return -EIO;\r
5677         }\r
5678 \r
5679         if(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE ||\r
5680                 check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE  ||\r
5681                 check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) {\r
5682                 DBG_871X("%s: device is busy.\n", __func__);\r
5683                 rtw_scan_abort(padapter);\r
5684         }\r
5685 \r
5686         if (request == NULL) {\r
5687                 DBG_871X("%s: invalid cfg80211_requests parameters.\n", __func__);\r
5688                 return -EINVAL;\r
5689         }\r
5690 \r
5691         ret = rtw_android_cfg80211_pno_setup(dev, request->ssids,\r
5692                         request->n_ssids, request->interval);\r
5693 \r
5694         if (ret < 0) {\r
5695                 DBG_871X("%s ret: %d\n", __func__, ret);\r
5696                 goto exit;\r
5697         }\r
5698 \r
5699         ret = rtw_android_pno_enable(dev, _TRUE);\r
5700         if (ret < 0) {\r
5701                 DBG_871X("%s ret: %d\n", __func__, ret);\r
5702                 goto exit;\r
5703         }\r
5704 exit:\r
5705         return ret;\r
5706 }\r
5707 \r
5708 static int cfg80211_rtw_sched_scan_stop(struct wiphy *wiphy,\r
5709                 struct net_device *dev) {\r
5710         return rtw_android_pno_enable(dev, _FALSE);\r
5711 }\r
5712 #endif /* CONFIG_PNO_SUPPORT */\r
5713 \r
5714 static int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf, int len)\r
5715 {       \r
5716         int ret = 0;\r
5717         uint wps_ielen = 0;\r
5718         u8 *wps_ie;\r
5719         u32     p2p_ielen = 0;\r
5720         u8 wps_oui[8]={0x0,0x50,0xf2,0x04};     \r
5721         u8 *p2p_ie;\r
5722         u32     wfd_ielen = 0;  \r
5723         u8 *wfd_ie;\r
5724         _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);\r
5725         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
5726         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);\r
5727 \r
5728         DBG_871X(FUNC_NDEV_FMT" ielen=%d\n", FUNC_NDEV_ARG(ndev), len);\r
5729         \r
5730         if(len>0)\r
5731         {\r
5732                 if((wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen)))\r
5733                 {       \r
5734                         #ifdef CONFIG_DEBUG_CFG80211\r
5735                         DBG_8192C("bcn_wps_ielen=%d\n", wps_ielen);\r
5736                         #endif\r
5737                 \r
5738                         if(pmlmepriv->wps_beacon_ie)\r
5739                         {\r
5740                                 u32 free_len = pmlmepriv->wps_beacon_ie_len;\r
5741                                 pmlmepriv->wps_beacon_ie_len = 0;\r
5742                                 rtw_mfree(pmlmepriv->wps_beacon_ie, free_len);\r
5743                                 pmlmepriv->wps_beacon_ie = NULL;                        \r
5744                         }       \r
5745 \r
5746                         pmlmepriv->wps_beacon_ie = rtw_malloc(wps_ielen);\r
5747                         if ( pmlmepriv->wps_beacon_ie == NULL) {\r
5748                                 DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
5749                                 return -EINVAL;\r
5750                         \r
5751                         }\r
5752                         \r
5753                         _rtw_memcpy(pmlmepriv->wps_beacon_ie, wps_ie, wps_ielen);\r
5754                         pmlmepriv->wps_beacon_ie_len = wps_ielen;\r
5755         \r
5756                         update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, _TRUE);\r
5757 \r
5758                 }\r
5759 \r
5760                 //buf += wps_ielen;\r
5761                 //len -= wps_ielen;\r
5762 \r
5763                 #ifdef CONFIG_P2P\r
5764                 if((p2p_ie=rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen)))\r
5765                 {\r
5766                         #ifdef CONFIG_DEBUG_CFG80211\r
5767                         DBG_8192C("bcn_p2p_ielen=%d\n", p2p_ielen);\r
5768                         #endif\r
5769                 \r
5770                         if(pmlmepriv->p2p_beacon_ie)\r
5771                         {\r
5772                                 u32 free_len = pmlmepriv->p2p_beacon_ie_len;\r
5773                                 pmlmepriv->p2p_beacon_ie_len = 0;\r
5774                                 rtw_mfree(pmlmepriv->p2p_beacon_ie, free_len);\r
5775                                 pmlmepriv->p2p_beacon_ie = NULL;                        \r
5776                         }       \r
5777 \r
5778                         pmlmepriv->p2p_beacon_ie = rtw_malloc(p2p_ielen);\r
5779                         if ( pmlmepriv->p2p_beacon_ie == NULL) {\r
5780                                 DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
5781                                 return -EINVAL;\r
5782                         \r
5783                         }\r
5784                         \r
5785                         _rtw_memcpy(pmlmepriv->p2p_beacon_ie, p2p_ie, p2p_ielen);\r
5786                         pmlmepriv->p2p_beacon_ie_len = p2p_ielen;\r
5787                         \r
5788                 }\r
5789                 #endif //CONFIG_P2P\r
5790                 \r
5791                 //buf += p2p_ielen;\r
5792                 //len -= p2p_ielen;\r
5793 \r
5794                 #ifdef CONFIG_WFD\r
5795                 if(rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) \r
5796                 {\r
5797                         #ifdef CONFIG_DEBUG_CFG80211\r
5798                         DBG_8192C("bcn_wfd_ielen=%d\n", wfd_ielen);\r
5799                         #endif\r
5800                         \r
5801                         if(pmlmepriv->wfd_beacon_ie)\r
5802                         {\r
5803                                 u32 free_len = pmlmepriv->wfd_beacon_ie_len;\r
5804                                 pmlmepriv->wfd_beacon_ie_len = 0;\r
5805                                 rtw_mfree(pmlmepriv->wfd_beacon_ie, free_len);\r
5806                                 pmlmepriv->wfd_beacon_ie = NULL;\r
5807                         }       \r
5808 \r
5809                         pmlmepriv->wfd_beacon_ie = rtw_malloc(wfd_ielen);\r
5810                         if ( pmlmepriv->wfd_beacon_ie == NULL) {\r
5811                                 DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
5812                                 return -EINVAL;\r
5813                         \r
5814                         }\r
5815                         rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_beacon_ie, &pmlmepriv->wfd_beacon_ie_len);                      \r
5816                 }\r
5817                 #endif //CONFIG_WFD\r
5818                 \r
5819                 pmlmeext->bstart_bss = _TRUE;\r
5820                 \r
5821         }\r
5822 \r
5823         return ret;\r
5824         \r
5825 }\r
5826 \r
5827 static int rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device *net, char *buf, int len)\r
5828 {\r
5829         int ret = 0;\r
5830         uint wps_ielen = 0;\r
5831         u8 *wps_ie;\r
5832         u32     p2p_ielen = 0;  \r
5833         u8 *p2p_ie;\r
5834         u32     wfd_ielen = 0;  \r
5835         u8 *wfd_ie;\r
5836         _adapter *padapter = (_adapter *)rtw_netdev_priv(net);\r
5837         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);    \r
5838 \r
5839 #ifdef CONFIG_DEBUG_CFG80211\r
5840         DBG_8192C("%s, ielen=%d\n", __func__, len);\r
5841 #endif\r
5842         \r
5843         if(len>0)\r
5844         {\r
5845                 if((wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen)))\r
5846                 {       \r
5847                         uint    attr_contentlen = 0;\r
5848                         u16     uconfig_method, *puconfig_method = NULL;\r
5849 \r
5850                         #ifdef CONFIG_DEBUG_CFG80211                    \r
5851                         DBG_8192C("probe_resp_wps_ielen=%d\n", wps_ielen);\r
5852                         #endif\r
5853                 \r
5854                         if(check_fwstate(pmlmepriv, WIFI_UNDER_WPS))\r
5855                         {\r
5856                                 u8 sr = 0;\r
5857                                 rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8*)(&sr), NULL);\r
5858 \r
5859                                 if (sr != 0)\r
5860                                 {\r
5861                                         DBG_871X("%s, got sr\n", __func__);\r
5862                                 }       \r
5863                                 else\r
5864                                 {                               \r
5865                                         DBG_8192C("GO mode process WPS under site-survey,  sr no set\n");\r
5866                                         return ret;\r
5867                                 }       \r
5868                         }                       \r
5869                 \r
5870                         if(pmlmepriv->wps_probe_resp_ie)\r
5871                         {\r
5872                                 u32 free_len = pmlmepriv->wps_probe_resp_ie_len;\r
5873                                 pmlmepriv->wps_probe_resp_ie_len = 0;\r
5874                                 rtw_mfree(pmlmepriv->wps_probe_resp_ie, free_len);\r
5875                                 pmlmepriv->wps_probe_resp_ie = NULL;                    \r
5876                         }       \r
5877 \r
5878                         pmlmepriv->wps_probe_resp_ie = rtw_malloc(wps_ielen);\r
5879                         if ( pmlmepriv->wps_probe_resp_ie == NULL) {\r
5880                                 DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
5881                                 return -EINVAL;\r
5882                         \r
5883                         }\r
5884                         \r
5885                         //add PUSH_BUTTON config_method by driver self in wpsie of probe_resp at GO Mode \r
5886                         if ( (puconfig_method = (u16*)rtw_get_wps_attr_content( wps_ie, wps_ielen, WPS_ATTR_CONF_METHOD , NULL, &attr_contentlen)) != NULL )\r
5887                         {\r
5888                                 //struct registry_priv *pregistrypriv = &padapter->registrypriv;\r
5889                                 struct wireless_dev *wdev = padapter->rtw_wdev;\r
5890                                 \r
5891                                 #ifdef CONFIG_DEBUG_CFG80211            \r
5892                                 //printk("config_method in wpsie of probe_resp = 0x%x\n", be16_to_cpu(*puconfig_method));\r
5893                                 #endif\r
5894                                 \r
5895                                 //if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)\r
5896                                 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)\r
5897                                 if(wdev->iftype != NL80211_IFTYPE_P2P_GO) //for WIFI-DIRECT LOGO 4.2.2, AUTO GO can't set PUSH_BUTTON flags\r
5898                                 {\r
5899                                         uconfig_method = WPS_CM_PUSH_BUTTON;\r
5900                                         uconfig_method = cpu_to_be16( uconfig_method );\r
5901                         \r
5902                                         *puconfig_method |= uconfig_method;                     \r
5903                                 }       \r
5904                                 #endif\r
5905                         }\r
5906                         \r
5907                         _rtw_memcpy(pmlmepriv->wps_probe_resp_ie, wps_ie, wps_ielen);\r
5908                         pmlmepriv->wps_probe_resp_ie_len = wps_ielen;\r
5909                         \r
5910                 }\r
5911 \r
5912                 //buf += wps_ielen;\r
5913                 //len -= wps_ielen;\r
5914 \r
5915                 #ifdef CONFIG_P2P\r
5916                 if((p2p_ie=rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen))) \r
5917                 {\r
5918                         u8 is_GO = _FALSE;                      \r
5919                         u32 attr_contentlen = 0;\r
5920                         u16 cap_attr=0;\r
5921 \r
5922                         #ifdef CONFIG_DEBUG_CFG80211\r
5923                         DBG_8192C("probe_resp_p2p_ielen=%d\n", p2p_ielen);\r
5924                         #endif                  \r
5925 \r
5926                         //Check P2P Capability ATTR\r
5927                         if( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*) &attr_contentlen) )\r
5928                         {\r
5929                                 u8 grp_cap=0;\r
5930                                 //DBG_8192C( "[%s] Got P2P Capability Attr!!\n", __FUNCTION__ );\r
5931                                 cap_attr = le16_to_cpu(cap_attr);\r
5932                                 grp_cap = (u8)((cap_attr >> 8)&0xff);\r
5933                                 \r
5934                                 is_GO = (grp_cap&BIT(0)) ? _TRUE:_FALSE;\r
5935 \r
5936                                 if(is_GO)\r
5937                                         DBG_8192C("Got P2P Capability Attr, grp_cap=0x%x, is_GO\n", grp_cap);\r
5938                         }\r
5939 \r
5940 \r
5941                         if(is_GO == _FALSE)\r
5942                         {\r
5943                                 if(pmlmepriv->p2p_probe_resp_ie)\r
5944                                 {\r
5945                                         u32 free_len = pmlmepriv->p2p_probe_resp_ie_len;\r
5946                                         pmlmepriv->p2p_probe_resp_ie_len = 0;\r
5947                                         rtw_mfree(pmlmepriv->p2p_probe_resp_ie, free_len);\r
5948                                         pmlmepriv->p2p_probe_resp_ie = NULL;            \r
5949                                 }       \r
5950 \r
5951                                 pmlmepriv->p2p_probe_resp_ie = rtw_malloc(p2p_ielen);\r
5952                                 if ( pmlmepriv->p2p_probe_resp_ie == NULL) {\r
5953                                         DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
5954                                         return -EINVAL;\r
5955                                 \r
5956                                 }\r
5957                                 _rtw_memcpy(pmlmepriv->p2p_probe_resp_ie, p2p_ie, p2p_ielen);\r
5958                                 pmlmepriv->p2p_probe_resp_ie_len = p2p_ielen;\r
5959                         }               \r
5960                         else\r
5961                         {\r
5962                                 if(pmlmepriv->p2p_go_probe_resp_ie)\r
5963                                 {\r
5964                                         u32 free_len = pmlmepriv->p2p_go_probe_resp_ie_len;\r
5965                                         pmlmepriv->p2p_go_probe_resp_ie_len = 0;\r
5966                                         rtw_mfree(pmlmepriv->p2p_go_probe_resp_ie, free_len);\r
5967                                         pmlmepriv->p2p_go_probe_resp_ie = NULL;                 \r
5968                                 }       \r
5969 \r
5970                                 pmlmepriv->p2p_go_probe_resp_ie = rtw_malloc(p2p_ielen);\r
5971                                 if ( pmlmepriv->p2p_go_probe_resp_ie == NULL) {\r
5972                                         DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
5973                                         return -EINVAL;\r
5974                         \r
5975                                 }\r
5976                                 _rtw_memcpy(pmlmepriv->p2p_go_probe_resp_ie, p2p_ie, p2p_ielen);\r
5977                                 pmlmepriv->p2p_go_probe_resp_ie_len = p2p_ielen;\r
5978                         }\r
5979                         \r
5980                 }\r
5981                 #endif //CONFIG_P2P\r
5982                 \r
5983                 //buf += p2p_ielen;\r
5984                 //len -= p2p_ielen;\r
5985 \r
5986                 #ifdef CONFIG_WFD\r
5987                 if(rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) \r
5988                 {\r
5989                         #ifdef CONFIG_DEBUG_CFG80211\r
5990                         DBG_8192C("probe_resp_wfd_ielen=%d\n", wfd_ielen);\r
5991                         #endif\r
5992                         \r
5993                         if(pmlmepriv->wfd_probe_resp_ie)\r
5994                         {\r
5995                                 u32 free_len = pmlmepriv->wfd_probe_resp_ie_len;\r
5996                                 pmlmepriv->wfd_probe_resp_ie_len = 0;\r
5997                                 rtw_mfree(pmlmepriv->wfd_probe_resp_ie, free_len);\r
5998                                 pmlmepriv->wfd_probe_resp_ie = NULL;\r
5999                         }       \r
6000 \r
6001                         pmlmepriv->wfd_probe_resp_ie = rtw_malloc(wfd_ielen);\r
6002                         if ( pmlmepriv->wfd_probe_resp_ie == NULL) {\r
6003                                 DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
6004                                 return -EINVAL;\r
6005                         \r
6006                         }\r
6007                         rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_probe_resp_ie, &pmlmepriv->wfd_probe_resp_ie_len);                      \r
6008                 }\r
6009                 #endif //CONFIG_WFD\r
6010                 \r
6011         }\r
6012 \r
6013         return ret;\r
6014         \r
6015 }\r
6016 \r
6017 static int rtw_cfg80211_set_assoc_resp_wpsp2pie(struct net_device *net, char *buf, int len)\r
6018 {\r
6019         int ret = 0;\r
6020         _adapter *padapter = (_adapter *)rtw_netdev_priv(net);\r
6021         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
6022 \r
6023         DBG_8192C("%s, ielen=%d\n", __func__, len);\r
6024         \r
6025         if(len>0)\r
6026         {\r
6027                 if(pmlmepriv->wps_assoc_resp_ie)\r
6028                 {\r
6029                         u32 free_len = pmlmepriv->wps_assoc_resp_ie_len;\r
6030                         pmlmepriv->wps_assoc_resp_ie_len = 0;\r
6031                         rtw_mfree(pmlmepriv->wps_assoc_resp_ie, free_len);\r
6032                         pmlmepriv->wps_assoc_resp_ie = NULL;\r
6033                 }       \r
6034 \r
6035                 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(len);\r
6036                 if ( pmlmepriv->wps_assoc_resp_ie == NULL) {\r
6037                         DBG_8192C("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);\r
6038                         return -EINVAL;\r
6039                         \r
6040                 }\r
6041                 _rtw_memcpy(pmlmepriv->wps_assoc_resp_ie, buf, len);\r
6042                 pmlmepriv->wps_assoc_resp_ie_len = len;\r
6043         }\r
6044 \r
6045         return ret;\r
6046         \r
6047 }\r
6048 \r
6049 int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len,\r
6050         int type)\r
6051 {\r
6052         int ret = 0;\r
6053         uint wps_ielen = 0;\r
6054         u32     p2p_ielen = 0;\r
6055 \r
6056 #ifdef CONFIG_DEBUG_CFG80211\r
6057         DBG_8192C("%s, ielen=%d\n", __func__, len);\r
6058 #endif\r
6059 \r
6060         if(     (rtw_get_wps_ie(buf, len, NULL, &wps_ielen) && (wps_ielen>0))\r
6061                 #ifdef CONFIG_P2P\r
6062                 || (rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen) && (p2p_ielen>0))\r
6063                 #endif\r
6064         )               \r
6065         {       \r
6066                 if (net != NULL) \r
6067                 {\r
6068                         switch (type) \r
6069                         {\r
6070                                 case 0x1: //BEACON\r
6071                                 ret = rtw_cfg80211_set_beacon_wpsp2pie(net, buf, len);\r
6072                                 break;\r
6073                                 case 0x2: //PROBE_RESP\r
6074                                 ret = rtw_cfg80211_set_probe_resp_wpsp2pie(net, buf, len);\r
6075                                 break;\r
6076                                 case 0x4: //ASSOC_RESP\r
6077                                 ret = rtw_cfg80211_set_assoc_resp_wpsp2pie(net, buf, len);\r
6078                                 break;\r
6079                         }               \r
6080                 }\r
6081         }       \r
6082 \r
6083         return ret;\r
6084         \r
6085 }\r
6086 \r
6087 static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, enum ieee80211_band band, u8 rf_type)\r
6088 {\r
6089 \r
6090 #define MAX_BIT_RATE_40MHZ_MCS15        300     /* Mbps */\r
6091 #define MAX_BIT_RATE_40MHZ_MCS7         150     /* Mbps */\r
6092 \r
6093         ht_cap->ht_supported = _TRUE;\r
6094 \r
6095         ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |\r
6096                                         IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |\r
6097                                         IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;\r
6098 \r
6099         /*\r
6100          *Maximum length of AMPDU that the STA can receive.\r
6101          *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)\r
6102          */\r
6103         ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;\r
6104 \r
6105         /*Minimum MPDU start spacing , */\r
6106         ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;\r
6107 \r
6108         ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;\r
6109 \r
6110         /*\r
6111          *hw->wiphy->bands[IEEE80211_BAND_2GHZ]\r
6112          *base on ant_num\r
6113          *rx_mask: RX mask\r
6114          *if rx_ant =1 rx_mask[0]=0xff;==>MCS0-MCS7\r
6115          *if rx_ant =2 rx_mask[1]=0xff;==>MCS8-MCS15\r
6116          *if rx_ant >=3 rx_mask[2]=0xff;\r
6117          *if BW_40 rx_mask[4]=0x01;\r
6118          *highest supported RX rate\r
6119          */\r
6120         if(rf_type == RF_1T1R)\r
6121         {\r
6122                 ht_cap->mcs.rx_mask[0] = 0xFF;\r
6123                 ht_cap->mcs.rx_mask[1] = 0x00;\r
6124                 ht_cap->mcs.rx_mask[4] = 0x01;\r
6125 \r
6126                 ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;\r
6127         }\r
6128         else if((rf_type == RF_1T2R) || (rf_type==RF_2T2R))\r
6129         {\r
6130                 ht_cap->mcs.rx_mask[0] = 0xFF;\r
6131                 ht_cap->mcs.rx_mask[1] = 0xFF;\r
6132                 ht_cap->mcs.rx_mask[4] = 0x01;\r
6133 \r
6134                 ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;\r
6135         }\r
6136         else\r
6137         {\r
6138                 DBG_8192C("%s, error rf_type=%d\n", __func__, rf_type);\r
6139         }       \r
6140         \r
6141 }\r
6142 \r
6143 void rtw_cfg80211_init_wiphy(_adapter *padapter)\r
6144 {\r
6145         u8 rf_type;\r
6146         struct ieee80211_supported_band *bands;\r
6147         struct wireless_dev *pwdev = padapter->rtw_wdev;\r
6148         struct wiphy *wiphy = pwdev->wiphy;\r
6149         \r
6150         rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));\r
6151 \r
6152         DBG_8192C("%s:rf_type=%d\n", __func__, rf_type);\r
6153 \r
6154         if (padapter->registrypriv.wireless_mode & WIRELESS_11G)\r
6155         {\r
6156                 bands = wiphy->bands[IEEE80211_BAND_2GHZ];\r
6157                 if(bands)\r
6158                         rtw_cfg80211_init_ht_capab(&bands->ht_cap, IEEE80211_BAND_2GHZ, rf_type);\r
6159         }\r
6160 \r
6161         if (padapter->registrypriv.wireless_mode & WIRELESS_11A)\r
6162         {\r
6163                 bands = wiphy->bands[IEEE80211_BAND_5GHZ];\r
6164                 if(bands)\r
6165                         rtw_cfg80211_init_ht_capab(&bands->ht_cap, IEEE80211_BAND_5GHZ, rf_type);\r
6166         }\r
6167 \r
6168         /* init regulary domain */\r
6169         rtw_regd_init(padapter);\r
6170 \r
6171         /* copy mac_addr to wiphy */\r
6172         _rtw_memcpy(wiphy->perm_addr, adapter_mac_addr(padapter), ETH_ALEN);\r
6173 \r
6174 }\r
6175 \r
6176 /*\r
6177 struct ieee80211_iface_limit rtw_limits[] = {\r
6178         { .max = 1, .types = BIT(NL80211_IFTYPE_STATION)\r
6179                                         | BIT(NL80211_IFTYPE_ADHOC)\r
6180 #ifdef CONFIG_AP_MODE\r
6181                                         | BIT(NL80211_IFTYPE_AP)\r
6182 #endif\r
6183 #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE))\r
6184                                         | BIT(NL80211_IFTYPE_P2P_CLIENT)\r
6185                                         | BIT(NL80211_IFTYPE_P2P_GO)\r
6186 #endif\r
6187         },\r
6188         {.max = 1, .types = BIT(NL80211_IFTYPE_MONITOR)},\r
6189 };\r
6190 \r
6191 struct ieee80211_iface_combination rtw_combinations = {\r
6192         .limits = rtw_limits,\r
6193         .n_limits = ARRAY_SIZE(rtw_limits),\r
6194         .max_interfaces = 2,\r
6195         .num_different_channels = 1,\r
6196 };\r
6197 */\r
6198 \r
6199 static void rtw_cfg80211_preinit_wiphy(_adapter *padapter, struct wiphy *wiphy)\r
6200 {\r
6201 \r
6202         wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;\r
6203 \r
6204         wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;\r
6205         wiphy->max_scan_ie_len = RTW_SCAN_IE_LEN_MAX;   \r
6206         wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;\r
6207 \r
6208 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) || defined(COMPAT_KERNEL_RELEASE)     \r
6209         wiphy->max_remain_on_channel_duration = RTW_MAX_REMAIN_ON_CHANNEL_DURATION;\r
6210 #endif\r
6211         \r
6212         wiphy->interface_modes =        BIT(NL80211_IFTYPE_STATION)\r
6213                                                                 | BIT(NL80211_IFTYPE_ADHOC)\r
6214 #ifdef CONFIG_AP_MODE\r
6215                                                                 | BIT(NL80211_IFTYPE_AP)\r
6216                                                                 #ifndef CONFIG_RADIO_WORK\r
6217                                                                 | BIT(NL80211_IFTYPE_MONITOR)\r
6218                                                                 #endif\r
6219 #endif\r
6220 #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE))\r
6221                                                                 | BIT(NL80211_IFTYPE_P2P_CLIENT)\r
6222                                                                 | BIT(NL80211_IFTYPE_P2P_GO)\r
6223 #endif\r
6224                                                                 ;\r
6225 \r
6226 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)    \r
6227 #ifdef CONFIG_AP_MODE\r
6228         wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;\r
6229 #endif //CONFIG_AP_MODE \r
6230 #endif          \r
6231 \r
6232 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))\r
6233         #ifndef CONFIG_RADIO_WORK\r
6234         wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);\r
6235         #endif\r
6236 #endif\r
6237 \r
6238         /*\r
6239         wiphy->iface_combinations = &rtw_combinations;\r
6240         wiphy->n_iface_combinations = 1;\r
6241         */\r
6242 \r
6243         wiphy->cipher_suites = rtw_cipher_suites;\r
6244         wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);\r
6245 \r
6246         /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */\r
6247                 wiphy->bands[IEEE80211_BAND_2GHZ] = rtw_spt_band_alloc(IEEE80211_BAND_2GHZ);\r
6248 #ifdef CONFIG_IEEE80211_BAND_5GHZ\r
6249         /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */\r
6250                 wiphy->bands[IEEE80211_BAND_5GHZ] = rtw_spt_band_alloc(IEEE80211_BAND_5GHZ);\r
6251 #endif\r
6252         \r
6253 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) && LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))\r
6254         wiphy->flags |= WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS;\r
6255 #endif\r
6256 \r
6257 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))\r
6258         wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;\r
6259         wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME;\r
6260 #endif\r
6261 \r
6262 #if defined(CONFIG_PM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
6263         wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;\r
6264 #ifdef CONFIG_PNO_SUPPORT\r
6265         wiphy->max_sched_scan_ssids = MAX_PNO_LIST_COUNT;\r
6266 #endif\r
6267 #endif\r
6268 \r
6269 #if defined(CONFIG_PM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
6270 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0))\r
6271         wiphy->wowlan = wowlan_stub;\r
6272 #else\r
6273         wiphy->wowlan = &wowlan_stub;\r
6274 #endif\r
6275 #endif\r
6276 \r
6277 #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0))\r
6278         wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;\r
6279 #ifndef CONFIG_TDLS_DRIVER_SETUP\r
6280         wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; //Driver handles key exchange\r
6281         wiphy->flags |= NL80211_ATTR_HT_CAPABILITY;\r
6282 #endif //CONFIG_TDLS_DRIVER_SETUP\r
6283 #endif /* CONFIG_TDLS */\r
6284 \r
6285         if(padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)\r
6286                 wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;\r
6287         else \r
6288                 wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;\r
6289 \r
6290 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0))\r
6291         //wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;\r
6292 #endif\r
6293 \r
6294 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)\r
6295         rtw_cfgvendor_attach(wiphy);\r
6296 #endif\r
6297 }\r
6298 \r
6299 static struct cfg80211_ops rtw_cfg80211_ops = {\r
6300         .change_virtual_intf = cfg80211_rtw_change_iface,\r
6301         .add_key = cfg80211_rtw_add_key,\r
6302         .get_key = cfg80211_rtw_get_key,\r
6303         .del_key = cfg80211_rtw_del_key,\r
6304         .set_default_key = cfg80211_rtw_set_default_key,\r
6305 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))\r
6306         .set_rekey_data = cfg80211_rtw_set_rekey_data,\r
6307 #endif /*CONFIG_GTK_OL*/\r
6308         .get_station = cfg80211_rtw_get_station,\r
6309         .scan = cfg80211_rtw_scan,\r
6310         .set_wiphy_params = cfg80211_rtw_set_wiphy_params,\r
6311         .connect = cfg80211_rtw_connect,\r
6312         .disconnect = cfg80211_rtw_disconnect,\r
6313         .join_ibss = cfg80211_rtw_join_ibss,\r
6314         .leave_ibss = cfg80211_rtw_leave_ibss,\r
6315         .set_tx_power = cfg80211_rtw_set_txpower,\r
6316         .get_tx_power = cfg80211_rtw_get_txpower,\r
6317         .set_power_mgmt = cfg80211_rtw_set_power_mgmt,\r
6318         .set_pmksa = cfg80211_rtw_set_pmksa,\r
6319         .del_pmksa = cfg80211_rtw_del_pmksa,\r
6320         .flush_pmksa = cfg80211_rtw_flush_pmksa,\r
6321         \r
6322 #ifdef CONFIG_AP_MODE\r
6323         .add_virtual_intf = cfg80211_rtw_add_virtual_intf,\r
6324         .del_virtual_intf = cfg80211_rtw_del_virtual_intf,\r
6325 \r
6326         #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(COMPAT_KERNEL_RELEASE)\r
6327         .add_beacon = cfg80211_rtw_add_beacon,\r
6328         .set_beacon = cfg80211_rtw_set_beacon,\r
6329         .del_beacon = cfg80211_rtw_del_beacon,\r
6330         #else\r
6331         .start_ap = cfg80211_rtw_start_ap,\r
6332         .change_beacon = cfg80211_rtw_change_beacon,\r
6333         .stop_ap = cfg80211_rtw_stop_ap,\r
6334         #endif\r
6335         \r
6336         .add_station = cfg80211_rtw_add_station,\r
6337         .del_station = cfg80211_rtw_del_station,\r
6338         .change_station = cfg80211_rtw_change_station,\r
6339         .dump_station = cfg80211_rtw_dump_station,\r
6340         .change_bss = cfg80211_rtw_change_bss,\r
6341         #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))\r
6342         .set_channel = cfg80211_rtw_set_channel,\r
6343         #endif\r
6344         //.auth = cfg80211_rtw_auth,\r
6345         //.assoc = cfg80211_rtw_assoc,  \r
6346 #endif //CONFIG_AP_MODE\r
6347 \r
6348 #ifdef CONFIG_P2P\r
6349         .remain_on_channel = cfg80211_rtw_remain_on_channel,\r
6350         .cancel_remain_on_channel = cfg80211_rtw_cancel_remain_on_channel,\r
6351 #endif\r
6352 \r
6353 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)     \r
6354         .mgmt_tx = cfg80211_rtw_mgmt_tx,\r
6355         .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,\r
6356 #elif  (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,34) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,35))\r
6357         .action = cfg80211_rtw_mgmt_tx,\r
6358 #endif\r
6359 \r
6360 #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0))\r
6361         .tdls_mgmt = cfg80211_rtw_tdls_mgmt,\r
6362         .tdls_oper = cfg80211_rtw_tdls_oper,\r
6363 #endif /* CONFIG_TDLS */\r
6364 \r
6365 #if defined(CONFIG_PNO_SUPPORT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))\r
6366         .sched_scan_start = cfg80211_rtw_sched_scan_start,\r
6367         .sched_scan_stop = cfg80211_rtw_sched_scan_stop,\r
6368 #endif /* CONFIG_PNO_SUPPORT */\r
6369 };\r
6370 \r
6371 int rtw_wdev_alloc(_adapter *padapter, struct device *dev)\r
6372 {\r
6373         int ret = 0;\r
6374         struct wiphy *wiphy;\r
6375         struct wireless_dev *wdev;\r
6376         struct rtw_wdev_priv *pwdev_priv;\r
6377         struct net_device *pnetdev = padapter->pnetdev;\r
6378         \r
6379         DBG_8192C("%s(padapter=%p)\n", __func__, padapter);\r
6380 \r
6381         /* wiphy */\r
6382         wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(_adapter*));\r
6383         if (!wiphy) {\r
6384                 DBG_8192C("Couldn't allocate wiphy device\n");\r
6385                 ret = -ENOMEM;\r
6386                 goto exit;\r
6387         }\r
6388         set_wiphy_dev(wiphy, dev);\r
6389         *((_adapter**)wiphy_priv(wiphy)) = padapter;\r
6390         rtw_cfg80211_preinit_wiphy(padapter, wiphy);\r
6391 \r
6392         ret = wiphy_register(wiphy);\r
6393         if (ret < 0) {\r
6394                 DBG_8192C("Couldn't register wiphy device\n");\r
6395                 goto free_wiphy;\r
6396         }\r
6397 \r
6398         /*  wdev */\r
6399         wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));\r
6400         if (!wdev) {\r
6401                 DBG_8192C("Couldn't allocate wireless device\n");\r
6402                 ret = -ENOMEM;\r
6403                 goto unregister_wiphy;\r
6404         }\r
6405         wdev->wiphy = wiphy;\r
6406         wdev->netdev = pnetdev;\r
6407 \r
6408         wdev->iftype = NL80211_IFTYPE_STATION; // will be init in rtw_hal_init()\r
6409                                                // Must sync with _rtw_init_mlme_priv() \r
6410                                                                                    // pmlmepriv->fw_state = WIFI_STATION_STATE\r
6411         //wdev->iftype = NL80211_IFTYPE_MONITOR; // for rtw_setopmode_cmd() in cfg80211_rtw_change_iface()\r
6412         padapter->rtw_wdev = wdev;\r
6413         pnetdev->ieee80211_ptr = wdev;\r
6414 \r
6415         //init pwdev_priv\r
6416         pwdev_priv = adapter_wdev_data(padapter);\r
6417         pwdev_priv->rtw_wdev = wdev;\r
6418         pwdev_priv->pmon_ndev = NULL;\r
6419         pwdev_priv->ifname_mon[0] = '\0';\r
6420         pwdev_priv->padapter = padapter;\r
6421         pwdev_priv->scan_request = NULL;\r
6422         _rtw_spinlock_init(&pwdev_priv->scan_req_lock);\r
6423                 \r
6424         pwdev_priv->p2p_enabled = _FALSE;\r
6425         pwdev_priv->provdisc_req_issued = _FALSE;\r
6426         rtw_wdev_invit_info_init(&pwdev_priv->invit_info);\r
6427         rtw_wdev_nego_info_init(&pwdev_priv->nego_info);\r
6428                 \r
6429         pwdev_priv->bandroid_scan = _FALSE;\r
6430 \r
6431         if(padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)\r
6432                 pwdev_priv->power_mgmt = _TRUE;\r
6433         else\r
6434                 pwdev_priv->power_mgmt = _FALSE;\r
6435         \r
6436 #ifdef CONFIG_CONCURRENT_MODE\r
6437         ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);       \r
6438         ATOMIC_SET(&pwdev_priv->ro_ch_to, 1);   \r
6439 #endif\r
6440 \r
6441         return ret;\r
6442 \r
6443         rtw_mfree((u8*)wdev, sizeof(struct wireless_dev));\r
6444 unregister_wiphy:\r
6445         wiphy_unregister(wiphy);\r
6446  free_wiphy:\r
6447         wiphy_free(wiphy);\r
6448 exit:\r
6449         return ret;\r
6450         \r
6451 }\r
6452 \r
6453 void rtw_wdev_free(struct wireless_dev *wdev)\r
6454 {\r
6455         DBG_8192C("%s(wdev=%p)\n", __func__, wdev);\r
6456 \r
6457         if (!wdev)\r
6458                 return;\r
6459 \r
6460         rtw_spt_band_free(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]);\r
6461         rtw_spt_band_free(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]);\r
6462         \r
6463         wiphy_free(wdev->wiphy);\r
6464 \r
6465         rtw_mfree((u8*)wdev, sizeof(struct wireless_dev));\r
6466 }\r
6467 \r
6468 void rtw_wdev_unregister(struct wireless_dev *wdev)\r
6469 {\r
6470         struct net_device *ndev;\r
6471         _adapter *adapter;\r
6472         struct rtw_wdev_priv *pwdev_priv;\r
6473 \r
6474         DBG_8192C("%s(wdev=%p)\n", __func__, wdev);\r
6475 \r
6476         if (!wdev)\r
6477                 return;\r
6478 \r
6479         if(!(ndev = wdev_to_ndev(wdev)))\r
6480                 return;\r
6481 \r
6482         adapter = (_adapter *)rtw_netdev_priv(ndev);\r
6483         pwdev_priv = adapter_wdev_data(adapter);\r
6484 \r
6485         rtw_cfg80211_indicate_scan_done(adapter, _TRUE);\r
6486 \r
6487         if (pwdev_priv->pmon_ndev) {\r
6488                 DBG_8192C("%s, unregister monitor interface\n", __func__);\r
6489                 unregister_netdev(pwdev_priv->pmon_ndev);\r
6490         }\r
6491 \r
6492 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)\r
6493         rtw_cfgvendor_detach(wdev->wiphy);\r
6494 #endif\r
6495 \r
6496         wiphy_unregister(wdev->wiphy);\r
6497 }\r
6498 \r
6499 #endif //CONFIG_IOCTL_CFG80211\r
6500 \r