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