OSDN Git Service

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