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