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