OSDN Git Service

Remove another set of unecessary typedefs
[android-x86/external-modules-rtl8723au.git] / core / rtw_mlme_ext.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 _RTW_MLME_EXT_C_
21
22 #include <drv_conf.h>
23 #include <osdep_service.h>
24 #include <drv_types.h>
25 #include <wifi.h>
26 #include <rtw_mlme_ext.h>
27 #include <wlan_bssdef.h>
28 #include <mlme_osdep.h>
29 #include <recv_osdep.h>
30
31 #ifdef CONFIG_BT_COEXIST
32 #include <rtl8723a_hal.h>
33 #endif
34
35 struct mlme_handler mlme_sta_tbl[]={
36         {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
37         {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
38         {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
39         {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
40         {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
41         {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
42
43         /*----------------------------------------------------------
44                                         below 2 are reserved
45         -----------------------------------------------------------*/
46         {0,                                     "DoReserved",           &DoReserved},
47         {0,                                     "DoReserved",           &DoReserved},
48         {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
49         {WIFI_ATIM,                     "OnATIM",               &OnAtim},
50         {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
51         {WIFI_AUTH,                     "OnAuth",               &OnAuthClient},
52         {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
53         {WIFI_ACTION,           "OnAction",             &OnAction},
54 };
55
56 #ifdef _CONFIG_NATIVEAP_MLME_
57 struct mlme_handler mlme_ap_tbl[]={
58         {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
59         {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
60         {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
61         {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
62         {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
63         {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
64
65         /*----------------------------------------------------------
66                                         below 2 are reserved
67         -----------------------------------------------------------*/
68         {0,                                     "DoReserved",           &DoReserved},
69         {0,                                     "DoReserved",           &DoReserved},
70         {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
71         {WIFI_ATIM,                     "OnATIM",               &OnAtim},
72         {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
73         {WIFI_AUTH,                     "OnAuth",               &OnAuth},
74         {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
75         {WIFI_ACTION,           "OnAction",             &OnAction},
76 };
77 #endif
78
79 struct action_handler OnAction_tbl[]={
80         {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,        "ACTION_SPECTRUM_MGMT", on_action_spct},
81         {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
82         {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
83         {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
84         {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
85         {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
86         {RTW_WLAN_CATEGORY_FT, "ACTION_FT",     &DoReserved},
87         {RTW_WLAN_CATEGORY_HT,  "ACTION_HT",    &OnAction_ht},
88         {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
89         {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
90         {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},
91 };
92
93 u8      null_addr[ETH_ALEN]= {0,0,0,0,0,0};
94
95 /**************************************************
96 OUI definitions for the vendor specific IE
97 ***************************************************/
98 unsigned char   RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
99 unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
100 unsigned char   WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
101 unsigned char   P2P_OUI[] = {0x50,0x6F,0x9A,0x09};
102 unsigned char   WFD_OUI[] = {0x50,0x6F,0x9A,0x0A};
103
104 unsigned char   WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
105 unsigned char   WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
106
107 unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
108 unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
109
110 extern unsigned char REALTEK_96B_IE[];
111
112 /********************************************************
113 MCS rate definitions
114 *********************************************************/
115 #ifdef CONFIG_DISABLE_MCS13TO15
116 unsigned char   MCS_rate_2R_MCS13TO15_OFF[16] = {0xff, 0x1f, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
117 unsigned char   MCS_rate_2R[16] = {0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
118 #else /* CONFIG_DISABLE_MCS13TO15 */
119 unsigned char   MCS_rate_2R[16] = {0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
120 #endif /* CONFIG_DISABLE_MCS13TO15 */
121 unsigned char   MCS_rate_1R[16] = {0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
122
123 /********************************************************
124 ChannelPlan definitions
125 *********************************************************/
126
127 static RT_CHANNEL_PLAN_2G       RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
128         {{1,2,3,4,5,6,7,8,9,10,11,12,13},13},           /*  0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
129         {{1,2,3,4,5,6,7,8,9,10,11,12,13},13},           /*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
130         {{1,2,3,4,5,6,7,8,9,10,11},11},                 /*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
131         {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14},        /*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
132         {{10,11,12,13},4},                                      /*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
133         {{},0},                                                                 /*  0x05, RT_CHANNEL_DOMAIN_2G_NULL */
134 };
135
136 static RT_CHANNEL_PLAN_5G       RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
137         {{},0},                                                                                                                                                                 /*  0x00, RT_CHANNEL_DOMAIN_5G_NULL */
138         {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140},19},                                             /*  0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
139         {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,149,153,157,161,165},24}, /*  0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
140         {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,149,153,157,161,165},22},                 /*  0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
141         {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,149,153,157,161,165},24}, /*  0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
142         {{36,40,44,48,149,153,157,161,165},9},                                                                                                          /*  0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
143         {{36,40,44,48,52,56,60,64,149,153,157,161,165},13},                                                                                     /*  0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
144         {{36,40,44,48,52,56,60,64,149,153,157,161},12},                                                                                         /*  0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
145         {{149,153,157,161,165},5},                                                                                                                                      /*  0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
146         {{36,40,44,48,52,56,60,64},8},                                                                                                                          /*  0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
147         {{36,40,44,48,52,56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},20},                                 /*  0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
148         {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,149,153,157,161,165},20},                                 /*  0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
149         {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140},19},                                             /*  0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
150         {{36,40,44,48,52,56,60,64},8},                                                                                                                          /*  0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
151         {{100,104,108,112,116,120,124,128,132,136,140},11},                                                                                     /*  0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
152         {{56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},15},                                                                /*  0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
153         {{56,60,64,149,153,157,161,165},8},                                                                                                                     /*  0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
154
155         /*  Driver self defined for old channel plan Compatible ,Remember to modify if have new channel plan definition ===== */
156         {{36,40,44,48,52,56,60,64,100,104,108,112,116,132,136,140,149,153,157,161,165},21},                             /*  0x11, RT_CHANNEL_DOMAIN_5G_FCC */
157         {{36,40,44,48},4},                                                                                                                                                      /*  0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
158         {{36,40,44,48,149,153,157,161},8},                                                                                                                              /*  0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
159 };
160
161 static RT_CHANNEL_PLAN_MAP      RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
162         /*  0x00 ~ 0x1F , Old Define ===== */
163         {0x02,0x11},    /* 0x00, RT_CHANNEL_DOMAIN_FCC */
164         {0x02,0x0A},    /* 0x01, RT_CHANNEL_DOMAIN_IC */
165         {0x01,0x01},    /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
166         {0x01,0x00},    /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
167         {0x01,0x00},    /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
168         {0x03,0x00},    /* 0x05, RT_CHANNEL_DOMAIN_MKK */
169         {0x03,0x00},    /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
170         {0x01,0x09},    /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
171         {0x03,0x09},    /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
172         {0x03,0x00},    /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
173         {0x00,0x00},    /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
174         {0x02,0x0F},    /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
175         {0x01,0x08},    /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
176         {0x02,0x06},    /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
177         {0x02,0x0B},    /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
178         {0x02,0x09},    /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
179         {0x01,0x01},    /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
180         {0x02,0x05},    /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
181         {0x01,0x12},    /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
182         {0x00,0x04},    /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
183         {0x02,0x10},    /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
184         {0x00,0x12},    /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
185         {0x00,0x13},    /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
186         {0x03,0x12},    /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
187         {0x05,0x08},    /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
188         {0x02,0x08},    /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
189         {0x00,0x00},    /* 0x1A, */
190         {0x00,0x00},    /* 0x1B, */
191         {0x00,0x00},    /* 0x1C, */
192         {0x00,0x00},    /* 0x1D, */
193         {0x00,0x00},    /* 0x1E, */
194         {0x05,0x04},    /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
195         /*  0x20 ~ 0x7F ,New Define ===== */
196         {0x00,0x00},    /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
197         {0x01,0x00},    /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
198         {0x02,0x00},    /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
199         {0x03,0x00},    /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
200         {0x04,0x00},    /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
201         {0x02,0x04},    /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
202         {0x00,0x01},    /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
203         {0x03,0x0C},    /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
204         {0x00,0x0B},    /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
205         {0x00,0x05},    /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
206         {0x00,0x00},    /* 0x2A, */
207         {0x00,0x00},    /* 0x2B, */
208         {0x00,0x00},    /* 0x2C, */
209         {0x00,0x00},    /* 0x2D, */
210         {0x00,0x00},    /* 0x2E, */
211         {0x00,0x00},    /* 0x2F, */
212         {0x00,0x06},    /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
213         {0x00,0x07},    /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
214         {0x00,0x08},    /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
215         {0x00,0x09},    /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
216         {0x02,0x0A},    /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
217         {0x00,0x02},    /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
218         {0x00,0x03},    /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
219         {0x03,0x0D},    /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
220         {0x03,0x0E},    /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
221         {0x02,0x0F},    /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
222         {0x00,0x00},    /* 0x3A, */
223         {0x00,0x00},    /* 0x3B, */
224         {0x00,0x00},    /* 0x3C, */
225         {0x00,0x00},    /* 0x3D, */
226         {0x00,0x00},    /* 0x3E, */
227         {0x00,0x00},    /* 0x3F, */
228         {0x02,0x10},    /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
229         {0x03,0x00},    /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
230 };
231
232 static RT_CHANNEL_PLAN_MAP      RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03,0x02}; /* use the conbination for max channel numbers */
233
234 /*
235  * Search the @param channel_num in given @param channel_set
236  * @ch_set: the given channel set
237  * @ch: the given channel number
238  *
239  * return the index of channel_num in channel_set, -1 if not found
240  */
241 int rtw_ch_set_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch)
242 {
243         int i;
244         for(i=0;ch_set[i].ChannelNum!=0;i++){
245                 if(ch == ch_set[i].ChannelNum)
246                         break;
247         }
248
249         if(i >= ch_set[i].ChannelNum)
250                 return -1;
251         return i;
252 }
253
254 /****************************************************************************
255
256 Following are the initialization functions for WiFi MLME
257
258 *****************************************************************************/
259
260 int init_hw_mlme_ext(_adapter *padapter)
261 {
262         struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
263
264         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
265         return _SUCCESS;
266 }
267
268 static void init_mlme_ext_priv_value(_adapter* padapter)
269 {
270         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
271         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
272
273 #ifdef CONFIG_TDLS
274         u8 i;
275 #endif
276
277         unsigned char   mixed_datarate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,_9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_, 0xff};
278         unsigned char   mixed_basicrate[NumRates] ={_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,};
279
280         ATOMIC_SET(&pmlmeext->event_seq, 0);
281         pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
282
283         pmlmeext->cur_channel = padapter->registrypriv.channel;
284         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
285         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
286
287         pmlmeext->retry = 0;
288
289         pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
290
291         /* memcpy(pmlmeext->channel_set, DefaultChannelPlan[padapter->mlmepriv.ChannelPlan].Channel, DefaultChannelPlan[padapter->mlmepriv.ChannelPlan].Len); */
292         /* memcpy(pmlmeext->channel_set, default_channel_set, MAX_CHANNEL_NUM); */
293         memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
294         memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
295
296         if(pmlmeext->cur_channel > 14)
297                 pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
298         else
299                 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
300
301         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
302         pmlmeext->sitesurvey_res.channel_idx = 0;
303         pmlmeext->sitesurvey_res.bss_cnt = 0;
304         pmlmeext->scan_abort = _FALSE;
305
306         pmlmeinfo->state = WIFI_FW_NULL_STATE;
307         pmlmeinfo->reauth_count = 0;
308         pmlmeinfo->reassoc_count = 0;
309         pmlmeinfo->link_count = 0;
310         pmlmeinfo->auth_seq = 0;
311         pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
312         pmlmeinfo->key_index = 0;
313         pmlmeinfo->iv = 0;
314
315         pmlmeinfo->enc_algo = _NO_PRIVACY_;
316         pmlmeinfo->authModeToggle = 0;
317
318         memset(pmlmeinfo->chg_txt, 0, 128);
319
320         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
321         pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
322
323         pmlmeinfo->dialogToken = 0;
324
325         pmlmeext->action_public_rxseq = 0xffff;
326         pmlmeext->action_public_dialog_token = 0xff;
327 }
328
329 static int has_channel(RT_CHANNEL_INFO *channel_set,
330                                            u8 chanset_size,
331                                            u8 chan) {
332         int i;
333
334         for (i = 0; i < chanset_size; i++) {
335                 if (channel_set[i].ChannelNum == chan) {
336                         return 1;
337                 }
338         }
339
340         return 0;
341 }
342
343 static void init_channel_list(_adapter *padapter, RT_CHANNEL_INFO *channel_set,
344                                                           u8 chanset_size,
345                                                           struct p2p_channels *channel_list) {
346
347         struct p2p_oper_class_map op_class[] = {
348                 { IEEE80211G,  81,   1,  13,  1, BW20 },
349                 { IEEE80211G,  82,  14,  14,  1, BW20 },
350                 { IEEE80211A, 115,  36,  48,  4, BW20 },
351                 { IEEE80211A, 116,  36,  44,  8, BW40PLUS },
352                 { IEEE80211A, 117,  40,  48,  8, BW40MINUS },
353                 { IEEE80211A, 124, 149, 161,  4, BW20 },
354                 { IEEE80211A, 125, 149, 169,  4, BW20 },
355                 { IEEE80211A, 126, 149, 157,  8, BW40PLUS },
356                 { IEEE80211A, 127, 153, 161,  8, BW40MINUS },
357                 { -1, 0, 0, 0, 0, BW20 }
358         };
359
360         int cla, op;
361
362         cla = 0;
363
364         for (op = 0; op_class[op].op_class; op++) {
365                 u8 ch;
366                 struct p2p_oper_class_map *o = &op_class[op];
367                 struct p2p_reg_class *reg = NULL;
368
369                 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
370                         if (!has_channel(channel_set, chanset_size, ch)) {
371                                 continue;
372                         }
373
374                         if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
375                                 continue;
376
377                         if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
378                                 ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
379                                 continue;
380
381                         if (reg == NULL) {
382                                 reg = &channel_list->reg_class[cla];
383                                 cla++;
384                                 reg->reg_class = o->op_class;
385                                 reg->channels = 0;
386                         }
387                         reg->channel[reg->channels] = ch;
388                         reg->channels++;
389                 }
390         }
391         channel_list->reg_classes = cla;
392 }
393
394 static u8 init_channel_set(_adapter* padapter, u8 ChannelPlan, RT_CHANNEL_INFO *channel_set)
395 {
396         u8      index,chanset_size = 0;
397         u8      b5GBand = _FALSE, b2_4GBand = _FALSE;
398         u8      Index2G = 0, Index5G=0;
399
400         memset(channel_set, 0, sizeof(RT_CHANNEL_INFO)*MAX_CHANNEL_NUM);
401
402         if(ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
403         {
404                 DBG_8723A("ChannelPlan ID %x error !!!!!\n",ChannelPlan);
405                 return chanset_size;
406         }
407
408         if(padapter->registrypriv.wireless_mode & WIRELESS_11G)
409         {
410                 b2_4GBand = _TRUE;
411                 if(RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
412                         Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
413                 else
414                         Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
415         }
416
417         if(padapter->registrypriv.wireless_mode & WIRELESS_11A)
418         {
419                 b5GBand = _TRUE;
420                 if(RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
421                         Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
422                 else
423                         Index5G = RTW_ChannelPlanMap[ChannelPlan].Index5G;
424         }
425
426         if(b2_4GBand)
427         {
428                 for(index=0;index<RTW_ChannelPlan2G[Index2G].Len;index++)
429                 {
430                         channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
431
432                         if(     (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */
433                                 (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == ChannelPlan)     )
434                         {
435                                 if(channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
436                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
437                                 else if((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
438                                         channel_set[chanset_size].ScanType  = SCAN_PASSIVE;
439                         }
440                         else if(RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan ||
441                                 RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan ||
442                                 RT_CHANNEL_DOMAIN_2G_WORLD == Index2G)/*  channel 12~13, passive scan */
443                         {
444                                 if(channel_set[chanset_size].ChannelNum <= 11)
445                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
446                                 else
447                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
448                         }
449                         else
450                         {
451                                 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
452                         }
453
454                         chanset_size++;
455                 }
456         }
457
458         if(b5GBand)
459         {
460                 for(index=0;index<RTW_ChannelPlan5G[Index5G].Len;index++)
461                 {
462 #ifdef CONFIG_DFS
463                         channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index];
464                         if ( channel_set[chanset_size].ChannelNum <= 48
465                                 || channel_set[chanset_size].ChannelNum >= 149 )
466                         {
467                                 if(RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)/* passive scan for all 5G channels */
468                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
469                                 else
470                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
471                         }
472                         else
473                         {
474                                 channel_set[chanset_size].ScanType = SCAN_PASSIVE;
475                         }
476                         chanset_size++;
477 #else /* CONFIG_DFS */
478                         if ( RTW_ChannelPlan5G[Index5G].Channel[index] <= 48
479                                 || RTW_ChannelPlan5G[Index5G].Channel[index] >= 149 ) {
480                                 channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index];
481                                 if(RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)/* passive scan for all 5G channels */
482                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
483                                 else
484                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
485                                 DBG_8723A("%s(): channel_set[%d].ChannelNum = %d\n", __FUNCTION__, chanset_size, channel_set[chanset_size].ChannelNum);
486                                 chanset_size++;
487                         }
488 #endif /* CONFIG_DFS */
489                 }
490         }
491
492         return chanset_size;
493 }
494
495 int     init_mlme_ext_priv(_adapter* padapter)
496 {
497         int     res = _SUCCESS;
498         struct registry_priv* pregistrypriv = &padapter->registrypriv;
499         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
500         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
501         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
502
503         /*  We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */
504         /* memset((u8 *)pmlmeext, 0, sizeof(struct mlme_ext_priv)); */
505
506         pmlmeext->padapter = padapter;
507
508         /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */
509
510         init_mlme_ext_priv_value(padapter);
511         pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
512
513         init_mlme_ext_timer(padapter);
514
515 #ifdef CONFIG_AP_MODE
516         init_mlme_ap_info(padapter);
517 #endif
518
519         pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan,pmlmeext->channel_set);
520         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
521
522         pmlmeext->chan_scan_time = SURVEY_TO;
523         pmlmeext->mlmeext_init = _TRUE;
524
525 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
526         pmlmeext->active_keep_alive_check = _TRUE;
527 #endif
528
529 #ifdef DBG_FIXED_CHAN
530         pmlmeext->fixed_chan = 0xFF;
531 #endif
532
533         return res;
534 }
535
536 void free_mlme_ext_priv (struct mlme_ext_priv *pmlmeext)
537 {
538         _adapter *padapter = pmlmeext->padapter;
539
540         if (!padapter)
541                 return;
542
543         if (padapter->bDriverStopped == _TRUE)
544         {
545                 _cancel_timer_ex(&pmlmeext->survey_timer);
546                 _cancel_timer_ex(&pmlmeext->link_timer);
547                 /* _cancel_timer_ex(&pmlmeext->ADDBA_timer); */
548         }
549 }
550
551 static u8 cmp_pkt_chnl_diff(_adapter *padapter,u8* pframe,uint packet_len)
552 {       /*  if the channel is same, return 0. else return channel differential */
553         uint len;
554         u8 channel;
555         u8 *p;
556         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, packet_len - _BEACON_IE_OFFSET_);
557         if (p)
558         {
559                 channel = *(p + 2);
560                 if(padapter->mlmeextpriv.cur_channel >= channel)
561                 {
562                         return (padapter->mlmeextpriv.cur_channel - channel);
563                 }
564                 else
565                 {
566                         return (channel-padapter->mlmeextpriv.cur_channel);
567                 }
568         }
569         else
570         {
571                 return 0;
572         }
573 }
574
575 static void _mgt_dispatcher(_adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
576 {
577         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
578         u8 *pframe = precv_frame->u.hdr.rx_data;
579
580           if(ptable->func)
581         {
582          /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
583                 if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv),
584                            ETH_ALEN) &&
585                     memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
586                 {
587                         return;
588                 }
589
590                 ptable->func(padapter, precv_frame);
591         }
592 }
593
594 void mgt_dispatcher(_adapter *padapter, union recv_frame *precv_frame)
595 {
596         int index;
597         struct mlme_handler *ptable;
598 #ifdef CONFIG_AP_MODE
599         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
600 #endif /* CONFIG_AP_MODE */
601         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
602         u8 *pframe = precv_frame->u.hdr.rx_data;
603         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
604
605         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
606                  ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n",
607                   GetFrameType(pframe), GetFrameSubType(pframe)));
608
609         if (GetFrameType(pframe) != WIFI_MGT_TYPE)
610         {
611                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe)));
612                 return;
613         }
614
615         /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
616         if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv),
617                    ETH_ALEN) &&
618             memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
619         {
620                 return;
621         }
622
623         ptable = mlme_sta_tbl;
624
625         index = GetFrameSubType(pframe) >> 4;
626
627 #ifdef CONFIG_TDLS
628         if((index << 4)==WIFI_ACTION){
629                 /* category==public (4), action==TDLS_DISCOVERY_RESPONSE */
630                 if(*(pframe+24)==0x04 && *(pframe+25)==TDLS_DISCOVERY_RESPONSE){
631                         DBG_8723A("recv tdls discovery response frame\n");
632                         On_TDLS_Dis_Rsp(padapter, precv_frame);
633                 }
634         }
635 #endif /* CONFIG_TDLS */
636
637         if (index > 13)
638         {
639                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Currently we do not support reserved sub-fr-type=%d\n", index));
640                 return;
641         }
642         ptable += index;
643
644 #if 1
645         if (psta != NULL)
646         {
647                 if (GetRetry(pframe))
648                 {
649                         if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum)
650                         {
651                                 /* drop the duplicate management frame */
652                                 DBG_8723A("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num);
653                                 return;
654                         }
655                 }
656                 psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
657         }
658 #else
659
660         if(GetRetry(pframe))
661         {
662                 /* RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("drop due to decache!\n")); */
663                 /* return; */
664         }
665 #endif
666
667 #ifdef CONFIG_AP_MODE
668         switch (GetFrameSubType(pframe))
669         {
670                 case WIFI_AUTH:
671                         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
672                                 ptable->func = &OnAuth;
673                         else
674                                 ptable->func = &OnAuthClient;
675                         /* pass through */
676                 case WIFI_ASSOCREQ:
677                 case WIFI_REASSOCREQ:
678                         _mgt_dispatcher(padapter, ptable, precv_frame);
679 #ifdef CONFIG_HOSTAPD_MLME
680                         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
681                                 rtw_hostapd_mlme_rx(padapter, precv_frame);
682 #endif
683                         break;
684                 case WIFI_PROBEREQ:
685                         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
686                         {
687 #ifdef CONFIG_HOSTAPD_MLME
688                                 rtw_hostapd_mlme_rx(padapter, precv_frame);
689 #else
690                                 _mgt_dispatcher(padapter, ptable, precv_frame);
691 #endif
692                         }
693                         else
694                                 _mgt_dispatcher(padapter, ptable, precv_frame);
695                         break;
696                 case WIFI_BEACON:
697                         _mgt_dispatcher(padapter, ptable, precv_frame);
698                         break;
699                 case WIFI_ACTION:
700                         /* if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) */
701                         _mgt_dispatcher(padapter, ptable, precv_frame);
702                         break;
703                 default:
704                         _mgt_dispatcher(padapter, ptable, precv_frame);
705                         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
706                                 rtw_hostapd_mlme_rx(padapter, precv_frame);
707                         break;
708         }
709 #else
710
711         _mgt_dispatcher(padapter, ptable, precv_frame);
712
713 #endif
714 }
715
716 #ifdef CONFIG_P2P
717 u32 p2p_listen_state_process(_adapter *padapter, unsigned char *da)
718 {
719         bool response = _TRUE;
720
721 #ifdef CONFIG_IOCTL_CFG80211
722         if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == _FALSE
723                 || padapter->mlmepriv.wps_probe_resp_ie == NULL
724                 || padapter->mlmepriv.p2p_probe_resp_ie == NULL
725         )
726         {
727                 DBG_8723A("DON'T issue_probersp_p2p: p2p_enabled:%d, wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p\n",
728                         wdev_to_priv(padapter->rtw_wdev)->p2p_enabled,
729                         padapter->mlmepriv.wps_probe_resp_ie,
730                         padapter->mlmepriv.p2p_probe_resp_ie);
731                 response = _FALSE;
732         }
733 #else
734
735         /*      do nothing if the device name is empty */
736         if ( !padapter->wdinfo.device_name_len )
737         {
738                 response        = _FALSE;
739         }
740 #endif
741
742         if (response == _TRUE)
743                 issue_probersp_p2p( padapter, da);
744
745         return _SUCCESS;
746 }
747 #endif /* CONFIG_P2P */
748
749 /****************************************************************************
750
751 Following are the callback functions for each subtype of the management frames
752
753 *****************************************************************************/
754
755 unsigned int OnProbeReq(_adapter *padapter, union recv_frame *precv_frame)
756 {
757         unsigned int    ielen;
758         unsigned char   *p;
759         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
760         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
761         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
762         WLAN_BSSID_EX   *cur = &(pmlmeinfo->network);
763         u8 *pframe = precv_frame->u.hdr.rx_data;
764         uint len = precv_frame->u.hdr.len;
765         u8 is_valid_p2p_probereq = _FALSE;
766
767 #ifdef CONFIG_P2P
768         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
769         struct rx_pkt_attrib    *pattrib = &precv_frame->u.hdr.attrib;
770         u8 wifi_test_chk_rate = 1;
771
772         if (    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
773                 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
774                 !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
775                 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
776                 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)
777            )
778         {
779                 /*      Commented by Albert 2011/03/17 */
780                 /*      mcs_rate = 0 -> CCK 1M rate */
781                 /*      mcs_rate = 1 -> CCK 2M rate */
782                 /*      mcs_rate = 2 -> CCK 5.5M rate */
783                 /*      mcs_rate = 3 -> CCK 11M rate */
784                 /*      In the P2P mode, the driver should not support the CCK rate */
785
786                 /*      Commented by Kurt 2012/10/16 */
787                 /*      IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */
788 #ifdef CONFIG_WIFI_TEST
789                 if ( pattrib->mcs_rate <= 3 )
790                 {
791                         wifi_test_chk_rate = 0;
792                 }
793 #endif /* CONFIG_WIFI_TEST */
794
795                 if( wifi_test_chk_rate == 1 )
796                 {
797                         if((is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len)) == _TRUE)
798                         {
799                                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
800                                 {
801 #ifndef CONFIG_IOCTL_CFG80211
802 /*  FIXME */
803                                         report_survey_event(padapter, precv_frame);
804 #endif
805                                         p2p_listen_state_process( padapter,  get_sa(pframe));
806
807                                         return _SUCCESS;
808                                 }
809
810                                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
811                                 {
812                                         goto _continue;
813                                 }
814                         }
815                 }
816         }
817
818 _continue:
819 #endif /* CONFIG_P2P */
820
821         if(check_fwstate(pmlmepriv, WIFI_STATION_STATE))
822         {
823                 return _SUCCESS;
824         }
825
826         if(check_fwstate(pmlmepriv, _FW_LINKED) == _FALSE &&
827                 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)==_FALSE)
828         {
829                 return _SUCCESS;
830         }
831
832         /* DBG_8723A("+OnProbeReq\n"); */
833
834 #ifdef CONFIG_CONCURRENT_MODE
835         if(((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
836                 check_buddy_fwstate(padapter, _FW_UNDER_LINKING|_FW_UNDER_SURVEY))
837         {
838                 /* don't process probe req */
839                 return _SUCCESS;
840         }
841 #endif
842
843         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
844                         len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
845
846         /* check (wildcard) SSID */
847         if (p != NULL)
848         {
849                 if(is_valid_p2p_probereq == _TRUE)
850                 {
851                         goto _issue_probersp;
852                 }
853
854                 if ((ielen != 0 &&
855                       memcmp((void *)(p+2), cur->Ssid.Ssid,
856                              cur->Ssid.SsidLength)) ||
857                     (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
858                 {
859                         return _SUCCESS;
860                 }
861
862 _issue_probersp:
863
864                 if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&
865                         pmlmepriv->cur_network.join_res == _TRUE)
866                 {
867                         /* DBG_8723A("+issue_probersp during ap mode\n"); */
868                         issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
869                 }
870
871         }
872
873         return _SUCCESS;
874 }
875
876 unsigned int OnProbeRsp(_adapter *padapter, union recv_frame *precv_frame)
877 {
878         struct sta_info         *psta;
879         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
880         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
881         struct sta_priv         *pstapriv = &padapter->stapriv;
882         u8      *pframe = precv_frame->u.hdr.rx_data;
883 #ifdef CONFIG_P2P
884         struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
885 #endif
886
887 #ifdef CONFIG_P2P
888         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
889         {
890                 if ( _TRUE == pwdinfo->tx_prov_disc_info.benable )
891                 {
892                         if (!memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr,
893                                     GetAddr2Ptr(pframe), ETH_ALEN))
894                         {
895                                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
896                                 {
897                                         pwdinfo->tx_prov_disc_info.benable = _FALSE;
898                                         issue_p2p_provision_request( padapter,
899                                                                                                 pwdinfo->tx_prov_disc_info.ssid.Ssid,
900                                                                                                 pwdinfo->tx_prov_disc_info.ssid.SsidLength,
901                                                                                                 pwdinfo->tx_prov_disc_info.peerDevAddr );
902                                 }
903                                 else if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
904                                 {
905                                         pwdinfo->tx_prov_disc_info.benable = _FALSE;
906                                         issue_p2p_provision_request( padapter,
907                                                                                                 NULL,
908                                                                                                 0,
909                                                                                                 pwdinfo->tx_prov_disc_info.peerDevAddr );
910                                 }
911                         }
912                 }
913                 return _SUCCESS;
914         }
915         else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
916         {
917                 if ( _TRUE == pwdinfo->nego_req_info.benable )
918                 {
919                         DBG_8723A( "[%s] P2P State is GONEGO ING!\n", __FUNCTION__ );
920                         if (!memcmp(pwdinfo->nego_req_info.peerDevAddr,
921                                     GetAddr2Ptr(pframe), ETH_ALEN))
922                         {
923                                 pwdinfo->nego_req_info.benable = _FALSE;
924                                 issue_p2p_GO_request( padapter, pwdinfo->nego_req_info.peerDevAddr);
925                         }
926                 }
927         }
928         else if( rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ ) )
929         {
930                 if ( _TRUE == pwdinfo->invitereq_info.benable )
931                 {
932                         DBG_8723A( "[%s] P2P_STATE_TX_INVITE_REQ!\n", __FUNCTION__ );
933                         if (!memcmp( pwdinfo->invitereq_info.peer_macaddr,
934                                      GetAddr2Ptr(pframe), ETH_ALEN))
935                         {
936                                 pwdinfo->invitereq_info.benable = _FALSE;
937                                 issue_p2p_invitation_request( padapter, pwdinfo->invitereq_info.peer_macaddr );
938                         }
939                 }
940         }
941 #endif
942
943         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
944         {
945                 report_survey_event(padapter, precv_frame);
946 #ifdef CONFIG_CONCURRENT_MODE
947                 report_survey_event(padapter->pbuddy_adapter, precv_frame);
948 #endif
949 #ifdef CONFIG_DUALMAC_CONCURRENT
950                 dc_report_survey_event(padapter, precv_frame);
951 #endif
952                 return _SUCCESS;
953         }
954
955         return _SUCCESS;
956 }
957
958 unsigned int OnBeacon(_adapter *padapter, union recv_frame *precv_frame)
959 {
960         int cam_idx;
961         struct sta_info *psta;
962         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
963         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
964         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
965         struct sta_priv *pstapriv = &padapter->stapriv;
966         u8 *pframe = precv_frame->u.hdr.rx_data;
967         uint len = precv_frame->u.hdr.len;
968         WLAN_BSSID_EX *pbss;
969         int ret = _SUCCESS;
970         u8 *p = NULL;
971         u32 ielen = 0;
972
973 #ifdef CONFIG_ATTEMPT_TO_FIX_AP_BEACON_ERROR
974         p = rtw_get_ie(pframe + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ielen, precv_frame->u.hdr.len -sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_);
975         if ((p != NULL) && (ielen > 0))
976         {
977                 if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D))
978                 {
979                         /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */
980                         DBG_8723A("[WIFIDBG] Error in ESR IE is detected in Beacon of BSSID:"MAC_FMT". Fix the length of ESR IE to avoid failed Beacon parsing.\n", MAC_ARG(GetAddr3Ptr(pframe)));
981                         *(p + 1) = ielen - 1;
982                 }
983         }
984 #endif
985
986         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
987         {
988                 report_survey_event(padapter, precv_frame);
989 #ifdef CONFIG_CONCURRENT_MODE
990                 report_survey_event(padapter->pbuddy_adapter, precv_frame);
991 #endif
992
993 #ifdef CONFIG_DUALMAC_CONCURRENT
994                 dc_report_survey_event(padapter, precv_frame);
995 #endif
996
997                 return _SUCCESS;
998         }
999
1000         if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network),
1001                     ETH_ALEN)) {
1002                 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL)
1003                 {
1004                         /* we should update current network before auth, or some IE is wrong */
1005                         pbss = (WLAN_BSSID_EX*)rtw_malloc(sizeof(WLAN_BSSID_EX));
1006                         if (pbss) {
1007                                 if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
1008                                         update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE);
1009                                         rtw_get_bcn_info(&(pmlmepriv->cur_network));
1010                                 }
1011                                 rtw_mfree((u8*)pbss, sizeof(WLAN_BSSID_EX));
1012                         }
1013
1014                         /* check the vendor of the assoc AP */
1015                         pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), len-sizeof(struct rtw_ieee80211_hdr_3addr));
1016
1017                         /* update TSF Value */
1018                         update_TSF(pmlmeext, pframe, len);
1019
1020                         /* start auth */
1021                         start_clnt_auth(padapter);
1022
1023                         return _SUCCESS;
1024                 }
1025
1026                 if(((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1027                 {
1028                         if ((psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe))) != NULL)
1029                         {
1030                                 #ifdef CONFIG_PATCH_JOIN_WRONG_CHANNEL
1031                                 /* Merge from 8712 FW code */
1032                                 if (cmp_pkt_chnl_diff(padapter,pframe,len) != 0)
1033                                 {            /*  join wrong channel, deauth and reconnect */
1034                                         issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
1035
1036                                         report_del_sta_event(padapter,(&(pmlmeinfo->network))->MacAddress, WLAN_REASON_JOIN_WRONG_CHANNEL);
1037                                         pmlmeinfo->state &= (~WIFI_FW_ASSOC_SUCCESS);
1038                                         return _SUCCESS;
1039                                 }
1040                                 #endif /* CONFIG_PATCH_JOIN_WRONG_CHANNEL */
1041
1042                                 ret = rtw_check_bcn_info(padapter, pframe, len);
1043                                 if (!ret) {
1044                                                 DBG_8723A_LEVEL(_drv_always_, "ap has changed, disconnect now\n ");
1045                                                 receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 65535);
1046                                                 return _SUCCESS;
1047                                 }
1048                                 /* update WMM, ERP in the beacon */
1049                                 /* todo: the timer is used instead of the number of the beacon received */
1050                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
1051                                 {
1052                                         /* DBG_8723A("update_bcn_info\n"); */
1053                                         update_beacon_info(padapter, pframe, len, psta);
1054                                 }
1055
1056 #ifdef CONFIG_DFS
1057                                 process_csa_ie(padapter, pframe, len);  /* channel switch announcement */
1058 #endif /* CONFIG_DFS */
1059
1060 #ifdef CONFIG_P2P_PS
1061                                 process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
1062 #endif /* CONFIG_P2P_PS */
1063
1064                         }
1065                 }
1066                 else if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
1067                 {
1068                         if ((psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe))) != NULL)
1069                         {
1070                                 /* update WMM, ERP in the beacon */
1071                                 /* todo: the timer is used instead of the number of the beacon received */
1072                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
1073                                 {
1074                                         /* DBG_8723A("update_bcn_info\n"); */
1075                                         update_beacon_info(padapter, pframe, len, psta);
1076                                 }
1077
1078                         }
1079                         else
1080                         {
1081                                 /* allocate a new CAM entry for IBSS station */
1082                                 if ((cam_idx = allocate_fw_sta_entry(padapter)) == NUM_STA)
1083                                 {
1084                                         goto _END_ONBEACON_;
1085                                 }
1086
1087                                 /* get supported rate */
1088                                 if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL)
1089                                 {
1090                                         pmlmeinfo->FW_sta_info[cam_idx].status = 0;
1091                                         goto _END_ONBEACON_;
1092                                 }
1093
1094                                 /* update TSF Value */
1095                                 update_TSF(pmlmeext, pframe, len);
1096
1097                                 /* report sta add event */
1098                                 report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
1099                         }
1100                 }
1101         }
1102
1103 _END_ONBEACON_:
1104
1105         return _SUCCESS;
1106 }
1107
1108 unsigned int OnAuth(_adapter *padapter, union recv_frame *precv_frame)
1109 {
1110 #ifdef CONFIG_AP_MODE
1111         _irqL irqL;
1112         unsigned int    auth_mode, seq, ie_len;
1113         unsigned char   *sa, *p;
1114         u16     algorithm;
1115         int     status;
1116         static struct sta_info stat;
1117         struct  sta_info        *pstat=NULL;
1118         struct  sta_priv *pstapriv = &padapter->stapriv;
1119         struct security_priv *psecuritypriv = &padapter->securitypriv;
1120         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1121         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1122         u8 *pframe = precv_frame->u.hdr.rx_data;
1123         uint len = precv_frame->u.hdr.len;
1124
1125 #ifdef CONFIG_CONCURRENT_MODE
1126         if(((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
1127                 check_buddy_fwstate(padapter, _FW_UNDER_LINKING|_FW_UNDER_SURVEY))
1128         {
1129                 /* don't process auth request; */
1130                 return _SUCCESS;
1131         }
1132 #endif /* CONFIG_CONCURRENT_MODE */
1133
1134         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1135                 return _FAIL;
1136
1137         DBG_8723A("+OnAuth\n");
1138
1139         sa = GetAddr2Ptr(pframe);
1140
1141         auth_mode = psecuritypriv->dot11AuthAlgrthm;
1142         seq = cpu_to_le16(*(u16*)((unsigned long)pframe + WLAN_HDR_A3_LEN + 2));
1143         algorithm = cpu_to_le16(*(u16*)((unsigned long)pframe + WLAN_HDR_A3_LEN));
1144
1145         DBG_8723A("auth alg=%x, seq=%X\n", algorithm, seq);
1146
1147         if (auth_mode == 2 &&
1148                         psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
1149                         psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
1150                 auth_mode = 0;
1151
1152         if ((algorithm > 0 && auth_mode == 0) ||        /*  rx a shared-key auth but shared not enabled */
1153                 (algorithm == 0 && auth_mode == 1) )    /*  rx a open-system auth but shared-key is enabled */
1154         {
1155                 DBG_8723A("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",
1156                         algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
1157
1158                 status = _STATS_NO_SUPP_ALG_;
1159
1160                 goto auth_fail;
1161         }
1162
1163         if(rtw_access_ctrl(padapter, sa) == _FALSE)
1164         {
1165                 status = _STATS_UNABLE_HANDLE_STA_;
1166                 goto auth_fail;
1167         }
1168
1169         pstat = rtw_get_stainfo(pstapriv, sa);
1170         if (pstat == NULL)
1171         {
1172                 /*  allocate a new one */
1173                 DBG_8723A("going to alloc stainfo for sa="MAC_FMT"\n",  MAC_ARG(sa));
1174                 pstat = rtw_alloc_stainfo(pstapriv, sa);
1175                 if (pstat == NULL)
1176                 {
1177                         DBG_8723A(" Exceed the upper limit of supported clients...\n");
1178                         status = _STATS_UNABLE_HANDLE_STA_;
1179                         goto auth_fail;
1180                 }
1181
1182                 pstat->state = WIFI_FW_AUTH_NULL;
1183                 pstat->auth_seq = 0;
1184
1185                 /* pstat->flags = 0; */
1186                 /* pstat->capability = 0; */
1187         }
1188         else
1189         {
1190                 spin_lock_bh(&pstapriv->asoc_list_lock);
1191                 if(rtw_is_list_empty(&pstat->asoc_list)==_FALSE)
1192                 {
1193                         rtw_list_delete(&pstat->asoc_list);
1194                         pstapriv->asoc_list_cnt--;
1195                         if (pstat->expire_to > 0)
1196                         {
1197                                 /* TODO: STA re_auth within expire_to */
1198                         }
1199                 }
1200                 spin_unlock_bh(&pstapriv->asoc_list_lock);
1201
1202                 if (seq==1) {
1203                         /* TODO: STA re_auth and auth timeout */
1204                 }
1205         }
1206
1207         spin_lock_bh(&pstapriv->auth_list_lock);
1208         if (rtw_is_list_empty(&pstat->auth_list))
1209         {
1210                 rtw_list_insert_tail(&pstat->auth_list, &pstapriv->auth_list);
1211                 pstapriv->auth_list_cnt++;
1212         }
1213         spin_unlock_bh(&pstapriv->auth_list_lock);
1214
1215         if (pstat->auth_seq == 0)
1216                 pstat->expire_to = pstapriv->auth_to;
1217
1218         if ((pstat->auth_seq + 1) != seq)
1219         {
1220                 DBG_8723A("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
1221                         seq, pstat->auth_seq+1);
1222                 status = _STATS_OUT_OF_AUTH_SEQ_;
1223                 goto auth_fail;
1224         }
1225
1226         if (algorithm==0 && (auth_mode == 0 || auth_mode == 2))
1227         {
1228                 if (seq == 1)
1229                 {
1230                         pstat->state &= ~WIFI_FW_AUTH_NULL;
1231                         pstat->state |= WIFI_FW_AUTH_SUCCESS;
1232                         pstat->expire_to = pstapriv->assoc_to;
1233                         pstat->authalg = algorithm;
1234                 }
1235                 else
1236                 {
1237                         DBG_8723A("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
1238                                 seq, pstat->auth_seq+1);
1239                         status = _STATS_OUT_OF_AUTH_SEQ_;
1240                         goto auth_fail;
1241                 }
1242         }
1243         else /*  shared system or auto authentication */
1244         {
1245                 if (seq == 1)
1246                 {
1247                         /* prepare for the challenging txt... */
1248                         pstat->state &= ~WIFI_FW_AUTH_NULL;
1249                         pstat->state |= WIFI_FW_AUTH_STATE;
1250                         pstat->authalg = algorithm;
1251                         pstat->auth_seq = 2;
1252                 }
1253                 else if (seq == 3)
1254                 {
1255                         /* checking for challenging txt... */
1256                         DBG_8723A("checking for challenging txt...\n");
1257
1258                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len,
1259                                         len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
1260
1261                         if((p==NULL) || (ie_len<=0))
1262                         {
1263                                 DBG_8723A("auth rejected because challenge failure!(1)\n");
1264                                 status = _STATS_CHALLENGE_FAIL_;
1265                                 goto auth_fail;
1266                         }
1267
1268                         if (!memcmp((void *)(p + 2), pstat->chg_txt, 128))
1269                         {
1270                                 pstat->state &= (~WIFI_FW_AUTH_STATE);
1271                                 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1272                                 /*  challenging txt is correct... */
1273                                 pstat->expire_to =  pstapriv->assoc_to;
1274                         }
1275                         else
1276                         {
1277                                 DBG_8723A("auth rejected because challenge failure!\n");
1278                                 status = _STATS_CHALLENGE_FAIL_;
1279                                 goto auth_fail;
1280                         }
1281                 }
1282                 else
1283                 {
1284                         DBG_8723A("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
1285                                 seq, pstat->auth_seq+1);
1286                         status = _STATS_OUT_OF_AUTH_SEQ_;
1287                         goto auth_fail;
1288                 }
1289         }
1290
1291         /*  Now, we are going to issue_auth... */
1292         pstat->auth_seq = seq + 1;
1293
1294 #ifdef CONFIG_NATIVEAP_MLME
1295         issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
1296 #endif
1297
1298         if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1299                 pstat->auth_seq = 0;
1300
1301         return _SUCCESS;
1302
1303 auth_fail:
1304
1305         if(pstat)
1306                 rtw_free_stainfo(padapter , pstat);
1307
1308         pstat = &stat;
1309         memset((char *)pstat, '\0', sizeof(stat));
1310         pstat->auth_seq = 2;
1311         memcpy(pstat->hwaddr, sa, 6);
1312
1313 #ifdef CONFIG_NATIVEAP_MLME
1314         issue_auth(padapter, pstat, (unsigned short)status);
1315 #endif
1316
1317 #endif
1318         return _FAIL;
1319 }
1320
1321 unsigned int OnAuthClient(_adapter *padapter, union recv_frame *precv_frame)
1322 {
1323         unsigned int    seq, len, status, algthm, offset;
1324         unsigned char   *p;
1325         unsigned int    go2asoc = 0;
1326         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1327         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1328         u8 *pframe = precv_frame->u.hdr.rx_data;
1329         uint pkt_len = precv_frame->u.hdr.len;
1330
1331         DBG_8723A("%s\n", __FUNCTION__);
1332
1333         /* check A1 matches or not */
1334         if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1335                 return _SUCCESS;
1336
1337         if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1338                 return _SUCCESS;
1339
1340         offset = (GetPrivacy(pframe))? 4: 0;
1341
1342         algthm  = le16_to_cpu(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN + offset));
1343         seq     = le16_to_cpu(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN + offset + 2));
1344         status  = le16_to_cpu(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN + offset + 4));
1345
1346         if (status != 0)
1347         {
1348                 DBG_8723A("clnt auth fail, status: %d\n", status);
1349                 if(status == 13)/*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
1350                 {
1351                         if(pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1352                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
1353                         else
1354                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1355                         /* pmlmeinfo->reauth_count = 0; */
1356                 }
1357
1358                 set_link_timer(pmlmeext, 1);
1359                 goto authclnt_fail;
1360         }
1361
1362         if (seq == 2)
1363         {
1364                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1365                 {
1366                          /*  legendary shared system */
1367                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
1368                                 pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
1369
1370                         if (p == NULL)
1371                         {
1372                                 /* DBG_8723A("marc: no challenge text?\n"); */
1373                                 goto authclnt_fail;
1374                         }
1375
1376                         memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
1377                         pmlmeinfo->auth_seq = 3;
1378                         issue_auth(padapter, NULL, 0);
1379                         set_link_timer(pmlmeext, REAUTH_TO);
1380
1381                         return _SUCCESS;
1382                 }
1383                 else
1384                 {
1385                         /*  open system */
1386                         go2asoc = 1;
1387                 }
1388         }
1389         else if (seq == 4)
1390         {
1391                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1392                 {
1393                         go2asoc = 1;
1394                 }
1395                 else
1396                 {
1397                         goto authclnt_fail;
1398                 }
1399         }
1400         else
1401         {
1402                 /*  this is also illegal */
1403                 /* DBG_8723A("marc: clnt auth failed due to illegal seq=%x\n", seq); */
1404                 goto authclnt_fail;
1405         }
1406
1407         if (go2asoc)
1408         {
1409                 DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
1410                 start_clnt_assoc(padapter);
1411                 return _SUCCESS;
1412         }
1413
1414 authclnt_fail:
1415
1416         /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
1417
1418         return _FAIL;
1419 }
1420
1421 unsigned int OnAssocReq(_adapter *padapter, union recv_frame *precv_frame)
1422 {
1423 #ifdef CONFIG_AP_MODE
1424         _irqL irqL;
1425         u16 capab_info, listen_interval;
1426         struct rtw_ieee802_11_elems elems;
1427         struct sta_info *pstat;
1428         unsigned char           reassoc, *p, *pos, *wpa_ie;
1429         unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
1430         int             i, ie_len, wpa_ie_len, left;
1431         unsigned char           supportRate[16];
1432         int                                     supportRateNum;
1433         unsigned short          status = _STATS_SUCCESSFUL_;
1434         unsigned short          frame_type, ie_offset=0;
1435         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1436         struct security_priv *psecuritypriv = &padapter->securitypriv;
1437         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1438         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1439         WLAN_BSSID_EX   *cur = &(pmlmeinfo->network);
1440         struct sta_priv *pstapriv = &padapter->stapriv;
1441         u8 *pframe = precv_frame->u.hdr.rx_data;
1442         uint pkt_len = precv_frame->u.hdr.len;
1443 #ifdef CONFIG_P2P
1444         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
1445         u8 p2p_status_code = P2P_STATUS_SUCCESS;
1446         u8 *p2pie;
1447         u32 p2pielen = 0;
1448 #ifdef CONFIG_WFD
1449         u8      wfd_ie[ 128 ] = { 0x00 };
1450         u32     wfd_ielen = 0;
1451 #endif /*  CONFIG_WFD */
1452 #endif /* CONFIG_P2P */
1453
1454 #ifdef CONFIG_CONCURRENT_MODE
1455         if(((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
1456                 check_buddy_fwstate(padapter, _FW_UNDER_LINKING|_FW_UNDER_SURVEY))
1457         {
1458                 /* don't process assoc request; */
1459                 return _SUCCESS;
1460         }
1461 #endif /* CONFIG_CONCURRENT_MODE */
1462
1463         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1464                 return _FAIL;
1465
1466         frame_type = GetFrameSubType(pframe);
1467         if (frame_type == WIFI_ASSOCREQ)
1468         {
1469                 reassoc = 0;
1470                 ie_offset = _ASOCREQ_IE_OFFSET_;
1471         }
1472         else /*  WIFI_REASSOCREQ */
1473         {
1474                 reassoc = 1;
1475                 ie_offset = _REASOCREQ_IE_OFFSET_;
1476         }
1477
1478         if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
1479                 DBG_8723A("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
1480                        "\n", reassoc, (unsigned long)pkt_len);
1481                 return _FAIL;
1482         }
1483
1484         pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1485         if (pstat == (struct sta_info *)NULL)
1486         {
1487                 status = _RSON_CLS2_;
1488                 goto asoc_class2_error;
1489         }
1490
1491         capab_info = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN);
1492         /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */
1493         /* listen_interval = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN+2)); */
1494         listen_interval = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN+2);
1495
1496         left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
1497         pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
1498
1499         DBG_8723A("%s\n", __FUNCTION__);
1500
1501         /*  check if this stat has been successfully authenticated/assocated */
1502         if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS))
1503         {
1504                 if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS))
1505                 {
1506                         status = _RSON_CLS2_;
1507                         goto asoc_class2_error;
1508                 }
1509                 else
1510                 {
1511                         pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1512                         pstat->state |= WIFI_FW_ASSOC_STATE;
1513                 }
1514         }
1515         else
1516         {
1517                 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1518                 pstat->state |= WIFI_FW_ASSOC_STATE;
1519         }
1520
1521         pstat->capability = capab_info;
1522
1523         /* now parse all ieee802_11 ie to point to elems */
1524         if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
1525             !elems.ssid) {
1526                 DBG_8723A("STA " MAC_FMT " sent invalid association request\n",
1527                        MAC_ARG(pstat->hwaddr));
1528                 status = _STATS_FAILURE_;
1529                 goto OnAssocReqFail;
1530         }
1531
1532         /*  now we should check all the fields... */
1533         /*  checking SSID */
1534         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
1535                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1536         if (p == NULL)
1537         {
1538                 status = _STATS_FAILURE_;
1539         }
1540
1541         if (ie_len == 0) /*  broadcast ssid, however it is not allowed in assocreq */
1542                 status = _STATS_FAILURE_;
1543         else
1544         {
1545                 /*  check if ssid match */
1546                 if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
1547                         status = _STATS_FAILURE_;
1548
1549                 if (ie_len != cur->Ssid.SsidLength)
1550                         status = _STATS_FAILURE_;
1551         }
1552
1553         if(_STATS_SUCCESSFUL_ != status)
1554                 goto OnAssocReqFail;
1555
1556         /*  check if the supported rate is ok */
1557         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1558         if (p == NULL) {
1559                 DBG_8723A("Rx a sta assoc-req which supported rate is empty!\n");
1560                 /*  use our own rate set as statoin used */
1561                 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1562                 /* supportRateNum = AP_BSSRATE_LEN; */
1563
1564                 status = _STATS_FAILURE_;
1565                 goto OnAssocReqFail;
1566         }
1567         else {
1568                 memcpy(supportRate, p+2, ie_len);
1569                 supportRateNum = ie_len;
1570
1571                 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &ie_len,
1572                                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1573                 if (p !=  NULL) {
1574
1575                         if(supportRateNum<=sizeof(supportRate))
1576                         {
1577                                 memcpy(supportRate+supportRateNum, p+2, ie_len);
1578                                 supportRateNum += ie_len;
1579                         }
1580                 }
1581         }
1582
1583         /* todo: mask supportRate between AP & STA -> move to update raid */
1584         /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1585
1586         /* update station supportRate */
1587         pstat->bssratelen = supportRateNum;
1588         memcpy(pstat->bssrateset, supportRate, supportRateNum);
1589         UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1590
1591         /* check RSN/WPA/WPS */
1592         pstat->dot8021xalg = 0;
1593         pstat->wpa_psk = 0;
1594         pstat->wpa_group_cipher = 0;
1595         pstat->wpa2_group_cipher = 0;
1596         pstat->wpa_pairwise_cipher = 0;
1597         pstat->wpa2_pairwise_cipher = 0;
1598         memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1599         if((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1600
1601                 int group_cipher=0, pairwise_cipher=0;
1602
1603                 wpa_ie = elems.rsn_ie;
1604                 wpa_ie_len = elems.rsn_ie_len;
1605
1606                 if(rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1607                         pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1608                         pstat->wpa_psk |= BIT(1);
1609
1610                         pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
1611                         pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
1612
1613                         if(!pstat->wpa2_group_cipher)
1614                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1615
1616                         if(!pstat->wpa2_pairwise_cipher)
1617                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1618                 } else {
1619                         status = WLAN_STATUS_INVALID_IE;
1620                 }
1621
1622         } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1623
1624                 int group_cipher=0, pairwise_cipher=0;
1625
1626                 wpa_ie = elems.wpa_ie;
1627                 wpa_ie_len = elems.wpa_ie_len;
1628
1629                 if(rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1630                         pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1631                         pstat->wpa_psk |= BIT(0);
1632
1633                         pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
1634                         pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
1635
1636                         if(!pstat->wpa_group_cipher)
1637                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1638
1639                         if(!pstat->wpa_pairwise_cipher)
1640                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1641
1642                 } else {
1643                         status = WLAN_STATUS_INVALID_IE;
1644                 }
1645
1646         } else {
1647                 wpa_ie = NULL;
1648                 wpa_ie_len = 0;
1649         }
1650
1651         if(_STATS_SUCCESSFUL_ != status)
1652                 goto OnAssocReqFail;
1653
1654         pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1655         if(wpa_ie == NULL) {
1656                 if (elems.wps_ie) {
1657                         DBG_8723A("STA included WPS IE in "
1658                                    "(Re)Association Request - assume WPS is "
1659                                    "used\n");
1660                         pstat->flags |= WLAN_STA_WPS;
1661                 } else {
1662                         DBG_8723A("STA did not include WPA/RSN IE "
1663                                    "in (Re)Association Request - possible WPS "
1664                                    "use\n");
1665                         pstat->flags |= WLAN_STA_MAYBE_WPS;
1666                 }
1667
1668                 /*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1669                 /*  that the selected registrar of AP is _FLASE */
1670                 if ((psecuritypriv->wpa_psk > 0) &&
1671                     (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
1672                         if(pmlmepriv->wps_beacon_ie) {
1673                                 u8 selected_registrar = 0;
1674
1675                                 rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len,
1676                                                          WPS_ATTR_SELECTED_REGISTRAR , &selected_registrar, NULL);
1677
1678                                 if(!selected_registrar) {
1679                                         DBG_8723A("selected_registrar is _FALSE , or AP is not ready to do WPS\n");
1680
1681                                         status = _STATS_UNABLE_HANDLE_STA_;
1682
1683                                         goto OnAssocReqFail;
1684                                 }
1685                         }
1686                 }
1687         } else {
1688                 int copy_len;
1689
1690                 if(psecuritypriv->wpa_psk == 0) {
1691                         DBG_8723A("STA " MAC_FMT ": WPA/RSN IE in association "
1692                         "request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr));
1693
1694                         status = WLAN_STATUS_INVALID_IE;
1695
1696                         goto OnAssocReqFail;
1697                 }
1698
1699                 if (elems.wps_ie) {
1700                         DBG_8723A("STA included WPS IE in "
1701                                    "(Re)Association Request - WPS is "
1702                                    "used\n");
1703                         pstat->flags |= WLAN_STA_WPS;
1704                         copy_len=0;
1705                 } else {
1706                         copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
1707                 }
1708
1709                 if(copy_len>0)
1710                         memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
1711
1712         }
1713
1714         /*  check if there is WMM IE & support WWM-PS */
1715         pstat->flags &= ~WLAN_STA_WME;
1716         pstat->qos_option = 0;
1717         pstat->qos_info = 0;
1718         pstat->has_legacy_ac = _TRUE;
1719         pstat->uapsd_vo = 0;
1720         pstat->uapsd_vi = 0;
1721         pstat->uapsd_be = 0;
1722         pstat->uapsd_bk = 0;
1723         if (pmlmepriv->qospriv.qos_option)
1724         {
1725                 p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
1726                 for (;;)
1727                 {
1728                         p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1729                         if (p != NULL) {
1730                                 if (!memcmp(p+2, WMM_IE, 6)) {
1731
1732                                         pstat->flags |= WLAN_STA_WME;
1733
1734                                         pstat->qos_option = 1;
1735                                         pstat->qos_info = *(p+8);
1736
1737                                         pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
1738
1739                                         if((pstat->qos_info&0xf) !=0xf)
1740                                                 pstat->has_legacy_ac = _TRUE;
1741                                         else
1742                                                 pstat->has_legacy_ac = _FALSE;
1743
1744                                         if(pstat->qos_info&0xf)
1745                                         {
1746                                                 if(pstat->qos_info&BIT(0))
1747                                                         pstat->uapsd_vo = BIT(0)|BIT(1);
1748                                                 else
1749                                                         pstat->uapsd_vo = 0;
1750
1751                                                 if(pstat->qos_info&BIT(1))
1752                                                         pstat->uapsd_vi = BIT(0)|BIT(1);
1753                                                 else
1754                                                         pstat->uapsd_vi = 0;
1755
1756                                                 if(pstat->qos_info&BIT(2))
1757                                                         pstat->uapsd_bk = BIT(0)|BIT(1);
1758                                                 else
1759                                                         pstat->uapsd_bk = 0;
1760
1761                                                 if(pstat->qos_info&BIT(3))
1762                                                         pstat->uapsd_be = BIT(0)|BIT(1);
1763                                                 else
1764                                                         pstat->uapsd_be = 0;
1765
1766                                         }
1767
1768                                         break;
1769                                 }
1770                         }
1771                         else {
1772                                 break;
1773                         }
1774                         p = p + ie_len + 2;
1775                 }
1776         }
1777
1778 #ifdef CONFIG_80211N_HT
1779         /* save HT capabilities in the sta object */
1780         memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
1781         if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap))
1782         {
1783                 pstat->flags |= WLAN_STA_HT;
1784
1785                 pstat->flags |= WLAN_STA_WME;
1786
1787                 memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));
1788
1789         } else
1790                 pstat->flags &= ~WLAN_STA_HT;
1791
1792         if((pmlmepriv->htpriv.ht_option == _FALSE) && (pstat->flags&WLAN_STA_HT))
1793         {
1794                 status = _STATS_FAILURE_;
1795                 goto OnAssocReqFail;
1796         }
1797
1798         if ((pstat->flags & WLAN_STA_HT) &&
1799                     ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1800                       (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP)))
1801         {
1802                 DBG_8723A("HT: " MAC_FMT " tried to "
1803                                    "use TKIP with HT association\n", MAC_ARG(pstat->hwaddr));
1804
1805                 /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1806                 /* goto OnAssocReqFail; */
1807         }
1808 #endif /* CONFIG_80211N_HT */
1809
1810        /*  */
1811         pstat->flags |= WLAN_STA_NONERP;
1812         for (i = 0; i < pstat->bssratelen; i++) {
1813                 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1814                         pstat->flags &= ~WLAN_STA_NONERP;
1815                         break;
1816                 }
1817         }
1818
1819         if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1820                 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1821         else
1822                 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1823
1824         if (status != _STATS_SUCCESSFUL_)
1825                 goto OnAssocReqFail;
1826
1827 #ifdef CONFIG_P2P
1828         pstat->is_p2p_device = _FALSE;
1829         if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1830         {
1831                 if( (p2pie=rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , NULL, &p2pielen)))
1832                 {
1833                         pstat->is_p2p_device = _TRUE;
1834                         if((p2p_status_code=(u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat))>0)
1835                         {
1836                                 pstat->p2p_status_code = p2p_status_code;
1837                                 status = _STATS_CAP_FAIL_;
1838                                 goto OnAssocReqFail;
1839                         }
1840                 }
1841 #ifdef CONFIG_WFD
1842                 if(rtw_get_wfd_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , wfd_ie, &wfd_ielen ))
1843                 {
1844                         u8      attr_content[ 10 ] = { 0x00 };
1845                         u32     attr_contentlen = 0;
1846
1847                         DBG_8723A( "[%s] WFD IE Found!!\n", __FUNCTION__ );
1848                         rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
1849                         if ( attr_contentlen )
1850                         {
1851                                 pwdinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );
1852                                 DBG_8723A( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_rtsp_ctrlport );
1853                         }
1854                 }
1855 #endif
1856         }
1857         pstat->p2p_status_code = p2p_status_code;
1858 #endif /* CONFIG_P2P */
1859
1860         /* TODO: identify_proprietary_vendor_ie(); */
1861         /*  Realtek proprietary IE */
1862         /*  identify if this is Broadcom sta */
1863         /*  identify if this is ralink sta */
1864         /*  Customer proprietary IE */
1865
1866         /* get a unique AID */
1867         if (pstat->aid > 0) {
1868                 DBG_8723A("  old AID %d\n", pstat->aid);
1869         } else {
1870                 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1871                         if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1872                                 break;
1873
1874                 if (pstat->aid > NUM_STA)
1875                         pstat->aid = NUM_STA;
1876                 if (pstat->aid > pstapriv->max_num_sta) {
1877
1878                         pstat->aid = 0;
1879
1880                         DBG_8723A("  no room for more AIDs\n");
1881
1882                         status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1883
1884                         goto OnAssocReqFail;
1885
1886                 } else {
1887                         pstapriv->sta_aid[pstat->aid - 1] = pstat;
1888                         DBG_8723A("allocate new AID = (%d)\n", pstat->aid);
1889                 }
1890         }
1891
1892         pstat->state &= (~WIFI_FW_ASSOC_STATE);
1893         pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1894
1895         spin_lock_bh(&pstapriv->auth_list_lock);
1896         if (!rtw_is_list_empty(&pstat->auth_list))
1897         {
1898                 rtw_list_delete(&pstat->auth_list);
1899                 pstapriv->auth_list_cnt--;
1900         }
1901         spin_unlock_bh(&pstapriv->auth_list_lock);
1902
1903         spin_lock_bh(&pstapriv->asoc_list_lock);
1904         if (rtw_is_list_empty(&pstat->asoc_list))
1905         {
1906                 pstat->expire_to = pstapriv->expire_to;
1907                 rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1908                 pstapriv->asoc_list_cnt++;
1909         }
1910         spin_unlock_bh(&pstapriv->asoc_list_lock);
1911
1912         /*  now the station is qualified to join our BSS... */
1913         if(pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_==status))
1914         {
1915 #ifdef CONFIG_NATIVEAP_MLME
1916                 /* 1 bss_cap_update & sta_info_update */
1917                 bss_cap_update_on_sta_join(padapter, pstat);
1918                 sta_info_update(padapter, pstat);
1919
1920                 /* issue assoc rsp before notify station join event. */
1921                 if (frame_type == WIFI_ASSOCREQ)
1922                         issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1923                 else
1924                         issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1925
1926                 /* 2 - report to upper layer */
1927                 DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n");
1928                 #ifdef CONFIG_IOCTL_CFG80211
1929                 if (1) {
1930                         #ifdef COMPAT_KERNEL_RELEASE
1931                         rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len);
1932                         #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
1933                         rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len);
1934                         #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */
1935                         spin_lock_bh(&pstat->lock);
1936                         if(pstat->passoc_req)
1937                         {
1938                                 rtw_mfree(pstat->passoc_req, pstat->assoc_req_len);
1939                                 pstat->passoc_req = NULL;
1940                                 pstat->assoc_req_len = 0;
1941                         }
1942
1943                         pstat->passoc_req =  rtw_zmalloc(pkt_len);
1944                         if(pstat->passoc_req)
1945                         {
1946                                 memcpy(pstat->passoc_req, pframe, pkt_len);
1947                                 pstat->assoc_req_len = pkt_len;
1948                         }
1949                         spin_unlock_bh(&pstat->lock);
1950                         #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */
1951                 }
1952                 else
1953                 #endif /* CONFIG_IOCTL_CFG80211 */
1954                 {
1955                         rtw_indicate_sta_assoc_event(padapter, pstat);
1956                 }
1957
1958                 /* 3-(1) report sta add event */
1959                 report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
1960 #endif
1961         }
1962
1963         return _SUCCESS;
1964
1965 asoc_class2_error:
1966
1967 #ifdef CONFIG_NATIVEAP_MLME
1968         issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1969 #endif
1970
1971         return _FAIL;
1972
1973 OnAssocReqFail:
1974
1975 #ifdef CONFIG_NATIVEAP_MLME
1976         pstat->aid = 0;
1977         if (frame_type == WIFI_ASSOCREQ)
1978                 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1979         else
1980                 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1981 #endif
1982
1983 #endif /* CONFIG_AP_MODE */
1984
1985         return _FAIL;
1986 }
1987
1988 unsigned int OnAssocRsp(_adapter *padapter, union recv_frame *precv_frame)
1989 {
1990         uint i;
1991         int res;
1992         unsigned short  status;
1993         PNDIS_802_11_VARIABLE_IEs       pIE;
1994         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1995         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1996         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1997         /* WLAN_BSSID_EX                        *cur_network = &(pmlmeinfo->network); */
1998         u8 *pframe = precv_frame->u.hdr.rx_data;
1999         uint pkt_len = precv_frame->u.hdr.len;
2000         PNDIS_802_11_VARIABLE_IEs       pWapiIE = NULL;
2001
2002         DBG_8723A("%s\n", __FUNCTION__);
2003
2004         /* check A1 matches or not */
2005         if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
2006                 return _SUCCESS;
2007
2008         if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
2009                 return _SUCCESS;
2010
2011         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
2012                 return _SUCCESS;
2013
2014         _cancel_timer_ex(&pmlmeext->link_timer);
2015
2016         /* status */
2017         if ((status = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 2))) > 0)
2018         {
2019                 DBG_8723A("assoc reject, status code: %d\n", status);
2020                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
2021                 res = -4;
2022                 goto report_assoc_result;
2023         }
2024
2025         /* get capabilities */
2026         pmlmeinfo->capability = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
2027
2028         /* set slot time */
2029         pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
2030
2031         /* AID */
2032         res = pmlmeinfo->aid = (int)(le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
2033
2034         /* following are moved to join event callback function */
2035         /* to handle HT, WMM, rate adaptive, update MAC reg */
2036         /* for not to handle the synchronous IO in the tasklet */
2037         for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;)
2038         {
2039                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pframe + i);
2040
2041                 switch (pIE->ElementID)
2042                 {
2043                         case _VENDOR_SPECIFIC_IE_:
2044                                 if (!memcmp(pIE->data, WMM_PARA_OUI, 6))/* WMM */
2045                                 {
2046                                         WMM_param_handler(padapter, pIE);
2047                                 }
2048 #if defined(CONFIG_P2P) && defined(CONFIG_WFD)
2049                                 else if (!memcmp(pIE->data, WFD_OUI, 4))/* WFD */
2050                                 {
2051                                         DBG_8723A( "[%s] Found WFD IE\n", __FUNCTION__ );
2052                                         WFD_info_handler( padapter, pIE );
2053                                 }
2054 #endif
2055                                 break;
2056
2057 #ifdef CONFIG_WAPI_SUPPORT
2058                         case _WAPI_IE_:
2059                                 pWapiIE = pIE;
2060                                 break;
2061 #endif
2062
2063                         case _HT_CAPABILITY_IE_:        /* HT caps */
2064                                 HT_caps_handler(padapter, pIE);
2065                                 break;
2066
2067                         case _HT_EXTRA_INFO_IE_:        /* HT info */
2068                                 HT_info_handler(padapter, pIE);
2069                                 break;
2070
2071                         case _ERPINFO_IE_:
2072                                 ERP_IE_handler(padapter, pIE);
2073
2074                         default:
2075                                 break;
2076                 }
2077
2078                 i += (pIE->Length + 2);
2079         }
2080
2081 #ifdef CONFIG_WAPI_SUPPORT
2082         rtw_wapi_on_assoc_ok(padapter, pIE);
2083 #endif
2084
2085         pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
2086         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
2087
2088         /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
2089         UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
2090
2091 report_assoc_result:
2092         if (res > 0) {
2093                 rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
2094         } else {
2095                 rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
2096         }
2097
2098         report_join_res(padapter, res);
2099
2100         return _SUCCESS;
2101 }
2102
2103 unsigned int OnDeAuth(_adapter *padapter, union recv_frame *precv_frame)
2104 {
2105         unsigned short  reason;
2106         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2107         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2108         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2109         u8 *pframe = precv_frame->u.hdr.rx_data;
2110 #ifdef CONFIG_P2P
2111         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
2112 #endif /* CONFIG_P2P */
2113
2114         /* check A3 */
2115         if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network),
2116                    ETH_ALEN))
2117                 return _SUCCESS;
2118
2119 #ifdef CONFIG_P2P
2120         if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
2121         {
2122                 _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
2123                 _set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
2124         }
2125 #endif /* CONFIG_P2P */
2126
2127         reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
2128
2129         DBG_8723A("%s Reason code(%d)\n", __FUNCTION__,reason);
2130
2131 #ifdef CONFIG_AP_MODE
2132         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
2133         {
2134                 _irqL irqL;
2135                 struct sta_info *psta;
2136                 struct sta_priv *pstapriv = &padapter->stapriv;
2137
2138                 /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
2139                 /* rtw_free_stainfo(padapter, psta); */
2140                 /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
2141
2142                 DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
2143                                 reason, GetAddr2Ptr(pframe));
2144
2145                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
2146                 if(psta)
2147                 {
2148                         u8 updated;
2149
2150                         spin_lock_bh(&pstapriv->asoc_list_lock);
2151                         if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
2152                         {
2153                                 rtw_list_delete(&psta->asoc_list);
2154                                 pstapriv->asoc_list_cnt--;
2155                                 updated = ap_free_sta(padapter, psta, _FALSE, reason);
2156
2157                         }
2158                         spin_unlock_bh(&pstapriv->asoc_list_lock);
2159
2160                         associated_clients_update(padapter, updated);
2161                 }
2162
2163                 return _SUCCESS;
2164         }
2165         else
2166 #endif
2167         {
2168                 DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n",
2169                                 reason, GetAddr3Ptr(pframe));
2170
2171                 receive_disconnect(padapter, GetAddr3Ptr(pframe) ,reason);
2172         }
2173         pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
2174         return _SUCCESS;
2175 }
2176
2177 unsigned int OnDisassoc(_adapter *padapter, union recv_frame *precv_frame)
2178 {
2179         unsigned short  reason;
2180         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2181         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2182         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2183         u8 *pframe = precv_frame->u.hdr.rx_data;
2184 #ifdef CONFIG_P2P
2185         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
2186 #endif /* CONFIG_P2P */
2187
2188         /* check A3 */
2189         if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
2190                 return _SUCCESS;
2191
2192 #ifdef CONFIG_P2P
2193         if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
2194         {
2195                 _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
2196                 _set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
2197         }
2198 #endif /* CONFIG_P2P */
2199
2200         reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
2201
2202         DBG_8723A("%s Reason code(%d)\n", __FUNCTION__,reason);
2203
2204 #ifdef CONFIG_AP_MODE
2205         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
2206         {
2207                 _irqL irqL;
2208                 struct sta_info *psta;
2209                 struct sta_priv *pstapriv = &padapter->stapriv;
2210
2211                 /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
2212                 /* rtw_free_stainfo(padapter, psta); */
2213                 /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
2214
2215                 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
2216                                 reason, GetAddr2Ptr(pframe));
2217
2218                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
2219                 if(psta)
2220                 {
2221                         u8 updated;
2222
2223                         spin_lock_bh(&pstapriv->asoc_list_lock);
2224                         if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
2225                         {
2226                                 rtw_list_delete(&psta->asoc_list);
2227                                 pstapriv->asoc_list_cnt--;
2228                                 updated = ap_free_sta(padapter, psta, _FALSE, reason);
2229
2230                         }
2231                         spin_unlock_bh(&pstapriv->asoc_list_lock);
2232
2233                         associated_clients_update(padapter, updated);
2234                 }
2235
2236                 return _SUCCESS;
2237         }
2238         else
2239 #endif
2240         {
2241                 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
2242                                 reason, GetAddr3Ptr(pframe));
2243
2244                 receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
2245         }
2246         pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
2247         return _SUCCESS;
2248 }
2249
2250 unsigned int OnAtim(_adapter *padapter, union recv_frame *precv_frame)
2251 {
2252         DBG_8723A("%s\n", __FUNCTION__);
2253         return _SUCCESS;
2254 }
2255
2256 unsigned int on_action_spct_ch_switch(_adapter *padapter, struct sta_info *psta, u8 *ies, uint ies_len)
2257 {
2258         unsigned int ret = _FAIL;
2259         struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv;
2260         struct mlme_ext_info    *pmlmeinfo = &(mlmeext->mlmext_info);
2261
2262         if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
2263                 ret = _SUCCESS;
2264                 goto exit;
2265         }
2266
2267         if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
2268
2269                 int ch_switch_mode = -1, ch = -1, ch_switch_cnt = -1;
2270                 int ch_offset = -1;
2271                 u8 bwmode;
2272                 struct ieee80211_info_element *ie;
2273
2274                 DBG_8723A(FUNC_NDEV_FMT" from "MAC_FMT"\n",
2275                         FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(psta->hwaddr));
2276
2277                 for_each_ie(ie, ies, ies_len) {
2278                         if (ie->id == WLAN_EID_CHANNEL_SWITCH) {
2279                                 ch_switch_mode = ie->data[0];
2280                                 ch = ie->data[1];
2281                                 ch_switch_cnt = ie->data[2];
2282                                 DBG_8723A("ch_switch_mode:%d, ch:%d, ch_switch_cnt:%d\n",
2283                                         ch_switch_mode, ch, ch_switch_cnt);
2284                         }
2285                         else if (ie->id == WLAN_EID_SECONDARY_CHANNEL_OFFSET) {
2286                                 ch_offset = secondary_ch_offset_to_hal_ch_offset(ie->data[0]);
2287                                 DBG_8723A("ch_offset:%d\n", ch_offset);
2288                         }
2289                 }
2290
2291                 if (ch == -1)
2292                         return _SUCCESS;
2293
2294                 if (ch_offset == -1)
2295                         bwmode = mlmeext->cur_bwmode;
2296                 else
2297                         bwmode = (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) ?
2298                                 HT_CHANNEL_WIDTH_20 : HT_CHANNEL_WIDTH_40;
2299
2300                 ch_offset = (ch_offset == -1) ? mlmeext->cur_ch_offset : ch_offset;
2301
2302                 /* todo:
2303                  * 1. the decision of channel switching
2304                  * 2. things after channel switching
2305                  */
2306
2307                 ret = rtw_set_ch_cmd(padapter, ch, bwmode, ch_offset, _TRUE);
2308         }
2309
2310 exit:
2311         return ret;
2312 }
2313
2314 unsigned int on_action_spct(_adapter *padapter, union recv_frame *precv_frame)
2315 {
2316         unsigned int ret = _FAIL;
2317         struct sta_info *psta = NULL;
2318         struct sta_priv *pstapriv = &padapter->stapriv;
2319         u8 *pframe = precv_frame->u.hdr.rx_data;
2320         uint frame_len = precv_frame->u.hdr.len;
2321         u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2322         u8 category;
2323         u8 action;
2324
2325         DBG_8723A(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
2326
2327         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
2328
2329         if (!psta)
2330                 goto exit;
2331
2332         category = frame_body[0];
2333         if(category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
2334                 goto exit;
2335
2336         action = frame_body[1];
2337         switch (action) {
2338         case RTW_WLAN_ACTION_SPCT_MSR_REQ:
2339         case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
2340         case RTW_WLAN_ACTION_SPCT_TPC_REQ:
2341         case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
2342                 break;
2343         case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
2344                 #ifdef CONFIG_SPCT_CH_SWITCH
2345                 ret = on_action_spct_ch_switch(padapter, psta, &frame_body[2],
2346                         frame_len-(frame_body-pframe)-2);
2347                 #endif
2348                 break;
2349         default:
2350                 break;
2351         }
2352
2353 exit:
2354         return ret;
2355 }
2356
2357 unsigned int OnAction_qos(_adapter *padapter, union recv_frame *precv_frame)
2358 {
2359         return _SUCCESS;
2360 }
2361
2362 unsigned int OnAction_dls(_adapter *padapter, union recv_frame *precv_frame)
2363 {
2364         return _SUCCESS;
2365 }
2366
2367 unsigned int OnAction_back(_adapter *padapter, union recv_frame *precv_frame)
2368 {
2369         u8 *addr;
2370         struct sta_info *psta=NULL;
2371         struct recv_reorder_ctrl *preorder_ctrl;
2372         unsigned char           *frame_body;
2373         unsigned char           category, action;
2374         unsigned short  tid, status, reason_code = 0;
2375         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2376         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2377         u8 *pframe = precv_frame->u.hdr.rx_data;
2378         struct sta_priv *pstapriv = &padapter->stapriv;
2379 #ifdef CONFIG_80211N_HT
2380         /* check RA matches or not */
2381         if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
2382                 return _SUCCESS;
2383
2384         DBG_8723A("%s\n", __FUNCTION__);
2385
2386         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
2387                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2388                         return _SUCCESS;
2389
2390         addr = GetAddr2Ptr(pframe);
2391         psta = rtw_get_stainfo(pstapriv, addr);
2392
2393         if(psta==NULL)
2394                 return _SUCCESS;
2395
2396         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2397
2398         category = frame_body[0];
2399         if (category == RTW_WLAN_CATEGORY_BACK)/*  representing Block Ack */
2400         {
2401 #ifdef CONFIG_TDLS
2402                 if((psta->tdls_sta_state & TDLS_LINKED_STATE) &&
2403                         (psta->htpriv.ht_option==_TRUE) &&
2404                         (psta->htpriv.ampdu_enable==_TRUE) )
2405                 {
2406                         /* do nothing; just don't want to return _SUCCESS; */
2407                 } else
2408 #endif /* CONFIG_TDLS */
2409                 if (!pmlmeinfo->HT_enable)
2410                         return _SUCCESS;
2411                 action = frame_body[1];
2412                 DBG_8723A("%s, action=%d\n", __FUNCTION__, action);
2413                 switch (action) {
2414                 case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
2415                         memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
2416                         /* process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */
2417                         process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), addr);
2418
2419                         if(pmlmeinfo->bAcceptAddbaReq == _TRUE)
2420                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
2421                         else
2422                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
2423                         break;
2424                 case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
2425                         status = RTW_GET_LE16(&frame_body[3]);
2426                         tid = ((frame_body[5] >> 2) & 0x7);
2427                         if (status == 0) {      /* successful */
2428                                 DBG_8723A("agg_enable for TID=%d\n", tid);
2429                                 psta->htpriv.agg_enable_bitmap |= 1 << tid;
2430                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2431                         } else {
2432                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2433                         }
2434
2435                         break;
2436                 case RTW_WLAN_ACTION_DELBA: /* DELBA */
2437                         if ((frame_body[3] & BIT(3)) == 0) {
2438                                 psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
2439                                 psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
2440
2441                                 /* reason_code = frame_body[4] | (frame_body[5] << 8); */
2442                                 reason_code = RTW_GET_LE16(&frame_body[4]);
2443                         } else if((frame_body[3] & BIT(3)) == BIT(3)) {
2444                                 tid = (frame_body[3] >> 4) & 0x0F;
2445
2446                                 preorder_ctrl =  &psta->recvreorder_ctrl[tid];
2447                                 preorder_ctrl->enable = _FALSE;
2448                                 preorder_ctrl->indicate_seq = 0xffff;
2449                                 #ifdef DBG_RX_SEQ
2450                                 DBG_8723A("DBG_RX_SEQ %s:%d indicate_seq:%u \n", __FUNCTION__, __LINE__,
2451                                         preorder_ctrl->indicate_seq);
2452                                 #endif
2453                         }
2454
2455                         DBG_8723A("%s(): DELBA: %x(%x)\n", __FUNCTION__,pmlmeinfo->agg_enable_bitmap, reason_code);
2456                         /* todo: how to notify the host while receiving DELETE BA */
2457                         break;
2458                 default:
2459                         break;
2460                 }
2461         }
2462 #endif /* CONFIG_80211N_HT */
2463         return _SUCCESS;
2464 }
2465
2466 #ifdef CONFIG_P2P
2467
2468 static int get_reg_classes_full_count(struct p2p_channels channel_list) {
2469         int cnt = 0;
2470         int i;
2471
2472         for (i = 0; i < channel_list.reg_classes; i++) {
2473                 cnt += channel_list.reg_class[i].channels;
2474         }
2475
2476         return cnt;
2477 }
2478
2479 static void get_channel_cnt_24g_5gl_5gh(  struct mlme_ext_priv *pmlmeext, u8* p24g_cnt, u8* p5gl_cnt, u8* p5gh_cnt )
2480 {
2481         int     i = 0;
2482
2483         *p24g_cnt = 0;
2484         *p5gl_cnt = 0;
2485         *p5gh_cnt = 0;
2486
2487         for( i = 0; i < pmlmeext->max_chan_nums; i++ )
2488         {
2489                 if ( pmlmeext->channel_set[ i ].ChannelNum <= 14 )
2490                 {
2491                         (*p24g_cnt)++;
2492                 }
2493                 else if ( ( pmlmeext->channel_set[ i ].ChannelNum > 14 ) && ( pmlmeext->channel_set[ i ].ChannelNum <= 48 ) )
2494                 {
2495                         /*      Just include the channel 36, 40, 44, 48 channels for 5G low */
2496                         (*p5gl_cnt)++;
2497                 }
2498                 else if ( ( pmlmeext->channel_set[ i ].ChannelNum >= 149 ) && ( pmlmeext->channel_set[ i ].ChannelNum <= 161 ) )
2499                 {
2500                         /*      Just include the channel 149, 153, 157, 161 channels for 5G high */
2501                         (*p5gh_cnt)++;
2502                 }
2503         }
2504 }
2505
2506 void issue_p2p_GO_request(_adapter *padapter, u8* raddr)
2507 {
2508
2509         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
2510         u8                      action = P2P_PUB_ACTION_ACTION;
2511         u32                     p2poui = cpu_to_be32(P2POUI);
2512         u8                      oui_subtype = P2P_GO_NEGO_REQ;
2513         u8                      wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
2514         u8                      wpsielen = 0, p2pielen = 0, i;
2515         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
2516         u16                     len_channellist_attr = 0;
2517 #ifdef CONFIG_WFD
2518         u32                                     wfdielen = 0;
2519 #endif /* CONFIG_WFD */
2520
2521         struct xmit_frame                       *pmgntframe;
2522         struct pkt_attrib                       *pattrib;
2523         unsigned char                                   *pframe;
2524         struct rtw_ieee80211_hdr        *pwlanhdr;
2525         unsigned short                          *fctrl;
2526         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
2527         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2528         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2529         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
2530
2531         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
2532         {
2533                 return;
2534         }
2535
2536         DBG_8723A( "[%s] In\n", __FUNCTION__ );
2537         /* update attribute */
2538         pattrib = &pmgntframe->attrib;
2539         update_mgntframe_attrib(padapter, pattrib);
2540
2541         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2542
2543         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2544         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
2545
2546         fctrl = &(pwlanhdr->frame_ctl);
2547         *(fctrl) = 0;
2548
2549         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2550         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2551         memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
2552
2553         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2554         pmlmeext->mgnt_seq++;
2555         SetFrameSubType(pframe, WIFI_ACTION);
2556
2557         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
2558         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
2559
2560         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
2561         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
2562         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
2563         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
2564         pwdinfo->negotiation_dialog_token = 1;  /*      Initialize the dialog value */
2565         pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &(pattrib->pktlen));
2566
2567         /*      WPS Section */
2568         wpsielen = 0;
2569         /*      WPS OUI */
2570         *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
2571         wpsielen += 4;
2572
2573         /*      WPS version */
2574         /*      Type: */
2575         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
2576         wpsielen += 2;
2577
2578         /*      Length: */
2579         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
2580         wpsielen += 2;
2581
2582         /*      Value: */
2583         wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
2584
2585         /*      Device Password ID */
2586         /*      Type: */
2587         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
2588         wpsielen += 2;
2589
2590         /*      Length: */
2591         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
2592         wpsielen += 2;
2593
2594         /*      Value: */
2595
2596         if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN )
2597         {
2598                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_USER_SPEC );
2599         }
2600         else if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN )
2601         {
2602                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );
2603         }
2604         else if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC )
2605         {
2606                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_PBC );
2607         }
2608
2609         wpsielen += 2;
2610
2611         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
2612
2613         /*      P2P IE Section. */
2614
2615         /*      P2P OUI */
2616         p2pielen = 0;
2617         p2pie[ p2pielen++ ] = 0x50;
2618         p2pie[ p2pielen++ ] = 0x6F;
2619         p2pie[ p2pielen++ ] = 0x9A;
2620         p2pie[ p2pielen++ ] = 0x09;     /*      WFA P2P v1.0 */
2621
2622         /*      Commented by Albert 20110306 */
2623         /*      According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
2624         /*      1. P2P Capability */
2625         /*      2. Group Owner Intent */
2626         /*      3. Configuration Timeout */
2627         /*      4. Listen Channel */
2628         /*      5. Extended Listen Timing */
2629         /*      6. Intended P2P Interface Address */
2630         /*      7. Channel List */
2631         /*      8. P2P Device Info */
2632         /*      9. Operating Channel */
2633
2634         /*      P2P Capability */
2635         /*      Type: */
2636         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
2637
2638         /*      Length: */
2639         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
2640         p2pielen += 2;
2641
2642         /*      Value: */
2643         /*      Device Capability Bitmap, 1 byte */
2644         p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
2645
2646         /*      Group Capability Bitmap, 1 byte */
2647         if ( pwdinfo->persistent_supported )
2648         {
2649                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2650         }
2651         else
2652         {
2653                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
2654         }
2655
2656         /*      Group Owner Intent */
2657         /*      Type: */
2658         p2pie[ p2pielen++ ] = P2P_ATTR_GO_INTENT;
2659
2660         /*      Length: */
2661         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
2662         p2pielen += 2;
2663
2664         /*      Value: */
2665         /*      Todo the tie breaker bit. */
2666         p2pie[ p2pielen++ ] = ( ( pwdinfo->intent << 1 ) | BIT(0) );
2667
2668         /*      Configuration Timeout */
2669         /*      Type: */
2670         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
2671
2672         /*      Length: */
2673         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
2674         p2pielen += 2;
2675
2676         /*      Value: */
2677         p2pie[ p2pielen++ ] = 200;      /*      2 seconds needed to be the P2P GO */
2678         p2pie[ p2pielen++ ] = 200;      /*      2 seconds needed to be the P2P Client */
2679
2680         /*      Listen Channel */
2681         /*      Type: */
2682         p2pie[ p2pielen++ ] = P2P_ATTR_LISTEN_CH;
2683
2684         /*      Length: */
2685         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
2686         p2pielen += 2;
2687
2688         /*      Value: */
2689         /*      Country String */
2690         p2pie[ p2pielen++ ] = 'X';
2691         p2pie[ p2pielen++ ] = 'X';
2692
2693         /*      The third byte should be set to 0x04. */
2694         /*      Described in the "Operating Channel Attribute" section. */
2695         p2pie[ p2pielen++ ] = 0x04;
2696
2697         /*      Operating Class */
2698         p2pie[ p2pielen++ ] = 0x51;     /*      Copy from SD7 */
2699
2700         /*      Channel Number */
2701         p2pie[ p2pielen++ ] = pwdinfo->listen_channel;  /*      listening channel number */
2702
2703         /*      Extended Listen Timing ATTR */
2704         /*      Type: */
2705         p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
2706
2707         /*      Length: */
2708         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
2709         p2pielen += 2;
2710
2711         /*      Value: */
2712         /*      Availability Period */
2713         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
2714         p2pielen += 2;
2715
2716         /*      Availability Interval */
2717         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
2718         p2pielen += 2;
2719
2720         /*      Intended P2P Interface Address */
2721         /*      Type: */
2722         p2pie[ p2pielen++ ] = P2P_ATTR_INTENTED_IF_ADDR;
2723
2724         /*      Length: */
2725         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
2726         p2pielen += 2;
2727
2728         /*      Value: */
2729         memcpy(p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
2730         p2pielen += ETH_ALEN;
2731
2732         /*      Channel List */
2733         /*      Type: */
2734         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
2735
2736         /*  Length: */
2737         /*  Country String(3) */
2738         /*  + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */
2739         /*  + number of channels in all classes */
2740         len_channellist_attr = 3
2741            + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
2742            + get_reg_classes_full_count(pmlmeext->channel_list);
2743
2744 #ifdef CONFIG_CONCURRENT_MODE
2745         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
2746         {
2747                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
2748         }
2749         else
2750         {
2751                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
2752         }
2753 #else
2754
2755         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
2756
2757 #endif
2758         p2pielen += 2;
2759
2760         /*      Value: */
2761         /*      Country String */
2762         p2pie[ p2pielen++ ] = 'X';
2763         p2pie[ p2pielen++ ] = 'X';
2764
2765         /*      The third byte should be set to 0x04. */
2766         /*      Described in the "Operating Channel Attribute" section. */
2767         p2pie[ p2pielen++ ] = 0x04;
2768
2769         /*      Channel Entry List */
2770
2771 #ifdef CONFIG_CONCURRENT_MODE
2772         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
2773         {
2774                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
2775                 struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
2776
2777                 /*      Operating Class */
2778                 if ( pbuddy_mlmeext->cur_channel > 14 )
2779                 {
2780                         if ( pbuddy_mlmeext->cur_channel >= 149 )
2781                         {
2782                                 p2pie[ p2pielen++ ] = 0x7c;
2783                         }
2784                         else
2785                         {
2786                                 p2pie[ p2pielen++ ] = 0x73;
2787                         }
2788                 }
2789                 else
2790                 {
2791                         p2pie[ p2pielen++ ] = 0x51;
2792                 }
2793
2794                 /*      Number of Channels */
2795                 /*      Just support 1 channel and this channel is AP's channel */
2796                 p2pie[ p2pielen++ ] = 1;
2797
2798                 /*      Channel List */
2799                 p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
2800         }
2801         else
2802         {
2803                 int i,j;
2804                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2805                         /*      Operating Class */
2806                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2807
2808                         /*      Number of Channels */
2809                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2810
2811                         /*      Channel List */
2812                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2813                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2814                         }
2815                 }
2816         }
2817 #else /*  CONFIG_CONCURRENT_MODE */
2818         {
2819                 int i,j;
2820                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2821                         /*      Operating Class */
2822                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2823
2824                         /*      Number of Channels */
2825                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2826
2827                         /*      Channel List */
2828                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2829                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2830                         }
2831                 }
2832         }
2833 #endif /*  CONFIG_CONCURRENT_MODE */
2834
2835         /*      Device Info */
2836         /*      Type: */
2837         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
2838
2839         /*      Length: */
2840         /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2841         /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2842         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
2843         p2pielen += 2;
2844
2845         /*      Value: */
2846         /*      P2P Device Address */
2847         memcpy(p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
2848         p2pielen += ETH_ALEN;
2849
2850         /*      Config Method */
2851         /*      This field should be big endian. Noted by P2P specification. */
2852
2853         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
2854
2855         p2pielen += 2;
2856
2857         /*      Primary Device Type */
2858         /*      Category ID */
2859         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
2860         p2pielen += 2;
2861
2862         /*      OUI */
2863         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
2864         p2pielen += 4;
2865
2866         /*      Sub Category ID */
2867         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
2868         p2pielen += 2;
2869
2870         /*      Number of Secondary Device Types */
2871         p2pie[ p2pielen++ ] = 0x00;     /*      No Secondary Device Type List */
2872
2873         /*      Device Name */
2874         /*      Type: */
2875         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
2876         p2pielen += 2;
2877
2878         /*      Length: */
2879         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
2880         p2pielen += 2;
2881
2882         /*      Value: */
2883         memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len );
2884         p2pielen += pwdinfo->device_name_len;
2885
2886         /*      Operating Channel */
2887         /*      Type: */
2888         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
2889
2890         /*      Length: */
2891         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
2892         p2pielen += 2;
2893
2894         /*      Value: */
2895         /*      Country String */
2896         p2pie[ p2pielen++ ] = 'X';
2897         p2pie[ p2pielen++ ] = 'X';
2898
2899         /*      The third byte should be set to 0x04. */
2900         /*      Described in the "Operating Channel Attribute" section. */
2901         p2pie[ p2pielen++ ] = 0x04;
2902
2903         /*      Operating Class */
2904         if ( pwdinfo->operating_channel <= 14 )
2905         {
2906                 /*      Operating Class */
2907                 p2pie[ p2pielen++ ] = 0x51;
2908         }
2909         else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
2910         {
2911                 /*      Operating Class */
2912                 p2pie[ p2pielen++ ] = 0x73;
2913         }
2914         else
2915         {
2916                 /*      Operating Class */
2917                 p2pie[ p2pielen++ ] = 0x7c;
2918         }
2919
2920         /*      Channel Number */
2921         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       /*      operating channel number */
2922
2923         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
2924
2925 #ifdef CONFIG_WFD
2926         wfdielen = build_nego_req_wfd_ie(pwdinfo, pframe);
2927         pframe += wfdielen;
2928         pattrib->pktlen += wfdielen;
2929 #endif /* CONFIG_WFD */
2930
2931         pattrib->last_txcmdsz = pattrib->pktlen;
2932
2933         dump_mgntframe(padapter, pmgntframe);
2934
2935         return;
2936 }
2937
2938 void issue_p2p_GO_response(_adapter *padapter, u8* raddr, u8* frame_body,uint len, u8 result)
2939 {
2940
2941         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
2942         u8                      action = P2P_PUB_ACTION_ACTION;
2943         u32                     p2poui = cpu_to_be32(P2POUI);
2944         u8                      oui_subtype = P2P_GO_NEGO_RESP;
2945         u8                      wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
2946         u8                      p2pielen = 0, i;
2947         uint                    wpsielen = 0;
2948         u16                     wps_devicepassword_id = 0x0000;
2949         uint                    wps_devicepassword_id_len = 0;
2950         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh;
2951         u16                     len_channellist_attr = 0;
2952
2953         struct xmit_frame                       *pmgntframe;
2954         struct pkt_attrib                       *pattrib;
2955         unsigned char                                   *pframe;
2956         struct rtw_ieee80211_hdr        *pwlanhdr;
2957         unsigned short                          *fctrl;
2958         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
2959         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2960         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2961         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
2962
2963 #ifdef CONFIG_WFD
2964         u32                                     wfdielen = 0;
2965 #endif /* CONFIG_WFD */
2966
2967         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
2968         {
2969                 return;
2970         }
2971
2972         DBG_8723A( "[%s] In, result = %d\n", __FUNCTION__,  result );
2973         /* update attribute */
2974         pattrib = &pmgntframe->attrib;
2975         update_mgntframe_attrib(padapter, pattrib);
2976
2977         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2978
2979         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2980         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
2981
2982         fctrl = &(pwlanhdr->frame_ctl);
2983         *(fctrl) = 0;
2984
2985         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2986         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2987         memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
2988
2989         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2990         pmlmeext->mgnt_seq++;
2991         SetFrameSubType(pframe, WIFI_ACTION);
2992
2993         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
2994         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
2995
2996         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
2997         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
2998         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
2999         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
3000         pwdinfo->negotiation_dialog_token = frame_body[7];      /*      The Dialog Token of provisioning discovery request frame. */
3001         pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
3002
3003         /*      Commented by Albert 20110328 */
3004         /*      Try to get the device password ID from the WPS IE of group negotiation request frame */
3005         /*      WiFi Direct test plan 5.1.15 */
3006         rtw_get_wps_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
3007         rtw_get_wps_attr_content( wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
3008         wps_devicepassword_id = be16_to_cpu( wps_devicepassword_id );
3009
3010         memset( wpsie, 0x00, 255 );
3011         wpsielen = 0;
3012
3013         /*      WPS Section */
3014         wpsielen = 0;
3015         /*      WPS OUI */
3016         *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
3017         wpsielen += 4;
3018
3019         /*      WPS version */
3020         /*      Type: */
3021         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
3022         wpsielen += 2;
3023
3024         /*      Length: */
3025         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
3026         wpsielen += 2;
3027
3028         /*      Value: */
3029         wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
3030
3031         /*      Device Password ID */
3032         /*      Type: */
3033         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
3034         wpsielen += 2;
3035
3036         /*      Length: */
3037         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
3038         wpsielen += 2;
3039
3040         /*      Value: */
3041         if ( wps_devicepassword_id == WPS_DPID_USER_SPEC )
3042         {
3043                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );
3044         }
3045         else if ( wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC )
3046         {
3047                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_USER_SPEC );
3048         }
3049         else
3050         {
3051                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_PBC );
3052         }
3053         wpsielen += 2;
3054
3055         /*      Commented by Kurt 20120113 */
3056         /*      If some device wants to do p2p handshake without sending prov_disc_req */
3057         /*      We have to get peer_req_cm from here. */
3058         if (!memcmp( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3) )
3059         {
3060                 if ( wps_devicepassword_id == WPS_DPID_USER_SPEC )
3061                 {
3062                         memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3 );
3063                 }
3064                 else if ( wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC )
3065                 {
3066                         memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3 );
3067                 }
3068                 else
3069                 {
3070                         memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3 );
3071                 }
3072         }
3073
3074         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
3075
3076         /*      P2P IE Section. */
3077
3078         /*      P2P OUI */
3079         p2pielen = 0;
3080         p2pie[ p2pielen++ ] = 0x50;
3081         p2pie[ p2pielen++ ] = 0x6F;
3082         p2pie[ p2pielen++ ] = 0x9A;
3083         p2pie[ p2pielen++ ] = 0x09;     /*      WFA P2P v1.0 */
3084
3085         /*      Commented by Albert 20100908 */
3086         /*      According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */
3087         /*      1. Status */
3088         /*      2. P2P Capability */
3089         /*      3. Group Owner Intent */
3090         /*      4. Configuration Timeout */
3091         /*      5. Operating Channel */
3092         /*      6. Intended P2P Interface Address */
3093         /*      7. Channel List */
3094         /*      8. Device Info */
3095         /*      9. Group ID     ( Only GO ) */
3096
3097         /*      ToDo: */
3098
3099         /*      P2P Status */
3100         /*      Type: */
3101         p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
3102
3103         /*      Length: */
3104         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
3105         p2pielen += 2;
3106
3107         /*      Value: */
3108         p2pie[ p2pielen++ ] = result;
3109
3110         /*      P2P Capability */
3111         /*      Type: */
3112         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
3113
3114         /*      Length: */
3115         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3116         p2pielen += 2;
3117
3118         /*      Value: */
3119         /*      Device Capability Bitmap, 1 byte */
3120
3121         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
3122         {
3123                 /*      Commented by Albert 2011/03/08 */
3124                 /*      According to the P2P specification */
3125                 /*      if the sending device will be client, the P2P Capability should be reserved of group negotation response frame */
3126                 p2pie[ p2pielen++ ] = 0;
3127         }
3128         else
3129         {
3130                 /*      Be group owner or meet the error case */
3131                 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
3132         }
3133
3134         /*      Group Capability Bitmap, 1 byte */
3135         if ( pwdinfo->persistent_supported )
3136         {
3137                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
3138         }
3139         else
3140         {
3141                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
3142         }
3143
3144         /*      Group Owner Intent */
3145         /*      Type: */
3146         p2pie[ p2pielen++ ] = P2P_ATTR_GO_INTENT;
3147
3148         /*      Length: */
3149         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
3150         p2pielen += 2;
3151
3152         /*      Value: */
3153         if ( pwdinfo->peer_intent & 0x01 )
3154         {
3155                 /*      Peer's tie breaker bit is 1, our tie breaker bit should be 0 */
3156                 p2pie[ p2pielen++ ] = ( pwdinfo->intent << 1 );
3157         }
3158         else
3159         {
3160                 /*      Peer's tie breaker bit is 0, our tie breaker bit should be 1 */
3161                 p2pie[ p2pielen++ ] = ( ( pwdinfo->intent << 1 ) | BIT(0) );
3162         }
3163
3164         /*      Configuration Timeout */
3165         /*      Type: */
3166         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
3167
3168         /*      Length: */
3169         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3170         p2pielen += 2;
3171
3172         /*      Value: */
3173         p2pie[ p2pielen++ ] = 200;      /*      2 seconds needed to be the P2P GO */
3174         p2pie[ p2pielen++ ] = 200;      /*      2 seconds needed to be the P2P Client */
3175
3176         /*      Operating Channel */
3177         /*      Type: */
3178         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
3179
3180         /*      Length: */
3181         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
3182         p2pielen += 2;
3183
3184         /*      Value: */
3185         /*      Country String */
3186         p2pie[ p2pielen++ ] = 'X';
3187         p2pie[ p2pielen++ ] = 'X';
3188
3189         /*      The third byte should be set to 0x04. */
3190         /*      Described in the "Operating Channel Attribute" section. */
3191         p2pie[ p2pielen++ ] = 0x04;
3192
3193         /*      Operating Class */
3194         if ( pwdinfo->operating_channel <= 14 )
3195         {
3196                 /*      Operating Class */
3197                 p2pie[ p2pielen++ ] = 0x51;
3198         }
3199         else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
3200         {
3201                 /*      Operating Class */
3202                 p2pie[ p2pielen++ ] = 0x73;
3203         }
3204         else
3205         {
3206                 /*      Operating Class */
3207                 p2pie[ p2pielen++ ] = 0x7c;
3208         }
3209
3210         /*      Channel Number */
3211         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       /*      operating channel number */
3212
3213         /*      Intended P2P Interface Address */
3214         /*      Type: */
3215         p2pie[ p2pielen++ ] = P2P_ATTR_INTENTED_IF_ADDR;
3216
3217         /*      Length: */
3218         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
3219         p2pielen += 2;
3220
3221         /*      Value: */
3222         memcpy(p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3223         p2pielen += ETH_ALEN;
3224
3225         /*      Channel List */
3226         /*      Type: */
3227         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
3228
3229         /*  Country String(3) */
3230         /*  + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */
3231         /*  + number of channels in all classes */
3232         len_channellist_attr = 3
3233            + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
3234            + get_reg_classes_full_count(pmlmeext->channel_list);
3235
3236 #ifdef CONFIG_CONCURRENT_MODE
3237         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3238         {
3239                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
3240         }
3241         else
3242         {
3243                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3244         }
3245 #else
3246
3247         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3248
3249  #endif
3250         p2pielen += 2;
3251
3252         /*      Value: */
3253         /*      Country String */
3254         p2pie[ p2pielen++ ] = 'X';
3255         p2pie[ p2pielen++ ] = 'X';
3256
3257         /*      The third byte should be set to 0x04. */
3258         /*      Described in the "Operating Channel Attribute" section. */
3259         p2pie[ p2pielen++ ] = 0x04;
3260
3261         /*      Channel Entry List */
3262
3263 #ifdef CONFIG_CONCURRENT_MODE
3264         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3265         {
3266                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
3267                 struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3268
3269                 /*      Operating Class */
3270                 if ( pbuddy_mlmeext->cur_channel > 14 )
3271                 {
3272                         if ( pbuddy_mlmeext->cur_channel >= 149 )
3273                         {
3274                                 p2pie[ p2pielen++ ] = 0x7c;
3275                         }
3276                         else
3277                         {
3278                                 p2pie[ p2pielen++ ] = 0x73;
3279                         }
3280                 }
3281                 else
3282                 {
3283                         p2pie[ p2pielen++ ] = 0x51;
3284                 }
3285
3286                 /*      Number of Channels */
3287                 /*      Just support 1 channel and this channel is AP's channel */
3288                 p2pie[ p2pielen++ ] = 1;
3289
3290                 /*      Channel List */
3291                 p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
3292         }
3293         else
3294         {
3295                 int i, j;
3296                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3297                         /*      Operating Class */
3298                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3299
3300                         /*      Number of Channels */
3301                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3302
3303                         /*      Channel List */
3304                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3305                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3306                         }
3307                 }
3308         }
3309 #else /*  CONFIG_CONCURRENT_MODE */
3310         {
3311                 int i, j;
3312                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3313                         /*      Operating Class */
3314                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3315
3316                         /*      Number of Channels */
3317                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3318
3319                         /*      Channel List */
3320                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3321                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3322                         }
3323                 }
3324         }
3325 #endif /*  CONFIG_CONCURRENT_MODE */
3326
3327         /*      Device Info */
3328         /*      Type: */
3329         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
3330
3331         /*      Length: */
3332         /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
3333         /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
3334         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
3335         p2pielen += 2;
3336
3337         /*      Value: */
3338         /*      P2P Device Address */
3339         memcpy(p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3340         p2pielen += ETH_ALEN;
3341
3342         /*      Config Method */
3343         /*      This field should be big endian. Noted by P2P specification. */
3344
3345         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
3346
3347         p2pielen += 2;
3348
3349         /*      Primary Device Type */
3350         /*      Category ID */
3351         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
3352         p2pielen += 2;
3353
3354         /*      OUI */
3355         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
3356         p2pielen += 4;
3357
3358         /*      Sub Category ID */
3359         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
3360         p2pielen += 2;
3361
3362         /*      Number of Secondary Device Types */
3363         p2pie[ p2pielen++ ] = 0x00;     /*      No Secondary Device Type List */
3364
3365         /*      Device Name */
3366         /*      Type: */
3367         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
3368         p2pielen += 2;
3369
3370         /*      Length: */
3371         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
3372         p2pielen += 2;
3373
3374         /*      Value: */
3375         memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len );
3376         p2pielen += pwdinfo->device_name_len;
3377
3378         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
3379         {
3380                 /*      Group ID Attribute */
3381                 /*      Type: */
3382                 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
3383
3384                 /*      Length: */
3385                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + pwdinfo->nego_ssidlen );
3386                 p2pielen += 2;
3387
3388                 /*      Value: */
3389                 /*      p2P Device Address */
3390                 memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN );
3391                 p2pielen += ETH_ALEN;
3392
3393                 /*      SSID */
3394                 memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
3395                 p2pielen += pwdinfo->nego_ssidlen;
3396
3397         }
3398
3399         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
3400
3401 #ifdef CONFIG_WFD
3402         wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe);
3403         pframe += wfdielen;
3404         pattrib->pktlen += wfdielen;
3405 #endif /* CONFIG_WFD */
3406
3407         pattrib->last_txcmdsz = pattrib->pktlen;
3408
3409         dump_mgntframe(padapter, pmgntframe);
3410
3411         return;
3412 }
3413
3414 void issue_p2p_GO_confirm(_adapter *padapter, u8* raddr, u8 result)
3415 {
3416
3417         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3418         u8                      action = P2P_PUB_ACTION_ACTION;
3419         u32                     p2poui = cpu_to_be32(P2POUI);
3420         u8                      oui_subtype = P2P_GO_NEGO_CONF;
3421         u8                      wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
3422         u8                      wpsielen = 0, p2pielen = 0;
3423
3424         struct xmit_frame                       *pmgntframe;
3425         struct pkt_attrib                       *pattrib;
3426         unsigned char                                   *pframe;
3427         struct rtw_ieee80211_hdr        *pwlanhdr;
3428         unsigned short                          *fctrl;
3429         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3430         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3431         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3432         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
3433 #ifdef CONFIG_WFD
3434         u32                                     wfdielen = 0;
3435 #endif /* CONFIG_WFD */
3436
3437         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
3438         {
3439                 return;
3440         }
3441
3442         DBG_8723A( "[%s] In\n", __FUNCTION__ );
3443         /* update attribute */
3444         pattrib = &pmgntframe->attrib;
3445         update_mgntframe_attrib(padapter, pattrib);
3446
3447         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3448
3449         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3450         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3451
3452         fctrl = &(pwlanhdr->frame_ctl);
3453         *(fctrl) = 0;
3454
3455         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3456         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3457         memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
3458
3459         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3460         pmlmeext->mgnt_seq++;
3461         SetFrameSubType(pframe, WIFI_ACTION);
3462
3463         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3464         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3465
3466         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3467         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3468         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
3469         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
3470         pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
3471
3472         /*      P2P IE Section. */
3473
3474         /*      P2P OUI */
3475         p2pielen = 0;
3476         p2pie[ p2pielen++ ] = 0x50;
3477         p2pie[ p2pielen++ ] = 0x6F;
3478         p2pie[ p2pielen++ ] = 0x9A;
3479         p2pie[ p2pielen++ ] = 0x09;     /*      WFA P2P v1.0 */
3480
3481         /*      Commented by Albert 20110306 */
3482         /*      According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */
3483         /*      1. Status */
3484         /*      2. P2P Capability */
3485         /*      3. Operating Channel */
3486         /*      4. Channel List */
3487         /*      5. Group ID     ( if this WiFi is GO ) */
3488
3489         /*      P2P Status */
3490         /*      Type: */
3491         p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
3492
3493         /*      Length: */
3494         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
3495         p2pielen += 2;
3496
3497         /*      Value: */
3498         p2pie[ p2pielen++ ] = result;
3499
3500         /*      P2P Capability */
3501         /*      Type: */
3502         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
3503
3504         /*      Length: */
3505         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3506         p2pielen += 2;
3507
3508         /*      Value: */
3509         /*      Device Capability Bitmap, 1 byte */
3510         p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
3511
3512         /*      Group Capability Bitmap, 1 byte */
3513         if ( pwdinfo->persistent_supported )
3514         {
3515                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
3516         }
3517         else
3518         {
3519                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
3520         }
3521
3522         /*      Operating Channel */
3523         /*      Type: */
3524         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
3525
3526         /*      Length: */
3527         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
3528         p2pielen += 2;
3529
3530         /*      Value: */
3531         /*      Country String */
3532         p2pie[ p2pielen++ ] = 'X';
3533         p2pie[ p2pielen++ ] = 'X';
3534
3535         /*      The third byte should be set to 0x04. */
3536         /*      Described in the "Operating Channel Attribute" section. */
3537         p2pie[ p2pielen++ ] = 0x04;
3538
3539         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
3540         {
3541                 if ( pwdinfo->peer_operating_ch <= 14 )
3542                 {
3543                         /*      Operating Class */
3544                         p2pie[ p2pielen++ ] = 0x51;
3545                 }
3546                 else if ( ( pwdinfo->peer_operating_ch >= 36 ) && ( pwdinfo->peer_operating_ch <= 48 ) )
3547                 {
3548                         /*      Operating Class */
3549                         p2pie[ p2pielen++ ] = 0x73;
3550                 }
3551                 else
3552                 {
3553                         /*      Operating Class */
3554                         p2pie[ p2pielen++ ] = 0x7c;
3555                 }
3556
3557                 p2pie[ p2pielen++ ] = pwdinfo->peer_operating_ch;
3558         }
3559         else
3560         {
3561                 if ( pwdinfo->operating_channel <= 14 )
3562                 {
3563                         /*      Operating Class */
3564                         p2pie[ p2pielen++ ] = 0x51;
3565                 }
3566                 else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
3567                 {
3568                         /*      Operating Class */
3569                         p2pie[ p2pielen++ ] = 0x73;
3570                 }
3571                 else
3572                 {
3573                         /*      Operating Class */
3574                         p2pie[ p2pielen++ ] = 0x7c;
3575                 }
3576
3577                 /*      Channel Number */
3578                 p2pie[ p2pielen++ ] = pwdinfo->operating_channel;               /*      Use the listen channel as the operating channel */
3579         }
3580
3581         /*      Channel List */
3582         /*      Type: */
3583         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
3584
3585         /*      Length: */
3586         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( pwdinfo->channel_list_attr_len );
3587         p2pielen += 2;
3588
3589         /*      Value: */
3590         memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len );
3591         p2pielen += pwdinfo->channel_list_attr_len;
3592
3593         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
3594         {
3595                 /*      Group ID Attribute */
3596                 /*      Type: */
3597                 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
3598
3599                 /*      Length: */
3600                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + pwdinfo->nego_ssidlen );
3601                 p2pielen += 2;
3602
3603                 /*      Value: */
3604                 /*      p2P Device Address */
3605                 memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN );
3606                 p2pielen += ETH_ALEN;
3607
3608                 /*      SSID */
3609                 memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
3610                 p2pielen += pwdinfo->nego_ssidlen;
3611         }
3612
3613         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
3614
3615 #ifdef CONFIG_WFD
3616         wfdielen = build_nego_confirm_wfd_ie(pwdinfo, pframe);
3617         pframe += wfdielen;
3618         pattrib->pktlen += wfdielen;
3619 #endif /* CONFIG_WFD */
3620
3621         pattrib->last_txcmdsz = pattrib->pktlen;
3622
3623         dump_mgntframe(padapter, pmgntframe);
3624
3625         return;
3626 }
3627
3628 void issue_p2p_invitation_request(_adapter *padapter, u8* raddr )
3629 {
3630
3631         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3632         u8                      action = P2P_PUB_ACTION_ACTION;
3633         u32                     p2poui = cpu_to_be32(P2POUI);
3634         u8                      oui_subtype = P2P_INVIT_REQ;
3635         u8                      p2pie[ 255 ] = { 0x00 };
3636         u8                      p2pielen = 0, i;
3637         u8                      dialogToken = 3;
3638         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
3639         u16                     len_channellist_attr = 0;
3640 #ifdef CONFIG_WFD
3641         u32                                     wfdielen = 0;
3642 #endif /* CONFIG_WFD */
3643 #ifdef CONFIG_CONCURRENT_MODE
3644         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
3645         struct wifidirect_info  *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
3646         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
3647         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3648 #endif
3649
3650         struct xmit_frame                       *pmgntframe;
3651         struct pkt_attrib                       *pattrib;
3652         unsigned char                                   *pframe;
3653         struct rtw_ieee80211_hdr        *pwlanhdr;
3654         unsigned short                          *fctrl;
3655         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3656         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3657         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3658         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
3659
3660         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
3661         {
3662                 return;
3663         }
3664
3665         /* update attribute */
3666         pattrib = &pmgntframe->attrib;
3667         update_mgntframe_attrib(padapter, pattrib);
3668
3669         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3670
3671         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3672         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3673
3674         fctrl = &(pwlanhdr->frame_ctl);
3675         *(fctrl) = 0;
3676
3677         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3678         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3679         memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
3680
3681         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3682         pmlmeext->mgnt_seq++;
3683         SetFrameSubType(pframe, WIFI_ACTION);
3684
3685         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3686         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3687
3688         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3689         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3690         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
3691         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
3692         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
3693
3694         /*      P2P IE Section. */
3695
3696         /*      P2P OUI */
3697         p2pielen = 0;
3698         p2pie[ p2pielen++ ] = 0x50;
3699         p2pie[ p2pielen++ ] = 0x6F;
3700         p2pie[ p2pielen++ ] = 0x9A;
3701         p2pie[ p2pielen++ ] = 0x09;     /*      WFA P2P v1.0 */
3702
3703         /*      Commented by Albert 20101011 */
3704         /*      According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */
3705         /*      1. Configuration Timeout */
3706         /*      2. Invitation Flags */
3707         /*      3. Operating Channel    ( Only GO ) */
3708         /*      4. P2P Group BSSID      ( Should be included if I am the GO ) */
3709         /*      5. Channel List */
3710         /*      6. P2P Group ID */
3711         /*      7. P2P Device Info */
3712
3713         /*      Configuration Timeout */
3714         /*      Type: */
3715         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
3716
3717         /*      Length: */
3718         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3719         p2pielen += 2;
3720
3721         /*      Value: */
3722         p2pie[ p2pielen++ ] = 200;      /*      2 seconds needed to be the P2P GO */
3723         p2pie[ p2pielen++ ] = 200;      /*      2 seconds needed to be the P2P Client */
3724
3725         /*      Invitation Flags */
3726         /*      Type: */
3727         p2pie[ p2pielen++ ] = P2P_ATTR_INVITATION_FLAGS;
3728
3729         /*      Length: */
3730         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
3731         p2pielen += 2;
3732
3733         /*      Value: */
3734         p2pie[ p2pielen++ ] = P2P_INVITATION_FLAGS_PERSISTENT;
3735
3736         /*      Operating Channel */
3737         /*      Type: */
3738         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
3739
3740         /*      Length: */
3741         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
3742         p2pielen += 2;
3743
3744         /*      Value: */
3745         /*      Country String */
3746         p2pie[ p2pielen++ ] = 'X';
3747         p2pie[ p2pielen++ ] = 'X';
3748
3749         /*      The third byte should be set to 0x04. */
3750         /*      Described in the "Operating Channel Attribute" section. */
3751         p2pie[ p2pielen++ ] = 0x04;
3752
3753         /*      Operating Class */
3754         if ( pwdinfo->invitereq_info.operating_ch <= 14 )
3755                 p2pie[ p2pielen++ ] = 0x51;
3756         else if ( ( pwdinfo->invitereq_info.operating_ch >= 36 ) && ( pwdinfo->invitereq_info.operating_ch <= 48 ) )
3757                 p2pie[ p2pielen++ ] = 0x73;
3758         else
3759                 p2pie[ p2pielen++ ] = 0x7c;
3760
3761         /*      Channel Number */
3762         p2pie[ p2pielen++ ] = pwdinfo->invitereq_info.operating_ch;     /*      operating channel number */
3763
3764         if (!memcmp(myid(&padapter->eeprompriv),
3765                     pwdinfo->invitereq_info.go_bssid, ETH_ALEN))
3766         {
3767                 /*      P2P Group BSSID */
3768                 /*      Type: */
3769                 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_BSSID;
3770
3771                 /*      Length: */
3772                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
3773                 p2pielen += 2;
3774
3775                 /*      Value: */
3776                 /*      P2P Device Address for GO */
3777                 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN );
3778                 p2pielen += ETH_ALEN;
3779         }
3780
3781         /*      Channel List */
3782         /*      Type: */
3783         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
3784
3785         /*      Length: */
3786         /*  Country String(3) */
3787         /*  + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */
3788         /*  + number of channels in all classes */
3789         len_channellist_attr = 3
3790            + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
3791            + get_reg_classes_full_count(pmlmeext->channel_list);
3792
3793 #ifdef CONFIG_CONCURRENT_MODE
3794         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3795         {
3796                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
3797         }
3798         else
3799         {
3800                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3801         }
3802 #else
3803
3804         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3805
3806  #endif
3807         p2pielen += 2;
3808
3809         /*      Value: */
3810         /*      Country String */
3811         p2pie[ p2pielen++ ] = 'X';
3812         p2pie[ p2pielen++ ] = 'X';
3813
3814         /*      The third byte should be set to 0x04. */
3815         /*      Described in the "Operating Channel Attribute" section. */
3816         p2pie[ p2pielen++ ] = 0x04;
3817
3818         /*      Channel Entry List */
3819 #ifdef CONFIG_CONCURRENT_MODE
3820         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3821         {
3822                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
3823                 struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3824
3825                 /*      Operating Class */
3826                 if ( pbuddy_mlmeext->cur_channel > 14 )
3827                 {
3828                         if ( pbuddy_mlmeext->cur_channel >= 149 )
3829                         {
3830                                 p2pie[ p2pielen++ ] = 0x7c;
3831                         }
3832                         else
3833                         {
3834                                 p2pie[ p2pielen++ ] = 0x73;
3835                         }
3836                 }
3837                 else
3838                 {
3839                         p2pie[ p2pielen++ ] = 0x51;
3840                 }
3841
3842                 /*      Number of Channels */
3843                 /*      Just support 1 channel and this channel is AP's channel */
3844                 p2pie[ p2pielen++ ] = 1;
3845
3846                 /*      Channel List */
3847                 p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
3848         }
3849         else
3850         {
3851                 int i, j;
3852                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3853                         /*      Operating Class */
3854                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3855
3856                         /*      Number of Channels */
3857                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3858
3859                         /*      Channel List */
3860                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3861                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3862                         }
3863                 }
3864         }
3865 #else /*  CONFIG_CONCURRENT_MODE */
3866         {
3867                 int i, j;
3868                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3869                         /*      Operating Class */
3870                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3871
3872                         /*      Number of Channels */
3873                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3874
3875                         /*      Channel List */
3876                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3877                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3878                         }
3879                 }
3880         }
3881 #endif /*  CONFIG_CONCURRENT_MODE */
3882
3883         /*      P2P Group ID */
3884         /*      Type: */
3885         p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
3886
3887         /*      Length: */
3888         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 6 + pwdinfo->invitereq_info.ssidlen );
3889         p2pielen += 2;
3890
3891         /*      Value: */
3892         /*      P2P Device Address for GO */
3893         memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN );
3894         p2pielen += ETH_ALEN;
3895
3896         /*      SSID */
3897         memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen );
3898         p2pielen += pwdinfo->invitereq_info.ssidlen;
3899
3900         /*      Device Info */
3901         /*      Type: */
3902         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
3903
3904         /*      Length: */
3905         /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
3906         /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
3907         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
3908         p2pielen += 2;
3909
3910         /*      Value: */
3911         /*      P2P Device Address */
3912         memcpy(p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3913         p2pielen += ETH_ALEN;
3914
3915         /*      Config Method */
3916         /*      This field should be big endian. Noted by P2P specification. */
3917         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY );
3918         p2pielen += 2;
3919
3920         /*      Primary Device Type */
3921         /*      Category ID */
3922         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
3923         p2pielen += 2;
3924
3925         /*      OUI */
3926         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
3927         p2pielen += 4;
3928
3929         /*      Sub Category ID */
3930         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
3931         p2pielen += 2;
3932
3933         /*      Number of Secondary Device Types */
3934         p2pie[ p2pielen++ ] = 0x00;     /*      No Secondary Device Type List */
3935
3936         /*      Device Name */
3937         /*      Type: */
3938         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
3939         p2pielen += 2;
3940
3941         /*      Length: */
3942         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
3943         p2pielen += 2;
3944
3945         /*      Value: */
3946         memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
3947         p2pielen += pwdinfo->device_name_len;
3948
3949         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
3950
3951 #ifdef CONFIG_WFD
3952         wfdielen = build_invitation_req_wfd_ie(pwdinfo, pframe);
3953         pframe += wfdielen;
3954         pattrib->pktlen += wfdielen;
3955 #endif /* CONFIG_WFD */
3956
3957         pattrib->last_txcmdsz = pattrib->pktlen;
3958
3959         dump_mgntframe(padapter, pmgntframe);
3960
3961         return;
3962 }
3963
3964 void issue_p2p_invitation_response(_adapter *padapter, u8* raddr, u8 dialogToken, u8 status_code)
3965 {
3966
3967         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3968         u8                      action = P2P_PUB_ACTION_ACTION;
3969         u32                     p2poui = cpu_to_be32(P2POUI);
3970         u8                      oui_subtype = P2P_INVIT_RESP;
3971         u8                      p2pie[ 255 ] = { 0x00 };
3972         u8                      p2pielen = 0, i;
3973         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
3974         u16                     len_channellist_attr = 0;
3975 #ifdef CONFIG_CONCURRENT_MODE
3976         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
3977         struct wifidirect_info  *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
3978         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
3979         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3980 #endif
3981 #ifdef CONFIG_WFD
3982         u32                                     wfdielen = 0;
3983 #endif /* CONFIG_WFD */
3984
3985         struct xmit_frame                       *pmgntframe;
3986         struct pkt_attrib                       *pattrib;
3987         unsigned char                                   *pframe;
3988         struct rtw_ieee80211_hdr        *pwlanhdr;
3989         unsigned short                          *fctrl;
3990         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3991         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3992         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3993         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
3994
3995         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
3996         {
3997                 return;
3998         }
3999
4000         /* update attribute */
4001         pattrib = &pmgntframe->attrib;
4002         update_mgntframe_attrib(padapter, pattrib);
4003
4004         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4005
4006         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4007         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4008
4009         fctrl = &(pwlanhdr->frame_ctl);
4010         *(fctrl) = 0;
4011
4012         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
4013         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4014         memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
4015
4016         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4017         pmlmeext->mgnt_seq++;
4018         SetFrameSubType(pframe, WIFI_ACTION);
4019
4020         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4021         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4022
4023         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4024         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4025         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
4026         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
4027         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
4028
4029         /*      P2P IE Section. */
4030
4031         /*      P2P OUI */
4032         p2pielen = 0;
4033         p2pie[ p2pielen++ ] = 0x50;
4034         p2pie[ p2pielen++ ] = 0x6F;
4035         p2pie[ p2pielen++ ] = 0x9A;
4036         p2pie[ p2pielen++ ] = 0x09;     /*      WFA P2P v1.0 */
4037
4038         /*      Commented by Albert 20101005 */
4039         /*      According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */
4040         /*      1. Status */
4041         /*      2. Configuration Timeout */
4042         /*      3. Operating Channel    ( Only GO ) */
4043         /*      4. P2P Group BSSID      ( Only GO ) */
4044         /*      5. Channel List */
4045
4046         /*      P2P Status */
4047         /*      Type: */
4048         p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
4049
4050         /*      Length: */
4051         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
4052         p2pielen += 2;
4053
4054         /*      Value: */
4055         /*      When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
4056         /*      Sent the event receiving the P2P Invitation Req frame to DMP UI. */
4057         /*      DMP had to compare the MAC address to find out the profile. */
4058         /*      So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
4059         /*      If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */
4060         /*      to NB to rebuild the persistent group. */
4061         p2pie[ p2pielen++ ] = status_code;
4062
4063         /*      Configuration Timeout */
4064         /*      Type: */
4065         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
4066
4067         /*      Length: */
4068         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
4069         p2pielen += 2;
4070
4071         /*      Value: */
4072         p2pie[ p2pielen++ ] = 200;      /*      2 seconds needed to be the P2P GO */
4073         p2pie[ p2pielen++ ] = 200;      /*      2 seconds needed to be the P2P Client */
4074
4075         if( status_code == P2P_STATUS_SUCCESS )
4076         {
4077                 if( rtw_p2p_chk_role( pwdinfo, P2P_ROLE_GO ) )
4078                 {
4079                         /*      The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */
4080                         /*      In this case, the P2P Invitation response frame should carry the two more P2P attributes. */
4081                         /*      First one is operating channel attribute. */
4082                         /*      Second one is P2P Group BSSID attribute. */
4083
4084                         /*      Operating Channel */
4085                         /*      Type: */
4086                         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
4087
4088                         /*      Length: */
4089                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
4090                         p2pielen += 2;
4091
4092                         /*      Value: */
4093                         /*      Country String */
4094                         p2pie[ p2pielen++ ] = 'X';
4095                         p2pie[ p2pielen++ ] = 'X';
4096
4097                         /*      The third byte should be set to 0x04. */
4098                         /*      Described in the "Operating Channel Attribute" section. */
4099                         p2pie[ p2pielen++ ] = 0x04;
4100
4101                         /*      Operating Class */
4102                         p2pie[ p2pielen++ ] = 0x51;     /*      Copy from SD7 */
4103
4104                         /*      Channel Number */
4105                         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       /*      operating channel number */
4106
4107                         /*      P2P Group BSSID */
4108                         /*      Type: */
4109                         p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_BSSID;
4110
4111                         /*      Length: */
4112                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
4113                         p2pielen += 2;
4114
4115                         /*      Value: */
4116                         /*      P2P Device Address for GO */
4117                         memcpy(p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
4118                         p2pielen += ETH_ALEN;
4119
4120                 }
4121
4122                 /*      Channel List */
4123                 /*      Type: */
4124                 p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
4125
4126                 /*      Length: */
4127                 /*  Country String(3) */
4128                 /*  + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */
4129                 /*  + number of channels in all classes */
4130                 len_channellist_attr = 3
4131                         + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
4132                         + get_reg_classes_full_count(pmlmeext->channel_list);
4133
4134 #ifdef CONFIG_CONCURRENT_MODE
4135                 if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4136                 {
4137                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
4138                 }
4139                 else
4140                 {
4141                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
4142                 }
4143 #else
4144
4145                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
4146
4147 #endif
4148                 p2pielen += 2;
4149
4150                 /*      Value: */
4151                 /*      Country String */
4152                 p2pie[ p2pielen++ ] = 'X';
4153                 p2pie[ p2pielen++ ] = 'X';
4154
4155                 /*      The third byte should be set to 0x04. */
4156                 /*      Described in the "Operating Channel Attribute" section. */
4157                 p2pie[ p2pielen++ ] = 0x04;
4158
4159                 /*      Channel Entry List */
4160 #ifdef CONFIG_CONCURRENT_MODE
4161                 if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4162                 {
4163                         _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
4164                         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4165
4166                         /*      Operating Class */
4167                         if ( pbuddy_mlmeext->cur_channel > 14 )
4168                         {
4169                                 if ( pbuddy_mlmeext->cur_channel >= 149 )
4170                                 {
4171                                         p2pie[ p2pielen++ ] = 0x7c;
4172                                 }
4173                                 else
4174                                 {
4175                                         p2pie[ p2pielen++ ] = 0x73;
4176                                 }
4177                         }
4178                         else
4179                         {
4180                                 p2pie[ p2pielen++ ] = 0x51;
4181                         }
4182
4183                         /*      Number of Channels */
4184                         /*      Just support 1 channel and this channel is AP's channel */
4185                         p2pie[ p2pielen++ ] = 1;
4186
4187                         /*      Channel List */
4188                         p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
4189                 }
4190                 else
4191                 {
4192                         int i, j;
4193                         for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
4194                                 /*      Operating Class */
4195                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
4196
4197                                 /*      Number of Channels */
4198                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
4199
4200                                 /*      Channel List */
4201                                 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
4202                                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
4203                                 }
4204                         }
4205                 }
4206 #else /*  CONFIG_CONCURRENT_MODE */
4207                 {
4208                         int i, j;
4209                         for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
4210                                 /*      Operating Class */
4211                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
4212
4213                                 /*      Number of Channels */
4214                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
4215
4216                                 /*      Channel List */
4217                                 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
4218                                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
4219                                 }
4220                         }
4221                 }
4222 #endif /*  CONFIG_CONCURRENT_MODE */
4223         }
4224
4225         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
4226
4227 #ifdef CONFIG_WFD
4228         wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe);
4229         pframe += wfdielen;
4230         pattrib->pktlen += wfdielen;
4231 #endif /* CONFIG_WFD */
4232
4233         pattrib->last_txcmdsz = pattrib->pktlen;
4234
4235         dump_mgntframe(padapter, pmgntframe);
4236
4237         return;
4238 }
4239
4240 void issue_p2p_provision_request(_adapter *padapter, u8* pssid, u8 ussidlen, u8* pdev_raddr )
4241 {
4242         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
4243         u8                      action = P2P_PUB_ACTION_ACTION;
4244         u8                      dialogToken = 1;
4245         u32                     p2poui = cpu_to_be32(P2POUI);
4246         u8                      oui_subtype = P2P_PROVISION_DISC_REQ;
4247         u8                      wpsie[ 100 ] = { 0x00 };
4248         u8                      wpsielen = 0;
4249         u32                     p2pielen = 0;
4250 #ifdef CONFIG_WFD
4251         u32                                     wfdielen = 0;
4252 #endif /* CONFIG_WFD */
4253
4254         struct xmit_frame                       *pmgntframe;
4255         struct pkt_attrib                       *pattrib;
4256         unsigned char                                   *pframe;
4257         struct rtw_ieee80211_hdr        *pwlanhdr;
4258         unsigned short                          *fctrl;
4259         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
4260         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4261         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4262         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4263
4264         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
4265         {
4266                 return;
4267         }
4268
4269         DBG_8723A( "[%s] In\n", __FUNCTION__ );
4270         /* update attribute */
4271         pattrib = &pmgntframe->attrib;
4272         update_mgntframe_attrib(padapter, pattrib);
4273
4274         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4275
4276         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4277         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4278
4279         fctrl = &(pwlanhdr->frame_ctl);
4280         *(fctrl) = 0;
4281
4282         memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
4283         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4284         memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
4285
4286         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4287         pmlmeext->mgnt_seq++;
4288         SetFrameSubType(pframe, WIFI_ACTION);
4289
4290         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4291         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4292
4293         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4294         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4295         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
4296         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
4297         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
4298
4299         p2pielen = build_prov_disc_request_p2p_ie( pwdinfo, pframe, pssid, ussidlen, pdev_raddr );
4300
4301         pframe += p2pielen;
4302         pattrib->pktlen += p2pielen;
4303
4304         wpsielen = 0;
4305         /*      WPS OUI */
4306         *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
4307         wpsielen += 4;
4308
4309         /*      WPS version */
4310         /*      Type: */
4311         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
4312         wpsielen += 2;
4313
4314         /*      Length: */
4315         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
4316         wpsielen += 2;
4317
4318         /*      Value: */
4319         wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
4320
4321         /*      Config Method */
4322         /*      Type: */
4323         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
4324         wpsielen += 2;
4325
4326         /*      Length: */
4327         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
4328         wpsielen += 2;
4329
4330         /*      Value: */
4331         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->tx_prov_disc_info.wps_config_method_request );
4332         wpsielen += 2;
4333
4334         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
4335
4336 #ifdef CONFIG_WFD
4337         wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
4338         pframe += wfdielen;
4339         pattrib->pktlen += wfdielen;
4340 #endif /* CONFIG_WFD */
4341
4342         pattrib->last_txcmdsz = pattrib->pktlen;
4343
4344         dump_mgntframe(padapter, pmgntframe);
4345
4346         return;
4347 }
4348
4349 u8 is_matched_in_profilelist( u8* peermacaddr, struct profile_info* profileinfo )
4350 {
4351         u8 i, match_result = 0;
4352
4353         DBG_8723A( "[%s] peermac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
4354                     peermacaddr[0], peermacaddr[1],peermacaddr[2],peermacaddr[3],peermacaddr[4],peermacaddr[5]);
4355
4356         for( i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++ )
4357         {
4358                DBG_8723A( "[%s] profileinfo_mac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
4359                             profileinfo->peermac[0], profileinfo->peermac[1],profileinfo->peermac[2],profileinfo->peermac[3],profileinfo->peermac[4],profileinfo->peermac[5]);
4360                 if (!memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN))
4361                 {
4362                         match_result = 1;
4363                         DBG_8723A( "[%s] Match!\n", __FUNCTION__ );
4364                         break;
4365                 }
4366         }
4367
4368         return (match_result );
4369 }
4370
4371 void issue_probersp_p2p(_adapter *padapter, unsigned char *da)
4372 {
4373         struct xmit_frame                       *pmgntframe;
4374         struct pkt_attrib                       *pattrib;
4375         unsigned char                                   *pframe;
4376         struct rtw_ieee80211_hdr        *pwlanhdr;
4377         unsigned short                          *fctrl;
4378         unsigned char                                   *mac;
4379         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
4380         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4381         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4382         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4383         /* WLAN_BSSID_EX                        *cur_network = &(pmlmeinfo->network); */
4384         u16                                     beacon_interval = 100;
4385         u16                                     capInfo = 0;
4386         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4387         u8                                      wpsie[255] = { 0x00 };
4388         u32                                     wpsielen = 0, p2pielen = 0;
4389 #ifdef CONFIG_WFD
4390         u32                                     wfdielen = 0;
4391 #endif /* CONFIG_WFD */
4392 #ifdef CONFIG_IOCTL_CFG80211
4393         struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
4394         struct ieee80211_channel *ieee_ch = &pcfg80211_wdinfo->remain_on_ch_channel;
4395         u8 listen_channel = (u8) ieee80211_frequency_to_channel(ieee_ch->center_freq);
4396 #endif /* CONFIG_IOCTL_CFG80211 */
4397 #ifdef CONFIG_INTEL_WIDI
4398         u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 };
4399 #endif /* CONFIG_INTEL_WIDI */
4400
4401         /* DBG_8723A("%s\n", __FUNCTION__); */
4402
4403         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
4404         {
4405                 return;
4406         }
4407
4408         /* update attribute */
4409         pattrib = &pmgntframe->attrib;
4410         update_mgntframe_attrib(padapter, pattrib);
4411
4412         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4413
4414         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4415         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4416
4417         mac = myid(&(padapter->eeprompriv));
4418
4419         fctrl = &(pwlanhdr->frame_ctl);
4420         *(fctrl) = 0;
4421         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
4422         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
4423
4424         /*      Use the device address for BSSID field. */
4425         memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
4426
4427         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4428         pmlmeext->mgnt_seq++;
4429         SetFrameSubType(fctrl, WIFI_PROBERSP);
4430
4431         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4432         pattrib->pktlen = pattrib->hdrlen;
4433         pframe += pattrib->hdrlen;
4434
4435         /* timestamp will be inserted by hardware */
4436         pframe += 8;
4437         pattrib->pktlen += 8;
4438
4439         /*  beacon interval: 2 bytes */
4440         memcpy(pframe, (unsigned char *) &beacon_interval, 2);
4441         pframe += 2;
4442         pattrib->pktlen += 2;
4443
4444         /*      capability info: 2 bytes */
4445         /*      ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */
4446         capInfo |= cap_ShortPremble;
4447         capInfo |= cap_ShortSlot;
4448
4449         memcpy(pframe, (unsigned char *) &capInfo, 2);
4450         pframe += 2;
4451         pattrib->pktlen += 2;
4452
4453         /*  SSID */
4454         pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
4455
4456         /*  supported rates... */
4457         /*      Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 ) */
4458         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
4459
4460         /*  DS parameter set */
4461 #ifdef CONFIG_IOCTL_CFG80211
4462         if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && listen_channel !=0 )
4463         {
4464                 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&listen_channel, &pattrib->pktlen);
4465         }
4466         else
4467 #endif /* CONFIG_IOCTL_CFG80211 */
4468         {
4469                 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
4470         }
4471
4472 #ifdef CONFIG_IOCTL_CFG80211
4473         if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
4474         {
4475                 if( pmlmepriv->wps_probe_resp_ie != NULL && pmlmepriv->p2p_probe_resp_ie != NULL )
4476                 {
4477                         /* WPS IE */
4478                         memcpy(pframe, pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
4479                         pattrib->pktlen += pmlmepriv->wps_probe_resp_ie_len;
4480                         pframe += pmlmepriv->wps_probe_resp_ie_len;
4481
4482                         /* P2P IE */
4483                         memcpy(pframe, pmlmepriv->p2p_probe_resp_ie, pmlmepriv->p2p_probe_resp_ie_len);
4484                         pattrib->pktlen += pmlmepriv->p2p_probe_resp_ie_len;
4485                         pframe += pmlmepriv->p2p_probe_resp_ie_len;
4486                 }
4487         }
4488         else
4489 #endif /* CONFIG_IOCTL_CFG80211 */
4490         {
4491
4492                 /*      Todo: WPS IE */
4493                 /*      Noted by Albert 20100907 */
4494                 /*      According to the WPS specification, all the WPS attribute is presented by Big Endian. */
4495
4496                 wpsielen = 0;
4497                 /*      WPS OUI */
4498                 *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
4499                 wpsielen += 4;
4500
4501                 /*      WPS version */
4502                 /*      Type: */
4503                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
4504                 wpsielen += 2;
4505
4506                 /*      Length: */
4507                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
4508                 wpsielen += 2;
4509
4510                 /*      Value: */
4511                 wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
4512
4513 #ifdef CONFIG_INTEL_WIDI
4514                 /*      Commented by Kurt */
4515                 /*      Appended WiDi info. only if we did issued_probereq_widi(), and then we saved ven. ext. in pmlmepriv->sa_ext. */
4516                 if (memcmp(pmlmepriv->sa_ext, zero_array_check,
4517                            L2SDTA_SERVICE_VE_LEN))
4518                 {
4519                         /* Sec dev type */
4520                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SEC_DEV_TYPE_LIST );
4521                         wpsielen += 2;
4522
4523                         /*      Length: */
4524                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
4525                         wpsielen += 2;
4526
4527                         /*      Value: */
4528                         /*      Category ID */
4529                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_DISPLAYS );
4530                         wpsielen += 2;
4531
4532                         /*      OUI */
4533                         *(u32*) ( wpsie + wpsielen ) = cpu_to_be32( INTEL_DEV_TYPE_OUI );
4534                         wpsielen += 4;
4535
4536                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_WIDI_CONSUMER_SINK );
4537                         wpsielen += 2;
4538
4539                         /*      Vendor Extension */
4540                         memcpy(wpsie + wpsielen, pmlmepriv->sa_ext, L2SDTA_SERVICE_VE_LEN );
4541                         wpsielen += L2SDTA_SERVICE_VE_LEN;
4542                 }
4543 #endif /* CONFIG_INTEL_WIDI */
4544
4545                 /*      WiFi Simple Config State */
4546                 /*      Type: */
4547                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SIMPLE_CONF_STATE );
4548                 wpsielen += 2;
4549
4550                 /*      Length: */
4551                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
4552                 wpsielen += 2;
4553
4554                 /*      Value: */
4555                 wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;   /*      Not Configured. */
4556
4557                 /*      Response Type */
4558                 /*      Type: */
4559                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_RESP_TYPE );
4560                 wpsielen += 2;
4561
4562                 /*      Length: */
4563                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
4564                 wpsielen += 2;
4565
4566                 /*      Value: */
4567                 wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
4568
4569                 /*      UUID-E */
4570                 /*      Type: */
4571                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_UUID_E );
4572                 wpsielen += 2;
4573
4574                 /*      Length: */
4575                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0010 );
4576                 wpsielen += 2;
4577
4578                 /*      Value: */
4579                 memcpy(wpsie + wpsielen, myid( &padapter->eeprompriv ), ETH_ALEN );
4580                 wpsielen += 0x10;
4581
4582                 /*      Manufacturer */
4583                 /*      Type: */
4584                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MANUFACTURER );
4585                 wpsielen += 2;
4586
4587                 /*      Length: */
4588                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0007 );
4589                 wpsielen += 2;
4590
4591                 /*      Value: */
4592                 memcpy(wpsie + wpsielen, "Realtek", 7 );
4593                 wpsielen += 7;
4594
4595                 /*      Model Name */
4596                 /*      Type: */
4597                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MODEL_NAME );
4598                 wpsielen += 2;
4599
4600                 /*      Length: */
4601                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0006 );
4602                 wpsielen += 2;
4603
4604                 /*      Value: */
4605                 memcpy(wpsie + wpsielen, "8192CU", 6 );
4606                 wpsielen += 6;
4607
4608                 /*      Model Number */
4609                 /*      Type: */
4610                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MODEL_NUMBER );
4611                 wpsielen += 2;
4612
4613                 /*      Length: */
4614                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
4615                 wpsielen += 2;
4616
4617                 /*      Value: */
4618                 wpsie[ wpsielen++ ] = 0x31;             /*      character 1 */
4619
4620                 /*      Serial Number */
4621                 /*      Type: */
4622                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SERIAL_NUMBER );
4623                 wpsielen += 2;
4624
4625                 /*      Length: */
4626                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( ETH_ALEN );
4627                 wpsielen += 2;
4628
4629                 /*      Value: */
4630                 memcpy(wpsie + wpsielen, "123456" , ETH_ALEN );
4631                 wpsielen += ETH_ALEN;
4632
4633                 /*      Primary Device Type */
4634                 /*      Type: */
4635                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
4636                 wpsielen += 2;
4637
4638                 /*      Length: */
4639                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
4640                 wpsielen += 2;
4641
4642                 /*      Value: */
4643                 /*      Category ID */
4644                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
4645                 wpsielen += 2;
4646
4647                 /*      OUI */
4648                 *(u32*) ( wpsie + wpsielen ) = cpu_to_be32( WPSOUI );
4649                 wpsielen += 4;
4650
4651                 /*      Sub Category ID */
4652                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
4653                 wpsielen += 2;
4654
4655                 /*      Device Name */
4656                 /*      Type: */
4657                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
4658                 wpsielen += 2;
4659
4660                 /*      Length: */
4661                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->device_name_len );
4662                 wpsielen += 2;
4663
4664                 /*      Value: */
4665                 if (pwdinfo->device_name_len)
4666                 {
4667                         memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len );
4668                         wpsielen += pwdinfo->device_name_len;
4669                 }
4670
4671                 /*      Config Method */
4672                 /*      Type: */
4673                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
4674                 wpsielen += 2;
4675
4676                 /*      Length: */
4677                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
4678                 wpsielen += 2;
4679
4680                 /*      Value: */
4681                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
4682                 wpsielen += 2;
4683
4684                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
4685
4686                 p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
4687                 pframe += p2pielen;
4688                 pattrib->pktlen += p2pielen;
4689         }
4690
4691 #ifdef CONFIG_WFD
4692 #ifdef CONFIG_IOCTL_CFG80211
4693         if ( _TRUE == pwdinfo->wfd_info->wfd_enable )
4694 #endif /* CONFIG_IOCTL_CFG80211 */
4695         {
4696                 wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
4697                 pframe += wfdielen;
4698                 pattrib->pktlen += wfdielen;
4699         }
4700 #ifdef CONFIG_IOCTL_CFG80211
4701         else if (pmlmepriv->wfd_probe_resp_ie != NULL && pmlmepriv->wfd_probe_resp_ie_len>0)
4702         {
4703                 /* WFD IE */
4704                 memcpy(pframe, pmlmepriv->wfd_probe_resp_ie, pmlmepriv->wfd_probe_resp_ie_len);
4705                 pattrib->pktlen += pmlmepriv->wfd_probe_resp_ie_len;
4706                 pframe += pmlmepriv->wfd_probe_resp_ie_len;
4707         }
4708 #endif /* CONFIG_IOCTL_CFG80211 */
4709 #endif /* CONFIG_WFD */
4710
4711         pattrib->last_txcmdsz = pattrib->pktlen;
4712
4713         dump_mgntframe(padapter, pmgntframe);
4714
4715         return;
4716 }
4717
4718 int _issue_probereq_p2p(_adapter *padapter, u8 *da, int wait_ack)
4719 {
4720         int ret = _FAIL;
4721         struct xmit_frame               *pmgntframe;
4722         struct pkt_attrib               *pattrib;
4723         unsigned char                   *pframe;
4724         struct rtw_ieee80211_hdr        *pwlanhdr;
4725         unsigned short          *fctrl;
4726         unsigned char                   *mac;
4727         unsigned char                   bssrate[NumRates];
4728         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
4729         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4730         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4731         int     bssrate_len = 0;
4732         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4733         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4734         u8                                      wpsie[255] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
4735         u16                                     wpsielen = 0, p2pielen = 0;
4736 #ifdef CONFIG_WFD
4737         u32                                     wfdielen = 0;
4738 #endif /* CONFIG_WFD */
4739
4740         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4741
4742         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
4743         {
4744                 goto exit;
4745         }
4746
4747         /* update attribute */
4748         pattrib = &pmgntframe->attrib;
4749         update_mgntframe_attrib(padapter, pattrib);
4750
4751         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4752
4753         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4754         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4755
4756         mac = myid(&(padapter->eeprompriv));
4757
4758         fctrl = &(pwlanhdr->frame_ctl);
4759         *(fctrl) = 0;
4760
4761         if (da) {
4762                 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
4763                 memcpy(pwlanhdr->addr3, da, ETH_ALEN);
4764         } else {
4765                 if ( ( pwdinfo->p2p_info.scan_op_ch_only ) || ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) )
4766                 {
4767                         /*      This two flags will be set when this is only the P2P client mode. */
4768                         memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
4769                         memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
4770                 }
4771                 else
4772                 {
4773                         /*      broadcast probe request frame */
4774                         memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
4775                         memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
4776                 }
4777         }
4778         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
4779
4780         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4781         pmlmeext->mgnt_seq++;
4782         SetFrameSubType(pframe, WIFI_PROBEREQ);
4783
4784         pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
4785         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
4786
4787         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
4788         {
4789                 pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &(pattrib->pktlen));
4790         }
4791         else
4792         {
4793                 pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &(pattrib->pktlen));
4794         }
4795         /*      Use the OFDM rate in the P2P probe request frame. ( 6(B), 9(B), 12(B), 24(B), 36, 48, 54 ) */
4796         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
4797
4798 #ifdef CONFIG_IOCTL_CFG80211
4799         if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
4800         {
4801                 if( pmlmepriv->wps_probe_req_ie != NULL && pmlmepriv->p2p_probe_req_ie != NULL )
4802                 {
4803                         /* WPS IE */
4804                         memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
4805                         pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
4806                         pframe += pmlmepriv->wps_probe_req_ie_len;
4807
4808                         /* P2P IE */
4809                         memcpy(pframe, pmlmepriv->p2p_probe_req_ie, pmlmepriv->p2p_probe_req_ie_len);
4810                         pattrib->pktlen += pmlmepriv->p2p_probe_req_ie_len;
4811                         pframe += pmlmepriv->p2p_probe_req_ie_len;
4812                 }
4813         }
4814         else
4815 #endif /* CONFIG_IOCTL_CFG80211 */
4816         {
4817
4818                 /*      WPS IE */
4819                 /*      Noted by Albert 20110221 */
4820                 /*      According to the WPS specification, all the WPS attribute is presented by Big Endian. */
4821
4822                 wpsielen = 0;
4823                 /*      WPS OUI */
4824                 *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
4825                 wpsielen += 4;
4826
4827                 /*      WPS version */
4828                 /*      Type: */
4829                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
4830                 wpsielen += 2;
4831
4832                 /*      Length: */
4833                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
4834                 wpsielen += 2;
4835
4836                 /*      Value: */
4837                 wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
4838
4839                 if( pmlmepriv->wps_probe_req_ie == NULL )
4840                 {
4841                         /*      UUID-E */
4842                         /*      Type: */
4843                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_UUID_E );
4844                         wpsielen += 2;
4845
4846                         /*      Length: */
4847                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0010 );
4848                         wpsielen += 2;
4849
4850                         /*      Value: */
4851                         memcpy(wpsie + wpsielen, myid( &padapter->eeprompriv ), ETH_ALEN );
4852                         wpsielen += 0x10;
4853
4854                         /*      Config Method */
4855                         /*      Type: */
4856                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
4857                         wpsielen += 2;
4858
4859                         /*      Length: */
4860                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
4861                         wpsielen += 2;
4862
4863                         /*      Value: */
4864                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
4865                         wpsielen += 2;
4866                 }
4867
4868                 /*      Device Name */
4869                 /*      Type: */
4870                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
4871                 wpsielen += 2;
4872
4873                 /*      Length: */
4874                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->device_name_len );
4875                 wpsielen += 2;
4876
4877                 /*      Value: */
4878                 memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len );
4879                 wpsielen += pwdinfo->device_name_len;
4880
4881                 /*      Primary Device Type */
4882                 /*      Type: */
4883                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
4884                 wpsielen += 2;
4885
4886                 /*      Length: */
4887                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
4888                 wpsielen += 2;
4889
4890                 /*      Value: */
4891                 /*      Category ID */
4892                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_RTK_WIDI );
4893                 wpsielen += 2;
4894
4895                 /*      OUI */
4896                 *(u32*) ( wpsie + wpsielen ) = cpu_to_be32( WPSOUI );
4897                 wpsielen += 4;
4898
4899                 /*      Sub Category ID */
4900                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_RTK_DMP );
4901                 wpsielen += 2;
4902
4903                 /*      Device Password ID */
4904                 /*      Type: */
4905                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
4906                 wpsielen += 2;
4907
4908                 /*      Length: */
4909                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
4910                 wpsielen += 2;
4911
4912                 /*      Value: */
4913                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );  /*      Registrar-specified */
4914                 wpsielen += 2;
4915
4916                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
4917
4918                 /*      P2P OUI */
4919                 p2pielen = 0;
4920                 p2pie[ p2pielen++ ] = 0x50;
4921                 p2pie[ p2pielen++ ] = 0x6F;
4922                 p2pie[ p2pielen++ ] = 0x9A;
4923                 p2pie[ p2pielen++ ] = 0x09;     /*      WFA P2P v1.0 */
4924
4925                 /*      Commented by Albert 20110221 */
4926                 /*      According to the P2P Specification, the probe request frame should contain 5 P2P attributes */
4927                 /*      1. P2P Capability */
4928                 /*      2. P2P Device ID if this probe request wants to find the specific P2P device */
4929                 /*      3. Listen Channel */
4930                 /*      4. Extended Listen Timing */
4931                 /*      5. Operating Channel if this WiFi is working as the group owner now */
4932
4933                 /*      P2P Capability */
4934                 /*      Type: */
4935                 p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
4936
4937                 /*      Length: */
4938                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
4939                 p2pielen += 2;
4940
4941                 /*      Value: */
4942                 /*      Device Capability Bitmap, 1 byte */
4943                 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
4944
4945                 /*      Group Capability Bitmap, 1 byte */
4946                 if ( pwdinfo->persistent_supported )
4947                         p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
4948                 else
4949                         p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
4950
4951                 /*      Listen Channel */
4952                 /*      Type: */
4953                 p2pie[ p2pielen++ ] = P2P_ATTR_LISTEN_CH;
4954
4955                 /*      Length: */
4956                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
4957                 p2pielen += 2;
4958
4959                 /*      Value: */
4960                 /*      Country String */
4961                 p2pie[ p2pielen++ ] = 'X';
4962                 p2pie[ p2pielen++ ] = 'X';
4963
4964                 /*      The third byte should be set to 0x04. */
4965                 /*      Described in the "Operating Channel Attribute" section. */
4966                 p2pie[ p2pielen++ ] = 0x04;
4967
4968                 /*      Operating Class */
4969                 p2pie[ p2pielen++ ] = 0x51;     /*      Copy from SD7 */
4970
4971                 /*      Channel Number */
4972                 p2pie[ p2pielen++ ] = pwdinfo->listen_channel;  /*      listen channel */
4973
4974                 /*      Extended Listen Timing */
4975                 /*      Type: */
4976                 p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
4977
4978                 /*      Length: */
4979                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
4980                 p2pielen += 2;
4981
4982                 /*      Value: */
4983                 /*      Availability Period */
4984                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
4985                 p2pielen += 2;
4986
4987                 /*      Availability Interval */
4988                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
4989                 p2pielen += 2;
4990
4991                 if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
4992                 {
4993                         /*      Operating Channel (if this WiFi is working as the group owner now) */
4994                         /*      Type: */
4995                         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
4996
4997                         /*      Length: */
4998                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
4999                         p2pielen += 2;
5000
5001                         /*      Value: */
5002                         /*      Country String */
5003                         p2pie[ p2pielen++ ] = 'X';
5004                         p2pie[ p2pielen++ ] = 'X';
5005
5006                         /*      The third byte should be set to 0x04. */
5007                         /*      Described in the "Operating Channel Attribute" section. */
5008                         p2pie[ p2pielen++ ] = 0x04;
5009
5010                         /*      Operating Class */
5011                         p2pie[ p2pielen++ ] = 0x51;     /*      Copy from SD7 */
5012
5013                         /*      Channel Number */
5014                         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       /*      operating channel number */
5015
5016                 }
5017
5018                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
5019
5020                 if( pmlmepriv->wps_probe_req_ie != NULL )
5021                 {
5022                         /* WPS IE */
5023                         memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
5024                         pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
5025                         pframe += pmlmepriv->wps_probe_req_ie_len;
5026                 }
5027         }
5028
5029 #ifdef CONFIG_WFD
5030 #ifdef CONFIG_IOCTL_CFG80211
5031         if ( _TRUE == pwdinfo->wfd_info->wfd_enable )
5032 #endif
5033         {
5034                 wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
5035                 pframe += wfdielen;
5036                 pattrib->pktlen += wfdielen;
5037         }
5038 #ifdef CONFIG_IOCTL_CFG80211
5039         else if (pmlmepriv->wfd_probe_req_ie != NULL && pmlmepriv->wfd_probe_req_ie_len>0)
5040         {
5041                 /* WFD IE */
5042                 memcpy(pframe, pmlmepriv->wfd_probe_req_ie, pmlmepriv->wfd_probe_req_ie_len);
5043                 pattrib->pktlen += pmlmepriv->wfd_probe_req_ie_len;
5044                 pframe += pmlmepriv->wfd_probe_req_ie_len;
5045         }
5046 #endif /* CONFIG_IOCTL_CFG80211 */
5047 #endif /* CONFIG_WFD */
5048
5049         pattrib->last_txcmdsz = pattrib->pktlen;
5050
5051         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
5052
5053         if (wait_ack) {
5054                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5055         } else {
5056                 dump_mgntframe(padapter, pmgntframe);
5057                 ret = _SUCCESS;
5058         }
5059
5060 exit:
5061         return ret;
5062 }
5063
5064 inline void issue_probereq_p2p(_adapter *adapter, u8 *da)
5065 {
5066         _issue_probereq_p2p(adapter, da, _FALSE);
5067 }
5068
5069 int issue_probereq_p2p_ex(_adapter *adapter, u8 *da, int try_cnt, int wait_ms)
5070 {
5071         int ret;
5072         int i = 0;
5073         u32 start = rtw_get_current_time();
5074
5075         do
5076         {
5077                 ret = _issue_probereq_p2p(adapter, da, wait_ms>0?_TRUE:_FALSE);
5078
5079                 i++;
5080
5081                 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
5082                         break;
5083
5084                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
5085                         rtw_msleep_os(wait_ms);
5086
5087         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
5088
5089         if (ret != _FAIL) {
5090                 ret = _SUCCESS;
5091                 #ifndef DBG_XMIT_ACK
5092                 goto exit;
5093                 #endif
5094         }
5095
5096         if (try_cnt && wait_ms) {
5097                 if (da)
5098                         DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
5099                                 FUNC_ADPT_ARG(adapter), MAC_ARG(da), rtw_get_oper_ch(adapter),
5100                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
5101                 else
5102                         DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5103                                 FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter),
5104                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
5105         }
5106 exit:
5107         return ret;
5108 }
5109
5110 #endif /* CONFIG_P2P */
5111
5112 s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
5113 {
5114         _adapter *adapter = recv_frame->u.hdr.adapter;
5115         struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
5116         u8 *frame = recv_frame->u.hdr.rx_data;
5117         u16 seq_ctrl = ( (recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
5118                 (recv_frame->u.hdr.attrib.frag_num & 0xf);
5119
5120         if (GetRetry(frame)) {
5121                 if (token >= 0) {
5122                         if ((seq_ctrl == mlmeext->action_public_rxseq)
5123                                 && (token == mlmeext->action_public_dialog_token))
5124                         {
5125                                 DBG_8723A(FUNC_ADPT_FMT" seq_ctrl=0x%x, rxseq=0x%x, token:%d\n",
5126                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
5127                                 return _FAIL;
5128                         }
5129                 } else {
5130                         if (seq_ctrl == mlmeext->action_public_rxseq) {
5131                                 DBG_8723A(FUNC_ADPT_FMT" seq_ctrl=0x%x, rxseq=0x%x\n",
5132                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
5133                                 return _FAIL;
5134                         }
5135                 }
5136         }
5137
5138         mlmeext->action_public_rxseq = seq_ctrl;
5139
5140         if (token >= 0)
5141                 mlmeext->action_public_dialog_token = token;
5142
5143         return _SUCCESS;
5144 }
5145
5146 unsigned int on_action_public_p2p(union recv_frame *precv_frame)
5147 {
5148         _adapter *padapter = precv_frame->u.hdr.adapter;
5149         u8 *pframe = precv_frame->u.hdr.rx_data;
5150         uint len = precv_frame->u.hdr.len;
5151         u8 *frame_body;
5152         u8 dialogToken=0;
5153 #ifdef CONFIG_P2P
5154         u8 *p2p_ie;
5155         u32     p2p_ielen, wps_ielen;
5156         struct  wifidirect_info *pwdinfo = &( padapter->wdinfo );
5157         u8      result = P2P_STATUS_SUCCESS;
5158         u8      empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
5159 #endif /* CONFIG_P2P */
5160
5161         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
5162
5163         dialogToken = frame_body[7];
5164
5165         if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
5166                 return _FAIL;
5167
5168 #ifdef CONFIG_P2P
5169         _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
5170 #ifdef CONFIG_IOCTL_CFG80211
5171         if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
5172         {
5173                 rtw_cfg80211_rx_p2p_action_public(padapter, pframe, len);
5174         }
5175         else
5176 #endif /* CONFIG_IOCTL_CFG80211 */
5177         {
5178                 /*      Do nothing if the driver doesn't enable the P2P function. */
5179                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
5180                         return _SUCCESS;
5181
5182                 len -= sizeof(struct rtw_ieee80211_hdr_3addr);
5183
5184                 switch( frame_body[ 6 ] )/* OUI Subtype */
5185                 {
5186                         case P2P_GO_NEGO_REQ:
5187                         {
5188                                 DBG_8723A( "[%s] Got GO Nego Req Frame\n", __FUNCTION__);
5189                                 memset( &pwdinfo->groupid_info, 0x00, sizeof( struct group_id_info ) );
5190
5191                                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
5192                                 {
5193                                         rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
5194                                 }
5195
5196                                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
5197                                 {
5198                                         /*      Commented by Albert 20110526 */
5199                                         /*      In this case, this means the previous nego fail doesn't be reset yet. */
5200                                         _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5201                                         /*      Restore the previous p2p state */
5202                                         rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
5203                                         DBG_8723A( "[%s] Restore the previous p2p state to %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo) );
5204                                 }
5205 #ifdef CONFIG_CONCURRENT_MODE
5206                                 if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
5207                                 {
5208                                         _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
5209                                 }
5210 #endif /*  CONFIG_CONCURRENT_MODE */
5211
5212                                 /*      Commented by Kurt 20110902 */
5213                                 /* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
5214                                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
5215                                         rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
5216
5217                                 /*      Commented by Kurt 20120113 */
5218                                 /*      Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
5219                                 if (!memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN))
5220                                         memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
5221
5222                                 result = process_p2p_group_negotation_req( pwdinfo, frame_body, len );
5223                                 issue_p2p_GO_response( padapter, GetAddr2Ptr(pframe), frame_body, len, result );
5224 #ifdef CONFIG_INTEL_WIDI
5225                                 if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) )
5226                                 {
5227                                         padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
5228                                         intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL);
5229                                 }
5230 #endif /* CONFIG_INTEL_WIDI */
5231
5232                                 /*      Commented by Albert 20110718 */
5233                                 /*      No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
5234 #ifdef CONFIG_CONCURRENT_MODE
5235                                 /*      Commented by Albert 20120107 */
5236                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
5237 #else /*  CONFIG_CONCURRENT_MODE */
5238                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
5239 #endif /*  CONFIG_CONCURRENT_MODE */
5240                                 break;
5241                         }
5242                         case P2P_GO_NEGO_RESP:
5243                         {
5244                                 DBG_8723A( "[%s] Got GO Nego Resp Frame\n", __FUNCTION__);
5245
5246                                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
5247                                 {
5248                                         /*      Commented by Albert 20110425 */
5249                                         /*      The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
5250                                         _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5251                                         pwdinfo->nego_req_info.benable = _FALSE;
5252                                         result = process_p2p_group_negotation_resp( pwdinfo, frame_body, len);
5253                                         issue_p2p_GO_confirm( pwdinfo->padapter, GetAddr2Ptr(pframe), result);
5254                                         if ( P2P_STATUS_SUCCESS == result )
5255                                         {
5256                                                 if ( rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT )
5257                                                 {
5258                                                         pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
5259                                                         pwdinfo->p2p_info.scan_op_ch_only = 1;
5260                                                         _set_timer( &pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH );
5261                                                 }
5262                                         }
5263
5264                                         /*      Reset the dialog token for group negotiation frames. */
5265                                         pwdinfo->negotiation_dialog_token = 1;
5266
5267                                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
5268                                         {
5269                                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
5270                                         }
5271                                 }
5272                                 else
5273                                 {
5274                                         DBG_8723A( "[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __FUNCTION__);
5275                                 }
5276
5277                                 break;
5278                         }
5279                         case P2P_GO_NEGO_CONF:
5280                         {
5281                                 DBG_8723A( "[%s] Got GO Nego Confirm Frame\n", __FUNCTION__);
5282                                 result = process_p2p_group_negotation_confirm( pwdinfo, frame_body, len);
5283                                 if ( P2P_STATUS_SUCCESS == result )
5284                                 {
5285                                         if ( rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT )
5286                                         {
5287                                                 pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
5288                                                 pwdinfo->p2p_info.scan_op_ch_only = 1;
5289                                                 _set_timer( &pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH );
5290                                         }
5291                                 }
5292                                 break;
5293                         }
5294                         case P2P_INVIT_REQ:
5295                         {
5296                                 /*      Added by Albert 2010/10/05 */
5297                                 /*      Received the P2P Invite Request frame. */
5298
5299                                 DBG_8723A( "[%s] Got invite request frame!\n", __FUNCTION__ );
5300                                 if ( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)) )
5301                                 {
5302                                         /*      Parse the necessary information from the P2P Invitation Request frame. */
5303                                         /*      For example: The MAC address of sending this P2P Invitation Request frame. */
5304                                         u32     attr_contentlen = 0;
5305                                         u8      status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
5306                                         struct group_id_info group_id;
5307                                         u8      invitation_flag = 0;
5308
5309                                         rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
5310                                         if ( attr_contentlen )
5311                                         {
5312
5313                                                 rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
5314                                                 /*      Commented by Albert 20120510 */
5315                                                 /*      Copy to the pwdinfo->p2p_peer_interface_addr. */
5316                                                 /*      So that the WFD UI ( or Sigma ) can get the peer interface address by using the following command. */
5317                                                 /*      #> iwpriv wlan0 p2p_get peer_ifa */
5318                                                 /*      After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
5319
5320                                                 if ( attr_contentlen )
5321                                                 {
5322                                                         DBG_8723A( "[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
5323                                                                         pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
5324                                                                         pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
5325                                                                         pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5] );
5326                                                 }
5327
5328                                                 if ( invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT )
5329                                                 {
5330                                                         /*      Re-invoke the persistent group. */
5331
5332                                                         memset( &group_id, 0x00, sizeof( struct group_id_info ) );
5333                                                         rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen);
5334                                                         if ( attr_contentlen )
5335                                                         {
5336                                                                 if (!memcmp(group_id.go_device_addr, myid( &padapter->eeprompriv), ETH_ALEN))
5337                                                                 {
5338                                                                         /*      The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
5339                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO );
5340                                                                         rtw_p2p_set_role( pwdinfo, P2P_ROLE_GO );
5341                                                                         status_code = P2P_STATUS_SUCCESS;
5342                                                                 }
5343                                                                 else
5344                                                                 {
5345                                                                         /*      The p2p device sending this p2p invitation request wants to be the persistent GO. */
5346                                                                         if ( is_matched_in_profilelist( pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[ 0 ] ) )
5347                                                                         {
5348                                                                                 u8 operatingch_info[5] = { 0x00 };
5349                                                                                 if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) )
5350                                                                                 {
5351                                                                                         if( rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4] ) )
5352                                                                                         {
5353                                                                                                 /*      The operating channel is acceptable for this device. */
5354                                                                                                 pwdinfo->rx_invitereq_info.operation_ch[0]= operatingch_info[4];
5355                                                                                                 pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
5356                                                                                                 _set_timer( &pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH );
5357                                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH );
5358                                                                                                 rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
5359                                                                                                 status_code = P2P_STATUS_SUCCESS;
5360                                                                                                 }
5361                                                                                         else
5362                                                                                         {
5363                                                                                                 /*      The operating channel isn't supported by this device. */
5364                                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
5365                                                                                                 rtw_p2p_set_role( pwdinfo, P2P_ROLE_DEVICE );
5366                                                                                                 status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
5367                                                                                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
5368                                                                                         }
5369                                                                                 }
5370                                                                                 else
5371                                                                                 {
5372                                                                                         /*      Commented by Albert 20121130 */
5373                                                                                         /*      Intel will use the different P2P IE to store the operating channel information */
5374                                                                                         /*      Workaround for Intel WiDi 3.5 */
5375                                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH );
5376                                                                                         rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
5377                                                                                         status_code = P2P_STATUS_SUCCESS;
5378                                                                                 }
5379                                                                         }
5380                                                                         else
5381                                                                         {
5382                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
5383                                                                                 #ifdef CONFIG_INTEL_WIDI
5384                                                                                 memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN );
5385                                                                                 rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
5386                                                                                 #endif /* CONFIG_INTEL_WIDI */
5387
5388                                                                                 status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
5389                                                                         }
5390                                                                 }
5391                                                         }
5392                                                         else
5393                                                         {
5394                                                                 DBG_8723A( "[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__ );
5395                                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
5396                                                         }
5397                                                 }
5398                                                 else
5399                                                 {
5400                                                         /*      Received the invitation to join a P2P group. */
5401
5402                                                         memset( &group_id, 0x00, sizeof( struct group_id_info ) );
5403                                                         rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen);
5404                                                         if ( attr_contentlen )
5405                                                         {
5406                                                                 if (!memcmp(group_id.go_device_addr, myid( &padapter->eeprompriv), ETH_ALEN))
5407                                                                 {
5408                                                                         /*      In this case, the GO can't be myself. */
5409                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
5410                                                                         status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
5411                                                                 }
5412                                                                 else
5413                                                                 {
5414                                                                         /*      The p2p device sending this p2p invitation request wants to join an existing P2P group */
5415                                                                         /*      Commented by Albert 2012/06/28 */
5416                                                                         /*      In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
5417                                                                         /*      The peer device address should be the destination address for the provisioning discovery request. */
5418                                                                         /*      Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
5419                                                                         /*      The peer interface address should be the address for WPS mac address */
5420                                                                         memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN );
5421                                                                         rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
5422                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN );
5423                                                                         status_code = P2P_STATUS_SUCCESS;
5424                                                                 }
5425                                                         }
5426                                                         else
5427                                                         {
5428                                                                 DBG_8723A( "[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__ );
5429                                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
5430                                                         }
5431                                                 }
5432                                         }
5433                                         else
5434                                         {
5435                                                 DBG_8723A( "[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __FUNCTION__ );
5436                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
5437                                         }
5438
5439                                         DBG_8723A( "[%s] status_code = %d\n", __FUNCTION__, status_code );
5440
5441                                         pwdinfo->inviteresp_info.token = frame_body[ 7 ];
5442                                         issue_p2p_invitation_response( padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code );
5443                                 }
5444 #ifdef CONFIG_INTEL_WIDI
5445                                 if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) )
5446                                 {
5447                                         padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
5448                                         intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL);
5449                                 }
5450 #endif /* CONFIG_INTEL_WIDI */
5451                                 break;
5452                         }
5453                         case P2P_INVIT_RESP:
5454                         {
5455                                 u8      attr_content = 0x00;
5456                                 u32     attr_contentlen = 0;
5457
5458                                 DBG_8723A( "[%s] Got invite response frame!\n", __FUNCTION__ );
5459                                 _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5460                                 if ( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)) )
5461                                 {
5462                                         rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
5463
5464                                         if ( attr_contentlen == 1 )
5465                                         {
5466                                                 DBG_8723A( "[%s] Status = %d\n", __FUNCTION__, attr_content );
5467                                                 pwdinfo->invitereq_info.benable = _FALSE;
5468
5469                                                 if ( attr_content == P2P_STATUS_SUCCESS )
5470                                                 {
5471                                                         if (!memcmp(pwdinfo->invitereq_info.go_bssid, myid( &padapter->eeprompriv), ETH_ALEN))
5472                                                         {
5473                                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO );
5474                                                         }
5475                                                         else
5476                                                         {
5477                                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
5478                                                         }
5479                                                         rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_OK );
5480                                                 }
5481                                                 else
5482                                                 {
5483                                                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
5484                                                         rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
5485                                                 }
5486                                         }
5487                                         else
5488                                         {
5489                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
5490                                                 rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
5491                                         }
5492                                 }
5493                                 else
5494                                 {
5495                                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
5496                                         rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
5497                                 }
5498
5499                                 if ( rtw_p2p_chk_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL ) )
5500                                 {
5501                                         _set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
5502                                 }
5503                                 break;
5504                         }
5505                         case P2P_DEVDISC_REQ:
5506
5507                                 process_p2p_devdisc_req(pwdinfo, pframe, len);
5508
5509                                 break;
5510
5511                         case P2P_DEVDISC_RESP:
5512
5513                                 process_p2p_devdisc_resp(pwdinfo, pframe, len);
5514
5515                                 break;
5516
5517                         case P2P_PROVISION_DISC_REQ:
5518                                 DBG_8723A( "[%s] Got Provisioning Discovery Request Frame\n", __FUNCTION__ );
5519                                 process_p2p_provdisc_req(pwdinfo, pframe, len);
5520                                 memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
5521
5522                                 /* 20110902 Kurt */
5523                                 /* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
5524                                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
5525                                         rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
5526
5527                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
5528                                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
5529 #ifdef CONFIG_INTEL_WIDI
5530                                 if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) )
5531                                 {
5532                                         padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
5533                                         intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL);
5534                                 }
5535 #endif /* CONFIG_INTEL_WIDI */
5536                                 break;
5537
5538                         case P2P_PROVISION_DISC_RESP:
5539                                 /*      Commented by Albert 20110707 */
5540                                 /*      Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
5541                                 DBG_8723A( "[%s] Got Provisioning Discovery Response Frame\n", __FUNCTION__ );
5542                                 /*      Commented by Albert 20110426 */
5543                                 /*      The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
5544                                 _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5545                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
5546                                 process_p2p_provdisc_resp(pwdinfo, pframe);
5547                                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
5548                                 break;
5549
5550                 }
5551         }
5552 #endif /* CONFIG_P2P */
5553
5554         return _SUCCESS;
5555 }
5556
5557 unsigned int on_action_public_vendor(union recv_frame *precv_frame)
5558 {
5559         unsigned int ret = _FAIL;
5560         u8 *pframe = precv_frame->u.hdr.rx_data;
5561         uint frame_len = precv_frame->u.hdr.len;
5562         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
5563
5564         if (!memcmp(frame_body + 2, P2P_OUI, 4)) {
5565                 ret = on_action_public_p2p(precv_frame);
5566         }
5567
5568         return ret;
5569 }
5570
5571 unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
5572 {
5573         unsigned int ret = _FAIL;
5574         u8 *pframe = precv_frame->u.hdr.rx_data;
5575         uint frame_len = precv_frame->u.hdr.len;
5576         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
5577         u8 token;
5578         _adapter *adapter = precv_frame->u.hdr.adapter;
5579         int cnt = 0;
5580         char msg[64];
5581
5582         token = frame_body[2];
5583
5584         if (rtw_action_public_decache(precv_frame, token) == _FAIL)
5585                 goto exit;
5586
5587         #ifdef CONFIG_IOCTL_CFG80211
5588         cnt += sprintf((msg+cnt), "%s(token:%u)", action_public_str(action), token);
5589         rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
5590         #endif
5591
5592         ret = _SUCCESS;
5593
5594 exit:
5595         return ret;
5596 }
5597
5598 unsigned int on_action_public(_adapter *padapter, union recv_frame *precv_frame)
5599 {
5600         unsigned int ret = _FAIL;
5601         u8 *pframe = precv_frame->u.hdr.rx_data;
5602         uint frame_len = precv_frame->u.hdr.len;
5603         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
5604         u8 category, action;
5605
5606         /* check RA matches or not */
5607         if (memcmp(myid(&(padapter->eeprompriv)),
5608                    GetAddr1Ptr(pframe), ETH_ALEN))
5609                 goto exit;
5610
5611         category = frame_body[0];
5612         if(category != RTW_WLAN_CATEGORY_PUBLIC)
5613                 goto exit;
5614
5615         action = frame_body[1];
5616         switch (action) {
5617         case ACT_PUBLIC_VENDOR:
5618                 ret = on_action_public_vendor(precv_frame);
5619                 break;
5620         default:
5621                 ret = on_action_public_default(precv_frame, action);
5622                 break;
5623         }
5624
5625 exit:
5626         return ret;
5627 }
5628
5629 unsigned int OnAction_ht(_adapter *padapter, union recv_frame *precv_frame)
5630 {
5631         return _SUCCESS;
5632 }
5633
5634 unsigned int OnAction_wmm(_adapter *padapter, union recv_frame *precv_frame)
5635 {
5636         return _SUCCESS;
5637 }
5638
5639 unsigned int OnAction_p2p(_adapter *padapter, union recv_frame *precv_frame)
5640 {
5641 #ifdef CONFIG_P2P
5642         u8 *frame_body;
5643         u8 category, OUI_Subtype, dialogToken=0;
5644         u8 *pframe = precv_frame->u.hdr.rx_data;
5645         uint len = precv_frame->u.hdr.len;
5646         struct  wifidirect_info *pwdinfo = &( padapter->wdinfo );
5647
5648         DBG_8723A("%s\n", __FUNCTION__);
5649
5650         /* check RA matches or not */
5651         if (memcmp(myid(&(padapter->eeprompriv)),
5652                    GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
5653                 return _SUCCESS;
5654
5655         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
5656
5657         category = frame_body[0];
5658         if(category != RTW_WLAN_CATEGORY_P2P)
5659                 return _SUCCESS;
5660
5661         if ( cpu_to_be32( *( ( u32* ) ( frame_body + 1 ) ) ) != P2POUI )
5662                 return _SUCCESS;
5663
5664 #ifdef CONFIG_IOCTL_CFG80211
5665         if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
5666         {
5667                 rtw_cfg80211_rx_action_p2p(padapter, pframe, len);
5668                 return _SUCCESS;
5669         }
5670         else
5671 #endif /* CONFIG_IOCTL_CFG80211 */
5672         {
5673                 len -= sizeof(struct rtw_ieee80211_hdr_3addr);
5674                 OUI_Subtype = frame_body[5];
5675                 dialogToken = frame_body[6];
5676
5677                 switch(OUI_Subtype)
5678                 {
5679                         case P2P_NOTICE_OF_ABSENCE:
5680
5681                                 break;
5682
5683                         case P2P_PRESENCE_REQUEST:
5684
5685                                 process_p2p_presence_req(pwdinfo, pframe, len);
5686
5687                                 break;
5688
5689                         case P2P_PRESENCE_RESPONSE:
5690
5691                                 break;
5692
5693                         case P2P_GO_DISC_REQUEST:
5694
5695                                 break;
5696
5697                         default:
5698                                 break;
5699
5700                 }
5701         }
5702 #endif /* CONFIG_P2P */
5703
5704         return _SUCCESS;
5705 }
5706
5707 unsigned int OnAction(_adapter *padapter, union recv_frame *precv_frame)
5708 {
5709         int i;
5710         unsigned char   category;
5711         struct action_handler *ptable;
5712         unsigned char   *frame_body;
5713         u8 *pframe = precv_frame->u.hdr.rx_data;
5714
5715         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
5716
5717         category = frame_body[0];
5718
5719         for(i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++)
5720         {
5721                 ptable = &OnAction_tbl[i];
5722
5723                 if(category == ptable->num)
5724                         ptable->func(padapter, precv_frame);
5725
5726         }
5727
5728         return _SUCCESS;
5729 }
5730
5731 unsigned int DoReserved(_adapter *padapter, union recv_frame *precv_frame)
5732 {
5733
5734         /* DBG_8723A("rcvd mgt frame(%x, %x)\n", (GetFrameSubType(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe)); */
5735         return _SUCCESS;
5736 }
5737
5738 struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
5739 {
5740         struct xmit_frame *pmgntframe;
5741         struct xmit_buf *pxmitbuf;
5742
5743         if (once)
5744                 pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
5745         else
5746                 pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
5747
5748         if (pmgntframe == NULL) {
5749                 DBG_8723A(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once);
5750                 goto exit;
5751         }
5752
5753         if ((pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv)) == NULL) {
5754                 DBG_8723A(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter));
5755                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
5756                 pmgntframe = NULL;
5757                 goto exit;
5758         }
5759
5760         pmgntframe->frame_tag = MGNT_FRAMETAG;
5761         pmgntframe->pxmitbuf = pxmitbuf;
5762         pmgntframe->buf_addr = pxmitbuf->pbuf;
5763         pxmitbuf->priv_data = pmgntframe;
5764
5765 exit:
5766         return pmgntframe;
5767 }
5768
5769 inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
5770 {
5771         return _alloc_mgtxmitframe(pxmitpriv, _FALSE);
5772 }
5773
5774 inline struct xmit_frame *alloc_mgtxmitframe_once(struct xmit_priv *pxmitpriv)
5775 {
5776         return _alloc_mgtxmitframe(pxmitpriv, _TRUE);
5777 }
5778
5779 /****************************************************************************
5780
5781 Following are some TX fuctions for WiFi MLME
5782
5783 *****************************************************************************/
5784
5785 void update_mgnt_tx_rate(_adapter *padapter, u8 rate)
5786 {
5787         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5788
5789         pmlmeext->tx_rate = rate;
5790         DBG_8723A("%s(): rate = %x\n",__FUNCTION__, rate);
5791 }
5792
5793 void update_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
5794 {
5795         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5796
5797         memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
5798
5799         pattrib->hdrlen = 24;
5800         pattrib->nr_frags = 1;
5801         pattrib->priority = 7;
5802         pattrib->mac_id = 0;
5803         pattrib->qsel = 0x12;
5804
5805         pattrib->pktlen = 0;
5806
5807         if(pmlmeext->cur_wireless_mode & WIRELESS_11B)
5808                 pattrib->raid = 6;/* b mode */
5809         else
5810                 pattrib->raid = 5;/* a/g mode */
5811
5812         pattrib->encrypt = _NO_PRIVACY_;
5813         pattrib->bswenc = _FALSE;
5814
5815         pattrib->qos_en = _FALSE;
5816         pattrib->ht_en = _FALSE;
5817         pattrib->bwmode = HT_CHANNEL_WIDTH_20;
5818         pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5819         pattrib->sgi = _FALSE;
5820
5821         pattrib->seqnum = pmlmeext->mgnt_seq;
5822
5823         pattrib->retry_ctrl = _TRUE;
5824 }
5825
5826 void dump_mgntframe(_adapter *padapter, struct xmit_frame *pmgntframe)
5827 {
5828         if(padapter->bSurpriseRemoved == _TRUE ||
5829                 padapter->bDriverStopped == _TRUE)
5830                 return;
5831
5832         rtw_hal_mgnt_xmit(padapter, pmgntframe);
5833 }
5834
5835 s32 dump_mgntframe_and_wait(_adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
5836 {
5837         s32 ret = _FAIL;
5838         _irqL irqL;
5839         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5840         struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
5841         struct submit_ctx sctx;
5842
5843         if(padapter->bSurpriseRemoved == _TRUE ||
5844                 padapter->bDriverStopped == _TRUE)
5845                 return ret;
5846
5847         rtw_sctx_init(&sctx, timeout_ms);
5848         pxmitbuf->sctx = &sctx;
5849
5850         ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
5851
5852         if (ret == _SUCCESS)
5853                 ret = rtw_sctx_wait(&sctx);
5854
5855         spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
5856         pxmitbuf->sctx = NULL;
5857         spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
5858
5859          return ret;
5860 }
5861
5862 s32 dump_mgntframe_and_wait_ack(_adapter *padapter, struct xmit_frame *pmgntframe)
5863 {
5864 #ifdef CONFIG_XMIT_ACK
5865         s32 ret = _FAIL;
5866         u32 timeout_ms = 500;/*   500ms */
5867         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
5868         #ifdef CONFIG_CONCURRENT_MODE
5869         if (padapter->pbuddy_adapter && !padapter->isprimary)
5870                 pxmitpriv = &(padapter->pbuddy_adapter->xmitpriv);
5871         #endif
5872
5873         if(padapter->bSurpriseRemoved == _TRUE ||
5874                 padapter->bDriverStopped == _TRUE)
5875                 return -1;
5876
5877         _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
5878         pxmitpriv->ack_tx = _TRUE;
5879
5880         pmgntframe->ack_report = 1;
5881         if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
5882                 ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
5883         }
5884
5885         pxmitpriv->ack_tx = _FALSE;
5886         _exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
5887
5888          return ret;
5889 #else /* CONFIG_XMIT_ACK */
5890         dump_mgntframe(padapter, pmgntframe);
5891         rtw_msleep_os(50);
5892         return _SUCCESS;
5893 #endif /* CONFIG_XMIT_ACK */
5894 }
5895
5896 int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
5897 {
5898         u8 *ssid_ie;
5899         int ssid_len_ori;
5900         int len_diff = 0;
5901
5902         ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
5903
5904         /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __FUNCTION__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
5905
5906         if(ssid_ie && ssid_len_ori>0)
5907         {
5908                 switch(hidden_ssid_mode)
5909                 {
5910                         case 1:
5911                         {
5912                                 u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
5913                                 u32 remain_len = 0;
5914
5915                                 remain_len = ies_len -(next_ie-ies);
5916
5917                                 ssid_ie[1] = 0;
5918                                 memcpy(ssid_ie+2, next_ie, remain_len);
5919                                 len_diff -= ssid_len_ori;
5920
5921                                 break;
5922                         }
5923                         case 2:
5924                                 memset(&ssid_ie[2], 0, ssid_len_ori);
5925                                 break;
5926                         default:
5927                                 break;
5928                 }
5929         }
5930
5931         return len_diff;
5932 }
5933
5934 void issue_beacon(_adapter *padapter, int timeout_ms)
5935 {
5936         struct xmit_frame       *pmgntframe;
5937         struct pkt_attrib       *pattrib;
5938         unsigned char   *pframe;
5939         struct rtw_ieee80211_hdr *pwlanhdr;
5940         unsigned short *fctrl;
5941         unsigned int    rate_len;
5942         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
5943 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
5944         _irqL irqL;
5945         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5946 #endif /* if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
5947         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5948         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5949         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
5950         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
5951 #ifdef CONFIG_P2P
5952         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
5953 #endif /* CONFIG_P2P */
5954
5955         /* DBG_8723A("%s\n", __FUNCTION__); */
5956
5957         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
5958         {
5959                 DBG_8723A("%s, alloc mgnt frame fail\n", __FUNCTION__);
5960                 return;
5961         }
5962 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
5963         spin_lock_bh(&pmlmepriv->bcn_update_lock);
5964 #endif /* if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
5965
5966         /* update attribute */
5967         pattrib = &pmgntframe->attrib;
5968         update_mgntframe_attrib(padapter, pattrib);
5969         pattrib->qsel = 0x10;
5970
5971         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5972
5973         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5974         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5975
5976         fctrl = &(pwlanhdr->frame_ctl);
5977         *(fctrl) = 0;
5978
5979         memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
5980         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5981         memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
5982
5983         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
5984         /* pmlmeext->mgnt_seq++; */
5985         SetFrameSubType(pframe, WIFI_BEACON);
5986
5987         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
5988         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
5989
5990         if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
5991         {
5992                 /* DBG_8723A("ie len=%d\n", cur_network->IELength); */
5993 #ifdef CONFIG_P2P
5994                 /*  for P2P : Primary Device Type & Device Name */
5995                 u32 wpsielen=0, insert_len=0;
5996                 u8 *wpsie=NULL;
5997                 wpsie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wpsielen);
5998
5999                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen>0)
6000                 {
6001                         uint wps_offset, remainder_ielen;
6002                         u8 *premainder_ie, *pframe_wscie;
6003
6004                         wps_offset = (uint)(wpsie - cur_network->IEs);
6005
6006                         premainder_ie = wpsie + wpsielen;
6007
6008                         remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
6009
6010 #ifdef CONFIG_IOCTL_CFG80211
6011                         if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
6012                         {
6013                                 if(pmlmepriv->wps_beacon_ie && pmlmepriv->wps_beacon_ie_len>0)
6014                                 {
6015                                         memcpy(pframe, cur_network->IEs, wps_offset);
6016                                         pframe += wps_offset;
6017                                         pattrib->pktlen += wps_offset;
6018
6019                                         memcpy(pframe, pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
6020                                         pframe += pmlmepriv->wps_beacon_ie_len;
6021                                         pattrib->pktlen += pmlmepriv->wps_beacon_ie_len;
6022
6023                                         /* copy remainder_ie to pframe */
6024                                         memcpy(pframe, premainder_ie, remainder_ielen);
6025                                         pframe += remainder_ielen;
6026                                         pattrib->pktlen += remainder_ielen;
6027                                 }
6028                                 else
6029                                 {
6030                                         memcpy(pframe, cur_network->IEs, cur_network->IELength);
6031                                         pframe += cur_network->IELength;
6032                                         pattrib->pktlen += cur_network->IELength;
6033                                 }
6034                         }
6035                         else
6036 #endif /* CONFIG_IOCTL_CFG80211 */
6037                         {
6038                                 pframe_wscie = pframe + wps_offset;
6039                                 memcpy(pframe, cur_network->IEs, wps_offset+wpsielen);
6040                                 pframe += (wps_offset + wpsielen);
6041                                 pattrib->pktlen += (wps_offset + wpsielen);
6042
6043                                 /* now pframe is end of wsc ie, insert Primary Device Type & Device Name */
6044                                 /*      Primary Device Type */
6045                                 /*      Type: */
6046                                 *(u16*) ( pframe + insert_len) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
6047                                 insert_len += 2;
6048
6049                                 /*      Length: */
6050                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( 0x0008 );
6051                                 insert_len += 2;
6052
6053                                 /*      Value: */
6054                                 /*      Category ID */
6055                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
6056                                 insert_len += 2;
6057
6058                                 /*      OUI */
6059                                 *(u32*) ( pframe + insert_len ) = cpu_to_be32( WPSOUI );
6060                                 insert_len += 4;
6061
6062                                 /*      Sub Category ID */
6063                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
6064                                 insert_len += 2;
6065
6066                                 /*      Device Name */
6067                                 /*      Type: */
6068                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
6069                                 insert_len += 2;
6070
6071                                 /*      Length: */
6072                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( pwdinfo->device_name_len );
6073                                 insert_len += 2;
6074
6075                                 /*      Value: */
6076                                 memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len );
6077                                 insert_len += pwdinfo->device_name_len;
6078
6079                                 /* update wsc ie length */
6080                                 *(pframe_wscie+1) = (wpsielen -2) + insert_len;
6081
6082                                 /* pframe move to end */
6083                                 pframe+=insert_len;
6084                                 pattrib->pktlen += insert_len;
6085
6086                                 /* copy remainder_ie to pframe */
6087                                 memcpy(pframe, premainder_ie, remainder_ielen);
6088                                 pframe += remainder_ielen;
6089                                 pattrib->pktlen += remainder_ielen;
6090                         }
6091                 }
6092                 else
6093 #endif /* CONFIG_P2P */
6094                 {
6095                         int len_diff;
6096                         memcpy(pframe, cur_network->IEs, cur_network->IELength);
6097                         len_diff = update_hidden_ssid(
6098                                 pframe+_BEACON_IE_OFFSET_
6099                                 , cur_network->IELength-_BEACON_IE_OFFSET_
6100                                 , pmlmeinfo->hidden_ssid_mode
6101                         );
6102                         pframe += (cur_network->IELength+len_diff);
6103                         pattrib->pktlen += (cur_network->IELength+len_diff);
6104                 }
6105
6106                 {
6107                         u8 *wps_ie;
6108                         uint wps_ielen;
6109                         u8 sr = 0;
6110                         wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof (struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
6111                                 pattrib->pktlen-sizeof (struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
6112                         if (wps_ie && wps_ielen>0) {
6113                                 rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8*)(&sr), NULL);
6114                         }
6115                         if (sr != 0)
6116                                 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
6117                         else
6118                                 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
6119                 }
6120
6121 #ifdef CONFIG_P2P
6122                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
6123                 {
6124                         u32 len;
6125 #ifdef CONFIG_IOCTL_CFG80211
6126                         if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
6127                         {
6128                                 len = pmlmepriv->p2p_beacon_ie_len;
6129                                 if(pmlmepriv->p2p_beacon_ie && len>0)
6130                                         memcpy(pframe, pmlmepriv->p2p_beacon_ie, len);
6131                         }
6132                         else
6133 #endif /* CONFIG_IOCTL_CFG80211 */
6134                         {
6135                                 len = build_beacon_p2p_ie(pwdinfo, pframe);
6136                         }
6137
6138                         pframe += len;
6139                         pattrib->pktlen += len;
6140 #ifdef CONFIG_WFD
6141 #ifdef CONFIG_IOCTL_CFG80211
6142                         if(_TRUE == pwdinfo->wfd_info->wfd_enable)
6143 #endif /* CONFIG_IOCTL_CFG80211 */
6144                         {
6145                                 len = build_beacon_wfd_ie( pwdinfo, pframe );
6146                         }
6147 #ifdef CONFIG_IOCTL_CFG80211
6148                         else
6149                         {
6150                                 len = 0;
6151                                 if(pmlmepriv->wfd_beacon_ie && pmlmepriv->wfd_beacon_ie_len>0)
6152                                 {
6153                                         len = pmlmepriv->wfd_beacon_ie_len;
6154                                         memcpy(pframe, pmlmepriv->wfd_beacon_ie, len);
6155                         }
6156                         }
6157 #endif /* CONFIG_IOCTL_CFG80211 */
6158                         pframe += len;
6159                         pattrib->pktlen += len;
6160 #endif /* CONFIG_WFD */
6161                 }
6162 #endif /* CONFIG_P2P */
6163
6164                 goto _issue_bcn;
6165
6166         }
6167
6168         /* below for ad-hoc mode */
6169
6170         /* timestamp will be inserted by hardware */
6171         pframe += 8;
6172         pattrib->pktlen += 8;
6173
6174         /*  beacon interval: 2 bytes */
6175
6176         memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
6177
6178         pframe += 2;
6179         pattrib->pktlen += 2;
6180
6181         /*  capability info: 2 bytes */
6182
6183         memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
6184
6185         pframe += 2;
6186         pattrib->pktlen += 2;
6187
6188         /*  SSID */
6189         pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
6190
6191         /*  supported rates... */
6192         rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
6193         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pattrib->pktlen);
6194
6195         /*  DS parameter set */
6196         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
6197
6198         /* if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
6199         {
6200                 u8 erpinfo=0;
6201                 u32 ATIMWindow;
6202                 /*  IBSS Parameter Set... */
6203                 /* ATIMWindow = cur->Configuration.ATIMWindow; */
6204                 ATIMWindow = 0;
6205                 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
6206
6207                 /* ERP IE */
6208                 pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
6209         }
6210
6211         /*  EXTERNDED SUPPORTED RATE */
6212         if (rate_len > 8)
6213         {
6214                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
6215         }
6216
6217         /* todo:HT for adhoc */
6218
6219 _issue_bcn:
6220
6221 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6222         pmlmepriv->update_bcn = _FALSE;
6223
6224         spin_unlock_bh(&pmlmepriv->bcn_update_lock);
6225 #endif /* if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
6226
6227         if ((pattrib->pktlen + TXDESC_SIZE) > 512)
6228         {
6229                 DBG_8723A("beacon frame too large\n");
6230                 return;
6231         }
6232
6233         pattrib->last_txcmdsz = pattrib->pktlen;
6234
6235         /* DBG_8723A("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */
6236         if(timeout_ms > 0)
6237                 dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
6238         else
6239                 dump_mgntframe(padapter, pmgntframe);
6240 }
6241
6242 void issue_probersp(_adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
6243 {
6244         struct xmit_frame                       *pmgntframe;
6245         struct pkt_attrib                       *pattrib;
6246         unsigned char                                   *pframe;
6247         struct rtw_ieee80211_hdr        *pwlanhdr;
6248         unsigned short                          *fctrl;
6249         unsigned char                                   *mac, *bssid;
6250         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
6251 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6252         u8 *pwps_ie;
6253         uint wps_ielen;
6254         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6255 #endif /* if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
6256         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6257         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6258         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
6259         unsigned int    rate_len;
6260 #ifdef CONFIG_P2P
6261         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
6262 #ifdef CONFIG_WFD
6263         u32                                     wfdielen = 0;
6264 #endif /* CONFIG_WFD */
6265 #endif /* CONFIG_P2P */
6266
6267         /* DBG_8723A("%s\n", __FUNCTION__); */
6268
6269         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
6270         {
6271                 DBG_8723A("%s, alloc mgnt frame fail\n", __FUNCTION__);
6272                 return;
6273         }
6274
6275         /* update attribute */
6276         pattrib = &pmgntframe->attrib;
6277         update_mgntframe_attrib(padapter, pattrib);
6278
6279         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6280
6281         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6282         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
6283
6284         mac = myid(&(padapter->eeprompriv));
6285         bssid = cur_network->MacAddress;
6286
6287         fctrl = &(pwlanhdr->frame_ctl);
6288         *(fctrl) = 0;
6289         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
6290         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
6291         memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
6292
6293         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6294         pmlmeext->mgnt_seq++;
6295         SetFrameSubType(fctrl, WIFI_PROBERSP);
6296
6297         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6298         pattrib->pktlen = pattrib->hdrlen;
6299         pframe += pattrib->hdrlen;
6300
6301         if(cur_network->IELength>MAX_IE_SZ)
6302                 return;
6303
6304 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6305         if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
6306         {
6307                 pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
6308
6309                 /* inerset & update wps_probe_resp_ie */
6310                 if((pmlmepriv->wps_probe_resp_ie!=NULL) && pwps_ie && (wps_ielen>0))
6311                 {
6312                         uint wps_offset, remainder_ielen;
6313                         u8 *premainder_ie;
6314
6315                         wps_offset = (uint)(pwps_ie - cur_network->IEs);
6316
6317                         premainder_ie = pwps_ie + wps_ielen;
6318
6319                         remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
6320
6321                         memcpy(pframe, cur_network->IEs, wps_offset);
6322                         pframe += wps_offset;
6323                         pattrib->pktlen += wps_offset;
6324
6325                         wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
6326                         if((wps_offset+wps_ielen+2)<=MAX_IE_SZ)
6327                         {
6328                                 memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
6329                                 pframe += wps_ielen+2;
6330                                 pattrib->pktlen += wps_ielen+2;
6331                         }
6332
6333                         if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)
6334                         {
6335                                 memcpy(pframe, premainder_ie, remainder_ielen);
6336                                 pframe += remainder_ielen;
6337                                 pattrib->pktlen += remainder_ielen;
6338                         }
6339                 }
6340                 else
6341                 {
6342                         memcpy(pframe, cur_network->IEs, cur_network->IELength);
6343                         pframe += cur_network->IELength;
6344                         pattrib->pktlen += cur_network->IELength;
6345                 }
6346
6347                 /* retrieve SSID IE from cur_network->Ssid */
6348                 {
6349                         u8 *ssid_ie;
6350                         int ssid_ielen;
6351                         int ssid_ielen_diff;
6352                         u8 buf[MAX_IE_SZ];
6353                         u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct rtw_ieee80211_hdr_3addr);
6354
6355                         ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
6356                                 (pframe-ies)-_FIXED_IE_LENGTH_);
6357
6358                         ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
6359
6360                         if (ssid_ie &&  cur_network->Ssid.SsidLength) {
6361                                 uint remainder_ielen;
6362                                 u8 *remainder_ie;
6363                                 remainder_ie = ssid_ie+2;
6364                                 remainder_ielen = (pframe-remainder_ie);
6365
6366                                 DBG_8723A_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));
6367                                 if (remainder_ielen > MAX_IE_SZ) {
6368                                         remainder_ielen = MAX_IE_SZ;
6369                                 }
6370
6371                                 memcpy(buf, remainder_ie, remainder_ielen);
6372                                 memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
6373                                 *(ssid_ie+1) = cur_network->Ssid.SsidLength;
6374                                 memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
6375
6376                                 pframe += ssid_ielen_diff;
6377                                 pattrib->pktlen += ssid_ielen_diff;
6378                         }
6379                 }
6380         }
6381         else
6382 #endif
6383         {
6384
6385                 /* timestamp will be inserted by hardware */
6386                 pframe += 8;
6387                 pattrib->pktlen += 8;
6388
6389                 /*  beacon interval: 2 bytes */
6390
6391                 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
6392
6393                 pframe += 2;
6394                 pattrib->pktlen += 2;
6395
6396                 /*  capability info: 2 bytes */
6397
6398                 memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
6399
6400                 pframe += 2;
6401                 pattrib->pktlen += 2;
6402
6403                 /* below for ad-hoc mode */
6404
6405                 /*  SSID */
6406                 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
6407
6408                 /*  supported rates... */
6409                 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
6410                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pattrib->pktlen);
6411
6412                 /*  DS parameter set */
6413                 pframe =rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
6414
6415                 if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
6416                 {
6417                         u8 erpinfo=0;
6418                         u32 ATIMWindow;
6419                         /*  IBSS Parameter Set... */
6420                         /* ATIMWindow = cur->Configuration.ATIMWindow; */
6421                         ATIMWindow = 0;
6422                         pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
6423
6424                         /* ERP IE */
6425                         pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
6426                 }
6427
6428                 /*  EXTERNDED SUPPORTED RATE */
6429                 if (rate_len > 8)
6430                 {
6431                         pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
6432                 }
6433
6434                 /* todo:HT for adhoc */
6435
6436         }
6437
6438 #ifdef CONFIG_P2P
6439         if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq)
6440         {
6441                 u32 len;
6442 #ifdef CONFIG_IOCTL_CFG80211
6443                 if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
6444                 {
6445                         /* if pwdinfo->role == P2P_ROLE_DEVICE will call issue_probersp_p2p() */
6446                         len = pmlmepriv->p2p_go_probe_resp_ie_len;
6447                         if(pmlmepriv->p2p_go_probe_resp_ie && len>0)
6448                                 memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie, len);
6449                 }
6450                 else
6451 #endif /* CONFIG_IOCTL_CFG80211 */
6452                 {
6453                         len = build_probe_resp_p2p_ie(pwdinfo, pframe);
6454                 }
6455
6456                 pframe += len;
6457                 pattrib->pktlen += len;
6458
6459 #ifdef CONFIG_WFD
6460 #ifdef CONFIG_IOCTL_CFG80211
6461                 if(_TRUE == pwdinfo->wfd_info->wfd_enable)
6462 #endif /* CONFIG_IOCTL_CFG80211 */
6463                 {
6464                         len = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
6465                 }
6466 #ifdef CONFIG_IOCTL_CFG80211
6467                 else
6468                 {
6469                         len = 0;
6470                         if(pmlmepriv->wfd_probe_resp_ie && pmlmepriv->wfd_probe_resp_ie_len>0)
6471                         {
6472                                 len = pmlmepriv->wfd_probe_resp_ie_len;
6473                                 memcpy(pframe, pmlmepriv->wfd_probe_resp_ie, len);
6474                         }
6475                 }
6476 #endif /* CONFIG_IOCTL_CFG80211 */
6477                 pframe += len;
6478                 pattrib->pktlen += len;
6479 #endif /* CONFIG_WFD */
6480
6481         }
6482 #endif /* CONFIG_P2P */
6483
6484         pattrib->last_txcmdsz = pattrib->pktlen;
6485
6486         dump_mgntframe(padapter, pmgntframe);
6487
6488         return;
6489 }
6490
6491 int _issue_probereq(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da, int wait_ack)
6492 {
6493         int ret = _FAIL;
6494         struct xmit_frame               *pmgntframe;
6495         struct pkt_attrib               *pattrib;
6496         unsigned char                   *pframe;
6497         struct rtw_ieee80211_hdr        *pwlanhdr;
6498         unsigned short          *fctrl;
6499         unsigned char                   *mac;
6500         unsigned char                   bssrate[NumRates];
6501         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
6502         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6503         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6504         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6505         int     bssrate_len = 0;
6506         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
6507
6508         RT_TRACE(_module_rtl871x_mlme_c_,_drv_notice_,("+issue_probereq\n"));
6509
6510         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
6511         {
6512                 goto exit;
6513         }
6514
6515         /* update attribute */
6516         pattrib = &pmgntframe->attrib;
6517         update_mgntframe_attrib(padapter, pattrib);
6518
6519         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6520
6521         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6522         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
6523
6524         mac = myid(&(padapter->eeprompriv));
6525
6526         fctrl = &(pwlanhdr->frame_ctl);
6527         *(fctrl) = 0;
6528
6529         if (da)
6530         {
6531                 /*      unicast probe request frame */
6532                 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
6533                 memcpy(pwlanhdr->addr3, da, ETH_ALEN);
6534         }
6535         else
6536         {
6537                 /*      broadcast probe request frame */
6538                 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
6539                 memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
6540         }
6541
6542         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
6543
6544         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6545         pmlmeext->mgnt_seq++;
6546         SetFrameSubType(pframe, WIFI_PROBEREQ);
6547
6548         pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
6549         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
6550
6551         if(pssid)
6552                 pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
6553         else
6554                 pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
6555
6556         get_rate_set(padapter, bssrate, &bssrate_len);
6557
6558         if (bssrate_len > 8)
6559         {
6560                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
6561                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
6562         }
6563         else
6564         {
6565                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
6566         }
6567
6568         /* add wps_ie for wps2.0 */
6569         if(pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie)
6570         {
6571                 memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
6572                 pframe += pmlmepriv->wps_probe_req_ie_len;
6573                 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
6574         }
6575
6576         pattrib->last_txcmdsz = pattrib->pktlen;
6577
6578         RT_TRACE(_module_rtl871x_mlme_c_,_drv_notice_,("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
6579
6580         if (wait_ack) {
6581                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
6582         } else {
6583                 dump_mgntframe(padapter, pmgntframe);
6584                 ret = _SUCCESS;
6585         }
6586
6587 exit:
6588         return ret;
6589 }
6590
6591 inline void issue_probereq(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da)
6592 {
6593         _issue_probereq(padapter, pssid, da, _FALSE);
6594 }
6595
6596 int issue_probereq_ex(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da,
6597         int try_cnt, int wait_ms)
6598 {
6599         int ret;
6600         int i = 0;
6601         u32 start = rtw_get_current_time();
6602
6603         do
6604         {
6605                 ret = _issue_probereq(padapter, pssid, da, wait_ms>0?_TRUE:_FALSE);
6606
6607                 i++;
6608
6609                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
6610                         break;
6611
6612                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
6613                         rtw_msleep_os(wait_ms);
6614
6615         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
6616
6617         if (ret != _FAIL) {
6618                 ret = _SUCCESS;
6619                 #ifndef DBG_XMIT_ACK
6620                 goto exit;
6621                 #endif
6622         }
6623
6624         if (try_cnt && wait_ms) {
6625                 if (da)
6626                         DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
6627                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
6628                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
6629                 else
6630                         DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
6631                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
6632                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
6633         }
6634 exit:
6635         return ret;
6636 }
6637
6638 /*  if psta == NULL, indiate we are station(client) now... */
6639 void issue_auth(_adapter *padapter, struct sta_info *psta, unsigned short status)
6640 {
6641         struct xmit_frame                       *pmgntframe;
6642         struct pkt_attrib                       *pattrib;
6643         unsigned char                                   *pframe;
6644         struct rtw_ieee80211_hdr        *pwlanhdr;
6645         unsigned short                          *fctrl;
6646         unsigned int                                    val32;
6647         unsigned short                          val16;
6648         int use_shared_key = 0;
6649         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
6650         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6651         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6652
6653         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
6654         {
6655                 return;
6656         }
6657
6658         /* update attribute */
6659         pattrib = &pmgntframe->attrib;
6660         update_mgntframe_attrib(padapter, pattrib);
6661
6662         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6663
6664         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6665         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
6666
6667         fctrl = &(pwlanhdr->frame_ctl);
6668         *(fctrl) = 0;
6669
6670         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6671         pmlmeext->mgnt_seq++;
6672         SetFrameSubType(pframe, WIFI_AUTH);
6673
6674         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
6675         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6676
6677         if(psta)/*  for AP mode */
6678         {
6679 #ifdef CONFIG_NATIVEAP_MLME
6680
6681                 memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
6682                 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
6683                 memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
6684
6685                 /*  setting auth algo number */
6686                 val16 = (u16)psta->authalg;
6687
6688                 if(status != _STATS_SUCCESSFUL_)
6689                         val16 = 0;
6690
6691                 if (val16)      {
6692                         val16 = cpu_to_le16(val16);
6693                         use_shared_key = 1;
6694                 }
6695
6696                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
6697
6698                 /*  setting auth seq number */
6699                 val16 =(u16)psta->auth_seq;
6700                 val16 = cpu_to_le16(val16);
6701                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
6702
6703                 /*  setting status code... */
6704                 val16 = status;
6705                 val16 = cpu_to_le16(val16);
6706                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));
6707
6708                 /*  added challenging text... */
6709                 if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
6710                 {
6711                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
6712                 }
6713 #endif
6714         }
6715         else
6716         {
6717                 memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
6718                 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
6719                 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
6720
6721                 /*  setting auth algo number */
6722                 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)? 1: 0;/*  0:OPEN System, 1:Shared key */
6723                 if (val16)      {
6724                         val16 = cpu_to_le16(val16);
6725                         use_shared_key = 1;
6726                 }
6727                 /* DBG_8723A("%s auth_algo= %s auth_seq=%d\n",__FUNCTION__,(pmlmeinfo->auth_algo==0)?"OPEN":"SHARED",pmlmeinfo->auth_seq); */
6728
6729                 /* setting IV for auth seq #3 */
6730                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
6731                 {
6732                         /* DBG_8723A("==> iv(%d),key_index(%d)\n",pmlmeinfo->iv,pmlmeinfo->key_index); */
6733                         val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
6734                         val32 = cpu_to_le32(val32);
6735                         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&val32, &(pattrib->pktlen));
6736
6737                         pattrib->iv_len = 4;
6738                 }
6739
6740                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
6741
6742                 /*  setting auth seq number */
6743                 val16 = pmlmeinfo->auth_seq;
6744                 val16 = cpu_to_le16(val16);
6745                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
6746
6747                 /*  setting status code... */
6748                 val16 = status;
6749                 val16 = cpu_to_le16(val16);
6750                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));
6751
6752                 /*  then checking to see if sending challenging text... */
6753                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
6754                 {
6755                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
6756
6757                         SetPrivacy(fctrl);
6758
6759                         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6760
6761                         pattrib->encrypt = _WEP40_;
6762
6763                         pattrib->icv_len = 4;
6764
6765                         pattrib->pktlen += pattrib->icv_len;
6766
6767                 }
6768
6769         }
6770
6771         pattrib->last_txcmdsz = pattrib->pktlen;
6772
6773         rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
6774         DBG_8723A("%s\n", __FUNCTION__);
6775         dump_mgntframe(padapter, pmgntframe);
6776
6777         return;
6778 }
6779
6780 void issue_asocrsp(_adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
6781 {
6782 #ifdef CONFIG_AP_MODE
6783         struct xmit_frame       *pmgntframe;
6784         struct rtw_ieee80211_hdr        *pwlanhdr;
6785         struct pkt_attrib *pattrib;
6786         unsigned char   *pbuf, *pframe;
6787         unsigned short val;
6788         unsigned short *fctrl;
6789         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
6790         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6791         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6792         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6793         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
6794         u8 *ie = pnetwork->IEs;
6795 #ifdef CONFIG_P2P
6796         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
6797 #ifdef CONFIG_WFD
6798         u32                                     wfdielen = 0;
6799 #endif /* CONFIG_WFD */
6800
6801 #endif /* CONFIG_P2P */
6802
6803         DBG_8723A("%s\n", __FUNCTION__);
6804
6805         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
6806         {
6807                 return;
6808         }
6809
6810         /* update attribute */
6811         pattrib = &pmgntframe->attrib;
6812         update_mgntframe_attrib(padapter, pattrib);
6813
6814         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6815
6816         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6817         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
6818
6819         fctrl = &(pwlanhdr->frame_ctl);
6820         *(fctrl) = 0;
6821
6822         memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
6823         memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
6824         memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
6825
6826         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6827         pmlmeext->mgnt_seq++;
6828         if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
6829                 SetFrameSubType(pwlanhdr, pkt_type);
6830         else
6831                 return;
6832
6833         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6834         pattrib->pktlen += pattrib->hdrlen;
6835         pframe += pattrib->hdrlen;
6836
6837         /* capability */
6838         val = *(unsigned short *)rtw_get_capability_from_ie(ie);
6839
6840         pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_ , (unsigned char *)&val, &(pattrib->pktlen));
6841
6842         status = cpu_to_le16(status);
6843         pframe = rtw_set_fixed_ie(pframe , _STATUS_CODE_ , (unsigned char *)&status, &(pattrib->pktlen));
6844
6845         val = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
6846         pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_ , (unsigned char *)&val, &(pattrib->pktlen));
6847
6848         if (pstat->bssratelen <= 8)
6849         {
6850                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
6851         }
6852         else
6853         {
6854                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
6855                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
6856         }
6857
6858 #ifdef CONFIG_80211N_HT
6859         if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option))
6860         {
6861                 uint ie_len=0;
6862
6863                 /* FILL HT CAP INFO IE */
6864                 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
6865                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
6866                 if(pbuf && ie_len>0)
6867                 {
6868                         memcpy(pframe, pbuf, ie_len+2);
6869                         pframe += (ie_len+2);
6870                         pattrib->pktlen +=(ie_len+2);
6871                 }
6872
6873                 /* FILL HT ADD INFO IE */
6874                 /* p = hostapd_eid_ht_operation(hapd, p); */
6875                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
6876                 if(pbuf && ie_len>0)
6877                 {
6878                         memcpy(pframe, pbuf, ie_len+2);
6879                         pframe += (ie_len+2);
6880                         pattrib->pktlen +=(ie_len+2);
6881                 }
6882
6883         }
6884 #endif
6885
6886         /* FILL WMM IE */
6887         if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option))
6888         {
6889                 uint ie_len=0;
6890                 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
6891
6892                 for (pbuf = ie + _BEACON_IE_OFFSET_; ;pbuf+= (ie_len + 2))
6893                 {
6894                         pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
6895                         if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6))
6896                         {
6897                                 memcpy(pframe, pbuf, ie_len+2);
6898                                 pframe += (ie_len+2);
6899                                 pattrib->pktlen +=(ie_len+2);
6900
6901                                 break;
6902                         }
6903
6904                         if ((pbuf == NULL) || (ie_len == 0))
6905                         {
6906                                 break;
6907                         }
6908                 }
6909
6910         }
6911
6912         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
6913         {
6914                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
6915         }
6916
6917         /* add WPS IE ie for wps 2.0 */
6918         if(pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len>0)
6919         {
6920                 memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
6921
6922                 pframe += pmlmepriv->wps_assoc_resp_ie_len;
6923                 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
6924         }
6925
6926 #ifdef CONFIG_P2P
6927 #ifndef CONFIG_IOCTL_CFG80211
6928         if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device == _TRUE))
6929         {
6930                 u32 len;
6931
6932                 len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
6933
6934                 pframe += len;
6935                 pattrib->pktlen += len;
6936         }
6937 #endif /* CONFIG_IOCTL_CFG80211 */
6938 #ifdef CONFIG_WFD
6939         if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)
6940 #ifdef CONFIG_IOCTL_CFG80211
6941                 && (_TRUE == pwdinfo->wfd_info->wfd_enable)
6942 #endif /* CONFIG_IOCTL_CFG80211 */
6943         )
6944         {
6945                 wfdielen = build_assoc_resp_wfd_ie(pwdinfo, pframe);
6946                 pframe += wfdielen;
6947                 pattrib->pktlen += wfdielen;
6948         }
6949 #endif /* CONFIG_WFD */
6950 #endif /* CONFIG_P2P */
6951
6952         pattrib->last_txcmdsz = pattrib->pktlen;
6953
6954         dump_mgntframe(padapter, pmgntframe);
6955
6956 #endif
6957 }
6958
6959 void issue_assocreq(_adapter *padapter)
6960 {
6961         int ret = _FAIL;
6962         struct xmit_frame                               *pmgntframe;
6963         struct pkt_attrib                               *pattrib;
6964         unsigned char                                   *pframe, *p;
6965         struct rtw_ieee80211_hdr                        *pwlanhdr;
6966         unsigned short                          *fctrl;
6967         unsigned short                          val16;
6968         unsigned int                                    i, j, ie_len, index=0;
6969         unsigned char                                   rf_type, bssrate[NumRates], sta_bssrate[NumRates];
6970         PNDIS_802_11_VARIABLE_IEs       pIE;
6971         struct registry_priv    *pregpriv = &padapter->registrypriv;
6972         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
6973         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6974         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6975         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6976         int     bssrate_len = 0, sta_bssrate_len = 0;
6977 #ifdef CONFIG_P2P
6978         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
6979         u8                                      p2pie[ 255 ] = { 0x00 };
6980         u16                                     p2pielen = 0;
6981 #ifdef CONFIG_WFD
6982         u32                                     wfdielen = 0;
6983 #endif /* CONFIG_WFD */
6984 #endif /* CONFIG_P2P */
6985
6986 #ifdef CONFIG_DFS
6987         u16     cap;
6988 #endif /* CONFIG_DFS */
6989
6990         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
6991                 goto exit;
6992
6993         /* update attribute */
6994         pattrib = &pmgntframe->attrib;
6995         update_mgntframe_attrib(padapter, pattrib);
6996
6997         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6998
6999         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7000         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7001
7002         fctrl = &(pwlanhdr->frame_ctl);
7003         *(fctrl) = 0;
7004         memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7005         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
7006         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7007
7008         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7009         pmlmeext->mgnt_seq++;
7010         SetFrameSubType(pframe, WIFI_ASSOCREQ);
7011
7012         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
7013         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7014
7015         /* caps */
7016
7017 #ifdef CONFIG_DFS
7018         memcpy(&cap, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
7019         cap |= BIT(8);
7020         memcpy(pframe, &cap, 2);
7021 #else
7022         memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
7023 #endif /* CONFIG_DFS */
7024
7025         pframe += 2;
7026         pattrib->pktlen += 2;
7027
7028         /* listen interval */
7029         /* todo: listen interval for power saving */
7030         val16 = cpu_to_le16(3);
7031         memcpy(pframe ,(unsigned char *)&val16, 2);
7032         pframe += 2;
7033         pattrib->pktlen += 2;
7034
7035         /* SSID */
7036         pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
7037
7038         /* supported rate & extended supported rate */
7039
7040 #if 1   /*  Check if the AP's supported rates are also supported by STA. */
7041         get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
7042         /* DBG_8723A("sta_bssrate_len=%d\n", sta_bssrate_len); */
7043
7044         if(pmlmeext->cur_channel == 14)/*  for JAPAN, channel 14 can only uses B Mode(CCK) */
7045         {
7046                 sta_bssrate_len = 4;
7047         }
7048
7049         /* for (i = 0; i < sta_bssrate_len; i++) { */
7050         /*      DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
7051         /*  */
7052
7053         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
7054                 if (pmlmeinfo->network.SupportedRates[i] == 0) break;
7055                 DBG_8723A("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
7056         }
7057
7058         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
7059                 if (pmlmeinfo->network.SupportedRates[i] == 0) break;
7060
7061                 /*  Check if the AP's supported rates are also supported by STA. */
7062                 for (j=0; j < sta_bssrate_len; j++) {
7063                          /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
7064                         if ( (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
7065                                         == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) {
7066                                 /* DBG_8723A("match i = %d, j=%d\n", i, j); */
7067                                 break;
7068                         } else {
7069                                 /* DBG_8723A("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)); */
7070                         }
7071                 }
7072
7073                 if (j == sta_bssrate_len) {
7074                         /*  the rate is not supported by STA */
7075                         DBG_8723A("%s(): the rate[%d]=%02X is not supported by STA!\n",__FUNCTION__, i, pmlmeinfo->network.SupportedRates[i]);
7076                 } else {
7077                         /*  the rate is supported by STA */
7078                         bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
7079                 }
7080         }
7081
7082         bssrate_len = index;
7083         DBG_8723A("bssrate_len = %d\n", bssrate_len);
7084
7085 #endif  /*  Check if the AP's supported rates are also supported by STA. */
7086
7087         if (bssrate_len == 0) {
7088                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
7089                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
7090                 goto exit; /* don't connect to AP if no joint supported rate */
7091         }
7092
7093         if (bssrate_len > 8)
7094         {
7095                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
7096                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
7097         }
7098         else
7099         {
7100                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
7101         }
7102
7103         /* RSN */
7104         p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(NDIS_802_11_FIXED_IEs)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.IELength - sizeof(NDIS_802_11_FIXED_IEs)));
7105         if (p != NULL)
7106         {
7107                 pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, (p + 2), &(pattrib->pktlen));
7108         }
7109
7110 #ifdef CONFIG_80211N_HT
7111         /* HT caps */
7112         if(padapter->mlmepriv.htpriv.ht_option==_TRUE)
7113         {
7114                 p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.IELength - sizeof(NDIS_802_11_FIXED_IEs)));
7115                 if ((p != NULL) && (!(is_ap_in_tkip(padapter))))
7116                 {
7117                         memcpy(&(pmlmeinfo->HT_caps), (p + 2), sizeof(struct HT_caps_element));
7118
7119                         /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
7120                         if (pregpriv->cbw40_enable == 0)
7121                         {
7122                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= (~(BIT(6) | BIT(1)));
7123                         }
7124                         else
7125                         {
7126                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= BIT(1);
7127                         }
7128
7129                         /* todo: disable SM power save mode */
7130                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= 0x000c;
7131
7132                         rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
7133                         /* switch (pregpriv->rf_config) */
7134                         switch(rf_type)
7135                         {
7136                                 case RF_1T1R:
7137
7138                                         if(pregpriv->rx_stbc)
7139                                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
7140
7141                                         memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16);
7142                                         break;
7143
7144                                 case RF_2T2R:
7145                                 case RF_1T2R:
7146                                 default:
7147
7148                                         if((pregpriv->rx_stbc == 0x3) ||/* enable for 2.4/5 GHz */
7149                                                 ((pmlmeext->cur_wireless_mode & WIRELESS_11_24N) && (pregpriv->rx_stbc == 0x1)) || /* enable for 2.4GHz */
7150                                                 ((pmlmeext->cur_wireless_mode & WIRELESS_11_5N) && (pregpriv->rx_stbc == 0x2)) || /* enable for 5GHz */
7151                                                 (pregpriv->wifi_spec==1))
7152                                         {
7153                                                 DBG_8723A("declare supporting RX STBC\n");
7154                                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */
7155                                         }
7156                                         #ifdef CONFIG_DISABLE_MCS13TO15
7157                                         if(pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40 && (pregpriv->wifi_spec!=1))
7158                                                 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R_MCS13TO15_OFF, 16);
7159                                         else
7160                                         memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R, 16);
7161                                         #else /* CONFIG_DISABLE_MCS13TO15 */
7162                                         memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R, 16);
7163                                         #endif /* CONFIG_DISABLE_MCS13TO15 */
7164                                         break;
7165                         }
7166 #ifdef RTL8192C_RECONFIG_TO_1T1R
7167                         {
7168                                 if(pregpriv->rx_stbc)
7169                                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
7170
7171                                 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16);
7172                         }
7173 #endif
7174                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
7175
7176 #ifdef CONFIG_BT_COEXIST
7177                         if (BT_1Ant(padapter) == _TRUE)
7178                         {
7179                                 /*  set to 8K */
7180                                 pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para &= (u8)~IEEE80211_HT_CAP_AMPDU_FACTOR;
7181 /*                              pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para |= MAX_AMPDU_FACTOR_8K */
7182                         }
7183 #endif
7184
7185                         pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
7186
7187                 }
7188         }
7189 #endif
7190
7191         /* vendor specific IE, such as WPA, WMM, WPS */
7192         for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pmlmeinfo->network.IELength;)
7193         {
7194                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pmlmeinfo->network.IEs + i);
7195
7196                 switch (pIE->ElementID)
7197                 {
7198                         case _VENDOR_SPECIFIC_IE_:
7199                                 if (!memcmp(pIE->data, RTW_WPA_OUI, 4) ||
7200                                     !memcmp(pIE->data, WMM_OUI, 4) ||
7201                                     !memcmp(pIE->data, WPS_OUI, 4)) {
7202                                         if (!padapter->registrypriv.wifi_spec)
7203                                         {
7204                                                 /* Commented by Kurt 20110629 */
7205                                                 /* In some older APs, WPS handshake */
7206                                                 /* would be fail if we append vender extensions informations to AP */
7207                                                 if (!memcmp(pIE->data,
7208                                                             WPS_OUI, 4)){
7209                                                         pIE->Length=14;
7210                                                 }
7211                                         }
7212                                         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &(pattrib->pktlen));
7213                                 }
7214                                 break;
7215
7216                         default:
7217                                 break;
7218                 }
7219
7220                 i += (pIE->Length + 2);
7221         }
7222
7223         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
7224         {
7225                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
7226         }
7227
7228 #ifdef CONFIG_WAPI_SUPPORT
7229         rtw_build_assoc_req_wapi_ie(padapter, pframe, pattrib);
7230 #endif
7231
7232 #ifdef CONFIG_P2P
7233
7234 #ifdef CONFIG_IOCTL_CFG80211
7235         if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
7236         {
7237                 if(pmlmepriv->p2p_assoc_req_ie && pmlmepriv->p2p_assoc_req_ie_len>0)
7238                 {
7239                         memcpy(pframe, pmlmepriv->p2p_assoc_req_ie, pmlmepriv->p2p_assoc_req_ie_len);
7240                         pframe += pmlmepriv->p2p_assoc_req_ie_len;
7241                         pattrib->pktlen += pmlmepriv->p2p_assoc_req_ie_len;
7242                 }
7243         }
7244         else
7245 #endif /* CONFIG_IOCTL_CFG80211 */
7246         {
7247                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
7248                 {
7249                         /*      Should add the P2P IE in the association request frame. */
7250                         /*      P2P OUI */
7251
7252                         p2pielen = 0;
7253                         p2pie[ p2pielen++ ] = 0x50;
7254                         p2pie[ p2pielen++ ] = 0x6F;
7255                         p2pie[ p2pielen++ ] = 0x9A;
7256                         p2pie[ p2pielen++ ] = 0x09;     /*      WFA P2P v1.0 */
7257
7258                         /*      Commented by Albert 20101109 */
7259                         /*      According to the P2P Specification, the association request frame should contain 3 P2P attributes */
7260                         /*      1. P2P Capability */
7261                         /*      2. Extended Listen Timing */
7262                         /*      3. Device Info */
7263                         /*      Commented by Albert 20110516 */
7264                         /*      4. P2P Interface */
7265
7266                         /*      P2P Capability */
7267                         /*      Type: */
7268                         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
7269
7270                         /*      Length: */
7271                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
7272                         p2pielen += 2;
7273
7274                         /*      Value: */
7275                         /*      Device Capability Bitmap, 1 byte */
7276                         p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
7277
7278                         /*      Group Capability Bitmap, 1 byte */
7279                         if ( pwdinfo->persistent_supported )
7280                                 p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
7281                         else
7282                                 p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
7283
7284                         /*      Extended Listen Timing */
7285                         /*      Type: */
7286                         p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
7287
7288                         /*      Length: */
7289                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
7290                         p2pielen += 2;
7291
7292                         /*      Value: */
7293                         /*      Availability Period */
7294                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
7295                         p2pielen += 2;
7296
7297                         /*      Availability Interval */
7298                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
7299                         p2pielen += 2;
7300
7301                         /*      Device Info */
7302                         /*      Type: */
7303                         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
7304
7305                         /*      Length: */
7306                         /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
7307                         /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
7308                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
7309                         p2pielen += 2;
7310
7311                         /*      Value: */
7312                         /*      P2P Device Address */
7313                         memcpy(p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
7314                         p2pielen += ETH_ALEN;
7315
7316                         /*      Config Method */
7317                         /*      This field should be big endian. Noted by P2P specification. */
7318                         if ( ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN ) ||
7319                                 ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN ) )
7320                         {
7321                                 *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY );
7322                         }
7323                         else
7324                         {
7325                                 *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_PBC );
7326                         }
7327
7328                         p2pielen += 2;
7329
7330                         /*      Primary Device Type */
7331                         /*      Category ID */
7332                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
7333                         p2pielen += 2;
7334
7335                         /*      OUI */
7336                         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
7337                         p2pielen += 4;
7338
7339                         /*      Sub Category ID */
7340                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
7341                         p2pielen += 2;
7342
7343                         /*      Number of Secondary Device Types */
7344                         p2pie[ p2pielen++ ] = 0x00;     /*      No Secondary Device Type List */
7345
7346                         /*      Device Name */
7347                         /*      Type: */
7348                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
7349                         p2pielen += 2;
7350
7351                         /*      Length: */
7352                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
7353                         p2pielen += 2;
7354
7355                         /*      Value: */
7356                         memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
7357                         p2pielen += pwdinfo->device_name_len;
7358
7359                         /*      P2P Interface */
7360                         /*      Type: */
7361                         p2pie[ p2pielen++ ] = P2P_ATTR_INTERFACE;
7362
7363                         /*      Length: */
7364                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x000D );
7365                         p2pielen += 2;
7366
7367                         /*      Value: */
7368                         memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );      /*      P2P Device Address */
7369                         p2pielen += ETH_ALEN;
7370
7371                         p2pie[ p2pielen++ ] = 1;        /*      P2P Interface Address Count */
7372
7373                         memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );      /*      P2P Interface Address List */
7374                         p2pielen += ETH_ALEN;
7375
7376                         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
7377
7378 #ifdef CONFIG_WFD
7379                         /* wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe); */
7380                         /* pframe += wfdielen; */
7381                         /* pattrib->pktlen += wfdielen; */
7382 #endif /* CONFIG_WFD */
7383                 }
7384         }
7385
7386 #endif /* CONFIG_P2P */
7387
7388 #ifdef CONFIG_WFD
7389 #ifdef CONFIG_IOCTL_CFG80211
7390         if ( _TRUE == pwdinfo->wfd_info->wfd_enable )
7391 #endif /* CONFIG_IOCTL_CFG80211 */
7392         {
7393                 wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);
7394                 pframe += wfdielen;
7395                 pattrib->pktlen += wfdielen;
7396         }
7397 #ifdef CONFIG_IOCTL_CFG80211
7398         else if (pmlmepriv->wfd_assoc_req_ie != NULL && pmlmepriv->wfd_assoc_req_ie_len>0)
7399         {
7400                 /* WFD IE */
7401                 memcpy(pframe, pmlmepriv->wfd_assoc_req_ie, pmlmepriv->wfd_assoc_req_ie_len);
7402                 pattrib->pktlen += pmlmepriv->wfd_assoc_req_ie_len;
7403                 pframe += pmlmepriv->wfd_assoc_req_ie_len;
7404         }
7405 #endif /* CONFIG_IOCTL_CFG80211 */
7406 #endif /* CONFIG_WFD */
7407
7408         pattrib->last_txcmdsz = pattrib->pktlen;
7409         dump_mgntframe(padapter, pmgntframe);
7410
7411         ret = _SUCCESS;
7412
7413 exit:
7414         if (ret == _SUCCESS)
7415                 rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
7416         else
7417                 rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
7418
7419         return;
7420 }
7421
7422 /* when wait_ack is ture, this function shoule be called at process context */
7423 static int _issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
7424 {
7425         int ret = _FAIL;
7426         struct xmit_frame                       *pmgntframe;
7427         struct pkt_attrib                       *pattrib;
7428         unsigned char                                   *pframe;
7429         struct rtw_ieee80211_hdr        *pwlanhdr;
7430         unsigned short                          *fctrl;
7431         struct xmit_priv        *pxmitpriv;
7432         struct mlme_ext_priv    *pmlmeext;
7433         struct mlme_ext_info    *pmlmeinfo;
7434
7435         /* DBG_8723A("%s:%d\n", __FUNCTION__, power_mode); */
7436
7437         if(!padapter)
7438                 goto exit;
7439
7440         pxmitpriv = &(padapter->xmitpriv);
7441         pmlmeext = &(padapter->mlmeextpriv);
7442         pmlmeinfo = &(pmlmeext->mlmext_info);
7443
7444         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7445         {
7446                 goto exit;
7447         }
7448
7449         /* update attribute */
7450         pattrib = &pmgntframe->attrib;
7451         update_mgntframe_attrib(padapter, pattrib);
7452         pattrib->retry_ctrl = _FALSE;
7453
7454         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7455
7456         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7457         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7458
7459         fctrl = &(pwlanhdr->frame_ctl);
7460         *(fctrl) = 0;
7461
7462         if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
7463         {
7464                 SetFrDs(fctrl);
7465         }
7466         else if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
7467         {
7468                 SetToDs(fctrl);
7469         }
7470
7471         if (power_mode)
7472         {
7473                 SetPwrMgt(fctrl);
7474         }
7475
7476         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
7477         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
7478         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7479
7480         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7481         pmlmeext->mgnt_seq++;
7482         SetFrameSubType(pframe, WIFI_DATA_NULL);
7483
7484         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
7485         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7486
7487         pattrib->last_txcmdsz = pattrib->pktlen;
7488
7489         if(wait_ack)
7490         {
7491                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
7492         }
7493         else
7494         {
7495                 dump_mgntframe(padapter, pmgntframe);
7496                 ret = _SUCCESS;
7497         }
7498
7499 exit:
7500         return ret;
7501 }
7502
7503 /* when wait_ms >0 , this function shoule be called at process context */
7504 /* da == NULL for station mode */
7505 int issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
7506 {
7507         int ret;
7508         int i = 0;
7509         u32 start = rtw_get_current_time();
7510         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7511         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7512
7513         /* da == NULL, assum it's null data for sta to ap*/
7514         if (da == NULL)
7515                 da = get_my_bssid(&(pmlmeinfo->network));
7516
7517         do
7518         {
7519                 ret = _issue_nulldata(padapter, da, power_mode, wait_ms>0?_TRUE:_FALSE);
7520
7521                 i++;
7522
7523                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
7524                         break;
7525
7526                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
7527                         rtw_msleep_os(wait_ms);
7528
7529         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
7530
7531         if (ret != _FAIL) {
7532                 ret = _SUCCESS;
7533                 #ifndef DBG_XMIT_ACK
7534                 goto exit;
7535                 #endif
7536         }
7537
7538         if (try_cnt && wait_ms) {
7539                 if (da)
7540                         DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
7541                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
7542                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
7543                 else
7544                         DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
7545                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
7546                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
7547         }
7548 exit:
7549         return ret;
7550 }
7551
7552 /* when wait_ack is ture, this function shoule be called at process context */
7553 static int _issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
7554 {
7555         int ret = _FAIL;
7556         struct xmit_frame                       *pmgntframe;
7557         struct pkt_attrib                       *pattrib;
7558         unsigned char                                   *pframe;
7559         struct rtw_ieee80211_hdr        *pwlanhdr;
7560         unsigned short                          *fctrl, *qc;
7561         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
7562         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7563         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7564
7565         DBG_8723A("%s\n", __FUNCTION__);
7566
7567         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7568         {
7569                 goto exit;
7570         }
7571
7572         /* update attribute */
7573         pattrib = &pmgntframe->attrib;
7574         update_mgntframe_attrib(padapter, pattrib);
7575
7576         pattrib->hdrlen +=2;
7577         pattrib->qos_en = _TRUE;
7578         pattrib->eosp = 1;
7579         pattrib->ack_policy = 0;
7580         pattrib->mdata = 0;
7581
7582         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7583
7584         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7585         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7586
7587         fctrl = &(pwlanhdr->frame_ctl);
7588         *(fctrl) = 0;
7589
7590         if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
7591         {
7592                 SetFrDs(fctrl);
7593         }
7594         else if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
7595         {
7596                 SetToDs(fctrl);
7597         }
7598
7599         if(pattrib->mdata)
7600                 SetMData(fctrl);
7601
7602         qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
7603
7604         SetPriority(qc, tid);
7605
7606         SetEOSP(qc, pattrib->eosp);
7607
7608         SetAckpolicy(qc, pattrib->ack_policy);
7609
7610         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
7611         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
7612         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7613
7614         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7615         pmlmeext->mgnt_seq++;
7616         SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
7617
7618         pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
7619         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
7620
7621         pattrib->last_txcmdsz = pattrib->pktlen;
7622
7623         if(wait_ack)
7624         {
7625                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
7626         }
7627         else
7628         {
7629                 dump_mgntframe(padapter, pmgntframe);
7630                 ret = _SUCCESS;
7631         }
7632
7633 exit:
7634         return ret;
7635 }
7636
7637 /* when wait_ms >0 , this function shoule be called at process context */
7638 /* da == NULL for station mode */
7639 int issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
7640 {
7641         int ret;
7642         int i = 0;
7643         u32 start = rtw_get_current_time();
7644         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7645         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7646
7647         /* da == NULL, assum it's null data for sta to ap*/
7648         if (da == NULL)
7649                 da = get_my_bssid(&(pmlmeinfo->network));
7650
7651         do
7652         {
7653                 ret = _issue_qos_nulldata(padapter, da, tid, wait_ms>0?_TRUE:_FALSE);
7654
7655                 i++;
7656
7657                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
7658                         break;
7659
7660                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
7661                         rtw_msleep_os(wait_ms);
7662
7663         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
7664
7665         if (ret != _FAIL) {
7666                 ret = _SUCCESS;
7667                 #ifndef DBG_XMIT_ACK
7668                 goto exit;
7669                 #endif
7670         }
7671
7672         if (try_cnt && wait_ms) {
7673                 if (da)
7674                         DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
7675                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
7676                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
7677                 else
7678                         DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
7679                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
7680                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
7681         }
7682 exit:
7683         return ret;
7684 }
7685
7686 static int _issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
7687 {
7688         struct xmit_frame                       *pmgntframe;
7689         struct pkt_attrib                       *pattrib;
7690         unsigned char                                   *pframe;
7691         struct rtw_ieee80211_hdr        *pwlanhdr;
7692         unsigned short                          *fctrl;
7693         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
7694         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7695         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7696         int ret = _FAIL;
7697 #ifdef CONFIG_P2P
7698         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
7699 #endif /* CONFIG_P2P */
7700
7701         /* DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */
7702
7703 #ifdef CONFIG_P2P
7704         if ( !( rtw_p2p_chk_state( pwdinfo, P2P_STATE_NONE ) ) && ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) )
7705         {
7706                 _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
7707                 _set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
7708         }
7709 #endif /* CONFIG_P2P */
7710
7711         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7712         {
7713                 goto exit;
7714         }
7715
7716         /* update attribute */
7717         pattrib = &pmgntframe->attrib;
7718         update_mgntframe_attrib(padapter, pattrib);
7719         pattrib->retry_ctrl = _FALSE;
7720
7721         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7722
7723         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7724         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7725
7726         fctrl = &(pwlanhdr->frame_ctl);
7727         *(fctrl) = 0;
7728
7729         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
7730         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
7731         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7732
7733         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7734         pmlmeext->mgnt_seq++;
7735         SetFrameSubType(pframe, WIFI_DEAUTH);
7736
7737         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
7738         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7739
7740         reason = cpu_to_le16(reason);
7741         pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_ , (unsigned char *)&reason, &(pattrib->pktlen));
7742
7743         pattrib->last_txcmdsz = pattrib->pktlen;
7744
7745         if(wait_ack)
7746         {
7747                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
7748         }
7749         else
7750         {
7751                 dump_mgntframe(padapter, pmgntframe);
7752                 ret = _SUCCESS;
7753         }
7754
7755 exit:
7756         return ret;
7757 }
7758
7759 int issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason)
7760 {
7761         DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
7762         return _issue_deauth(padapter, da, reason, _FALSE);
7763 }
7764
7765 int issue_deauth_ex(_adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
7766         int wait_ms)
7767 {
7768         int ret;
7769         int i = 0;
7770         u32 start = rtw_get_current_time();
7771
7772         do
7773         {
7774                 ret = _issue_deauth(padapter, da, reason, wait_ms>0?_TRUE:_FALSE);
7775
7776                 i++;
7777
7778                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
7779                         break;
7780
7781                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
7782                         rtw_msleep_os(wait_ms);
7783
7784         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
7785
7786         if (ret != _FAIL) {
7787                 ret = _SUCCESS;
7788                 #ifndef DBG_XMIT_ACK
7789                 goto exit;
7790                 #endif
7791         }
7792
7793         if (try_cnt && wait_ms) {
7794                 if (da)
7795                         DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
7796                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
7797                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
7798                 else
7799                         DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
7800                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
7801                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
7802         }
7803 exit:
7804         return ret;
7805 }
7806
7807 void issue_action_spct_ch_switch(_adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)
7808 {
7809         _irqL   irqL;
7810         _list           *plist, *phead;
7811         struct xmit_frame                       *pmgntframe;
7812         struct pkt_attrib                       *pattrib;
7813         unsigned char                           *pframe;
7814         struct rtw_ieee80211_hdr        *pwlanhdr;
7815         unsigned short                  *fctrl;
7816         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
7817         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
7818         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7819         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7820
7821         DBG_8723A(FUNC_NDEV_FMT" ra="MAC_FMT", ch:%u, offset:%u\n",
7822                 FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(ra), new_ch, ch_offset);
7823
7824         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7825                 return;
7826
7827         /* update attribute */
7828         pattrib = &pmgntframe->attrib;
7829         update_mgntframe_attrib(padapter, pattrib);
7830
7831         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7832
7833         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7834         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7835
7836         fctrl = &(pwlanhdr->frame_ctl);
7837         *(fctrl) = 0;
7838
7839         memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */
7840         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); /* TA */
7841         memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */
7842
7843         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7844         pmlmeext->mgnt_seq++;
7845         SetFrameSubType(pframe, WIFI_ACTION);
7846
7847         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
7848         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7849
7850         /* category, action */
7851         {
7852                 u8 category, action;
7853                 category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;
7854                 action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;
7855
7856                 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
7857                 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
7858         }
7859
7860         pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0);
7861         pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen),
7862                 hal_ch_offset_to_secondary_ch_offset(ch_offset));
7863
7864         pattrib->last_txcmdsz = pattrib->pktlen;
7865
7866         dump_mgntframe(padapter, pmgntframe);
7867 }
7868
7869 void issue_action_BA(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
7870 {
7871         u8      category = RTW_WLAN_CATEGORY_BACK;
7872         u16     start_seq;
7873         u16     BA_para_set;
7874         u16     reason_code;
7875         u16     BA_timeout_value;
7876         u16     BA_starting_seqctrl;
7877         HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;
7878         struct xmit_frame               *pmgntframe;
7879         struct pkt_attrib               *pattrib;
7880         u8                                      *pframe;
7881         struct rtw_ieee80211_hdr        *pwlanhdr;
7882         u16                                     *fctrl;
7883         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
7884         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7885         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7886         struct sta_info         *psta;
7887         struct sta_priv         *pstapriv = &padapter->stapriv;
7888         struct registry_priv            *pregpriv = &padapter->registrypriv;
7889 #ifdef CONFIG_BT_COEXIST
7890         u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
7891 #endif
7892
7893 #ifdef CONFIG_80211N_HT
7894         DBG_8723A("%s, category=%d, action=%d, status=%d\n", __FUNCTION__, category, action, status);
7895
7896         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7897         {
7898                 return;
7899         }
7900
7901         /* update attribute */
7902         pattrib = &pmgntframe->attrib;
7903         update_mgntframe_attrib(padapter, pattrib);
7904
7905         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7906
7907         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7908         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7909
7910         fctrl = &(pwlanhdr->frame_ctl);
7911         *(fctrl) = 0;
7912
7913         /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
7914         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
7915         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
7916         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7917
7918         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7919         pmlmeext->mgnt_seq++;
7920         SetFrameSubType(pframe, WIFI_ACTION);
7921
7922         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
7923         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7924
7925         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
7926         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
7927
7928       status = cpu_to_le16(status);
7929
7930         if (category == 3)
7931         {
7932                 switch (action)
7933                 {
7934                         case 0: /* ADDBA req */
7935                                 do {
7936                                         pmlmeinfo->dialogToken++;
7937                                 } while (pmlmeinfo->dialogToken == 0);
7938                                 pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
7939
7940 #ifdef CONFIG_BT_COEXIST
7941                                 if ((BT_1Ant(padapter) == _TRUE) &&
7942                                     ((pmlmeinfo->assoc_AP_vendor != broadcomAP) ||
7943                                      memcmp(raddr, tendaAPMac, 3)))
7944                                 {
7945                                         /*  A-MSDU NOT Supported */
7946                                         BA_para_set = 0;
7947                                         /*  immediate Block Ack */
7948                                         BA_para_set |= (1 << 1) & IEEE80211_ADDBA_PARAM_POLICY_MASK;
7949                                         /*  TID */
7950                                         BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
7951                                         /*  max buffer size is 8 MSDU */
7952                                         BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
7953                                 }
7954                                 else
7955 #endif
7956                                 {
7957                                         #if defined(CONFIG_RTL8188E) && defined(CONFIG_SDIO_HCI)
7958                                         BA_para_set = (0x0802 | ((status & 0xf) << 2)); /* immediate ack & 16 buffer size */
7959                                         #else
7960                                         BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
7961                                         #endif
7962                                 }
7963                                 BA_para_set = cpu_to_le16(BA_para_set);
7964                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
7965
7966                                 BA_timeout_value = 5000;/*  5ms */
7967                                 BA_timeout_value = cpu_to_le16(BA_timeout_value);
7968                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_timeout_value)), &(pattrib->pktlen));
7969
7970                                 /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */
7971                                 if ((psta = rtw_get_stainfo(pstapriv, raddr)) != NULL)
7972                                 {
7973                                         start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
7974
7975                                         DBG_8723A("BA_starting_seqctrl = %d for TID=%d\n", start_seq, status & 0x07);
7976
7977                                         psta->BA_starting_seqctrl[status & 0x07] = start_seq;
7978
7979                                         BA_starting_seqctrl = start_seq << 4;
7980                                 }
7981
7982                                 BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl);
7983                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_starting_seqctrl)), &(pattrib->pktlen));
7984                                 break;
7985
7986                         case 1: /* ADDBA rsp */
7987                                 pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
7988                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
7989                                 rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
7990                                 if(MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)
7991                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
7992                                 else if(MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)
7993                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
7994                                 else if(MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)
7995                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
7996                                 else if(MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)
7997                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
7998                                 else
7999                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
8000
8001 #ifdef CONFIG_BT_COEXIST
8002                                 if ((BT_1Ant(padapter) == _TRUE) &&
8003                                                 ((pmlmeinfo->assoc_AP_vendor != broadcomAP) ||
8004                                                 memcmp(raddr, tendaAPMac, 3)))
8005                                 {
8006                                         /*  max buffer size is 8 MSDU */
8007                                         BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
8008                                         BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
8009                                 }
8010 #endif
8011
8012                                 if(pregpriv->ampdu_amsdu==0)/* disabled */
8013                                         BA_para_set = cpu_to_le16(BA_para_set & ~BIT(0));
8014                                 else if(pregpriv->ampdu_amsdu==1)/* enabled */
8015                                         BA_para_set = cpu_to_le16(BA_para_set | BIT(0));
8016                                 else /* auto */
8017                                         BA_para_set = cpu_to_le16(BA_para_set);
8018
8019                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
8020                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
8021                                 break;
8022                         case 2:/* DELBA */
8023                                 BA_para_set = (status & 0x1F) << 3;
8024                                 BA_para_set = cpu_to_le16(BA_para_set);
8025                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
8026
8027                                 reason_code = 37;/* Requested from peer STA as it does not want to use the mechanism */
8028                                 reason_code = cpu_to_le16(reason_code);
8029                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(reason_code)), &(pattrib->pktlen));
8030                                 break;
8031                         default:
8032                                 break;
8033                 }
8034         }
8035
8036         pattrib->last_txcmdsz = pattrib->pktlen;
8037
8038         dump_mgntframe(padapter, pmgntframe);
8039 #endif /* CONFIG_80211N_HT */
8040 }
8041
8042 static void issue_action_BSSCoexistPacket(_adapter *padapter)
8043 {
8044         _irqL   irqL;
8045         _list           *plist, *phead;
8046         unsigned char category, action;
8047         struct xmit_frame                       *pmgntframe;
8048         struct pkt_attrib                       *pattrib;
8049         unsigned char                           *pframe;
8050         struct rtw_ieee80211_hdr        *pwlanhdr;
8051         unsigned short                  *fctrl;
8052         struct  wlan_network    *pnetwork = NULL;
8053         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
8054         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8055         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8056         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8057         _queue          *queue  = &(pmlmepriv->scanned_queue);
8058         u8 InfoContent[16] = {0};
8059         u8 ICS[8][15];
8060 #ifdef CONFIG_80211N_HT
8061         if((pmlmepriv->num_FortyMHzIntolerant==0) || (pmlmepriv->num_sta_no_ht==0))
8062                 return;
8063
8064         if(_TRUE == pmlmeinfo->bwmode_updated)
8065                 return;
8066
8067         DBG_8723A("%s\n", __FUNCTION__);
8068
8069         category = RTW_WLAN_CATEGORY_PUBLIC;
8070         action = ACT_PUBLIC_BSSCOEXIST;
8071
8072         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8073         {
8074                 return;
8075         }
8076
8077         /* update attribute */
8078         pattrib = &pmgntframe->attrib;
8079         update_mgntframe_attrib(padapter, pattrib);
8080
8081         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8082
8083         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8084         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8085
8086         fctrl = &(pwlanhdr->frame_ctl);
8087         *(fctrl) = 0;
8088
8089         memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8090         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8091         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8092
8093         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8094         pmlmeext->mgnt_seq++;
8095         SetFrameSubType(pframe, WIFI_ACTION);
8096
8097         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8098         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8099
8100         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
8101         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
8102
8103         /*  */
8104         if(pmlmepriv->num_FortyMHzIntolerant>0)
8105         {
8106                 u8 iedata=0;
8107
8108                 iedata |= BIT(2);/* 20 MHz BSS Width Request */
8109
8110                 pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));
8111
8112         }
8113
8114         /*  */
8115         memset(ICS, 0, sizeof(ICS));
8116         if(pmlmepriv->num_sta_no_ht>0)
8117         {
8118                 int i;
8119
8120                 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
8121
8122                 phead = get_list_head(queue);
8123                 plist = get_next(phead);
8124
8125                 while(1)
8126                 {
8127                         int len;
8128                         u8 *p;
8129                         WLAN_BSSID_EX *pbss_network;
8130
8131                         if (rtw_end_of_queue_search(phead,plist)== _TRUE)
8132                                 break;
8133
8134                         pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
8135
8136                         plist = get_next(plist);
8137
8138                         pbss_network = (WLAN_BSSID_EX *)&pnetwork->network;
8139
8140                         p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
8141                         if((p==NULL) || (len==0))/* non-HT */
8142                         {
8143                                 if((pbss_network->Configuration.DSConfig<=0) || (pbss_network->Configuration.DSConfig>14))
8144                                         continue;
8145
8146                                 ICS[0][pbss_network->Configuration.DSConfig]=1;
8147
8148                                 if(ICS[0][0] == 0)
8149                                         ICS[0][0] = 1;
8150                         }
8151
8152                 }
8153
8154                 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
8155
8156                 for(i= 0;i<8;i++)
8157                 {
8158                         if(ICS[i][0] == 1)
8159                         {
8160                                 int j, k = 0;
8161
8162                                 InfoContent[k] = i;
8163                                 /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent,i); */
8164                                 k++;
8165
8166                                 for(j=1;j<=14;j++)
8167                                 {
8168                                         if(ICS[i][j]==1)
8169                                         {
8170                                                 if(k<16)
8171                                                 {
8172                                                         InfoContent[k] = j; /* channel number */
8173                                                         /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
8174                                                         k++;
8175                                                 }
8176                                         }
8177                                 }
8178
8179                                 pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
8180
8181                         }
8182
8183                 }
8184
8185         }
8186
8187         pattrib->last_txcmdsz = pattrib->pktlen;
8188
8189         dump_mgntframe(padapter, pmgntframe);
8190 #endif /* CONFIG_80211N_HT */
8191 }
8192
8193 unsigned int send_delba(_adapter *padapter, u8 initiator, u8 *addr)
8194 {
8195         struct sta_priv *pstapriv = &padapter->stapriv;
8196         struct sta_info *psta = NULL;
8197         /* struct recv_reorder_ctrl *preorder_ctrl; */
8198         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8199         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8200         u16 tid;
8201
8202         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
8203                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
8204                         return _SUCCESS;
8205
8206         psta = rtw_get_stainfo(pstapriv, addr);
8207         if(psta==NULL)
8208                 return _SUCCESS;
8209
8210         /* DBG_8723A("%s:%s\n", __FUNCTION__, (initiator==0)?"RX_DIR":"TX_DIR"); */
8211
8212         if(initiator==0) /*  recipient */
8213         {
8214                 for(tid = 0;tid<MAXTID;tid++)
8215                 {
8216                         if(psta->recvreorder_ctrl[tid].enable == _TRUE)
8217                         {
8218                                 DBG_8723A("rx agg disable tid(%d)\n",tid);
8219                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
8220                                 psta->recvreorder_ctrl[tid].enable = _FALSE;
8221                                 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
8222                                 #ifdef DBG_RX_SEQ
8223                                 DBG_8723A("DBG_RX_SEQ %s:%d indicate_seq:%u \n", __FUNCTION__, __LINE__,
8224                                         psta->recvreorder_ctrl[tid].indicate_seq);
8225                                 #endif
8226                         }
8227                 }
8228         }
8229         else if(initiator == 1)/*  originator */
8230         {
8231 #ifdef CONFIG_80211N_HT
8232                 /* DBG_8723A("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap); */
8233                 for(tid = 0;tid<MAXTID;tid++)
8234                 {
8235                         if(psta->htpriv.agg_enable_bitmap & BIT(tid))
8236                         {
8237                                 DBG_8723A("tx agg disable tid(%d)\n",tid);
8238                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F) );
8239                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
8240                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
8241
8242                         }
8243                 }
8244 #endif /* CONFIG_80211N_HT */
8245         }
8246
8247         return _SUCCESS;
8248 }
8249
8250 unsigned int send_beacon(_adapter *padapter)
8251 {
8252         u8      bxmitok = _FALSE;
8253         int     issue=0;
8254         int poll = 0;
8255 /* ifdef CONFIG_CONCURRENT_MODE */
8256         /* struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); */
8257         /* struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); */
8258         /* _adapter *pbuddy_adapter = padapter->pbuddy_adapter; */
8259         /* struct mlme_priv *pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv); */
8260 /* endif */
8261
8262 #ifdef CONFIG_PCI_HCI
8263
8264         /* DBG_8723A("%s\n", __FUNCTION__); */
8265
8266         issue_beacon(padapter, 0);
8267
8268         return _SUCCESS;
8269
8270 #endif
8271
8272 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
8273         u32 start = rtw_get_current_time();
8274
8275         rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
8276         do{
8277                 issue_beacon(padapter, 100);
8278                 issue++;
8279                 do {
8280                         rtw_yield_os();
8281                         rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
8282                         poll++;
8283                 }while((poll%10)!=0 && _FALSE == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
8284
8285         }while(_FALSE == bxmitok && issue<100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
8286
8287         if(padapter->bSurpriseRemoved || padapter->bDriverStopped)
8288         {
8289                 return _FAIL;
8290         }
8291
8292         if(_FALSE == bxmitok)
8293         {
8294                 DBG_8723A("%s fail! %u ms\n", __FUNCTION__, rtw_get_passing_time_ms(start));
8295                 return _FAIL;
8296         }
8297         else
8298         {
8299                 u32 passing_time = rtw_get_passing_time_ms(start);
8300
8301                 if(passing_time > 100 || issue > 3)
8302                         DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));
8303                 /* else */
8304                 /*      DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start)); */
8305
8306                 return _SUCCESS;
8307         }
8308
8309 #endif
8310 }
8311
8312 /****************************************************************************
8313
8314 Following are some utitity fuctions for WiFi MLME
8315
8316 *****************************************************************************/
8317
8318 bool IsLegal5GChannel(
8319         IN PADAPTER                     Adapter,
8320         IN u8                   channel)
8321 {
8322
8323         int i=0;
8324         u8 Channel_5G[45] = {36,38,40,42,44,46,48,50,52,54,56,58,
8325                 60,62,64,100,102,104,106,108,110,112,114,116,118,120,122,
8326                 124,126,128,130,132,134,136,138,140,149,151,153,155,157,159,
8327                 161,163,165};
8328         for(i=0;i<sizeof(Channel_5G);i++)
8329                 if(channel == Channel_5G[i])
8330                         return _TRUE;
8331         return _FALSE;
8332 }
8333
8334 void site_survey(_adapter *padapter)
8335 {
8336         unsigned char           survey_channel = 0, val8;
8337         RT_SCAN_TYPE    ScanType = SCAN_PASSIVE;
8338         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8339         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8340         u32 initialgain = 0;
8341
8342 #ifdef CONFIG_P2P
8343
8344 #ifdef CONFIG_CONCURRENT_MODE
8345
8346 #ifdef CONFIG_STA_MODE_SCAN_UNDER_AP_MODE
8347         u8 stay_buddy_ch = 0;
8348 #endif /* CONFIG_STA_MODE_SCAN_UNDER_AP_MODE */
8349
8350         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8351         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
8352         struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
8353
8354 #endif /* CONFIG_CONCURRENT_MODE */
8355         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
8356         static unsigned char  prev_survey_channel = 0;
8357         static unsigned int p2p_scan_count = 0;
8358
8359         if ( ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) || ( pwdinfo->p2p_info.scan_op_ch_only ) )
8360         {
8361                 if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
8362                 {
8363                         survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
8364                 }
8365                 else
8366                 {
8367                         survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
8368                 }
8369                 ScanType = SCAN_ACTIVE;
8370         }
8371         else if(rtw_p2p_findphase_ex_is_social(pwdinfo))
8372         {
8373                 /*      Commented by Albert 2011/06/03 */
8374                 /*      The driver is in the find phase, it should go through the social channel. */
8375                 int ch_set_idx;
8376                 survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
8377                 ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, survey_channel);
8378                 if (ch_set_idx >= 0)
8379                         ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
8380                 else
8381                         ScanType = SCAN_ACTIVE;
8382         }
8383         else
8384 #endif /* CONFIG_P2P */
8385         {
8386                 struct rtw_ieee80211_channel *ch;
8387                 if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
8388                         ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
8389                         survey_channel = ch->hw_value;
8390                         ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
8391                 }
8392         }
8393
8394         if (0){
8395                 DBG_8723A(FUNC_ADPT_FMT" ch:%u (cnt:%u,idx:%d) at %dms, %c%c%c\n"
8396                 , FUNC_ADPT_ARG(padapter)
8397                 , survey_channel
8398                 , pwdinfo->find_phase_state_exchange_cnt, pmlmeext->sitesurvey_res.channel_idx
8399                 , rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
8400                 , ScanType?'A':'P', pmlmeext->sitesurvey_res.scan_mode?'A':'P'
8401                 , pmlmeext->sitesurvey_res.ssid[0].SsidLength?'S':' '
8402                 );
8403                 #ifdef DBG_FIXED_CHAN
8404                 DBG_8723A(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan);
8405                 #endif
8406         }
8407
8408         if(survey_channel != 0)
8409         {
8410                 /* PAUSE 4-AC Queue when site_survey */
8411                 /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
8412                 /* val8 |= 0x0f; */
8413                 /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
8414 #ifdef CONFIG_CONCURRENT_MODE
8415 #ifdef CONFIG_STA_MODE_SCAN_UNDER_AP_MODE
8416                 if((padapter->pbuddy_adapter->mlmeextpriv.mlmext_info.state&0x03) == WIFI_FW_AP_STATE)
8417                 {
8418                         if( pmlmeinfo->scan_cnt == RTW_SCAN_NUM_OF_CH )
8419                         {
8420                                 pmlmeinfo->scan_cnt = 0;
8421                                 survey_channel = pbuddy_mlmeext->cur_channel;
8422                                 ScanType = SCAN_ACTIVE;
8423                                 stay_buddy_ch = 1;
8424                         }
8425                         else
8426                         {
8427                                 if( pmlmeinfo->scan_cnt == 0 )
8428                                         stay_buddy_ch = 2;
8429                                 pmlmeinfo->scan_cnt++;
8430                         }
8431                 }
8432 #endif /* CONFIG_STA_MODE_SCAN_UNDER_AP_MODE */
8433 #endif /* CONFIG_CONCURRENT_MODE */
8434                 if(pmlmeext->sitesurvey_res.channel_idx == 0)
8435                 {
8436 #ifdef DBG_FIXED_CHAN
8437                         if(pmlmeext->fixed_chan !=0xff)
8438                                 set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
8439                         else
8440 #endif
8441                                 set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
8442                 }
8443                 else
8444                 {
8445 #ifdef DBG_FIXED_CHAN
8446                         if(pmlmeext->fixed_chan!=0xff)
8447                                 SelectChannel(padapter, pmlmeext->fixed_chan);
8448                         else
8449 #endif
8450                                 SelectChannel(padapter, survey_channel);
8451                 }
8452
8453 #ifdef CONFIG_STA_MODE_SCAN_UNDER_AP_MODE
8454                 if( stay_buddy_ch == 1 )
8455                 {
8456                         val8 = 0; /* survey done */
8457                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
8458
8459                         if(check_buddy_mlmeinfo_state(padapter, WIFI_FW_AP_STATE) &&
8460                                 check_buddy_fwstate(padapter, _FW_LINKED))
8461                         {
8462                                 update_beacon(padapter->pbuddy_adapter, 0, NULL, _TRUE);
8463                         }
8464                 }
8465                 else if( stay_buddy_ch == 2 )
8466                 {
8467                         val8 = 1; /* under site survey */
8468                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
8469                 }
8470 #endif /* CONFIG_STA_MODE_SCAN_UNDER_AP_MODE */
8471
8472                 if(ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */
8473                 {
8474                         #ifdef CONFIG_P2P
8475                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) ||
8476                                 rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)
8477                         )
8478                         {
8479                                 issue_probereq_p2p(padapter, NULL);
8480                                 issue_probereq_p2p(padapter, NULL);
8481                                 issue_probereq_p2p(padapter, NULL);
8482                         }
8483                         else
8484                         #endif /* CONFIG_P2P */
8485                         {
8486                                 int i;
8487                                 for(i=0;i<RTW_SSID_SCAN_AMOUNT;i++){
8488                                         if(pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
8489                                                 /* todo: to issue two probe req??? */
8490                                                 issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
8491                                                 /* rtw_msleep_os(SURVEY_TO>>1); */
8492                                                 issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
8493                                         }
8494                                 }
8495
8496                                 if(pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
8497                                         /* todo: to issue two probe req??? */
8498                                         issue_probereq(padapter, NULL, NULL);
8499                                         /* rtw_msleep_os(SURVEY_TO>>1); */
8500                                         issue_probereq(padapter, NULL, NULL);
8501                                 }
8502                         }
8503                 }
8504
8505 #ifdef CONFIG_STA_MODE_SCAN_UNDER_AP_MODE
8506                 if( stay_buddy_ch == 1 )
8507                         set_survey_timer(pmlmeext, pmlmeext->chan_scan_time * RTW_STAY_AP_CH_MILLISECOND );
8508                 else
8509 #endif /* CONFIG_STA_MODE_SCAN_UNDER_AP_MODE */
8510                         set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
8511
8512         }
8513         else
8514         {
8515
8516                 /*      channel number is 0 or this channel is not valid. */
8517
8518 #ifdef CONFIG_CONCURRENT_MODE
8519                 u8 cur_channel;
8520                 u8 cur_bwmode;
8521                 u8 cur_ch_offset;
8522
8523                 if(check_fwstate(pmlmepriv, _FW_LINKED))
8524                 {
8525                         cur_channel = pmlmeext->cur_channel;
8526                         cur_bwmode = pmlmeext->cur_bwmode;
8527                         cur_ch_offset = pmlmeext->cur_ch_offset;
8528                 }
8529                 /* else if((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) */
8530                 else if(check_buddy_fwstate(padapter, _FW_LINKED)) /*  for AP or STA */
8531                 {
8532                         cur_channel = pbuddy_mlmeext->cur_channel;
8533                         cur_bwmode = pbuddy_mlmeext->cur_bwmode;
8534                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
8535                 }
8536                 else
8537                 {
8538                         cur_channel = pmlmeext->cur_channel;
8539                         cur_bwmode = pmlmeext->cur_bwmode;
8540                         cur_ch_offset = pmlmeext->cur_ch_offset;
8541                 }
8542 #endif
8543
8544 #ifdef CONFIG_P2P
8545                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
8546                 {
8547                         if( ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) || ( pwdinfo->p2p_info.scan_op_ch_only ) )
8548                         {
8549                                 /*      Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */
8550                                 /*      This will let the following flow to run the scanning end. */
8551                                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
8552                         }
8553                         #ifdef CONFIG_DBG_P2P
8554                         DBG_8723A( "[%s] find phase exchange cnt = %d\n", __FUNCTION__, pwdinfo->find_phase_state_exchange_cnt );
8555                         #endif
8556                 }
8557
8558                 if(rtw_p2p_findphase_ex_is_needed(pwdinfo))
8559                 {
8560                         /*      Set the P2P State to the listen state of find phase and set the current channel to the listen channel */
8561                         set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
8562                         rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
8563                         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
8564
8565                         initialgain = 0xff; /* restore RX GAIN */
8566                         rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
8567                         /* turn on dynamic functions */
8568                         Restore_DM_Func_Flag(padapter);
8569                         /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, _TRUE); */
8570
8571                         _set_timer( &pwdinfo->find_phase_timer, ( u32 ) ( ( u32 ) ( pwdinfo->listen_dwell ) * 100 ) );
8572                 }
8573                 else
8574 #endif /* CONFIG_P2P */
8575                 {
8576
8577 #ifdef CONFIG_STA_MODE_SCAN_UNDER_AP_MODE
8578                         pmlmeinfo->scan_cnt = 0;
8579 #endif /* CONFIG_DMP_STA_NODE_SCAN_UNDER_AP_MODE */
8580
8581 #ifdef CONFIG_ANTENNA_DIVERSITY
8582                         /*  20100721:Interrupt scan operation here. */
8583                         /*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
8584                         /*  It compares the scan result and select beter one to do connection. */
8585                         if(rtw_hal_antdiv_before_linked(padapter))
8586                         {
8587                                 pmlmeext->sitesurvey_res.bss_cnt = 0;
8588                                 pmlmeext->sitesurvey_res.channel_idx = -1;
8589                                 pmlmeext->chan_scan_time = SURVEY_TO /2;
8590                                 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
8591                                 return;
8592                         }
8593 #endif
8594
8595 #ifdef CONFIG_P2P
8596                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
8597                         {
8598                         #ifdef CONFIG_CONCURRENT_MODE
8599                                 #ifndef CONFIG_IOCTL_CFG80211
8600                                 if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
8601                                 {
8602                                         _set_timer( &pwdinfo->ap_p2p_switch_timer, 500 );
8603                                 }
8604                                 #endif /* CONFIG_IOCTL_CFG80211 */
8605                                 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
8606                         #else
8607                                 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
8608                         #endif
8609                         }
8610                         rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
8611 #endif /* CONFIG_P2P */
8612
8613                         pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
8614
8615                         /* switch back to the original channel */
8616                         /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
8617
8618                         {
8619 #ifdef CONFIG_DUALMAC_CONCURRENT
8620                                 dc_set_channel_bwmode_survey_done(padapter);
8621 #else
8622 #ifndef CONFIG_IOCTL_CFG80211
8623                                 if( rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) )
8624                                 {
8625                                         set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
8626                                 }
8627                                 else
8628 #endif /* CONFIG_IOCTL_CFG80211 */
8629 #ifdef CONFIG_CONCURRENT_MODE
8630                                         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
8631 #else
8632                                         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8633 #endif /* CONFIG_DUALMAC_CONCURRENT */
8634 #endif /* CONFIG_CONCURRENT_MODE */
8635                         }
8636
8637                         /* flush 4-AC Queue after site_survey */
8638                         /* val8 = 0; */
8639                         /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
8640
8641                         /* config MSR */
8642                         Set_MSR(padapter, (pmlmeinfo->state & 0x3));
8643
8644                         initialgain = 0xff; /* restore RX GAIN */
8645                         rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
8646                         /* turn on dynamic functions */
8647                         Restore_DM_Func_Flag(padapter);
8648                         /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE); */
8649
8650                         if (is_client_associated_to_ap(padapter) == _TRUE)
8651                         {
8652                                 issue_nulldata(padapter, NULL, 0, 3, 500);
8653
8654 #ifdef CONFIG_CONCURRENT_MODE
8655                                 if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
8656                                 {
8657                                         DBG_8723A("adapter is surveydone(buddy_adapter is linked), issue nulldata(pwrbit=0)\n");
8658
8659                                         issue_nulldata(padapter->pbuddy_adapter, NULL, 0, 3, 500);
8660                                 }
8661 #endif
8662                         }
8663 #ifdef CONFIG_CONCURRENT_MODE
8664                         else if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
8665                         {
8666                                 issue_nulldata(padapter->pbuddy_adapter, NULL, 0, 3, 500);
8667                         }
8668 #endif
8669
8670                         val8 = 0; /* survey done */
8671                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
8672
8673                         report_surveydone_event(padapter);
8674
8675                         pmlmeext->chan_scan_time = SURVEY_TO;
8676                         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
8677
8678                         issue_action_BSSCoexistPacket(padapter);
8679                         issue_action_BSSCoexistPacket(padapter);
8680                         issue_action_BSSCoexistPacket(padapter);
8681
8682                 }
8683
8684 #ifdef CONFIG_CONCURRENT_MODE
8685                 if(check_buddy_mlmeinfo_state(padapter, WIFI_FW_AP_STATE) &&
8686                         check_buddy_fwstate(padapter, _FW_LINKED))
8687                 {
8688
8689                         DBG_8723A("survey done, current CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
8690
8691                         DBG_8723A("restart pbuddy_adapter's beacon\n");
8692
8693                         update_beacon(padapter->pbuddy_adapter, 0, NULL, _TRUE);
8694                 }
8695 #endif
8696
8697         }
8698
8699         return;
8700 }
8701
8702 /* collect bss info from Beacon and Probe request/response frames. */
8703 u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSID_EX *bssid)
8704 {
8705         int     i;
8706         u32     len;
8707         u8      *p;
8708         u16     val16, subtype;
8709         u8      *pframe = precv_frame->u.hdr.rx_data;
8710         u32     packet_len = precv_frame->u.hdr.len;
8711         u8 ie_offset;
8712         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
8713         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8714         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8715
8716         len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
8717
8718         if (len > MAX_IE_SZ)
8719         {
8720                 /* DBG_8723A("IE too long for survey event\n"); */
8721                 return _FAIL;
8722         }
8723
8724         memset(bssid, 0, sizeof(WLAN_BSSID_EX));
8725
8726         subtype = GetFrameSubType(pframe);
8727
8728         if(subtype==WIFI_BEACON) {
8729                 bssid->Reserved[0] = 1;
8730                 ie_offset = _BEACON_IE_OFFSET_;
8731         } else {
8732                 /*  FIXME : more type */
8733                 if (subtype == WIFI_PROBEREQ) {
8734                         ie_offset = _PROBEREQ_IE_OFFSET_;
8735                         bssid->Reserved[0] = 2;
8736                 } else if (subtype == WIFI_PROBERSP) {
8737                         ie_offset = _PROBERSP_IE_OFFSET_;
8738                         bssid->Reserved[0] = 3;
8739                 } else {
8740                         bssid->Reserved[0] = 0;
8741                         ie_offset = _FIXED_IE_LENGTH_;
8742                 }
8743         }
8744
8745         bssid->Length = sizeof(WLAN_BSSID_EX) - MAX_IE_SZ + len;
8746
8747         /* below is to copy the information element */
8748         bssid->IELength = len;
8749         memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
8750
8751         /* get the signal strength */
8752         bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /*  in dBM.raw data */
8753         bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
8754         bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
8755 #ifdef CONFIG_ANTENNA_DIVERSITY
8756         /* rtw_hal_get_hwreg(padapter, HW_VAR_CURRENT_ANTENNA, (u8 *)(&bssid->PhyInfo.Optimum_antenna)); */
8757         rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA,  &bssid->PhyInfo.Optimum_antenna);
8758 #endif
8759
8760         /*  checking SSID */
8761         if ((p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset)) == NULL)
8762         {
8763                 DBG_8723A("marc: cannot find SSID for survey event\n");
8764                 return _FAIL;
8765         }
8766
8767         if (*(p + 1))
8768         {
8769                 if (len > NDIS_802_11_LENGTH_SSID)
8770                 {
8771                         DBG_8723A("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
8772                         return _FAIL;
8773                 }
8774                 memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
8775                 bssid->Ssid.SsidLength = *(p + 1);
8776         }
8777         else
8778         {
8779                 bssid->Ssid.SsidLength = 0;
8780         }
8781
8782         memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
8783
8784         /* checking rate info... */
8785         i = 0;
8786         p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
8787         if (p != NULL)
8788         {
8789                 if (len > NDIS_802_11_LENGTH_RATES_EX)
8790                 {
8791                         DBG_8723A("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
8792                         return _FAIL;
8793                 }
8794                 memcpy(bssid->SupportedRates, (p + 2), len);
8795                 i = len;
8796         }
8797
8798         p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
8799         if (p != NULL)
8800         {
8801                 if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
8802                 {
8803                         DBG_8723A("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
8804                         return _FAIL;
8805                 }
8806                 memcpy(bssid->SupportedRates + i, (p + 2), len);
8807         }
8808
8809         /* todo: */
8810         {
8811                 bssid->NetworkTypeInUse = Ndis802_11OFDM24;
8812         }
8813
8814         if (bssid->IELength < 12)
8815                 return _FAIL;
8816
8817         /*  Checking for DSConfig */
8818         p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
8819
8820         bssid->Configuration.DSConfig = 0;
8821         bssid->Configuration.Length = 0;
8822
8823         if (p)
8824         {
8825                 bssid->Configuration.DSConfig = *(p + 2);
8826         }
8827         else
8828         {/*  In 5G, some ap do not have DSSET IE */
8829                 /*  checking HT info for channel */
8830                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
8831                 if(p)
8832                 {
8833                         struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
8834                         bssid->Configuration.DSConfig = HT_info->primary_channel;
8835                 }
8836                 else
8837                 { /*  use current channel */
8838                         bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
8839                 }
8840         }
8841
8842         if (subtype==WIFI_PROBEREQ)
8843         {
8844                 /*  FIXME */
8845                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
8846                 memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
8847                 bssid->Privacy = 1;
8848                 return _SUCCESS;
8849         }
8850
8851         memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
8852         bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod);
8853
8854         val16 = rtw_get_capability((WLAN_BSSID_EX *)bssid);
8855
8856         if (val16 & BIT(0))
8857         {
8858                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
8859                 memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
8860         }
8861         else
8862         {
8863                 bssid->InfrastructureMode = Ndis802_11IBSS;
8864                 memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
8865         }
8866
8867         if (val16 & BIT(4))
8868                 bssid->Privacy = 1;
8869         else
8870                 bssid->Privacy = 0;
8871
8872         bssid->Configuration.ATIMWindow = 0;
8873
8874         /* 20/40 BSS Coexistence check */
8875         if((pregistrypriv->wifi_spec==1) && (_FALSE == pmlmeinfo->bwmode_updated))
8876         {
8877                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8878 #ifdef CONFIG_80211N_HT
8879                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
8880                 if(p && len>0)
8881                 {
8882                         struct HT_caps_element  *pHT_caps;
8883                         pHT_caps = (struct HT_caps_element      *)(p + 2);
8884
8885                         if(pHT_caps->u.HT_cap_element.HT_caps_info&BIT(14))
8886                         {
8887                                 pmlmepriv->num_FortyMHzIntolerant++;
8888                         }
8889                 }
8890                 else
8891                 {
8892                         pmlmepriv->num_sta_no_ht++;
8893                 }
8894 #endif /* CONFIG_80211N_HT */
8895
8896         }
8897
8898 #ifdef CONFIG_INTEL_WIDI
8899         /* process_intel_widi_query_or_tigger(padapter, bssid); */
8900         if(process_intel_widi_query_or_tigger(padapter, bssid))
8901         {
8902                 return _FAIL;
8903         }
8904 #endif /*  CONFIG_INTEL_WIDI */
8905
8906         #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) & 1
8907         if(strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
8908                 DBG_8723A("Receiving %s("MAC_FMT", DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n"
8909                         , bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig
8910                         , rtw_get_oper_ch(padapter)
8911                         , bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi
8912                 );
8913         }
8914         #endif
8915
8916         /*  mark bss info receving from nearby channel as SignalQuality 101 */
8917         if(bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
8918         {
8919                 bssid->PhyInfo.SignalQuality= 101;
8920         }
8921
8922         return _SUCCESS;
8923 }
8924
8925 void start_create_ibss(_adapter* padapter)
8926 {
8927         unsigned short  caps;
8928         u8      val8;
8929         u8      join_type;
8930         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8931         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8932         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
8933         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
8934         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
8935
8936         /* update wireless mode */
8937         update_wireless_mode(padapter);
8938
8939         /* udpate capability */
8940         caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);
8941         update_capinfo(padapter, caps);
8942         if(caps&cap_IBSS)/* adhoc master */
8943         {
8944                 val8 = 0xcf;
8945                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
8946
8947                 /* switch channel */
8948                 /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
8949                 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
8950
8951                 beacon_timing_control(padapter);
8952
8953                 /* set msr to WIFI_FW_ADHOC_STATE */
8954                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
8955                 Set_MSR(padapter, (pmlmeinfo->state & 0x3));
8956
8957                 /* issue beacon */
8958                 if(send_beacon(padapter)==_FAIL)
8959                 {
8960                         RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("issuing beacon frame fail....\n"));
8961
8962                         report_join_res(padapter, -1);
8963                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
8964                 }
8965                 else
8966                 {
8967                         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
8968                         join_type = 0;
8969                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
8970
8971                         report_join_res(padapter, 1);
8972                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
8973                 }
8974         }
8975         else
8976         {
8977                 DBG_8723A("start_create_ibss, invalid cap:%x\n", caps);
8978                 return;
8979         }
8980 }
8981
8982 void start_clnt_join(_adapter* padapter)
8983 {
8984         unsigned short  caps;
8985         u8      val8;
8986         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8987         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8988         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
8989         int beacon_timeout;
8990
8991         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
8992         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
8993
8994         /* update wireless mode */
8995         update_wireless_mode(padapter);
8996
8997         /* udpate capability */
8998         caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);
8999         update_capinfo(padapter, caps);
9000         if (caps&cap_ESS)
9001         {
9002
9003 #ifdef CONFIG_DUALMAC_CONCURRENT
9004                 if(dc_handle_join_request(padapter) == _FAIL)
9005                {
9006                    DBG_8723A("dc_handle_join_request fail !!!\n");
9007                    return;
9008                 }
9009                 /* switch channel */
9010                set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
9011 #elif defined (CONFIG_CONCURRENT_MODE)
9012               if(concurrent_chk_start_clnt_join(padapter) == _FAIL)
9013                    return;
9014 #else /* NON CONCURRENT_MODE */
9015               /* switch channel */
9016                set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
9017 #endif
9018
9019                 Set_MSR(padapter, WIFI_FW_STATION_STATE);
9020
9021                 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
9022
9023 #ifdef CONFIG_WAPI_SUPPORT
9024                 if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI)
9025                 {
9026                         /* Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey. */
9027                         val8 = 0x4c;
9028                 }
9029 #endif
9030                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
9031
9032                 /* switch channel */
9033                 /* set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
9034
9035                 /* here wait for receiving the beacon to start auth */
9036                 /* and enable a timer */
9037                 beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
9038                 set_link_timer(pmlmeext, beacon_timeout);
9039                 _set_timer( &padapter->mlmepriv.assoc_timer,
9040                         (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) +beacon_timeout);
9041
9042                 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
9043         }
9044         else if (caps&cap_IBSS) /* adhoc client */
9045         {
9046 #ifdef CONFIG_DUALMAC_CONCURRENT
9047                 if(dc_handle_join_request(padapter) == _FAIL)
9048                 {
9049                         DBG_8723A("dc_handle_join_request for Ad-hoc fail !!!\n");
9050                         return;
9051                 }
9052 #endif
9053
9054                 Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
9055
9056                 val8 = 0xcf;
9057                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
9058
9059                 /* switch channel */
9060                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
9061
9062                 beacon_timing_control(padapter);
9063
9064                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
9065
9066                 report_join_res(padapter, 1);
9067         }
9068         else
9069         {
9070                 /* DBG_8723A("marc: invalid cap:%x\n", caps); */
9071                 return;
9072         }
9073 }
9074
9075 void start_clnt_auth(_adapter* padapter)
9076 {
9077         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9078         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9079
9080         _cancel_timer_ex(&pmlmeext->link_timer);
9081
9082         pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
9083         pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
9084
9085         pmlmeinfo->auth_seq = 1;
9086         pmlmeinfo->reauth_count = 0;
9087         pmlmeinfo->reassoc_count = 0;
9088         pmlmeinfo->link_count = 0;
9089         pmlmeext->retry = 0;
9090
9091         /*  Because of AP's not receiving deauth before */
9092         /*  AP may: 1)not response auth or 2)deauth us after link is complete */
9093         /*  issue deauth before issuing auth to deal with the situation */
9094         /*      Commented by Albert 2012/07/21 */
9095         /*      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
9096         issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
9097
9098         DBG_8723A_LEVEL(_drv_always_, "start auth\n");
9099         issue_auth(padapter, NULL, 0);
9100
9101         set_link_timer(pmlmeext, REAUTH_TO);
9102 }
9103
9104 void start_clnt_assoc(_adapter* padapter)
9105 {
9106         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9107         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9108
9109         _cancel_timer_ex(&pmlmeext->link_timer);
9110
9111         pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
9112         pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
9113
9114         issue_assocreq(padapter);
9115
9116         set_link_timer(pmlmeext, REASSOC_TO);
9117 }
9118
9119 unsigned int receive_disconnect(_adapter *padapter, unsigned char *MacAddr, unsigned short reason)
9120 {
9121         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9122         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9123
9124         /* check A3 */
9125         if (memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
9126                 return _SUCCESS;
9127
9128         DBG_8723A("%s\n", __FUNCTION__);
9129
9130         if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
9131         {
9132                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
9133                 {
9134                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
9135                         report_del_sta_event(padapter, MacAddr, reason);
9136
9137                 }
9138                 else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE)
9139                 {
9140                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
9141                         report_join_res(padapter, -2);
9142                 }
9143         }
9144
9145         return _SUCCESS;
9146 }
9147
9148 #ifdef CONFIG_80211D
9149 static void process_80211d(PADAPTER padapter, WLAN_BSSID_EX *bssid)
9150 {
9151         struct registry_priv *pregistrypriv;
9152         struct mlme_ext_priv *pmlmeext;
9153         RT_CHANNEL_INFO *chplan_new;
9154         u8 channel;
9155         u8 i;
9156
9157         pregistrypriv = &padapter->registrypriv;
9158         pmlmeext = &padapter->mlmeextpriv;
9159
9160         /*  Adjust channel plan by AP Country IE */
9161         if (pregistrypriv->enable80211d &&
9162                 (!pmlmeext->update_channel_plan_by_ap_done))
9163         {
9164                 u8 *ie, *p;
9165                 u32 len;
9166                 RT_CHANNEL_PLAN chplan_ap;
9167                 RT_CHANNEL_INFO chplan_sta[MAX_CHANNEL_NUM];
9168                 u8 country[4];
9169                 u8 fcn; /*  first channel number */
9170                 u8 noc; /*  number of channel */
9171                 u8 j, k;
9172
9173                 ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
9174                 if (!ie) return;
9175                 if (len < 6) return;
9176
9177                 ie += 2;
9178                 p = ie;
9179                 ie += len;
9180
9181                 memset(country, 0, 4);
9182                 memcpy(country, p, 3);
9183                 p += 3;
9184                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
9185                                 ("%s: 802.11d country=%s\n", __FUNCTION__, country));
9186
9187                 i = 0;
9188                 while ((ie - p) >= 3)
9189                 {
9190                         fcn = *(p++);
9191                         noc = *(p++);
9192                         p++;
9193
9194                         for (j = 0; j < noc; j++)
9195                         {
9196                                 if (fcn <= 14) channel = fcn + j; /*  2.4 GHz */
9197                                 else channel = fcn + j*4; /*  5 GHz */
9198
9199                                 chplan_ap.Channel[i++] = channel;
9200                         }
9201                 }
9202                 chplan_ap.Len = i;
9203
9204 #ifdef CONFIG_DEBUG_RTL871X
9205                 i = 0;
9206                 DBG_8723A("%s: AP[%s] channel plan {", __func__, bssid->Ssid.Ssid);
9207                 while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0))
9208                 {
9209                         DBG_8723A("%02d,", chplan_ap.Channel[i]);
9210                         i++;
9211                 }
9212                 DBG_8723A("}\n");
9213 #endif
9214
9215                 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
9216 #ifdef CONFIG_DEBUG_RTL871X
9217                 i = 0;
9218                 DBG_8723A("%s: STA channel plan {", __func__);
9219                 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0))
9220                 {
9221                         DBG_8723A("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType==SCAN_PASSIVE?'p':'a');
9222                         i++;
9223                 }
9224                 DBG_8723A("}\n");
9225 #endif
9226
9227                 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
9228                 chplan_new = pmlmeext->channel_set;
9229
9230                 i = j = k = 0;
9231                 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
9232                         do {
9233                                 if ((i == MAX_CHANNEL_NUM) ||
9234                                         (chplan_sta[i].ChannelNum == 0) ||
9235                                         (chplan_sta[i].ChannelNum > 14))
9236                                         break;
9237
9238                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
9239                                         break;
9240
9241                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
9242                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
9243                                         chplan_new[k].ScanType = SCAN_ACTIVE;
9244                                         i++;
9245                                         j++;
9246                                         k++;
9247                                 } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
9248                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
9249                                         chplan_new[k].ScanType = SCAN_PASSIVE;
9250                                         i++;
9251                                         k++;
9252                                 } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
9253                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
9254                                         chplan_new[k].ScanType = SCAN_ACTIVE;
9255                                         j++;
9256                                         k++;
9257                                 }
9258                         } while (1);
9259
9260                         /*  change AP not support channel to Passive scan */
9261                         while ((i < MAX_CHANNEL_NUM) &&
9262                                 (chplan_sta[i].ChannelNum != 0) &&
9263                                 (chplan_sta[i].ChannelNum <= 14)) {
9264                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
9265                                 chplan_new[k].ScanType = SCAN_PASSIVE;
9266                                 i++;
9267                                 k++;
9268                         }
9269
9270                         /*  add channel AP supported */
9271                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
9272                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
9273                                 chplan_new[k].ScanType = SCAN_ACTIVE;
9274                                 j++;
9275                                 k++;
9276                         }
9277                 } else {
9278                         /*  keep original STA 2.4G channel plan */
9279                         while ((i < MAX_CHANNEL_NUM) &&
9280                                 (chplan_sta[i].ChannelNum != 0) &&
9281                                 (chplan_sta[i].ChannelNum <= 14)) {
9282                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
9283                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
9284                                 i++;
9285                                 k++;
9286                         }
9287
9288                         /*  skip AP 2.4G channel plan */
9289                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
9290                                 j++;
9291                         }
9292                 }
9293
9294                 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
9295                         do {
9296                                 if ((i == MAX_CHANNEL_NUM) ||
9297                                     (chplan_sta[i].ChannelNum == 0))
9298                                         break;
9299
9300                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
9301                                         break;
9302
9303                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j])
9304                                 {
9305                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
9306                                         chplan_new[k].ScanType = SCAN_ACTIVE;
9307                                         i++;
9308                                         j++;
9309                                         k++;
9310                                 }
9311                                 else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j])
9312                                 {
9313                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
9314 /*                                      chplan_new[k].ScanType = chplan_sta[i].ScanType; */
9315                                         chplan_new[k].ScanType = SCAN_PASSIVE;
9316                                         i++;
9317                                         k++;
9318                                 }
9319                                 else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j])
9320                                 {
9321                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
9322                                         chplan_new[k].ScanType = SCAN_ACTIVE;
9323                                         j++;
9324                                         k++;
9325                                 }
9326                         } while (1);
9327
9328                         /*  change AP not support channel to Passive scan */
9329                         while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
9330                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
9331                                 chplan_new[k].ScanType = SCAN_PASSIVE;
9332                                 i++;
9333                                 k++;
9334                         }
9335
9336                         /*  add channel AP supported */
9337                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) {
9338                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
9339                                 chplan_new[k].ScanType = SCAN_ACTIVE;
9340                                 j++;
9341                                 k++;
9342                         }
9343                 } else {
9344                         /*  keep original STA 5G channel plan */
9345                         while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
9346                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
9347                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
9348                                 i++;
9349                                 k++;
9350                         }
9351                 }
9352
9353                 pmlmeext->update_channel_plan_by_ap_done = 1;
9354
9355 #ifdef CONFIG_DEBUG_RTL871X
9356                 k = 0;
9357                 DBG_8723A("%s: new STA channel plan {", __func__);
9358                 while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) {
9359                         DBG_8723A("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType==SCAN_PASSIVE?'p':'c');
9360                         k++;
9361                 }
9362                 DBG_8723A("}\n");
9363 #endif
9364         }
9365
9366         /*  If channel is used by AP, set channel scan type to active */
9367         channel = bssid->Configuration.DSConfig;
9368         chplan_new = pmlmeext->channel_set;
9369         i = 0;
9370         while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
9371                 if (chplan_new[i].ChannelNum == channel)
9372                 {
9373                         if (chplan_new[i].ScanType == SCAN_PASSIVE) {
9374                                 /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */
9375                                 if(channel >= 52 && channel <= 144)
9376                                         break;
9377
9378                                 chplan_new[i].ScanType = SCAN_ACTIVE;
9379                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
9380                                                  ("%s: change channel %d scan type from passive to active\n",
9381                                                   __FUNCTION__, channel));
9382                         }
9383                         break;
9384                 }
9385                 i++;
9386         }
9387 }
9388 #endif
9389
9390 /****************************************************************************
9391
9392 Following are the functions to report events
9393
9394 *****************************************************************************/
9395
9396 void report_survey_event(_adapter *padapter, union recv_frame *precv_frame)
9397 {
9398         struct cmd_obj *pcmd_obj;
9399         u8      *pevtcmd;
9400         u32 cmdsz;
9401         struct survey_event     *psurvey_evt;
9402         struct C2HEvent_Header *pc2h_evt_hdr;
9403         struct mlme_ext_priv *pmlmeext;
9404         struct cmd_priv *pcmdpriv;
9405
9406         if(!padapter)
9407                 return;
9408
9409         pmlmeext = &padapter->mlmeextpriv;
9410         pcmdpriv = &padapter->cmdpriv;
9411
9412         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
9413                 return;
9414
9415         cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
9416         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL) {
9417                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
9418                 return;
9419         }
9420
9421         _rtw_init_listhead(&pcmd_obj->list);
9422
9423         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
9424         pcmd_obj->cmdsz = cmdsz;
9425         pcmd_obj->parmbuf = pevtcmd;
9426
9427         pcmd_obj->rsp = NULL;
9428         pcmd_obj->rspsz  = 0;
9429
9430         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
9431         pc2h_evt_hdr->len = sizeof(struct survey_event);
9432         pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
9433         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
9434
9435         psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
9436
9437         if (collect_bss_info(padapter, precv_frame, (WLAN_BSSID_EX *)&psurvey_evt->bss) == _FAIL) {
9438                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
9439                 rtw_mfree((u8 *)pevtcmd, cmdsz);
9440                 return;
9441         }
9442
9443 #ifdef CONFIG_80211D
9444         process_80211d(padapter, &psurvey_evt->bss);
9445 #endif
9446
9447         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
9448
9449         pmlmeext->sitesurvey_res.bss_cnt++;
9450
9451         return;
9452 }
9453
9454 void report_surveydone_event(_adapter *padapter)
9455 {
9456         struct cmd_obj *pcmd_obj;
9457         u8      *pevtcmd;
9458         u32 cmdsz;
9459         struct surveydone_event *psurveydone_evt;
9460         struct C2HEvent_Header  *pc2h_evt_hdr;
9461         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
9462         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
9463
9464         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
9465         {
9466                 return;
9467         }
9468
9469         cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
9470         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
9471         {
9472                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
9473                 return;
9474         }
9475
9476         _rtw_init_listhead(&pcmd_obj->list);
9477
9478         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
9479         pcmd_obj->cmdsz = cmdsz;
9480         pcmd_obj->parmbuf = pevtcmd;
9481
9482         pcmd_obj->rsp = NULL;
9483         pcmd_obj->rspsz  = 0;
9484
9485         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
9486         pc2h_evt_hdr->len = sizeof(struct surveydone_event);
9487         pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
9488         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
9489
9490         psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
9491         psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
9492
9493         DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
9494
9495         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
9496
9497         return;
9498 }
9499
9500 void report_join_res(_adapter *padapter, int res)
9501 {
9502         struct cmd_obj *pcmd_obj;
9503         u8      *pevtcmd;
9504         u32 cmdsz;
9505         struct joinbss_event            *pjoinbss_evt;
9506         struct C2HEvent_Header  *pc2h_evt_hdr;
9507         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
9508         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9509         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
9510
9511         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
9512         {
9513                 return;
9514         }
9515
9516         cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
9517         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
9518         {
9519                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
9520                 return;
9521         }
9522
9523         _rtw_init_listhead(&pcmd_obj->list);
9524
9525         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
9526         pcmd_obj->cmdsz = cmdsz;
9527         pcmd_obj->parmbuf = pevtcmd;
9528
9529         pcmd_obj->rsp = NULL;
9530         pcmd_obj->rspsz  = 0;
9531
9532         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
9533         pc2h_evt_hdr->len = sizeof(struct joinbss_event);
9534         pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
9535         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
9536
9537         pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
9538         memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));
9539         pjoinbss_evt->network.join_res  = pjoinbss_evt->network.aid = res;
9540
9541         DBG_8723A("report_join_res(%d)\n", res);
9542
9543         rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
9544
9545         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
9546
9547         return;
9548 }
9549
9550 void report_del_sta_event(_adapter *padapter, unsigned char* MacAddr, unsigned short reason)
9551 {
9552         struct cmd_obj *pcmd_obj;
9553         u8      *pevtcmd;
9554         u32 cmdsz;
9555         struct sta_info *psta;
9556         int     mac_id;
9557         struct stadel_event                     *pdel_sta_evt;
9558         struct C2HEvent_Header  *pc2h_evt_hdr;
9559         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
9560         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
9561
9562         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
9563         {
9564                 return;
9565         }
9566
9567         cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
9568         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
9569         {
9570                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
9571                 return;
9572         }
9573
9574         _rtw_init_listhead(&pcmd_obj->list);
9575
9576         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
9577         pcmd_obj->cmdsz = cmdsz;
9578         pcmd_obj->parmbuf = pevtcmd;
9579
9580         pcmd_obj->rsp = NULL;
9581         pcmd_obj->rspsz  = 0;
9582
9583         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
9584         pc2h_evt_hdr->len = sizeof(struct stadel_event);
9585         pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
9586         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
9587
9588         pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
9589         memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
9590         memcpy((unsigned char *)(pdel_sta_evt->rsvd),(unsigned char *)(&reason),2);
9591
9592         psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
9593         if(psta)
9594                 mac_id = (int)psta->mac_id;
9595         else
9596                 mac_id = (-1);
9597
9598         pdel_sta_evt->mac_id = mac_id;
9599
9600         DBG_8723A("report_del_sta_event: delete STA, mac_id=%d\n", mac_id);
9601
9602         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
9603
9604         return;
9605 }
9606
9607 void report_add_sta_event(_adapter *padapter, unsigned char* MacAddr, int cam_idx)
9608 {
9609         struct cmd_obj *pcmd_obj;
9610         u8      *pevtcmd;
9611         u32 cmdsz;
9612         struct stassoc_event            *padd_sta_evt;
9613         struct C2HEvent_Header  *pc2h_evt_hdr;
9614         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
9615         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
9616
9617         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
9618         {
9619                 return;
9620         }
9621
9622         cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
9623         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
9624         {
9625                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
9626                 return;
9627         }
9628
9629         _rtw_init_listhead(&pcmd_obj->list);
9630
9631         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
9632         pcmd_obj->cmdsz = cmdsz;
9633         pcmd_obj->parmbuf = pevtcmd;
9634
9635         pcmd_obj->rsp = NULL;
9636         pcmd_obj->rspsz  = 0;
9637
9638         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
9639         pc2h_evt_hdr->len = sizeof(struct stassoc_event);
9640         pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
9641         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
9642
9643         padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
9644         memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
9645         padd_sta_evt->cam_id = cam_idx;
9646
9647         DBG_8723A("report_add_sta_event: add STA\n");
9648
9649         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
9650
9651         return;
9652 }
9653
9654 /****************************************************************************
9655
9656 Following are the event callback functions
9657
9658 *****************************************************************************/
9659
9660 /* for sta/adhoc mode */
9661 void update_sta_info(_adapter *padapter, struct sta_info *psta)
9662 {
9663         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
9664         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9665         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9666
9667         /* ERP */
9668         VCS_update(padapter, psta);
9669
9670 #ifdef CONFIG_80211N_HT
9671         /* HT */
9672         if(pmlmepriv->htpriv.ht_option)
9673         {
9674                 psta->htpriv.ht_option = _TRUE;
9675
9676                 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
9677
9678                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps)))
9679                         psta->htpriv.sgi = _TRUE;
9680
9681                 psta->qos_option = _TRUE;
9682
9683         }
9684         else
9685 #endif /* CONFIG_80211N_HT */
9686         {
9687 #ifdef CONFIG_80211N_HT
9688                 psta->htpriv.ht_option = _FALSE;
9689
9690                 psta->htpriv.ampdu_enable = _FALSE;
9691
9692                 psta->htpriv.sgi = _FALSE;
9693 #endif /* CONFIG_80211N_HT */
9694                 psta->qos_option = _FALSE;
9695
9696         }
9697 #ifdef CONFIG_80211N_HT
9698         psta->htpriv.bwmode = pmlmeext->cur_bwmode;
9699         psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
9700
9701         psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
9702         psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
9703 #endif /* CONFIG_80211N_HT */
9704
9705         /* QoS */
9706         if(pmlmepriv->qospriv.qos_option)
9707                 psta->qos_option = _TRUE;
9708
9709         psta->state = _FW_LINKED;
9710 }
9711
9712 void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res)
9713 {
9714         struct sta_info         *psta, *psta_bmc;
9715         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9716         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9717         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
9718         struct sta_priv         *pstapriv = &padapter->stapriv;
9719         u8      join_type;
9720         u16 media_status;
9721
9722         if(join_res < 0)
9723         {
9724                 join_type = 1;
9725                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
9726                 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
9727
9728                 /* restore to initial setting. */
9729                 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
9730
9731                 goto exit_mlmeext_joinbss_event_callback;
9732         }
9733
9734         if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
9735         {
9736                 /* for bc/mc */
9737                 psta_bmc = rtw_get_bcmc_stainfo(padapter);
9738                 if(psta_bmc)
9739                 {
9740                         pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
9741                         update_bmc_sta_support_rate(padapter, psta_bmc->mac_id);
9742                         Update_RA_Entry(padapter, psta_bmc);
9743                 }
9744         }
9745
9746         /* turn on dynamic functions */
9747         Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);
9748
9749         /*  update IOT-releated issue */
9750         update_IOT_info(padapter);
9751
9752         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
9753
9754         /* BCN interval */
9755         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
9756
9757         /* udpate capability */
9758         update_capinfo(padapter, pmlmeinfo->capability);
9759
9760         /* WMM, Update EDCA param */
9761         WMMOnAssocRsp(padapter);
9762
9763         /* HT */
9764         HTOnAssocRsp(padapter);
9765
9766 #ifndef CONFIG_CONCURRENT_MODE
9767         /*      Call set_channel_bwmode when the CONFIG_CONCURRENT_MODE doesn't be defined. */
9768         /* Set cur_channel&cur_bwmode&cur_ch_offset */
9769         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
9770 #endif
9771
9772         psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
9773         if (psta) /* only for infra. mode */
9774         {
9775                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
9776
9777                 /* DBG_8723A("set_sta_rate\n"); */
9778
9779                 psta->wireless_mode = pmlmeext->cur_wireless_mode;
9780
9781                 /* set per sta rate after updating HT cap. */
9782                 set_sta_rate(padapter, psta);
9783
9784                 #if (RATE_ADAPTIVE_SUPPORT==1)  /* for 88E RA */
9785                 rtw_hal_set_hwreg(padapter,HW_VAR_TX_RPT_MAX_MACID, (u8*)&psta->mac_id);
9786                 #endif
9787                 media_status = (psta->mac_id<<8)|1; /*   MACID|OPMODE: 1 means connect */
9788                 rtw_hal_set_hwreg(padapter,HW_VAR_H2C_MEDIA_STATUS_RPT,(u8 *)&media_status);
9789         }
9790
9791         join_type = 2;
9792         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
9793
9794         if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
9795         {
9796                 /*  correcting TSF */
9797                 correct_TSF(padapter, pmlmeext);
9798
9799                 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
9800         }
9801
9802 #ifdef CONFIG_LPS
9803         rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
9804 #endif
9805
9806 exit_mlmeext_joinbss_event_callback:
9807
9808 #ifdef CONFIG_DUALMAC_CONCURRENT
9809         dc_handle_join_done(padapter, join_res);
9810 #endif
9811 #ifdef CONFIG_CONCURRENT_MODE
9812         concurrent_chk_joinbss_done(padapter, join_res);
9813 #endif
9814
9815         DBG_8723A("=>%s\n", __FUNCTION__);
9816 }
9817
9818 void mlmeext_sta_add_event_callback(_adapter *padapter, struct sta_info *psta)
9819 {
9820         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
9821         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9822         u8      join_type;
9823
9824         DBG_8723A("%s\n", __FUNCTION__);
9825
9826         if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
9827         {
9828                 if(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)/* adhoc master or sta_count>1 */
9829                 {
9830                         /* nothing to do */
9831                 }
9832                 else/* adhoc client */
9833                 {
9834                         /* update TSF Value */
9835                         /* update_TSF(pmlmeext, pframe, len); */
9836
9837                         /*  correcting TSF */
9838                         correct_TSF(padapter, pmlmeext);
9839
9840                         /* start beacon */
9841                         if(send_beacon(padapter)==_FAIL)
9842                         {
9843                                 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
9844
9845                                 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
9846
9847                                 return;
9848                         }
9849
9850                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
9851
9852                 }
9853
9854                 join_type = 2;
9855                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
9856         }
9857
9858         pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
9859
9860         /* rate radaptive */
9861         Update_RA_Entry(padapter, psta);
9862
9863         /* update adhoc sta_info */
9864         update_sta_info(padapter, psta);
9865 }
9866
9867 void mlmeext_sta_del_event_callback(_adapter *padapter)
9868 {
9869         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9870         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9871
9872         if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
9873         {
9874                 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
9875
9876                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
9877                 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
9878
9879                 /* restore to initial setting. */
9880                 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
9881
9882 #ifdef CONFIG_DUALMAC_CONCURRENT
9883                 dc_set_channel_bwmode_disconnect(padapter);
9884 #else
9885 #ifdef CONFIG_CONCURRENT_MODE
9886                 if((check_buddy_fwstate(padapter, _FW_LINKED)) != _TRUE)
9887                 {
9888 #endif /* CONFIG_CONCURRENT_MODE */
9889
9890                 /* switch to the 20M Hz mode after disconnect */
9891                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
9892                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
9893
9894                 /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
9895                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
9896
9897 #ifdef CONFIG_CONCURRENT_MODE
9898                 }
9899 #endif /* CONFIG_CONCURRENT_MODE */
9900 #endif /* CONFIG_DUALMAC_CONCURRENT */
9901
9902                 flush_all_cam_entry(padapter);
9903
9904                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
9905
9906                 /* set MSR to no link state -> infra. mode */
9907                 Set_MSR(padapter, _HW_STATE_STATION_);
9908
9909                 _cancel_timer_ex(&pmlmeext->link_timer);
9910
9911         }
9912 }
9913
9914 /****************************************************************************
9915
9916 Following are the functions for the timer handlers
9917
9918 *****************************************************************************/
9919 void _linked_rx_signal_strehgth_display(_adapter *padapter);
9920 void _linked_rx_signal_strehgth_display(_adapter *padapter)
9921 {
9922         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9923       struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9924         u8 mac_id;
9925         int UndecoratedSmoothedPWDB;
9926         if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
9927         {
9928                 mac_id=0;
9929         }
9930         else if((pmlmeinfo->state&0x03) == _HW_STATE_AP_)
9931         {
9932                 mac_id=2;
9933         }
9934
9935         rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP,&mac_id);
9936
9937         rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
9938         DBG_8723A("UndecoratedSmoothedPWDB:%d\n",UndecoratedSmoothedPWDB);
9939 }
9940
9941 u8 chk_ap_is_alive(_adapter *padapter, struct sta_info *psta)
9942 {
9943         u8 ret = _FALSE;
9944         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9945         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9946
9947         #ifdef DBG_EXPIRATION_CHK
9948         DBG_8723A(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"
9949                                 /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/
9950                                 ", retry:%u\n"
9951                 , FUNC_ADPT_ARG(padapter)
9952                 , STA_RX_PKTS_DIFF_ARG(psta)
9953                 , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts
9954                 , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts
9955                 /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts
9956                 , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts
9957                 , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts
9958                 , pmlmeinfo->bcn_interval*/
9959                 , pmlmeext->retry
9960         );
9961
9962         DBG_8723A(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter)
9963                 , padapter->xmitpriv.tx_pkts
9964                 , pmlmeinfo->link_count
9965         );
9966         #endif
9967
9968         if((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
9969                 && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
9970                 && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
9971         )
9972         {
9973                 ret = _FALSE;
9974         }
9975         else
9976         {
9977                 ret = _TRUE;
9978         }
9979
9980         sta_update_last_rx_pkts(psta);
9981
9982         return ret;
9983 }
9984
9985 void linked_status_chk(_adapter *padapter)
9986 {
9987         u32     i;
9988         struct sta_info         *psta;
9989         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
9990         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9991         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9992         struct sta_priv         *pstapriv = &padapter->stapriv;
9993
9994         if(padapter->bRxRSSIDisplay)
9995                  _linked_rx_signal_strehgth_display(padapter);
9996
9997         #ifdef DBG_CONFIG_ERROR_DETECT
9998         rtw_hal_sreset_linked_status_check(padapter);
9999         #endif
10000
10001         if (is_client_associated_to_ap(padapter))
10002         {
10003                 /* linked infrastructure client mode */
10004
10005                 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
10006                 int rx_chk_limit;
10007
10008                 #if defined(DBG_ROAMING_TEST)
10009                 rx_chk_limit = 1;
10010                 #elif defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK)
10011                 rx_chk_limit = 4;
10012                 #else
10013                 rx_chk_limit = 8;
10014                 #endif
10015
10016                 #ifdef CONFIG_INTEL_WIDI
10017                 if (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_NONE)
10018                         rx_chk_limit = 1;
10019                 #endif
10020
10021                 if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
10022                 {
10023                         bool is_p2p_enable = _FALSE;
10024                         #ifdef CONFIG_P2P
10025                         is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
10026                         #endif
10027
10028                         if (chk_ap_is_alive(padapter, psta) == _FALSE)
10029                                 rx_chk = _FAIL;
10030
10031                         if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
10032                                 tx_chk = _FAIL;
10033
10034                         #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
10035                         if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
10036                                 u8 backup_oper_channel=0;
10037
10038                                 /* switch to correct channel of current network  before issue keep-alive frames */
10039                                 if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
10040                                         backup_oper_channel = rtw_get_oper_ch(padapter);
10041                                         SelectChannel(padapter, pmlmeext->cur_channel);
10042                                 }
10043
10044                                 if (rx_chk != _SUCCESS)
10045                                         issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
10046
10047                                 if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
10048                                         tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
10049                                         /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
10050                                         if (tx_chk == _SUCCESS && !is_p2p_enable)
10051                                                 rx_chk = _SUCCESS;
10052                                 }
10053
10054                                 /* back to the original operation channel */
10055                                 if(backup_oper_channel>0)
10056                                         SelectChannel(padapter, backup_oper_channel);
10057
10058                         }
10059                         else
10060                         #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
10061                         {
10062                                 if (rx_chk != _SUCCESS) {
10063                                         if (pmlmeext->retry == 0) {
10064                                                 #ifdef DBG_EXPIRATION_CHK
10065                                                 DBG_8723A("issue_probereq to trigger probersp, retry=%d\n", pmlmeext->retry);
10066                                                 #endif
10067                                                 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
10068                                                 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
10069                                                 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
10070                                         }
10071                                 }
10072
10073                                 if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) {
10074                                         #ifdef DBG_EXPIRATION_CHK
10075                                         DBG_8723A("%s issue_nulldata 0\n", __FUNCTION__);
10076                                         #endif
10077                                         tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0);
10078                                 }
10079                         }
10080
10081                         if (rx_chk == _FAIL) {
10082                                 pmlmeext->retry++;
10083                                 if (pmlmeext->retry > rx_chk_limit) {
10084                                         DBG_8723A_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
10085                                                 FUNC_ADPT_ARG(padapter));
10086                                         receive_disconnect(padapter, pmlmeinfo->network.MacAddress
10087                                                 , WLAN_REASON_EXPIRATION_CHK);
10088                                         return;
10089                                 }
10090                         } else {
10091                                 pmlmeext->retry = 0;
10092                         }
10093
10094                         if (tx_chk == _FAIL) {
10095                                 pmlmeinfo->link_count &= 0xf;
10096                         } else {
10097                                 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
10098                                 pmlmeinfo->link_count = 0;
10099                         }
10100
10101                 } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
10102         }
10103         else if (is_client_associated_to_ibss(padapter))
10104         {
10105                 /* linked IBSS mode */
10106                 /* for each assoc list entry to check the rx pkt counter */
10107                 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
10108                 {
10109                         if (pmlmeinfo->FW_sta_info[i].status == 1)
10110                         {
10111                                 psta = pmlmeinfo->FW_sta_info[i].psta;
10112
10113                                 if(NULL==psta) continue;
10114
10115                                 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta))
10116                                 {
10117
10118                                         if(pmlmeinfo->FW_sta_info[i].retry<3)
10119                                         {
10120                                                 pmlmeinfo->FW_sta_info[i].retry++;
10121                                         }
10122                                         else
10123                                         {
10124                                                 pmlmeinfo->FW_sta_info[i].retry = 0;
10125                                                 pmlmeinfo->FW_sta_info[i].status = 0;
10126                                                 report_del_sta_event(padapter, psta->hwaddr
10127                                                         , 65535/*  indicate disconnect caused by no rx */
10128                                                 );
10129                                         }
10130                                 }
10131                                 else
10132                                 {
10133                                         pmlmeinfo->FW_sta_info[i].retry = 0;
10134                                         pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
10135                                 }
10136                         }
10137                 }
10138
10139                 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
10140
10141         }
10142 }
10143
10144 void survey_timer_hdl(_adapter *padapter)
10145 {
10146         struct cmd_obj  *ph2c;
10147         struct sitesurvey_parm  *psurveyPara;
10148         struct cmd_priv                                 *pcmdpriv=&padapter->cmdpriv;
10149         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
10150 #ifdef CONFIG_P2P
10151         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
10152 #endif
10153
10154         /* DBG_8723A("marc: survey timer\n"); */
10155         /* issue rtw_sitesurvey_cmd */
10156         if (pmlmeext->sitesurvey_res.state > SCAN_START)
10157         {
10158                 if(pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
10159                 {
10160 #ifdef CONFIG_STA_MODE_SCAN_UNDER_AP_MODE
10161                         if( padapter->mlmeextpriv.mlmext_info.scan_cnt != RTW_SCAN_NUM_OF_CH )
10162 #endif /* CONFIG_STA_MODE_SCAN_UNDER_AP_MODE */
10163                                 pmlmeext->sitesurvey_res.channel_idx++;
10164                 }
10165
10166                 if(pmlmeext->scan_abort == _TRUE)
10167                 {
10168                         #ifdef CONFIG_P2P
10169                         if(!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE))
10170                         {
10171                                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
10172                                 pmlmeext->sitesurvey_res.channel_idx = 3;
10173                                 DBG_8723A("%s idx:%d, cnt:%u\n", __FUNCTION__
10174                                         , pmlmeext->sitesurvey_res.channel_idx
10175                                         , pwdinfo->find_phase_state_exchange_cnt
10176                                 );
10177                         }
10178                         else
10179                         #endif
10180                         {
10181                                 pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
10182                                 DBG_8723A("%s idx:%d\n", __FUNCTION__
10183                                         , pmlmeext->sitesurvey_res.channel_idx
10184                                 );
10185                         }
10186
10187                         pmlmeext->scan_abort = _FALSE;/* reset */
10188                 }
10189
10190                 if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10191                 {
10192                         goto exit_survey_timer_hdl;
10193                 }
10194
10195                 if ((psurveyPara = (struct sitesurvey_parm*)rtw_zmalloc(sizeof(struct sitesurvey_parm))) == NULL)
10196                 {
10197                         rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
10198                         goto exit_survey_timer_hdl;
10199                 }
10200
10201                 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
10202                 rtw_enqueue_cmd(pcmdpriv, ph2c);
10203         }
10204
10205 exit_survey_timer_hdl:
10206         return;
10207 }
10208
10209 void link_timer_hdl(_adapter *padapter)
10210 {
10211         /* static unsigned int          rx_pkt = 0; */
10212         /* static u64                           tx_cnt = 0; */
10213         /* struct xmit_priv             *pxmitpriv = &(padapter->xmitpriv); */
10214         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10215         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10216         /* struct sta_priv              *pstapriv = &padapter->stapriv; */
10217
10218         if (pmlmeinfo->state & WIFI_FW_AUTH_NULL)
10219         {
10220                 DBG_8723A("link_timer_hdl:no beacon while connecting\n");
10221                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
10222                 report_join_res(padapter, -3);
10223         }
10224         else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE)
10225         {
10226                 /* re-auth timer */
10227                 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT)
10228                 {
10229                         /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
10230                         /*  */
10231                                 pmlmeinfo->state = 0;
10232                                 report_join_res(padapter, -1);
10233                                 return;
10234                         /*  */
10235                         /* else */
10236                         /*  */
10237                         /*      pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
10238                         /*      pmlmeinfo->reauth_count = 0; */
10239                         /*  */
10240                 }
10241
10242                 DBG_8723A("link_timer_hdl: auth timeout and try again\n");
10243                 pmlmeinfo->auth_seq = 1;
10244                 issue_auth(padapter, NULL, 0);
10245                 set_link_timer(pmlmeext, REAUTH_TO);
10246         }
10247         else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)
10248         {
10249                 /* re-assoc timer */
10250                 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT)
10251                 {
10252                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
10253                         report_join_res(padapter, -2);
10254                         return;
10255                 }
10256
10257                 DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
10258                 issue_assocreq(padapter);
10259                 set_link_timer(pmlmeext, REASSOC_TO);
10260         }
10261
10262         return;
10263 }
10264
10265 void addba_timer_hdl(struct sta_info *psta)
10266 {
10267 #ifdef CONFIG_80211N_HT
10268         struct ht_priv  *phtpriv;
10269
10270         if(!psta)
10271                 return;
10272
10273         phtpriv = &psta->htpriv;
10274
10275         if((phtpriv->ht_option==_TRUE) && (phtpriv->ampdu_enable==_TRUE))
10276         {
10277                 if(phtpriv->candidate_tid_bitmap)
10278                         phtpriv->candidate_tid_bitmap=0x0;
10279
10280         }
10281 #endif /* CONFIG_80211N_HT */
10282 }
10283
10284 u8 NULL_hdl(_adapter *padapter, u8 *pbuf)
10285 {
10286         return H2C_SUCCESS;
10287 }
10288
10289 u8 setopmode_hdl(_adapter *padapter, u8 *pbuf)
10290 {
10291         u8      type;
10292         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10293         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10294         struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
10295
10296         if(psetop->mode == Ndis802_11APMode)
10297         {
10298                 pmlmeinfo->state = WIFI_FW_AP_STATE;
10299                 type = _HW_STATE_AP_;
10300 #ifdef CONFIG_NATIVEAP_MLME
10301                 /* start_ap_mode(padapter); */
10302 #endif
10303         }
10304         else if(psetop->mode == Ndis802_11Infrastructure)
10305         {
10306                 pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
10307                 pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to     STATION_STATE */
10308                 type = _HW_STATE_STATION_;
10309         }
10310         else if(psetop->mode == Ndis802_11IBSS)
10311         {
10312                 type = _HW_STATE_ADHOC_;
10313         }
10314         else
10315         {
10316                 type = _HW_STATE_NOLINK_;
10317         }
10318
10319         rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
10320         /* Set_NETYPE0_MSR(padapter, type); */
10321
10322         return H2C_SUCCESS;
10323 }
10324
10325 u8 createbss_hdl(_adapter *padapter, u8 *pbuf)
10326 {
10327         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10328         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10329         WLAN_BSSID_EX   *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
10330         struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
10331         /* u32  initialgain; */
10332
10333         if(pparm->network.InfrastructureMode == Ndis802_11APMode)
10334         {
10335 #ifdef CONFIG_AP_MODE
10336
10337                 if(pmlmeinfo->state == WIFI_FW_AP_STATE)
10338                 {
10339                         /* todo: */
10340                         return H2C_SUCCESS;
10341                 }
10342 #endif
10343         }
10344
10345         /* below is for ad-hoc master */
10346         if(pparm->network.InfrastructureMode == Ndis802_11IBSS)
10347         {
10348                 rtw_joinbss_reset(padapter);
10349
10350                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
10351                 pmlmeext->cur_ch_offset= HAL_PRIME_CHNL_OFFSET_DONT_CARE;
10352                 pmlmeinfo->ERP_enable = 0;
10353                 pmlmeinfo->WMM_enable = 0;
10354                 pmlmeinfo->HT_enable = 0;
10355                 pmlmeinfo->HT_caps_enable = 0;
10356                 pmlmeinfo->HT_info_enable = 0;
10357                 pmlmeinfo->agg_enable_bitmap = 0;
10358                 pmlmeinfo->candidate_tid_bitmap = 0;
10359
10360                 /* disable dynamic functions, such as high power, DIG */
10361                 Save_DM_Func_Flag(padapter);
10362                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
10363
10364                 /* config the initial gain under linking, need to write the BB registers */
10365                 /* initialgain = 0x1E; */
10366                 /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
10367
10368                 /* cancel link timer */
10369                 _cancel_timer_ex(&pmlmeext->link_timer);
10370
10371                 /* clear CAM */
10372                 flush_all_cam_entry(padapter);
10373
10374                 memcpy(pnetwork, pbuf, FIELD_OFFSET(WLAN_BSSID_EX, IELength));
10375                 pnetwork->IELength = ((WLAN_BSSID_EX *)pbuf)->IELength;
10376
10377                 if(pnetwork->IELength>MAX_IE_SZ)/* Check pbuf->IELength */
10378                         return H2C_PARAMETERS_ERROR;
10379
10380                 memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength);
10381
10382                 start_create_ibss(padapter);
10383
10384         }
10385
10386         return H2C_SUCCESS;
10387 }
10388
10389 u8 join_cmd_hdl(_adapter *padapter, u8 *pbuf)
10390 {
10391         u8      join_type;
10392         PNDIS_802_11_VARIABLE_IEs       pIE;
10393         struct registry_priv    *pregpriv = &padapter->registrypriv;
10394         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10395         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10396         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
10397 #ifdef CONFIG_ANTENNA_DIVERSITY
10398         struct joinbss_parm     *pparm = (struct joinbss_parm *)pbuf;
10399 #endif /* CONFIG_ANTENNA_DIVERSITY */
10400         u32 i;
10401         /* u32  initialgain; */
10402         /* u32  acparm; */
10403
10404         /* check already connecting to AP or not */
10405         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
10406         {
10407                 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
10408                 {
10409                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100);
10410                 }
10411
10412                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
10413
10414                 /* clear CAM */
10415                 flush_all_cam_entry(padapter);
10416
10417                 _cancel_timer_ex(&pmlmeext->link_timer);
10418
10419                 /* set MSR to nolink -> infra. mode */
10420                 /* Set_MSR(padapter, _HW_STATE_NOLINK_); */
10421                 Set_MSR(padapter, _HW_STATE_STATION_);
10422
10423                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
10424         }
10425
10426 #ifdef CONFIG_ANTENNA_DIVERSITY
10427         rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, _FALSE);
10428 #endif
10429
10430 #ifdef CONFIG_WAPI_SUPPORT
10431         rtw_wapi_clear_all_cam_entry(padapter);
10432 #endif
10433
10434         rtw_joinbss_reset(padapter);
10435
10436         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
10437         pmlmeext->cur_ch_offset= HAL_PRIME_CHNL_OFFSET_DONT_CARE;
10438         pmlmeinfo->ERP_enable = 0;
10439         pmlmeinfo->WMM_enable = 0;
10440         pmlmeinfo->HT_enable = 0;
10441         pmlmeinfo->HT_caps_enable = 0;
10442         pmlmeinfo->HT_info_enable = 0;
10443         pmlmeinfo->agg_enable_bitmap = 0;
10444         pmlmeinfo->candidate_tid_bitmap = 0;
10445         pmlmeinfo->bwmode_updated = _FALSE;
10446         /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
10447
10448         memcpy(pnetwork, pbuf, FIELD_OFFSET(WLAN_BSSID_EX, IELength));
10449         pnetwork->IELength = ((WLAN_BSSID_EX *)pbuf)->IELength;
10450
10451         if(pnetwork->IELength>MAX_IE_SZ)/* Check pbuf->IELength */
10452                 return H2C_PARAMETERS_ERROR;
10453
10454         memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength);
10455
10456         /* Check AP vendor to move rtw_joinbss_cmd() */
10457         /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */
10458
10459         for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;)
10460         {
10461                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
10462
10463                 switch (pIE->ElementID)
10464                 {
10465                         case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
10466                                 if (!memcmp(pIE->data, WMM_OUI, 4))
10467                                 {
10468                                         pmlmeinfo->WMM_enable = 1;
10469                                 }
10470                                 break;
10471
10472                         case _HT_CAPABILITY_IE_:        /* Get HT Cap IE. */
10473                                 pmlmeinfo->HT_caps_enable = 1;
10474                                 break;
10475
10476                         case _HT_EXTRA_INFO_IE_:        /* Get HT Info IE. */
10477 #ifdef CONFIG_80211N_HT
10478                                 pmlmeinfo->HT_info_enable = 1;
10479
10480                                 /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
10481 /* if !defined(CONFIG_CONCURRENT_MODE) && !defined(CONFIG_DUALMAC_CONCURRENT) */
10482 /*                              if(pmlmeinfo->assoc_AP_vendor == ciscoAP) */
10483 /* endif */
10484                                 {
10485                                         struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
10486
10487                                         if ((pregpriv->cbw40_enable) &&  (pht_info->infos[0] & BIT(2)))
10488                                         {
10489                                                 /* switch to the 40M Hz mode according to the AP */
10490                                                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
10491                                                 switch (pht_info->infos[0] & 0x3)
10492                                                 {
10493                                                         case 1:
10494                                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
10495                                                                 break;
10496
10497                                                         case 3:
10498                                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
10499                                                                 break;
10500
10501                                                         default:
10502                                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
10503                                                                 break;
10504                                                 }
10505
10506                                                 DBG_8723A("set ch/bw before connected\n");
10507                                         }
10508                                 }
10509 #endif /* CONFIG_80211N_HT */
10510                                 break;
10511
10512                         default:
10513                                 break;
10514                 }
10515
10516                 i += (pIE->Length + 2);
10517         }
10518         /* disable dynamic functions, such as high power, DIG */
10519         /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE); */
10520
10521         /* config the initial gain under linking, need to write the BB registers */
10522         /* initialgain = 0x1E; */
10523         /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
10524
10525         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
10526         join_type = 0;
10527         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
10528
10529         /* cancel link timer */
10530         _cancel_timer_ex(&pmlmeext->link_timer);
10531
10532         start_clnt_join(padapter);
10533
10534         return H2C_SUCCESS;
10535 }
10536
10537 u8 disconnect_hdl(_adapter *padapter, unsigned char *pbuf)
10538 {
10539         struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
10540         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10541         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10542         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
10543         u8      val8;
10544
10545         if (is_client_associated_to_ap(padapter))
10546         {
10547                 issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
10548         }
10549
10550         /* set_opmode_cmd(padapter, infra_client_with_mlme); */
10551
10552         /* pmlmeinfo->state = WIFI_FW_NULL_STATE; */
10553
10554         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
10555         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
10556
10557         /* restore to initial setting. */
10558         update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
10559
10560         if(((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
10561         {
10562                 /* Stop BCN */
10563                 val8 = 0;
10564                 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
10565         }
10566
10567         /* set MSR to no link state -> infra. mode */
10568         Set_MSR(padapter, _HW_STATE_STATION_);
10569
10570         pmlmeinfo->state = WIFI_FW_NULL_STATE;
10571
10572 #ifdef CONFIG_DUALMAC_CONCURRENT
10573         dc_set_channel_bwmode_disconnect(padapter);
10574 #else
10575 #ifdef CONFIG_CONCURRENT_MODE
10576         if((check_buddy_fwstate(padapter, _FW_LINKED)) != _TRUE)
10577         {
10578 #endif /* CONFIG_CONCURRENT_MODE */
10579                 /* switch to the 20M Hz mode after disconnect */
10580                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
10581                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
10582
10583                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
10584 #ifdef CONFIG_CONCURRENT_MODE
10585         }
10586 #endif /* CONFIG_CONCURRENT_MODE */
10587 #endif /* CONFIG_DUALMAC_CONCURRENT */
10588
10589         flush_all_cam_entry(padapter);
10590
10591         _cancel_timer_ex(&pmlmeext->link_timer);
10592
10593         rtw_free_uc_swdec_pending_queue(padapter);
10594
10595         return  H2C_SUCCESS;
10596 }
10597
10598 int rtw_scan_ch_decision(_adapter *padapter, struct rtw_ieee80211_channel *out,
10599         u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
10600 {
10601         int i, j;
10602         int scan_ch_num = 0;
10603         int set_idx;
10604         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10605
10606         /* clear out first */
10607         memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
10608
10609         /* acquire channels from in */
10610         j = 0;
10611         for (i=0;i<in_num;i++) {
10612                 if (0)
10613                 DBG_8723A(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
10614                 if(in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED)
10615                         && (set_idx=rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value)) >=0
10616                 )
10617                 {
10618                         memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
10619
10620                         if(pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
10621                                 out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
10622
10623                         j++;
10624                 }
10625                 if(j>=out_num)
10626                         break;
10627         }
10628
10629         /* if out is empty, use channel_set as default */
10630         if(j == 0) {
10631                 for (i=0;i<pmlmeext->max_chan_nums;i++) {
10632                         out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
10633
10634                         if(pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
10635                                 out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
10636
10637                         j++;
10638                 }
10639         }
10640
10641         if (padapter->setband == GHZ_24) {                              /*  2.4G */
10642                 for (i=0; i < j ; i++) {
10643                         if (out[i].hw_value > 35)
10644                                 memset(&out[i], 0 , sizeof(struct rtw_ieee80211_channel));
10645                         else
10646                                 scan_ch_num++;
10647                 }
10648                 j = scan_ch_num;
10649         } else if  (padapter->setband == GHZ_50) {                      /*  5G */
10650                 for (i=0; i < j ; i++) {
10651                         if (out[i].hw_value > 35) {
10652                                 memcpy(&out[scan_ch_num++], &out[i], sizeof(struct rtw_ieee80211_channel));
10653                         }
10654                 }
10655                 j = scan_ch_num;
10656         } else
10657                 {}
10658
10659         return j;
10660 }
10661
10662 u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf)
10663 {
10664         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10665         struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
10666         u8      bdelayscan = _FALSE;
10667         u8      val8;
10668         u32     initialgain;
10669         u32     i;
10670
10671 #ifdef CONFIG_P2P
10672         struct wifidirect_info* pwdinfo = &padapter->wdinfo;
10673 #endif
10674
10675         if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE)
10676         {
10677                 /* for first time sitesurvey_cmd */
10678                 rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
10679
10680                 pmlmeext->sitesurvey_res.state = SCAN_START;
10681                 pmlmeext->sitesurvey_res.bss_cnt = 0;
10682                 pmlmeext->sitesurvey_res.channel_idx = 0;
10683
10684                 for(i=0;i<RTW_SSID_SCAN_AMOUNT;i++){
10685                         if(pparm->ssid[i].SsidLength) {
10686                                 memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
10687                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength= pparm->ssid[i].SsidLength;
10688                         } else {
10689                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength= 0;
10690                         }
10691                 }
10692
10693                 pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
10694                         , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
10695                         , pparm->ch, pparm->ch_num
10696                 );
10697
10698                 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
10699
10700 #ifdef CONFIG_DUALMAC_CONCURRENT
10701                 bdelayscan = dc_handle_site_survey(padapter);
10702 #endif
10703
10704                 /* issue null data if associating to the AP */
10705                 if (is_client_associated_to_ap(padapter) == _TRUE)
10706                 {
10707                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
10708
10709                         /* switch to correct channel of current network  before issue keep-alive frames */
10710                         if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
10711                                 SelectChannel(padapter, pmlmeext->cur_channel);
10712                         }
10713
10714                         issue_nulldata(padapter, NULL, 1, 3, 500);
10715
10716 #ifdef CONFIG_CONCURRENT_MODE
10717                         if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
10718                         {
10719                                 DBG_8723A("adapter is scanning(buddy_adapter is linked), issue nulldata(pwrbit=1)\n");
10720
10721                                 issue_nulldata(padapter->pbuddy_adapter, NULL, 1, 3, 500);
10722                         }
10723 #endif
10724                         bdelayscan = _TRUE;
10725                 }
10726 #ifdef CONFIG_CONCURRENT_MODE
10727                 else if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
10728                 {
10729                         #ifdef CONFIG_TDLS
10730                         if(padapter->pbuddy_adapter->wdinfo.wfd_tdls_enable == 1)
10731                         {
10732                                 issue_tunneled_probe_req(padapter->pbuddy_adapter);
10733                         }
10734                         #endif /* CONFIG_TDLS */
10735
10736                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
10737
10738                         issue_nulldata(padapter->pbuddy_adapter, NULL, 1, 3, 500);
10739
10740                         bdelayscan = _TRUE;
10741                 }
10742 #endif
10743                 if(bdelayscan)
10744                 {
10745                         /* delay 50ms to protect nulldata(1). */
10746                         set_survey_timer(pmlmeext, 50);
10747                         return H2C_SUCCESS;
10748                 }
10749         }
10750
10751         if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL))
10752         {
10753                 /* disable dynamic functions, such as high power, DIG */
10754                 Save_DM_Func_Flag(padapter);
10755                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
10756
10757                 /* config the initial gain under scaning, need to write the BB registers */
10758 #ifdef CONFIG_IOCTL_CFG80211
10759                 if((wdev_to_priv(padapter->rtw_wdev))->p2p_enabled == _TRUE)
10760                 {
10761                         initialgain = 0x30;
10762                 }
10763                 else
10764                         initialgain = 0x1E;
10765 #else   /*      go through the WEXT interface CONFIG_IOCTL_CFG80211 */
10766 #ifdef CONFIG_P2P
10767                 if ( rtw_p2p_chk_state( pwdinfo, P2P_STATE_NONE ) )
10768                         initialgain = 0x1E;
10769                 else
10770                         initialgain = 0x28;
10771 #else   /*  CONFIG_P2P */
10772                 initialgain = 0x1E;
10773 #endif /*  CONFIG_P2P */
10774 #endif /*  CONFIG_IOCTL_CFG80211 */
10775
10776                 rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
10777
10778                 /* set MSR to no link state */
10779                 Set_MSR(padapter, _HW_STATE_NOLINK_);
10780
10781                 val8 = 1; /* under site survey */
10782                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
10783
10784                 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
10785         }
10786
10787         site_survey(padapter);
10788
10789         return H2C_SUCCESS;
10790 }
10791
10792 u8 setauth_hdl(_adapter *padapter, unsigned char *pbuf)
10793 {
10794         struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
10795         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10796         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10797
10798         if (pparm->mode < 4)
10799         {
10800                 pmlmeinfo->auth_algo = pparm->mode;
10801         }
10802
10803         return  H2C_SUCCESS;
10804 }
10805
10806 u8 setkey_hdl(_adapter *padapter, u8 *pbuf)
10807 {
10808         unsigned short                          ctrl;
10809         struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
10810         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10811         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10812         unsigned char                                   null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
10813
10814         /* main tx key for wep. */
10815         if(pparm->set_tx)
10816                 pmlmeinfo->key_index = pparm->keyid;
10817
10818         /* write cam */
10819         ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
10820
10821         DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
10822                         "keyid:%d\n", pparm->algorithm, pparm->keyid);
10823         write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
10824
10825         /* allow multicast packets to driver */
10826         padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
10827
10828         return H2C_SUCCESS;
10829 }
10830
10831 u8 set_stakey_hdl(_adapter *padapter, u8 *pbuf)
10832 {
10833         u16 ctrl=0;
10834         u8 cam_id;/* cam_entry */
10835         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10836         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10837         struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
10838 #ifdef CONFIG_TDLS
10839         struct tdls_info        *ptdlsinfo = &padapter->tdlsinfo;
10840         struct sta_priv *pstapriv = &padapter->stapriv;
10841         struct sta_info *psta;
10842 #endif /* CONFIG_TDLS */
10843
10844         /* cam_entry: */
10845         /* 0~3 for default key */
10846
10847         /* for concurrent mode (ap+sta): */
10848         /* default key is disable, using sw encrypt/decrypt */
10849         /* cam_entry = 4  for sta mode (macid=0) */
10850         /* cam_entry(macid+3) = 5 ~ N for ap mode (aid=1~N, macid=2 ~N) */
10851
10852         /* for concurrent mode (sta+sta): */
10853         /* default key is disable, using sw encrypt/decrypt */
10854         /* cam_entry = 4 mapping to macid=0 */
10855         /* cam_entry = 5 mapping to macid=2 */
10856
10857 #ifdef CONFIG_CONCURRENT_MODE
10858         if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
10859         {
10860                 struct sta_priv *pstapriv = &padapter->stapriv;
10861                 struct sta_info *psta;
10862
10863                 psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
10864
10865                 if(psta && psta->mac_id==2)
10866                 {
10867                         cam_id = 5;
10868                 }
10869                 else
10870                 {
10871                         cam_id = 4;
10872                 }
10873 /*
10874                 if(padapter->iface_type > PRIMARY_IFACE)
10875                 {
10876                         cam_id = 5;
10877                 }
10878                 else
10879                 {
10880                         cam_id = 4;
10881                 }
10882 */
10883         }
10884 #else
10885         cam_id = 4;
10886 #endif
10887
10888         DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n",
10889                         pparm->algorithm, cam_id);
10890         if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
10891         {
10892
10893                 struct sta_info *psta;
10894                 struct sta_priv *pstapriv = &padapter->stapriv;
10895
10896                 if(pparm->algorithm == _NO_PRIVACY_)    /*  clear cam entry */
10897                 {
10898                         clear_cam_entry(padapter, pparm->id);
10899                         return H2C_SUCCESS_RSP;
10900                 }
10901
10902                 psta = rtw_get_stainfo(pstapriv, pparm->addr);
10903                 if(psta)
10904                 {
10905                         ctrl = (BIT(15) | ((pparm->algorithm) << 2));
10906
10907                         DBG_8723A("r871x_set_stakey_hdl(): enc_algorithm=%d\n", pparm->algorithm);
10908
10909                         if((psta->mac_id<1) || (psta->mac_id>(NUM_STA-4)))
10910                         {
10911                                 DBG_8723A("r871x_set_stakey_hdl():set_stakey failed, mac_id(aid)=%d\n", psta->mac_id);
10912                                 return H2C_REJECTED;
10913                         }
10914
10915                         cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id=macid + 3, macid=aid+1; */
10916
10917                         DBG_8723A("Write CAM, mac_addr=%x:%x:%x:%x:%x:%x, cam_entry=%d\n", pparm->addr[0],
10918                                                 pparm->addr[1], pparm->addr[2], pparm->addr[3], pparm->addr[4],
10919                                                 pparm->addr[5], cam_id);
10920
10921                         write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
10922
10923                         return H2C_SUCCESS_RSP;
10924
10925                 }
10926                 else
10927                 {
10928                         DBG_8723A("r871x_set_stakey_hdl(): sta has been free\n");
10929                         return H2C_REJECTED;
10930                 }
10931
10932         }
10933
10934         /* below for sta mode */
10935
10936         if(pparm->algorithm == _NO_PRIVACY_)    /*  clear cam entry */
10937         {
10938                 clear_cam_entry(padapter, pparm->id);
10939                 return H2C_SUCCESS;
10940         }
10941
10942         ctrl = BIT(15) | ((pparm->algorithm) << 2);
10943
10944 #ifdef CONFIG_TDLS
10945         if(ptdlsinfo->clear_cam!=0){
10946                 clear_cam_entry(padapter, ptdlsinfo->clear_cam);
10947                 ptdlsinfo->clear_cam=0;
10948
10949                 return H2C_SUCCESS;
10950         }
10951
10952         psta = rtw_get_stainfo(pstapriv, pparm->addr);/* Get TDLS Peer STA */
10953         if( psta->tdls_sta_state&TDLS_LINKED_STATE ){
10954                 write_cam(padapter, psta->mac_id, ctrl, pparm->addr, pparm->key);
10955         }
10956         else
10957 #endif /* CONFIG_TDLS */
10958         write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
10959
10960         pmlmeinfo->enc_algo = pparm->algorithm;
10961
10962         return H2C_SUCCESS;
10963 }
10964
10965 u8 add_ba_hdl(_adapter *padapter, unsigned char *pbuf)
10966 {
10967         struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
10968         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10969         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10970
10971         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
10972
10973         if(!psta)
10974                 return  H2C_SUCCESS;
10975
10976 #ifdef CONFIG_80211N_HT
10977         if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
10978                 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
10979         {
10980                 /* pmlmeinfo->ADDBA_retry_count = 0; */
10981                 /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */
10982                 /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */
10983                 issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
10984                 /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */
10985                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
10986         }
10987 #ifdef CONFIG_TDLS
10988         else if((psta->tdls_sta_state & TDLS_LINKED_STATE)&&
10989                 (psta->htpriv.ht_option==_TRUE) &&
10990                 (psta->htpriv.ampdu_enable==_TRUE) )
10991         {
10992                 issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
10993                 /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */
10994                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
10995         }
10996 #endif /* CONFIG */
10997         else
10998         {
10999                 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
11000         }
11001 #endif /* CONFIG_80211N_HT */
11002         return  H2C_SUCCESS;
11003 }
11004
11005 u8 set_tx_beacon_cmd(_adapter* padapter)
11006 {
11007         struct cmd_obj  *ph2c;
11008         struct Tx_Beacon_param  *ptxBeacon_parm;
11009         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
11010         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11011         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11012         u8      res = _SUCCESS;
11013         int len_diff = 0;
11014
11015 _func_enter_;
11016
11017         if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
11018         {
11019                 res= _FAIL;
11020                 goto exit;
11021         }
11022
11023         if ((ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param))) == NULL)
11024         {
11025                 rtw_mfree((unsigned char *)ph2c, sizeof(struct  cmd_obj));
11026                 res= _FAIL;
11027                 goto exit;
11028         }
11029
11030         memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));
11031
11032         len_diff = update_hidden_ssid(
11033                 ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_
11034                 , ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_
11035                 , pmlmeinfo->hidden_ssid_mode
11036         );
11037         ptxBeacon_parm->network.IELength += len_diff;
11038
11039         init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
11040
11041         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
11042
11043 exit:
11044
11045 _func_exit_;
11046
11047         return res;
11048 }
11049
11050 u8 mlme_evt_hdl(_adapter *padapter, unsigned char *pbuf)
11051 {
11052         u8 evt_code, evt_seq;
11053         u16 evt_sz;
11054         uint    *peventbuf;
11055         void (*event_callback)(_adapter *dev, u8 *pbuf);
11056         struct evt_priv *pevt_priv = &(padapter->evtpriv);
11057
11058         peventbuf = (uint*)pbuf;
11059         evt_sz = (u16)(*peventbuf&0xffff);
11060         evt_seq = (u8)((*peventbuf>>24)&0x7f);
11061         evt_code = (u8)((*peventbuf>>16)&0xff);
11062
11063         #ifdef CHECK_EVENT_SEQ
11064         /*  checking event sequence... */
11065         if (evt_seq != (ATOMIC_READ(&pevt_priv->event_seq) & 0x7f) )
11066         {
11067                 RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("Evetn Seq Error! %d vs %d\n", (evt_seq & 0x7f), (ATOMIC_READ(&pevt_priv->event_seq) & 0x7f)));
11068
11069                 pevt_priv->event_seq = (evt_seq+1)&0x7f;
11070
11071                 goto _abort_event_;
11072         }
11073         #endif
11074
11075         /*  checking if event code is valid */
11076         if (evt_code >= MAX_C2HEVT) {
11077                 RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\nEvent Code(%d) mismatch!\n", evt_code));
11078                 goto _abort_event_;
11079         }
11080
11081         /*  checking if event size match the event parm size */
11082         if ((wlanevents[evt_code].parmsize != 0) &&
11083             (wlanevents[evt_code].parmsize != evt_sz)) {
11084                 RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
11085                         evt_code, wlanevents[evt_code].parmsize, evt_sz));
11086                 goto _abort_event_;
11087         }
11088
11089         ATOMIC_INC(&pevt_priv->event_seq);
11090
11091         peventbuf += 2;
11092
11093         if (peventbuf) {
11094                 event_callback = wlanevents[evt_code].event_callback;
11095                 event_callback(padapter, (u8*)peventbuf);
11096
11097                 pevt_priv->evt_done_cnt++;
11098         }
11099
11100 _abort_event_:
11101
11102         return H2C_SUCCESS;
11103 }
11104
11105 u8 h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)
11106 {
11107         if(!pbuf)
11108                 return H2C_PARAMETERS_ERROR;
11109
11110         return H2C_SUCCESS;
11111 }
11112
11113 u8 tx_beacon_hdl(_adapter *padapter, unsigned char *pbuf)
11114 {
11115         if(send_beacon(padapter)==_FAIL)
11116         {
11117                 DBG_8723A("issue_beacon, fail!\n");
11118                 return H2C_PARAMETERS_ERROR;
11119         }
11120 #ifdef CONFIG_AP_MODE
11121         else /* tx bc/mc frames after update TIM */
11122         {
11123                 _irqL irqL;
11124                 struct sta_info *psta_bmc;
11125                 _list   *xmitframe_plist, *xmitframe_phead;
11126                 struct xmit_frame *pxmitframe=NULL;
11127                 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
11128                 struct sta_priv  *pstapriv = &padapter->stapriv;
11129
11130                 /* for BC/MC Frames */
11131                 psta_bmc = rtw_get_bcmc_stainfo(padapter);
11132                 if(!psta_bmc)
11133                         return H2C_SUCCESS;
11134
11135                 if((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len>0))
11136                 {
11137 #ifndef CONFIG_PCI_HCI
11138                         rtw_msleep_os(10);/*  10ms, ATIM(HIQ) Windows */
11139 #endif
11140                         /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
11141                         spin_lock_bh(&pxmitpriv->lock);
11142
11143                         xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
11144                         xmitframe_plist = get_next(xmitframe_phead);
11145
11146                         while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
11147                         {
11148                                 pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
11149
11150                                 xmitframe_plist = get_next(xmitframe_plist);
11151
11152                                 rtw_list_delete(&pxmitframe->list);
11153
11154                                 psta_bmc->sleepq_len--;
11155                                 if(psta_bmc->sleepq_len>0)
11156                                         pxmitframe->attrib.mdata = 1;
11157                                 else
11158                                         pxmitframe->attrib.mdata = 0;
11159
11160                                 pxmitframe->attrib.triggered=1;
11161
11162                                 pxmitframe->attrib.qsel = 0x11;/* HIQ */
11163
11164                                 rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
11165
11166                                 /* pstapriv->tim_bitmap &= ~BIT(0); */
11167
11168                         }
11169
11170                         /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
11171                         spin_unlock_bh(&pxmitpriv->lock);
11172
11173 /* if defined(CONFIG_PCI_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) */
11174 #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
11175                         rtw_chk_hi_queue_cmd(padapter);
11176 #endif
11177
11178                 }
11179
11180         }
11181 #endif
11182
11183         return H2C_SUCCESS;
11184 }
11185
11186 #ifdef CONFIG_DUALMAC_CONCURRENT
11187 void dc_SelectChannel(_adapter *padapter, unsigned char channel)
11188 {
11189         PADAPTER ptarget_adapter;
11190
11191         if( (padapter->pbuddy_adapter != NULL) &&
11192                 (padapter->DualMacConcurrent == _TRUE) &&
11193                 (padapter->adapter_type == SECONDARY_ADAPTER))
11194         {
11195                 /*  only mac0 could control BB&RF */
11196                 ptarget_adapter = padapter->pbuddy_adapter;
11197         }
11198         else
11199         {
11200                 ptarget_adapter = padapter;
11201         }
11202
11203         _enter_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setch_mutex), NULL);
11204
11205         rtw_hal_set_chan(ptarget_adapter, channel);
11206
11207         _exit_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setch_mutex), NULL);
11208 }
11209
11210 void dc_SetBWMode(_adapter *padapter, unsigned short bwmode, unsigned char channel_offset)
11211 {
11212         PADAPTER ptarget_adapter;
11213
11214         if( (padapter->pbuddy_adapter != NULL) &&
11215                 (padapter->DualMacConcurrent == _TRUE) &&
11216                 (padapter->adapter_type == SECONDARY_ADAPTER))
11217         {
11218                 /*  only mac0 could control BB&RF */
11219                 ptarget_adapter = padapter->pbuddy_adapter;
11220         }
11221         else
11222         {
11223                 ptarget_adapter = padapter;
11224         }
11225
11226         _enter_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setbw_mutex), NULL);
11227
11228         rtw_hal_set_bwmode(ptarget_adapter, (HT_CHANNEL_WIDTH)bwmode, channel_offset);
11229
11230         _exit_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setbw_mutex), NULL);
11231 }
11232
11233 static void dc_change_band(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
11234 {
11235         u8      network_type,rate_len, total_rate_len,remainder_rate_len;
11236         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
11237         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
11238         u8      erpinfo=0x4;
11239
11240         /* DBG_8723A("%s\n", __FUNCTION__); */
11241
11242         if(pmlmeext->cur_channel >= 36)
11243         {
11244                 network_type = WIRELESS_11A;
11245                 total_rate_len = IEEE80211_NUM_OFDM_RATESLEN;
11246                 DBG_8723A("%s(): change to 5G Band\n",__FUNCTION__);
11247                 rtw_remove_bcn_ie(padapter, pnetwork, _ERPINFO_IE_);
11248         }
11249         else
11250         {
11251                 network_type = WIRELESS_11BG;
11252                 total_rate_len = IEEE80211_CCK_RATE_LEN+IEEE80211_NUM_OFDM_RATESLEN;
11253                 DBG_8723A("%s(): change to 2.4G Band\n",__FUNCTION__);
11254                 rtw_add_bcn_ie(padapter, pnetwork, _ERPINFO_IE_, &erpinfo, 1);
11255         }
11256
11257         rtw_set_supported_rate(pnetwork->SupportedRates, network_type);
11258
11259         UpdateBrateTbl(padapter, pnetwork->SupportedRates);
11260         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
11261
11262         if(total_rate_len > 8)
11263         {
11264                 rate_len = 8;
11265                 remainder_rate_len = total_rate_len - 8;
11266         }
11267         else
11268         {
11269                 rate_len = total_rate_len;
11270                 remainder_rate_len = 0;
11271         }
11272
11273         rtw_add_bcn_ie(padapter, pnetwork, _SUPPORTEDRATES_IE_, pnetwork->SupportedRates, rate_len);
11274
11275         if(remainder_rate_len)
11276         {
11277                 rtw_add_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_, (pnetwork->SupportedRates+8), remainder_rate_len);
11278         }
11279         else
11280         {
11281                 rtw_remove_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_);
11282         }
11283 }
11284
11285 void dc_set_channel_bwmode_disconnect(_adapter *padapter)
11286 {
11287         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11288         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
11289         struct mlme_priv *pbuddy_mlmepriv = NULL;
11290
11291         if(pbuddy_adapter != NULL &&
11292                 padapter->DualMacConcurrent == _TRUE)
11293         {
11294                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
11295                 if((check_fwstate(pbuddy_mlmepriv, _FW_LINKED)) != _TRUE)
11296                 {
11297                         /* switch to the 20M Hz mode after disconnect */
11298                         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
11299                         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
11300
11301                         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
11302                 }
11303         }
11304         else
11305         {
11306                 /* switch to the 20M Hz mode after disconnect */
11307                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
11308                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
11309
11310                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
11311         }
11312 }
11313
11314 u8 dc_handle_join_request(_adapter *padapter)
11315 {
11316         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11317         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11318         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
11319         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
11320         struct mlme_ext_priv *pbuddy_mlmeext = NULL;
11321         struct mlme_priv        *pbuddy_mlmepriv = NULL;
11322         u8      ret = _SUCCESS;
11323
11324         if(pbuddy_adapter != NULL &&
11325                 padapter->DualMacConcurrent == _TRUE)
11326         {
11327                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
11328                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
11329
11330                 if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel ||
11331                         pmlmeext->cur_bwmode != pbuddy_mlmeext->cur_bwmode ||
11332                         pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)
11333                 {
11334                         if((check_fwstate(pbuddy_mlmepriv, WIFI_AP_STATE)) == _TRUE)
11335                         {
11336                                 /* issue deauth to all stas if if2 is at ap mode */
11337                                 rtw_sta_flush(pbuddy_adapter);
11338
11339                                 /* rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0); */
11340                                 rtw_hal_set_hwreg(pbuddy_adapter, HW_VAR_CHECK_TXBUF, 0);
11341                         }
11342                         else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED) == _TRUE)
11343                         {
11344                                 if(pmlmeext->cur_channel == pbuddy_mlmeext->cur_channel)
11345                                 {
11346                                         /*  HT_CHANNEL_WIDTH_40 or HT_CHANNEL_WIDTH_20 but channel offset is different */
11347                                         if((pmlmeext->cur_bwmode == pbuddy_mlmeext->cur_bwmode) &&
11348                                                 (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset) )
11349                                         {
11350                                                 report_join_res(padapter, -4);
11351                                                 ret = _FAIL;
11352                                         }
11353                                 }
11354                                 else
11355                                 {
11356                                         report_join_res(padapter, -4);
11357                                         ret = _FAIL;
11358                                 }
11359                         }
11360                 }
11361                 else     if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
11362                 {
11363                         issue_nulldata(pbuddy_adapter, NULL, 1, 0, 0);
11364                 }
11365         }
11366
11367         return ret;
11368 }
11369
11370 void dc_handle_join_done(_adapter *padapter, u8 join_res)
11371 {
11372         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11373         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11374         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
11375         struct mlme_priv *pbuddy_mlmepriv = NULL;
11376         struct mlme_ext_priv *pbuddy_mlmeext = NULL;
11377         struct mlme_ext_info *pbuddy_mlmeinfo = NULL;
11378         WLAN_BSSID_EX *pbuddy_network_mlmeext = NULL;
11379         u8      change_band = _FALSE;
11380
11381         if(pbuddy_adapter != NULL &&
11382                 padapter->DualMacConcurrent == _TRUE)
11383         {
11384                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
11385                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
11386                 pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
11387                 pbuddy_network_mlmeext = &(pbuddy_mlmeinfo->network);
11388
11389                 if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
11390                                 check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
11391                 {
11392                         /* restart and update beacon */
11393                         DBG_8723A("after join, current adapter, CH=%d, BW=%d, offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
11394
11395                         if(join_res >= 0)
11396                         {
11397                                 u8 *p;
11398                                 int     ie_len;
11399                                 struct HT_info_element *pht_info=NULL;
11400
11401                                 if((pbuddy_mlmeext->cur_channel <= 14 && pmlmeext->cur_channel >= 36) ||
11402                                         (pbuddy_mlmeext->cur_channel >= 36 && pmlmeext->cur_channel <= 14))
11403                                 {
11404                                         change_band = _TRUE;
11405                                 }
11406
11407                                 /* sync channel/bwmode/ch_offset with another adapter */
11408                                 pbuddy_mlmeext->cur_channel = pmlmeext->cur_channel;
11409
11410                                 if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)
11411                                 {
11412                                         p = rtw_get_ie((pbuddy_network_mlmeext->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pbuddy_network_mlmeext->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
11413                                         if( p && ie_len)
11414                                         {
11415                                                 pht_info = (struct HT_info_element *)(p+2);
11416                                                 pht_info->infos[0] &= ~(BIT(0)|BIT(1)); /* no secondary channel is present */
11417                                         }
11418
11419                                         if(pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)
11420                                         {
11421                                                 pbuddy_mlmeext->cur_ch_offset = pmlmeext->cur_ch_offset;
11422
11423                                                 /* to update cur_ch_offset value in beacon */
11424                                                 if( pht_info )
11425                                                 {
11426                                                         switch(pmlmeext->cur_ch_offset)
11427                                                         {
11428                                                                 case HAL_PRIME_CHNL_OFFSET_LOWER:
11429                                                                         pht_info->infos[0] |= 0x1;
11430                                                                         break;
11431                                                                 case HAL_PRIME_CHNL_OFFSET_UPPER:
11432                                                                         pht_info->infos[0] |= 0x3;
11433                                                                         break;
11434                                                                 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
11435                                                                 default:
11436                                                                         break;
11437                                                         }
11438                                                 }
11439                                         }
11440                                         else if(pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20)
11441                                         {
11442                                                 pbuddy_mlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
11443                                                 pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
11444
11445                                                 if(pmlmeext->cur_channel>0 && pmlmeext->cur_channel<5)
11446                                                 {
11447                                                         if(pht_info)
11448                                                                 pht_info->infos[0] |= 0x1;
11449
11450                                                         pbuddy_mlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
11451                                                         pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
11452                                                 }
11453
11454                                                 if(pmlmeext->cur_channel>7 && pmlmeext->cur_channel<(14+1))
11455                                                 {
11456                                                         if(pht_info)
11457                                                                 pht_info->infos[0] |= 0x3;
11458
11459                                                         pbuddy_mlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
11460                                                         pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
11461                                                 }
11462
11463                                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
11464                                         }
11465                                 }
11466
11467                                 /*  to update channel value in beacon */
11468                                 pbuddy_network_mlmeext->Configuration.DSConfig = pmlmeext->cur_channel;
11469                                 p = rtw_get_ie((pbuddy_network_mlmeext->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (pbuddy_network_mlmeext->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
11470                                 if(p && ie_len>0)
11471                                         *(p + 2) = pmlmeext->cur_channel;
11472
11473                                 p = rtw_get_ie((pbuddy_network_mlmeext->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pbuddy_network_mlmeext->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
11474                                 if( p && ie_len)
11475                                 {
11476                                         pht_info = (struct HT_info_element *)(p+2);
11477                                         pht_info->primary_channel = pmlmeext->cur_channel;
11478                                 }
11479
11480                                 /*  update mlmepriv's cur_network */
11481                                 memcpy(&pbuddy_mlmepriv->cur_network.network, pbuddy_network_mlmeext, pbuddy_network_mlmeext->Length);
11482                         }
11483                         else
11484                         {
11485                                 /*  switch back to original channel/bwmode/ch_offset; */
11486                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
11487                         }
11488
11489                         DBG_8723A("after join, another adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
11490
11491                         if(change_band == _TRUE)
11492                                 dc_change_band(pbuddy_adapter, pbuddy_network_mlmeext);
11493
11494                         DBG_8723A("update pbuddy_adapter's beacon\n");
11495
11496                         update_beacon(pbuddy_adapter, 0, NULL, _TRUE);
11497                 }
11498                 else     if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
11499                 {
11500                         if((pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) &&
11501                                 (pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20))
11502                         {
11503                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
11504                         }
11505
11506                         issue_nulldata(pbuddy_adapter, NULL, 0, 0, 0);
11507                 }
11508         }
11509 }
11510
11511 int     dc_check_fwstate(_adapter *padapter, int fw_state)
11512 {
11513         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
11514         struct mlme_priv *pbuddy_mlmepriv = NULL;
11515
11516         if(padapter->pbuddy_adapter != NULL &&
11517                 padapter->DualMacConcurrent == _TRUE)
11518
11519         {
11520                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
11521
11522                 return check_fwstate(pbuddy_mlmepriv, fw_state);
11523         }
11524
11525         return _FALSE;
11526 }
11527
11528 u8 dc_handle_site_survey(_adapter *padapter)
11529 {
11530         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11531         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11532         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
11533
11534         /*  only mac0 can do scan request, help issue nulldata(1) for mac1 */
11535         if(pbuddy_adapter != NULL &&
11536                 padapter->DualMacConcurrent == _TRUE)
11537         {
11538                 if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
11539                 {
11540                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
11541
11542                         issue_nulldata(pbuddy_adapter, NULL, 1, 2, 0);
11543
11544                         return _TRUE;
11545                 }
11546         }
11547
11548         return _FALSE;
11549 }
11550
11551 void    dc_report_survey_event(_adapter *padapter, union recv_frame *precv_frame)
11552 {
11553         if(padapter->pbuddy_adapter != NULL &&
11554                 padapter->DualMacConcurrent == _TRUE)
11555         {
11556                 report_survey_event(padapter->pbuddy_adapter, precv_frame);
11557         }
11558 }
11559
11560 void dc_set_channel_bwmode_survey_done(_adapter *padapter)
11561 {
11562         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
11563         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11564         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
11565         struct mlme_priv *pbuddy_mlmepriv = NULL;
11566         struct mlme_ext_priv *pbuddy_mlmeext = NULL;
11567         struct mlme_ext_info *pbuddy_mlmeinfo = NULL;
11568         u8 cur_channel;
11569         u8 cur_bwmode;
11570         u8 cur_ch_offset;
11571
11572         if(pbuddy_adapter != NULL &&
11573                 padapter->DualMacConcurrent == _TRUE)
11574         {
11575                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
11576                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
11577                 pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
11578
11579                 if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
11580                 {
11581                         if(check_fwstate(pmlmepriv, _FW_LINKED) &&
11582                                 (pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40))
11583                         {
11584                                 cur_channel = pmlmeext->cur_channel;
11585                                 cur_bwmode = pmlmeext->cur_bwmode;
11586                                 cur_ch_offset = pmlmeext->cur_ch_offset;
11587                         }
11588                         else
11589                         {
11590                                 cur_channel = pbuddy_mlmeext->cur_channel;
11591                                 cur_bwmode = pbuddy_mlmeext->cur_bwmode;
11592                                 cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
11593                         }
11594                 }
11595                 else
11596                 {
11597                         cur_channel = pmlmeext->cur_channel;
11598                         cur_bwmode = pmlmeext->cur_bwmode;
11599                         cur_ch_offset = pmlmeext->cur_ch_offset;
11600                 }
11601
11602                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
11603
11604                 if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
11605                 {
11606                         /* issue null data */
11607                         issue_nulldata(pbuddy_adapter, NULL, 0, 0, 0);
11608                 }
11609
11610                 if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
11611                         check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
11612                 {
11613
11614                         DBG_8723A("survey done, current CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
11615
11616                         DBG_8723A("restart pbuddy_adapter's beacon\n");
11617
11618                         update_beacon(pbuddy_adapter, 0, NULL, _TRUE);
11619                 }
11620         }
11621         else
11622         {
11623                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
11624         }
11625 }
11626
11627 void dc_set_ap_channel_bandwidth(_adapter *padapter, u8 channel, u8 channel_offset, u8 bwmode)
11628 {
11629         u8      *p;
11630         u8      val8, cur_channel, cur_bwmode, cur_ch_offset, change_band;
11631         int     ie_len;
11632         struct registry_priv    *pregpriv = &padapter->registrypriv;
11633         struct mlme_priv                *pmlmepriv = &(padapter->mlmepriv);
11634         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
11635         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
11636         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11637         struct HT_info_element  *pht_info=NULL;
11638         _adapter        *pbuddy_adapter = padapter->pbuddy_adapter;
11639         struct mlme_priv        *pbuddy_mlmepriv = NULL;
11640         struct mlme_ext_priv    *pbuddy_mlmeext = NULL;
11641
11642         DBG_8723A("dualmac_concurrent_ap_set_channel_bwmode ==>\n");
11643
11644         cur_channel = channel;
11645         cur_bwmode = bwmode;
11646         cur_ch_offset = channel_offset;
11647         change_band = _FALSE;
11648
11649         p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
11650         if( p && ie_len)
11651         {
11652                 pht_info = (struct HT_info_element *)(p+2);
11653         }
11654
11655         if(pbuddy_adapter != NULL &&
11656                 padapter->DualMacConcurrent == _TRUE)
11657         {
11658                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
11659                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
11660
11661                 if(!check_fwstate(pbuddy_mlmepriv, _FW_LINKED|_FW_UNDER_LINKING|_FW_UNDER_SURVEY))
11662                 {
11663                         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
11664                 }
11665                 else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED)==_TRUE)
11666                 {
11667                         /* To sync cur_channel/cur_bwmode/cur_ch_offset with another adapter */
11668                         DBG_8723A("Another iface is at linked state, sync cur_channel/cur_bwmode/cur_ch_offset\n");
11669                         DBG_8723A("Another adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
11670                         DBG_8723A("Current adapter, CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
11671
11672                         cur_channel = pbuddy_mlmeext->cur_channel;
11673                         if(cur_bwmode == HT_CHANNEL_WIDTH_40)
11674                         {
11675                                 if(pht_info)
11676                                         pht_info->infos[0] &= ~(BIT(0)|BIT(1));
11677
11678                                 if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)
11679                                 {
11680                                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
11681
11682                                         /* to update cur_ch_offset value in beacon */
11683                                         if(pht_info)
11684                                         {
11685                                                 switch(cur_ch_offset)
11686                                                 {
11687                                                         case HAL_PRIME_CHNL_OFFSET_LOWER:
11688                                                                 pht_info->infos[0] |= 0x1;
11689                                                                 break;
11690                                                         case HAL_PRIME_CHNL_OFFSET_UPPER:
11691                                                                 pht_info->infos[0] |= 0x3;
11692                                                                 break;
11693                                                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
11694                                                         default:
11695                                                                 break;
11696                                                 }
11697                                         }
11698                                 }
11699                                 else if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20)
11700                                 {
11701                                         cur_bwmode = HT_CHANNEL_WIDTH_20;
11702                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
11703
11704                                         if(cur_channel>0 && cur_channel<5)
11705                                         {
11706                                                 if(pht_info)
11707                                                         pht_info->infos[0] |= 0x1;
11708
11709                                                 cur_bwmode = HT_CHANNEL_WIDTH_40;
11710                                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
11711                                         }
11712
11713                                         if(cur_channel>7 && cur_channel<(14+1))
11714                                         {
11715                                                 if(pht_info)
11716                                                         pht_info->infos[0] |= 0x3;
11717
11718                                                 cur_bwmode = HT_CHANNEL_WIDTH_40;
11719                                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
11720                                         }
11721
11722                                         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
11723                                 }
11724                         }
11725
11726                         /*  to update channel value in beacon */
11727                         pnetwork->Configuration.DSConfig = cur_channel;
11728                         p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
11729                         if(p && ie_len>0)
11730                                 *(p + 2) = cur_channel;
11731
11732                         if(pht_info)
11733                                 pht_info->primary_channel = cur_channel;
11734                 }
11735         }
11736         else
11737         {
11738                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
11739         }
11740
11741         DBG_8723A("CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
11742
11743         if((channel <= 14 && cur_channel >= 36) ||
11744                 (channel >= 36 && cur_channel <= 14))
11745         {
11746                 change_band = _TRUE;
11747         }
11748
11749         pmlmeext->cur_channel = cur_channel;
11750         pmlmeext->cur_bwmode = cur_bwmode;
11751         pmlmeext->cur_ch_offset = cur_ch_offset;
11752
11753         if(change_band == _TRUE)
11754                 dc_change_band(padapter, pnetwork);
11755
11756         DBG_8723A("dualmac_concurrent_ap_set_channel_bwmode <==\n");
11757 }
11758
11759 void dc_resume_xmit(_adapter *padapter)
11760 {
11761         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
11762
11763         if(pbuddy_adapter != NULL &&
11764                 padapter->DualMacConcurrent == _TRUE)
11765         {
11766                 DBG_8723A("dc_resume_xmit,  resume pbuddy_adapter Tx\n");
11767                 rtw_os_xmit_schedule(pbuddy_adapter);
11768         }
11769 }
11770
11771 u8      dc_check_xmit(_adapter *padapter)
11772 {
11773         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
11774         struct mlme_priv *pbuddy_mlmepriv = NULL;
11775
11776         if(pbuddy_adapter != NULL &&
11777                 padapter->DualMacConcurrent == _TRUE)
11778         {
11779                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
11780                 if (check_fwstate(pbuddy_mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
11781                 {
11782                         DBG_8723A("dc_check_xmit  pbuddy_adapter is under survey or under linking\n");
11783                         return _FALSE;
11784                 }
11785         }
11786
11787         return _TRUE;
11788 }
11789 #endif
11790
11791 #ifdef CONFIG_CONCURRENT_MODE
11792 int check_buddy_mlmeinfo_state(_adapter *padapter, u32 state)
11793 {
11794         PADAPTER pbuddy_adapter;
11795         struct mlme_ext_priv *pbuddy_mlmeext;
11796         struct mlme_ext_info *pbuddy_mlmeinfo;
11797
11798         if(padapter == NULL)
11799                 return _FALSE;
11800
11801         pbuddy_adapter = padapter->pbuddy_adapter;
11802
11803         if(pbuddy_adapter == NULL)
11804                 return _FALSE;
11805
11806         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
11807         pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
11808
11809         if((pbuddy_mlmeinfo->state&0x03) == state)
11810                 return _TRUE;
11811
11812         return _FALSE;
11813 }
11814
11815 int concurrent_chk_start_clnt_join(_adapter *padapter)
11816 {
11817         int ret = _FAIL;
11818         PADAPTER pbuddy_adapter;
11819         struct mlme_ext_priv *pbuddy_mlmeext;
11820         struct mlme_ext_info    *pbuddy_pmlmeinfo;
11821         struct mlme_priv *pbuddy_mlmepriv;
11822         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11823         unsigned char   cur_ch = pmlmeext->cur_channel;
11824         unsigned char   cur_bw = pmlmeext->cur_bwmode;
11825         unsigned char   cur_ch_offset = pmlmeext->cur_ch_offset;
11826
11827         if(!rtw_buddy_adapter_up(padapter))
11828         {
11829                 goto start_join_set_ch_bw;
11830         }
11831
11832         pbuddy_adapter = padapter->pbuddy_adapter;
11833         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
11834         pbuddy_pmlmeinfo = &(pbuddy_mlmeext->mlmext_info);
11835         pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
11836
11837         if((pbuddy_pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)/* for AP MODE */
11838         {
11839                 bool inform_ch_switch = _FALSE;
11840                 if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel)
11841                 {
11842                         inform_ch_switch = _TRUE;
11843                 }
11844                 else if((pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) &&
11845                         (pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) &&
11846                         (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset))
11847                 {
11848                         inform_ch_switch = _TRUE;
11849                 }
11850                 else if((pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20) &&
11851                         (pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40))
11852                 {
11853                         inform_ch_switch = _FALSE;
11854                         cur_ch = pmlmeext->cur_channel;
11855                         cur_bw = pbuddy_mlmeext->cur_bwmode;
11856                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
11857                 }
11858
11859                 if (inform_ch_switch) {
11860                         #ifdef CONFIG_SPCT_CH_SWITCH
11861                         if (1) {
11862                                 rtw_ap_inform_ch_switch(pbuddy_adapter, pmlmeext->cur_channel , pmlmeext->cur_ch_offset);
11863                         } else
11864                         #endif
11865                         {
11866                                 /* issue deauth to all stas if if2 is at ap mode */
11867                                 rtw_sta_flush(pbuddy_adapter);
11868                         }
11869                         rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
11870                 }
11871         }
11872         else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED) == _TRUE &&
11873                 check_fwstate(pbuddy_mlmepriv, WIFI_STATION_STATE) == _TRUE) /* for Client Mode/p2p client */
11874         {
11875 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
11876                 struct wifidirect_info *pbuddy_wdinfo = &(pbuddy_adapter->wdinfo);
11877                 if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
11878                 {
11879                         goto start_join_set_ch_bw;/* wlan0-sta mode has higher priority than p2p0-p2p client */
11880                 }
11881 #endif /* CONFIG_P2P && CONFIG_IOCTL_CFG80211 */
11882
11883                 if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel)
11884                 {
11885                         DBG_8723A("start_clnt_join(ch=%d), but channel mismatch with buddy(ch=%d) interface\n",
11886                                 pmlmeext->cur_channel, pbuddy_mlmeext->cur_channel);
11887
11888                         report_join_res(padapter, (-4));
11889
11890                         return ret;
11891                 }
11892
11893                 if((pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) &&
11894                         (pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) &&
11895                         (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset))
11896                 {
11897                         DBG_8723A("start_clnt_join(bwmode=%d, ch_offset=%d), but bwmode & ch_offset mismatch with buddy(bwmode=%d, ch_offset=%d) interface\n",
11898                                 pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
11899
11900                         report_join_res(padapter, (-4));
11901
11902                         return ret;
11903                 }
11904
11905         }
11906
11907 start_join_set_ch_bw:
11908
11909         set_channel_bwmode(padapter, cur_ch, cur_ch_offset, cur_bw);
11910
11911         return _SUCCESS;
11912 }
11913
11914 void concurrent_chk_joinbss_done(_adapter *padapter, int join_res)
11915 {
11916         struct mlme_ext_priv    *pmlmeext;
11917         struct mlme_ext_info    *pmlmeinfo;
11918         PADAPTER pbuddy_adapter;
11919         struct mlme_priv *pbuddy_mlmepriv;
11920         struct mlme_ext_priv *pbuddy_mlmeext;
11921         struct mlme_ext_info *pbuddy_mlmeinfo;
11922         WLAN_BSSID_EX *pbuddy_network_mlmeext;
11923
11924         if(!rtw_buddy_adapter_up(padapter))
11925         {
11926                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
11927                 return;
11928         }
11929
11930         pmlmeext = &padapter->mlmeextpriv;
11931         pmlmeinfo = &(pmlmeext->mlmext_info);
11932
11933         pbuddy_adapter = padapter->pbuddy_adapter;
11934         pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
11935         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
11936         pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
11937         pbuddy_network_mlmeext = &(pbuddy_mlmeinfo->network);
11938
11939         if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
11940                         check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
11941         {
11942                 /* restart and update beacon */
11943
11944                 DBG_8723A("after join,primary adapter, CH=%d, BW=%d, offset=%d\n"
11945                         , pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
11946
11947                 if(join_res >= 0)
11948                 {
11949                         u8 *p;
11950                         int     ie_len;
11951                         struct HT_info_element *pht_info=NULL;
11952
11953                         /* sync channel/bwmode/ch_offset with primary adapter */
11954                         pbuddy_mlmeext->cur_channel = pmlmeext->cur_channel;
11955                         if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)
11956                         {
11957                                 p = rtw_get_ie((pbuddy_network_mlmeext->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pbuddy_network_mlmeext->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
11958                                 if( p && ie_len)
11959                                 {
11960                                         pht_info = (struct HT_info_element *)(p+2);
11961                                         pht_info->infos[0] &= ~(BIT(0)|BIT(1)); /* no secondary channel is present */
11962                                 }
11963
11964                                 if(pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)
11965                                 {
11966                                         pbuddy_mlmeext->cur_ch_offset = pmlmeext->cur_ch_offset;
11967
11968                                         /* to update cur_ch_offset value in beacon */
11969                                         if( pht_info )
11970                                         {
11971                                                 switch(pmlmeext->cur_ch_offset)
11972                                                 {
11973                                                         case HAL_PRIME_CHNL_OFFSET_LOWER:
11974                                                                 pht_info->infos[0] |= 0x1;
11975                                                                 break;
11976                                                         case HAL_PRIME_CHNL_OFFSET_UPPER:
11977                                                                 pht_info->infos[0] |= 0x3;
11978                                                                 break;
11979                                                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
11980                                                         default:
11981                                                                 break;
11982                                                 }
11983
11984                                         }
11985
11986                                 }
11987                                 else if(pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20)
11988                                 {
11989                                         if(pmlmeext->cur_channel>=1 && pmlmeext->cur_channel<=4)
11990                                         {
11991                                                 if(pht_info)
11992                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
11993
11994                                                 pbuddy_mlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
11995                                                 pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
11996                                         }
11997                                         else if(pmlmeext->cur_channel>=5 && pmlmeext->cur_channel<=14)
11998                                         {
11999                                                 if(pht_info)
12000                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
12001
12002                                                 pbuddy_mlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
12003                                                 pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
12004                                         }
12005                                         else
12006                                         {
12007                                                 switch(pmlmeext->cur_channel)
12008                                                 {
12009                                                         case 36:
12010                                                         case 44:
12011                                                         case 52:
12012                                                         case 60:
12013                                                         case 100:
12014                                                         case 108:
12015                                                         case 116:
12016                                                         case 124:
12017                                                         case 132:
12018                                                         case 149:
12019                                                         case 157:
12020                                                         {
12021                                                                 if(pht_info)
12022                                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
12023                                                                 pbuddy_mlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
12024                                                                 pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
12025                                                                 break;
12026                                                         }
12027                                                         case 40:
12028                                                         case 48:
12029                                                         case 56:
12030                                                         case 64:
12031                                                         case 104:
12032                                                         case 112:
12033                                                         case 120:
12034                                                         case 128:
12035                                                         case 136:
12036                                                         case 153:
12037                                                         case 161:
12038                                                         {
12039                                                                 if(pht_info)
12040                                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
12041
12042                                                                 pbuddy_mlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
12043                                                                 pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
12044                                                                 break;
12045                                                         }
12046                                                         default:
12047                                                                 if(pht_info)
12048                                                                         pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
12049                                                                 pbuddy_mlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
12050                                                                 pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
12051                                                                 break;
12052
12053                                                 }
12054
12055                                         }
12056
12057                                 }
12058
12059                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
12060
12061                         }
12062                         else
12063                         {
12064                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
12065                         }
12066
12067                         /*  to update channel value in beacon */
12068                         pbuddy_network_mlmeext->Configuration.DSConfig = pmlmeext->cur_channel;
12069                         p = rtw_get_ie((pbuddy_network_mlmeext->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (pbuddy_network_mlmeext->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
12070                         if(p && ie_len>0)
12071                                 *(p + 2) = pmlmeext->cur_channel;
12072
12073                         p = rtw_get_ie((pbuddy_network_mlmeext->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pbuddy_network_mlmeext->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
12074                         if( p && ie_len)
12075                         {
12076                                 pht_info = (struct HT_info_element *)(p+2);
12077                                 pht_info->primary_channel = pmlmeext->cur_channel;
12078                         }
12079
12080                 }
12081                 else
12082                 {
12083                         /*  switch back to original channel/bwmode/ch_offset; */
12084                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
12085                 }
12086
12087                 DBG_8723A("after join, second adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
12088
12089                 DBG_8723A("update pbuddy_adapter's beacon\n");
12090
12091                 update_beacon(pbuddy_adapter, 0, NULL, _TRUE);
12092
12093         }
12094         else if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) &&
12095                         check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
12096         {
12097                 if(join_res >= 0)
12098                 {
12099                         pbuddy_mlmeext->cur_channel = pmlmeext->cur_channel;
12100                         if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)
12101                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
12102                         else if(pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)
12103                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
12104                         else
12105                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
12106                 }
12107                 else
12108                 {
12109                         /*  switch back to original channel/bwmode/ch_offset; */
12110                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
12111                 }
12112         }
12113         else
12114         {
12115                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
12116         }
12117 }
12118 #endif /* CONFIG_CONCURRENT_MODE */
12119
12120 u8 set_ch_hdl(_adapter *padapter, u8 *pbuf)
12121 {
12122         struct set_ch_parm *set_ch_parm;
12123         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
12124         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12125
12126         if(!pbuf)
12127                 return H2C_PARAMETERS_ERROR;
12128
12129         set_ch_parm = (struct set_ch_parm *)pbuf;
12130
12131         DBG_8723A(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
12132                 FUNC_NDEV_ARG(padapter->pnetdev),
12133                 set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
12134
12135         pmlmeext->cur_channel = set_ch_parm->ch;
12136         pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
12137         pmlmeext->cur_bwmode = set_ch_parm->bw;
12138
12139         set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
12140
12141         return  H2C_SUCCESS;
12142 }
12143
12144 u8 set_chplan_hdl(_adapter *padapter, unsigned char *pbuf)
12145 {
12146         struct SetChannelPlan_param *setChannelPlan_param;
12147         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
12148         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12149
12150         if(!pbuf)
12151                 return H2C_PARAMETERS_ERROR;
12152
12153         setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
12154
12155         pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
12156         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
12157
12158         return  H2C_SUCCESS;
12159 }
12160
12161 u8 led_blink_hdl(_adapter *padapter, unsigned char *pbuf)
12162 {
12163         struct LedBlink_param *ledBlink_param;
12164
12165         if(!pbuf)
12166                 return H2C_PARAMETERS_ERROR;
12167
12168         ledBlink_param = (struct LedBlink_param *)pbuf;
12169
12170         #ifdef CONFIG_LED_HANDLED_BY_CMD_THREAD
12171         BlinkHandler(ledBlink_param->pLed);
12172         #endif
12173
12174         return  H2C_SUCCESS;
12175 }
12176
12177 u8 set_csa_hdl(_adapter *padapter, unsigned char *pbuf)
12178 {
12179 #ifdef CONFIG_DFS
12180         struct SetChannelSwitch_param *setChannelSwitch_param;
12181         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
12182         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
12183         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
12184         u8 new_ch_no;
12185         u8 gval8 = 0x00, sval8 = 0xff;
12186
12187         if(!pbuf)
12188                 return H2C_PARAMETERS_ERROR;
12189
12190         setChannelSwitch_param = (struct SetChannelSwitch_param *)pbuf;
12191         new_ch_no = setChannelSwitch_param->new_ch_no;
12192
12193         rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, &gval8);
12194
12195         rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &sval8);
12196
12197         DBG_8723A("DFS detected! Swiching channel to %d!\n", new_ch_no);
12198         SelectChannel(padapter, new_ch_no);
12199
12200         rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &gval8);
12201
12202         rtw_free_network_queue(padapter, _TRUE);
12203         rtw_indicate_disconnect(padapter);
12204
12205         if ( ((new_ch_no >= 52) && (new_ch_no <= 64)) ||((new_ch_no >= 100) && (new_ch_no <= 140)) ) {
12206                 DBG_8723A("Switched to DFS band (ch %02x) again!!\n", new_ch_no);
12207         }
12208
12209         return  H2C_SUCCESS;
12210 #else
12211         return  H2C_REJECTED;
12212 #endif /* CONFIG_DFS */
12213 }
12214
12215 /*  TDLS_WRCR           : write RCR DATA BIT */
12216 /*  TDLS_SD_PTI         : issue peer traffic indication */
12217 /*  TDLS_CS_OFF         : go back to the channel linked with AP, terminating channel switch procedure */
12218 /*  TDLS_INIT_CH_SEN    : init channel sensing, receive all data and mgnt frame */
12219 /*  TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
12220 /*  TDLS_OFF_CH         : first time set channel to off channel */
12221 /*  TDLS_BASE_CH                : go back tp the channel linked with AP when set base channel as target channel */
12222 /*  TDLS_P_OFF_CH       : periodically go to off channel */
12223 /*  TDLS_P_BASE_CH      : periodically go back to base channel */
12224 /*  TDLS_RS_RCR         : restore RCR */
12225 /*  TDLS_CKALV_PH1      : check alive timer phase1 */
12226 /*  TDLS_CKALV_PH2      : check alive timer phase2 */
12227 /*  TDLS_FREE_STA       : free tdls sta */
12228 u8 tdls_hdl(_adapter *padapter, unsigned char *pbuf)
12229 {
12230 #ifdef CONFIG_TDLS
12231         _irqL irqL;
12232         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
12233         struct TDLSoption_param *TDLSoption;
12234         struct sta_info *ptdls_sta;
12235         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
12236         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
12237         u8 survey_channel, i, min, option;
12238
12239         if(!pbuf)
12240                 return H2C_PARAMETERS_ERROR;
12241
12242         TDLSoption = (struct TDLSoption_param *)pbuf;
12243
12244         ptdls_sta = rtw_get_stainfo( &(padapter->stapriv), TDLSoption->addr );
12245         option = TDLSoption->option;
12246
12247         if( ptdls_sta == NULL )
12248         {
12249                 if( option != TDLS_RS_RCR )
12250                         return H2C_REJECTED;
12251         }
12252
12253         /* spin_lock_bh(&(ptdlsinfo->hdl_lock)); */
12254         DBG_8723A("[%s] option:%d\n", __FUNCTION__, option);
12255
12256         switch(option){
12257                 case TDLS_WRCR:
12258                         /* As long as TDLS handshake success, we should set RCR_CBSSID_DATA bit to 0 */
12259                         /* such we can receive all kinds of data frames. */
12260                         rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_WRCR, 0);
12261                         DBG_8723A("TDLS with "MAC_FMT"\n", MAC_ARG(ptdls_sta->hwaddr));
12262
12263                         pmlmeinfo->FW_sta_info[ptdls_sta->mac_id].psta = ptdls_sta;
12264                         /* set TDLS sta rate. */
12265                         set_sta_rate(padapter, ptdls_sta);
12266                         break;
12267                 case TDLS_SD_PTI:
12268                         issue_tdls_peer_traffic_indication(padapter, ptdls_sta);
12269                         break;
12270                 case TDLS_CS_OFF:
12271                         _cancel_timer_ex(&ptdls_sta->base_ch_timer);
12272                         _cancel_timer_ex(&ptdls_sta->off_ch_timer);
12273                         SelectChannel(padapter, pmlmeext->cur_channel);
12274                         ptdls_sta->tdls_sta_state &= ~(TDLS_CH_SWITCH_ON_STATE |
12275                                                                 TDLS_PEER_AT_OFF_STATE |
12276                                                                 TDLS_AT_OFF_CH_STATE);
12277                         DBG_8723A("go back to base channel\n ");
12278                         issue_nulldata(padapter, NULL, 0, 0, 0);
12279                         break;
12280                 case TDLS_INIT_CH_SEN:
12281                         rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_INIT_CH_SEN, 0);
12282                         pmlmeext->sitesurvey_res.channel_idx = 0;
12283                         ptdls_sta->option = TDLS_DONE_CH_SEN;
12284                         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_DONE_CH_SEN);
12285                         break;
12286                 case TDLS_DONE_CH_SEN:
12287                         survey_channel = pmlmeext->channel_set[pmlmeext->sitesurvey_res.channel_idx].ChannelNum;
12288                         if(survey_channel){
12289                                 SelectChannel(padapter, survey_channel);
12290                                 ptdlsinfo->cur_channel = survey_channel;
12291                                 pmlmeext->sitesurvey_res.channel_idx++;
12292                                 _set_timer(&ptdls_sta->option_timer, SURVEY_TO);
12293                         }else{
12294                                 SelectChannel(padapter, pmlmeext->cur_channel);
12295
12296                                 rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_DONE_CH_SEN, 0);
12297
12298                                 if(ptdlsinfo->ch_sensing==1){
12299                                         ptdlsinfo->ch_sensing=0;
12300                                         ptdlsinfo->cur_channel=1;
12301                                         min=ptdlsinfo->collect_pkt_num[0];
12302                                         for(i=1; i<MAX_CHANNEL_NUM-1; i++){
12303                                                 if(min > ptdlsinfo->collect_pkt_num[i]){
12304                                                         ptdlsinfo->cur_channel=i+1;
12305                                                         min=ptdlsinfo->collect_pkt_num[i];
12306                                                 }
12307                                                 ptdlsinfo->collect_pkt_num[i]=0;
12308                                         }
12309                                         ptdlsinfo->collect_pkt_num[0]=0;
12310                                         ptdlsinfo->candidate_ch=ptdlsinfo->cur_channel;
12311                                         DBG_8723A("TDLS channel sensing done, candidate channel: %02x\n", ptdlsinfo->candidate_ch);
12312                                         ptdlsinfo->cur_channel=0;
12313
12314                                 }
12315
12316                                 if(ptdls_sta->tdls_sta_state & TDLS_PEER_SLEEP_STATE){
12317                                         ptdls_sta->tdls_sta_state |= TDLS_APSD_CHSW_STATE;
12318                                 }else{
12319                                         /* send null data with pwrbit==1 before send ch_switching_req to peer STA. */
12320                                         issue_nulldata(padapter, NULL, 1, 0, 0);
12321
12322                                         ptdls_sta->tdls_sta_state |= TDLS_CH_SW_INITIATOR_STATE;
12323
12324                                         issue_tdls_ch_switch_req(padapter, ptdls_sta->hwaddr);
12325                                         DBG_8723A("issue tdls ch switch req\n");
12326                                 }
12327                         }
12328                         break;
12329                 case TDLS_OFF_CH:
12330                         issue_nulldata(padapter, NULL, 1, 0, 0);
12331                         SelectChannel(padapter, ptdls_sta->off_ch);
12332
12333                         DBG_8723A("change channel to tar ch:%02x\n", ptdls_sta->off_ch);
12334                         ptdls_sta->tdls_sta_state |= TDLS_AT_OFF_CH_STATE;
12335                         ptdls_sta->tdls_sta_state &= ~(TDLS_PEER_AT_OFF_STATE);
12336                         _set_timer(&ptdls_sta->option_timer, (u32)ptdls_sta->ch_switch_time);
12337                         break;
12338                 case TDLS_BASE_CH:
12339                         _cancel_timer_ex(&ptdls_sta->base_ch_timer);
12340                         _cancel_timer_ex(&ptdls_sta->off_ch_timer);
12341                         SelectChannel(padapter, pmlmeext->cur_channel);
12342                         ptdls_sta->tdls_sta_state &= ~(TDLS_CH_SWITCH_ON_STATE |
12343                                                                 TDLS_PEER_AT_OFF_STATE |
12344                                                                 TDLS_AT_OFF_CH_STATE);
12345                         DBG_8723A("go back to base channel\n ");
12346                         issue_nulldata(padapter, NULL, 0, 0, 0);
12347                         _set_timer(&ptdls_sta->option_timer, (u32)ptdls_sta->ch_switch_time);
12348                         break;
12349                 case TDLS_P_OFF_CH:
12350                         SelectChannel(padapter, pmlmeext->cur_channel);
12351                         issue_nulldata(padapter, NULL, 0, 0, 0);
12352                         DBG_8723A("change channel to base ch:%02x\n", pmlmeext->cur_channel);
12353                         ptdls_sta->tdls_sta_state &= ~(TDLS_PEER_AT_OFF_STATE| TDLS_AT_OFF_CH_STATE);
12354                         _set_timer(&ptdls_sta->off_ch_timer, TDLS_STAY_TIME);
12355                         break;
12356                 case TDLS_P_BASE_CH:
12357                         issue_nulldata(ptdls_sta->padapter, NULL, 1, 0, 0);
12358                         SelectChannel(padapter, ptdls_sta->off_ch);
12359                         DBG_8723A("change channel to off ch:%02x\n", ptdls_sta->off_ch);
12360                         ptdls_sta->tdls_sta_state |= TDLS_AT_OFF_CH_STATE;
12361                         if((ptdls_sta->tdls_sta_state & TDLS_PEER_AT_OFF_STATE) != TDLS_PEER_AT_OFF_STATE){
12362                                 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta, 0);
12363                         }
12364                         _set_timer(&ptdls_sta->base_ch_timer, TDLS_STAY_TIME);
12365                         break;
12366                 case TDLS_RS_RCR:
12367                         rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_RS_RCR, 0);
12368                         DBG_8723A("wirte REG_RCR, set bit6 on\n");
12369                         break;
12370                 case TDLS_CKALV_PH1:
12371                         _set_timer(&ptdls_sta->alive_timer2, TDLS_ALIVE_TIMER_PH2);
12372                         break;
12373                 case TDLS_CKALV_PH2:
12374                         _set_timer(&ptdls_sta->alive_timer1, TDLS_ALIVE_TIMER_PH1);
12375                         break;
12376                 case TDLS_FREE_STA:
12377                         free_tdls_sta(padapter, ptdls_sta);
12378                         break;
12379
12380         }
12381
12382         /* spin_unlock_bh(&(ptdlsinfo->hdl_lock)); */
12383
12384         return H2C_SUCCESS;
12385 #else
12386         return H2C_REJECTED;
12387 #endif /* CONFIG_TDLS */
12388 }