85c89c7296971e5f269e11c31199024cde893665
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8188eu / 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_types.h>
23 #ifdef CONFIG_IOCTL_CFG80211
24 #include <rtw_wifi_regd.h>
25 #endif //CONFIG_IOCTL_CFG80211
26
27
28 struct mlme_handler mlme_sta_tbl[]={
29         {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
30         {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
31         {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
32         {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
33         {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
34         {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
35
36         /*----------------------------------------------------------
37                                         below 2 are reserved
38         -----------------------------------------------------------*/
39         {0,                                     "DoReserved",           &DoReserved},
40         {0,                                     "DoReserved",           &DoReserved},
41         {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
42         {WIFI_ATIM,                     "OnATIM",               &OnAtim},
43         {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
44         {WIFI_AUTH,                     "OnAuth",               &OnAuthClient},
45         {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
46         {WIFI_ACTION,           "OnAction",             &OnAction},
47         {WIFI_ACTION_NOACK,"OnActionNoAck",     &OnAction},
48 };
49
50 #ifdef _CONFIG_NATIVEAP_MLME_
51 struct mlme_handler mlme_ap_tbl[]={
52         {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
53         {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
54         {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
55         {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
56         {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
57         {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
58
59         /*----------------------------------------------------------
60                                         below 2 are reserved
61         -----------------------------------------------------------*/
62         {0,                                     "DoReserved",           &DoReserved},
63         {0,                                     "DoReserved",           &DoReserved},
64         {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
65         {WIFI_ATIM,                     "OnATIM",               &OnAtim},
66         {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
67         {WIFI_AUTH,                     "OnAuth",               &OnAuth},
68         {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
69         {WIFI_ACTION,           "OnAction",             &OnAction},
70         {WIFI_ACTION_NOACK,"OnActionNoAck",     &OnAction},
71 };
72 #endif
73
74 struct action_handler OnAction_tbl[]={
75         {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,        "ACTION_SPECTRUM_MGMT", on_action_spct},
76         {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
77         {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
78         {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
79         {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
80         {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
81         {RTW_WLAN_CATEGORY_FT, "ACTION_FT",     &DoReserved},
82         {RTW_WLAN_CATEGORY_HT,  "ACTION_HT",    &OnAction_ht},
83 #ifdef CONFIG_IEEE80211W
84         {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},
85 #else
86         {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
87 #endif //CONFIG_IEEE80211W
88         //add for CONFIG_IEEE80211W
89         {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved},
90         {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved},
91         {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
92         {RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &OnAction_vht},
93         {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},   
94 };
95
96
97 u8      null_addr[ETH_ALEN]= {0,0,0,0,0,0};
98
99 /**************************************************
100 OUI definitions for the vendor specific IE
101 ***************************************************/
102 unsigned char   RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
103 unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
104 unsigned char   WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
105 unsigned char   P2P_OUI[] = {0x50,0x6F,0x9A,0x09};
106 unsigned char   WFD_OUI[] = {0x50,0x6F,0x9A,0x0A};
107
108 unsigned char   WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
109 unsigned char   WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
110
111 unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
112 unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
113
114 extern unsigned char REALTEK_96B_IE[];
115
116 /********************************************************
117 MCS rate definitions
118 *********************************************************/
119 #ifdef CONFIG_DISABLE_MCS13TO15
120 unsigned char   MCS_rate_2R_MCS13TO15_OFF[16] = {0xff, 0x1f, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
121 unsigned char   MCS_rate_2R[16] = {0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
122 #else //CONFIG_DISABLE_MCS13TO15
123 unsigned char   MCS_rate_2R[16] = {0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
124 #endif //CONFIG_DISABLE_MCS13TO15
125 unsigned char   MCS_rate_1R[16] = {0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
126
127 /********************************************************
128 ChannelPlan definitions
129 *********************************************************/
130 /*static RT_CHANNEL_PLAN        DefaultChannelPlan[RT_CHANNEL_DOMAIN_MAX] = {
131         {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,100,104,108,112,116,132,136,140,149,153,157,161,165},32},                                     // 0x00, RT_CHANNEL_DOMAIN_FCC
132         {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},31},                                         // 0x01, RT_CHANNEL_DOMAIN_IC
133         {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140},32},                                               // 0x02, RT_CHANNEL_DOMAIN_ETSI
134         {{1,2,3,4,5,6,7,8,9,10,11,12,13},13},                                                                                                                                                                   // 0x03, RT_CHANNEL_DOMAIN_SPAIN
135         {{1,2,3,4,5,6,7,8,9,10,11,12,13},13},                                                                                                                                                                   // 0x04, RT_CHANNEL_DOMAIN_FRANCE
136         {{1,2,3,4,5,6,7,8,9,10,11,12,13},13},                                                                                                                                                                   // 0x05, RT_CHANNEL_DOMAIN_MKK
137         {{1,2,3,4,5,6,7,8,9,10,11,12,13},13},                                                                                                                                                                   // 0x06, RT_CHANNEL_DOMAIN_MKK1
138         {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},                                                                                                                           // 0x07, RT_CHANNEL_DOMAIN_ISRAEL
139         {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},                                                                                                                        // 0x08, RT_CHANNEL_DOMAIN_TELEC
140         {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14},                                                                                                                                                                // 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN
141         {{1,2,3,4,5,6,7,8,9,10,11,12,13},13},                                                                                                                                                                   // 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13
142         {{1,2,3,4,5,6,7,8,9,10,11,56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},26},                                                                        // 0x0B, RT_CHANNEL_DOMAIN_TAIWAN
143         {{1,2,3,4,5,6,7,8,9,10,11,12,13,149,153,157,161,165},18},                                                                                                                               // 0x0C, RT_CHANNEL_DOMAIN_CHINA
144         {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,149,153,157,161,165},24},                                                                                             // 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO
145         {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,149,153,157,161,165},31},                                         // 0x0E, RT_CHANNEL_DOMAIN_KOREA
146         {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64},19},                                                                                                                                 // 0x0F, RT_CHANNEL_DOMAIN_TURKEY
147         {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140},32},                                               // 0x10, RT_CHANNEL_DOMAIN_JAPAN
148         {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,149,153,157,161,165},20},                                                                                                                 // 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS
149         {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48},17},                                                                                                                                               // 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS
150         {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,149,153,157,161,165},37},   // 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G
151         {{1,2,3,4,5,6,7,8,9,10,11,56,60,64,149,153,157,161,165},19},                                                                                                                            // 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS
152 };*/
153
154 static RT_CHANNEL_PLAN_2G       RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
155         {{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
156         {{1,2,3,4,5,6,7,8,9,10,11,12,13},13},           // 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1
157         {{1,2,3,4,5,6,7,8,9,10,11},11},                 // 0x02, RT_CHANNEL_DOMAIN_2G_FCC1
158         {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14},        // 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1
159         {{10,11,12,13},4},                                              // 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2
160         {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14},        // 0x05, RT_CHANNEL_DOMAIN_2G_GLOBAL , Passive scan CH 12, 13, 14
161         {{},0},                                                         // 0x06, RT_CHANNEL_DOMAIN_2G_NULL
162 };
163
164 static RT_CHANNEL_PLAN_5G       RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
165         {{},0},                                                                                                                                                                 // 0x00, RT_CHANNEL_DOMAIN_5G_NULL
166         {{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
167         {{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
168         {{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
169         {{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
170         {{36,40,44,48,149,153,157,161,165},9},                                                                                                          // 0x05, RT_CHANNEL_DOMAIN_5G_FCC2
171         {{36,40,44,48,52,56,60,64,149,153,157,161,165},13},                                                                                     // 0x06, RT_CHANNEL_DOMAIN_5G_FCC3
172         {{36,40,44,48,52,56,60,64,149,153,157,161},12},                                                                                         // 0x07, RT_CHANNEL_DOMAIN_5G_FCC4
173         {{149,153,157,161,165},5},                                                                                                                                      // 0x08, RT_CHANNEL_DOMAIN_5G_FCC5
174         {{36,40,44,48,52,56,60,64},8},                                                                                                                          // 0x09, RT_CHANNEL_DOMAIN_5G_FCC6
175         {{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
176         {{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
177         {{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
178         {{36,40,44,48,52,56,60,64},8},                                                                                                                          // 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2
179         {{100,104,108,112,116,120,124,128,132,136,140},11},                                                                                     // 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3
180         {{56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},15},                                                                // 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1
181         {{56,60,64,149,153,157,161,165},8},                                                                                                                     // 0x10, RT_CHANNEL_DOMAIN_5G_NCC2
182         {{149,153,157,161,165},5},                                                                                                                                      // 0x11, RT_CHANNEL_DOMAIN_5G_NCC3
183         {{36,40,44,48},4},                                                                                                                                                      // 0x12, RT_CHANNEL_DOMAIN_5G_ETSI4
184         {{36,40,44,48,52,56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},20},                                 // 0x13, RT_CHANNEL_DOMAIN_5G_ETSI5
185         {{149,153,157,161},4},                                                                                                                                          // 0x14, RT_CHANNEL_DOMAIN_5G_FCC8
186         {{36,40,44,48,52,56,60,64},8},                                                                                                                          // 0x15, RT_CHANNEL_DOMAIN_5G_ETSI6
187         {{36,40,44,48,52,56,60,64,149,153,157,161,165},13},                                                                                     // 0x16, RT_CHANNEL_DOMAIN_5G_ETSI7
188         {{36,40,44,48,149,153,157,161,165},9},                                                                                                          // 0x17, RT_CHANNEL_DOMAIN_5G_ETSI8
189         {{100,104,108,112,116,120,124,128,132,136,140},11},                                                                                     // 0x18, RT_CHANNEL_DOMAIN_5G_ETSI9
190         {{149,153,157,161,165},5},                                                                                                                                      // 0x19, RT_CHANNEL_DOMAIN_5G_ETSI10
191         {{36,40,44,48,52,56,60,64,132,136,140,149,153,157,161,165},16},                                                                 // 0x1A, RT_CHANNEL_DOMAIN_5G_ETSI11
192         {{52,56,60,64,100,104,108,112,116,132,136,140,149,153,157,161,165},17},                                                 // 0x1B, RT_CHANNEL_DOMAIN_5G_NCC4
193         {{149,153,157,161},4},                                                                                                                                          // 0x1C, RT_CHANNEL_DOMAIN_5G_ETSI12
194         {{36,40,44,48,100,104,108,112,116,132,136,140,149,153,157,161,165},17},                                                 // 0x1D, RT_CHANNEL_DOMAIN_5G_FCC9
195         {{36,40,44,48,100,104,108,112,116,132,136,140},12},                                                                                     // 0x1E, RT_CHANNEL_DOMAIN_5G_ETSI13
196         {{36,40,44,48,52,56,60,64,100,104,108,112,116,132,136,140,149,153,157,161},20},                                 // 0x1F, RT_CHANNEL_DOMAIN_5G_FCC10
197
198         //===== Driver self defined for old channel plan Compatible ,Remember to modify if have new channel plan definition =====
199         {{36,40,44,48,52,56,60,64,100,104,108,112,116,132,136,140,149,153,157,161,165},21},                             // 0x20, RT_CHANNEL_DOMAIN_5G_FCC
200         {{36,40,44,48},4},                                                                                                                                                      // 0x21, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS
201         {{36,40,44,48,149,153,157,161},8},                                                                                                                      // 0x22, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS
202 };
203
204 static RT_CHANNEL_PLAN_MAP      RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
205         //===== 0x00 ~ 0x1F , Old Define =====
206         {0x02,0x20},    //0x00, RT_CHANNEL_DOMAIN_FCC
207         {0x02,0x0A},    //0x01, RT_CHANNEL_DOMAIN_IC
208         {0x01,0x01},    //0x02, RT_CHANNEL_DOMAIN_ETSI
209         {0x01,0x00},    //0x03, RT_CHANNEL_DOMAIN_SPAIN
210         {0x01,0x00},    //0x04, RT_CHANNEL_DOMAIN_FRANCE
211         {0x03,0x00},    //0x05, RT_CHANNEL_DOMAIN_MKK
212         {0x03,0x00},    //0x06, RT_CHANNEL_DOMAIN_MKK1
213         {0x01,0x09},    //0x07, RT_CHANNEL_DOMAIN_ISRAEL
214         {0x03,0x09},    //0x08, RT_CHANNEL_DOMAIN_TELEC
215         {0x03,0x00},    //0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN
216         {0x00,0x00},    //0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13
217         {0x02,0x0F},    //0x0B, RT_CHANNEL_DOMAIN_TAIWAN
218         {0x01,0x08},    //0x0C, RT_CHANNEL_DOMAIN_CHINA
219         {0x02,0x06},    //0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO
220         {0x02,0x0B},    //0x0E, RT_CHANNEL_DOMAIN_KOREA
221         {0x02,0x09},    //0x0F, RT_CHANNEL_DOMAIN_TURKEY
222         {0x01,0x01},    //0x10, RT_CHANNEL_DOMAIN_JAPAN
223         {0x02,0x05},    //0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS
224         {0x01,0x21},    //0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS
225         {0x00,0x04},    //0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G
226         {0x02,0x10},    //0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS
227         {0x00,0x21},    //0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS
228         {0x00,0x22},    //0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS
229         {0x03,0x21},    //0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS
230         {0x06,0x08},    //0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS
231         {0x02,0x08},    //0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS
232         {0x00,0x00},    //0x1A,
233         {0x00,0x00},    //0x1B,
234         {0x00,0x00},    //0x1C,
235         {0x00,0x00},    //0x1D,
236         {0x00,0x00},    //0x1E,
237         {0x06,0x04},    //0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G
238         //===== 0x20 ~ 0x7F ,New Define =====
239         {0x00,0x00},    //0x20, RT_CHANNEL_DOMAIN_WORLD_NULL
240         {0x01,0x00},    //0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL
241         {0x02,0x00},    //0x22, RT_CHANNEL_DOMAIN_FCC1_NULL
242         {0x03,0x00},    //0x23, RT_CHANNEL_DOMAIN_MKK1_NULL
243         {0x04,0x00},    //0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL
244         {0x02,0x04},    //0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1
245         {0x00,0x01},    //0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1
246         {0x03,0x0C},    //0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1
247         {0x00,0x0B},    //0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1
248         {0x00,0x05},    //0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2
249         {0x00,0x00},    //0x2A,
250         {0x00,0x00},    //0x2B,
251         {0x00,0x00},    //0x2C,
252         {0x00,0x00},    //0x2D,
253         {0x00,0x00},    //0x2E,
254         {0x00,0x00},    //0x2F,
255         {0x00,0x06},    //0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3
256         {0x00,0x07},    //0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4
257         {0x00,0x08},    //0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5
258         {0x00,0x09},    //0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6
259         {0x02,0x0A},    //0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7
260         {0x00,0x02},    //0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2
261         {0x00,0x03},    //0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3
262         {0x03,0x0D},    //0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2
263         {0x03,0x0E},    //0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3
264         {0x02,0x0F},    //0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1
265         {0x00,0x00},    //0x3A,
266         {0x00,0x00},    //0x3B,
267         {0x00,0x00},    //0x3C,
268         {0x00,0x00},    //0x3D,
269         {0x00,0x00},    //0x3E,
270         {0x00,0x00},    //0x3F,
271         {0x02,0x10},    //0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2
272         {0x05,0x00},    //0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL
273         {0x01,0x12},    //0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4
274         {0x02,0x05},    //0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2
275         {0x02,0x11},    //0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3
276         {0x00,0x13},    //0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5
277         {0x02,0x14},    //0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8
278         {0x00,0x15},    //0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6
279         {0x00,0x16},    //0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7
280         {0x00,0x17},    //0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8
281         {0x00,0x18},    //0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9
282         {0x00,0x19},    //0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10
283         {0x00,0x1A},    //0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11
284         {0x02,0x1B},    //0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4
285         {0x00,0x1C},    //0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12
286         {0x02,0x1D},    //0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9
287         {0x00,0x1E},    //0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13
288         {0x02,0x1F},    //0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10
289 };
290
291 static RT_CHANNEL_PLAN_MAP      RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03,0x02}; //use the conbination for max channel numbers
292
293 /*
294  * Search the @param ch in given @param ch_set
295  * @ch_set: the given channel set
296  * @ch: the given channel number
297  * 
298  * return the index of channel_num in channel_set, -1 if not found
299  */
300 int rtw_ch_set_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch)
301 {
302         int i;
303         for(i=0;ch_set[i].ChannelNum!=0;i++){
304                 if(ch == ch_set[i].ChannelNum)
305                         break;
306         }
307         
308         if(i >= ch_set[i].ChannelNum)
309                 return -1;
310         return i;
311 }
312
313 /*
314  * Check the @param ch is fit with setband setting of @param adapter
315  * @adapter: the given adapter
316  * @ch: the given channel number
317  * 
318  * return _TRUE when check valid, _FALSE not valid
319  */
320 bool rtw_mlme_band_check(_adapter *adapter, const u32 ch)
321 {
322         if (adapter->setband == GHZ24_50 /* 2.4G and 5G */
323                 || (adapter->setband == GHZ_24 && ch < 35) /* 2.4G only */
324                 || (adapter->setband == GHZ_50 && ch > 35) /* 5G only */
325         ) {
326                 return _TRUE;
327         }
328         return _FALSE;
329 }
330
331 /****************************************************************************
332
333 Following are the initialization functions for WiFi MLME
334
335 *****************************************************************************/
336
337 int init_hw_mlme_ext(_adapter *padapter)
338 {
339         struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
340
341         //set_opmode_cmd(padapter, infra_client_with_mlme);//removed
342
343         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
344
345         return _SUCCESS;
346 }
347
348 static void init_mlme_ext_priv_value(_adapter* padapter)
349 {
350         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
351         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
352
353 #ifdef CONFIG_TDLS
354         u8 i;
355 #endif
356
357         //unsigned char default_channel_set[MAX_CHANNEL_NUM] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0};
358         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};
359         unsigned char   mixed_basicrate[NumRates] ={_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,};
360
361         ATOMIC_SET(&pmlmeext->event_seq, 0);
362         pmlmeext->mgnt_seq = 0;//reset to zero when disconnect at client mode
363 #ifdef CONFIG_IEEE80211W
364         pmlmeext->sa_query_seq = 0;
365         pmlmeext->mgnt_80211w_IPN=0;
366         pmlmeext->mgnt_80211w_IPN_rx=0;
367 #endif //CONFIG_IEEE80211W
368         pmlmeext->cur_channel = padapter->registrypriv.channel;
369         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
370         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
371         
372         pmlmeext->retry = 0;
373
374         pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
375
376         //_rtw_memcpy(pmlmeext->channel_set, DefaultChannelPlan[padapter->mlmepriv.ChannelPlan].Channel, DefaultChannelPlan[padapter->mlmepriv.ChannelPlan].Len);
377         //_rtw_memcpy(pmlmeext->channel_set, default_channel_set, MAX_CHANNEL_NUM);
378         _rtw_memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
379         _rtw_memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
380
381         if(pmlmeext->cur_channel > 14)
382                 pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
383         else
384                 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
385
386         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
387         pmlmeext->sitesurvey_res.channel_idx = 0;
388         pmlmeext->sitesurvey_res.bss_cnt = 0;
389         pmlmeext->scan_abort = _FALSE;
390
391         pmlmeinfo->state = WIFI_FW_NULL_STATE;
392         pmlmeinfo->reauth_count = 0;
393         pmlmeinfo->reassoc_count = 0;
394         pmlmeinfo->link_count = 0;
395         pmlmeinfo->auth_seq = 0;
396         pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
397         pmlmeinfo->key_index = 0;
398         pmlmeinfo->iv = 0;
399
400         pmlmeinfo->enc_algo = _NO_PRIVACY_;
401         pmlmeinfo->authModeToggle = 0;
402
403         _rtw_memset(pmlmeinfo->chg_txt, 0, 128);
404
405         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
406         pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
407
408         pmlmeinfo->dialogToken = 0;
409
410         pmlmeext->action_public_rxseq = 0xffff;
411         pmlmeext->action_public_dialog_token = 0xff;
412 }
413
414 static int has_channel(RT_CHANNEL_INFO *channel_set,
415                                            u8 chanset_size,
416                                            u8 chan) {
417         int i;
418
419         for (i = 0; i < chanset_size; i++) {
420                 if (channel_set[i].ChannelNum == chan) {
421                         return 1;
422                 }
423         }
424
425         return 0;
426 }
427
428 static void init_channel_list(_adapter *padapter, RT_CHANNEL_INFO *channel_set,
429                                                           u8 chanset_size,
430                                                           struct p2p_channels *channel_list) {
431
432         struct p2p_oper_class_map op_class[] = {
433                 { IEEE80211G,  81,   1,  13,  1, BW20 },
434                 { IEEE80211G,  82,  14,  14,  1, BW20 },
435 #if 0 /* Do not enable HT40 on 2 GHz */
436                 { IEEE80211G,  83,   1,   9,  1, BW40PLUS },
437                 { IEEE80211G,  84,   5,  13,  1, BW40MINUS },
438 #endif
439                 { IEEE80211A, 115,  36,  48,  4, BW20 },
440                 { IEEE80211A, 116,  36,  44,  8, BW40PLUS },
441                 { IEEE80211A, 117,  40,  48,  8, BW40MINUS },
442                 { IEEE80211A, 124, 149, 161,  4, BW20 },
443                 { IEEE80211A, 125, 149, 169,  4, BW20 },
444                 { IEEE80211A, 126, 149, 157,  8, BW40PLUS },
445                 { IEEE80211A, 127, 153, 161,  8, BW40MINUS },
446                 { -1, 0, 0, 0, 0, BW20 }
447         };
448
449         int cla, op;
450
451         cla = 0;
452
453         for (op = 0; op_class[op].op_class; op++) {
454                 u8 ch;
455                 struct p2p_oper_class_map *o = &op_class[op];
456                 struct p2p_reg_class *reg = NULL;
457
458                 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
459                         if (!has_channel(channel_set, chanset_size, ch)) {
460                                 continue;
461                         }
462
463                         if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
464                                 continue;
465
466                         if ((0 < (padapter->registrypriv.bw_mode & 0xf0)) &&
467                                 ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
468                                 continue;
469
470                         if (reg == NULL) {
471                                 reg = &channel_list->reg_class[cla];
472                                 cla++;
473                                 reg->reg_class = o->op_class;
474                                 reg->channels = 0;
475                         }
476                         reg->channel[reg->channels] = ch;
477                         reg->channels++;
478                 }
479         }
480         channel_list->reg_classes = cla;
481
482 }
483
484 static u8 init_channel_set(_adapter* padapter, u8 ChannelPlan, RT_CHANNEL_INFO *channel_set)
485 {
486         u8      index,chanset_size = 0;
487         u8      b5GBand = _FALSE, b2_4GBand = _FALSE;
488         u8      Index2G = 0, Index5G=0;
489
490         _rtw_memset(channel_set, 0, sizeof(RT_CHANNEL_INFO)*MAX_CHANNEL_NUM);
491
492         if(ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
493         {
494                 DBG_871X("ChannelPlan ID %x error !!!!!\n",ChannelPlan);
495                 return chanset_size;
496         }
497
498         if(IsSupported24G(padapter->registrypriv.wireless_mode))
499         {
500                 b2_4GBand = _TRUE;
501                 if(RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
502                         Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
503                 else
504                         Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
505         }
506
507         if(IsSupported5G(padapter->registrypriv.wireless_mode))
508         {
509                 b5GBand = _TRUE;
510                 if(RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
511                         Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
512                 else
513                         Index5G = RTW_ChannelPlanMap[ChannelPlan].Index5G;
514         }
515
516         if(b2_4GBand)
517         {
518                 for(index=0;index<RTW_ChannelPlan2G[Index2G].Len;index++)
519                 {
520                         channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
521
522                         if(     (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||//Channel 1~11 is active, and 12~14 is passive
523                                 (RT_CHANNEL_DOMAIN_GLOBAL_NULL == ChannelPlan)  )
524                         {
525                                 if(channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
526                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
527                                 else if((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
528                                         channel_set[chanset_size].ScanType  = SCAN_PASSIVE;                     
529                         }
530                         else if(RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan ||
531                                 RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan ||
532                                 RT_CHANNEL_DOMAIN_2G_WORLD == Index2G)// channel 12~13, passive scan
533                         {
534                                 if(channel_set[chanset_size].ChannelNum <= 11)
535                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
536                                 else
537                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
538                         }
539                         else
540                         {
541                                 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
542                         }
543
544                         chanset_size++;
545                 }
546         }
547
548         if(b5GBand)
549         {
550                 for(index=0;index<RTW_ChannelPlan5G[Index5G].Len;index++)
551                 {
552 #ifdef CONFIG_DFS
553                         channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index];
554                         if ( channel_set[chanset_size].ChannelNum <= 48 
555                                 || channel_set[chanset_size].ChannelNum >= 149 )
556                         {
557                                 if(RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)//passive scan for all 5G channels
558                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
559                                 else
560                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
561                         }
562                         else
563                         {
564                                 channel_set[chanset_size].ScanType = SCAN_PASSIVE;
565                         }
566                         chanset_size++;
567 #else /* CONFIG_DFS */
568                         if ( RTW_ChannelPlan5G[Index5G].Channel[index] <= 48 
569                                 || RTW_ChannelPlan5G[Index5G].Channel[index] >= 149 ) {
570                                 channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index];
571                                 if(RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)//passive scan for all 5G channels
572                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
573                                 else
574                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
575                                 DBG_871X("%s(): channel_set[%d].ChannelNum = %d\n", __FUNCTION__, chanset_size, channel_set[chanset_size].ChannelNum);
576                                 chanset_size++;
577                         }
578 #endif /* CONFIG_DFS */
579                 }
580         }
581
582         DBG_871X("%s ChannelPlan ID %x Chan num:%d  \n",__FUNCTION__,ChannelPlan,chanset_size);
583         return chanset_size;
584 }
585
586 int     init_mlme_ext_priv(_adapter* padapter)
587 {
588         int     res = _SUCCESS;
589         struct registry_priv* pregistrypriv = &padapter->registrypriv;
590         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
591         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
592         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
593
594         // We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
595         //_rtw_memset((u8 *)pmlmeext, 0, sizeof(struct mlme_ext_priv));
596
597         pmlmeext->padapter = padapter;
598
599         //fill_fwpriv(padapter, &(pmlmeext->fwpriv));
600
601         init_mlme_ext_priv_value(padapter);
602         pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
603         
604         init_mlme_ext_timer(padapter);
605
606 #ifdef CONFIG_AP_MODE
607         init_mlme_ap_info(padapter);    
608 #endif
609
610         pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan,pmlmeext->channel_set);
611         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
612         pmlmeext->last_scan_time = 0;
613         pmlmeext->chan_scan_time = SURVEY_TO;
614         pmlmeext->mlmeext_init = _TRUE;
615
616
617 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK   
618         pmlmeext->active_keep_alive_check = _TRUE;
619 #else
620         pmlmeext->active_keep_alive_check = _FALSE;
621 #endif
622
623 #ifdef DBG_FIXED_CHAN           
624         pmlmeext->fixed_chan = 0xFF;    
625 #endif
626
627         return res;
628
629 }
630
631 void free_mlme_ext_priv (struct mlme_ext_priv *pmlmeext)
632 {
633         _adapter *padapter = pmlmeext->padapter;
634
635         if (!padapter)
636                 return;
637
638         if (padapter->bDriverStopped == _TRUE)
639         {
640                 _cancel_timer_ex(&pmlmeext->survey_timer);
641                 _cancel_timer_ex(&pmlmeext->link_timer);
642                 //_cancel_timer_ex(&pmlmeext->ADDBA_timer);
643         }
644 }
645
646 static u8 cmp_pkt_chnl_diff(_adapter *padapter,u8* pframe,uint packet_len)
647 {       // if the channel is same, return 0. else return channel differential   
648         uint len;
649         u8 channel;     
650         u8 *p;          
651         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, packet_len - _BEACON_IE_OFFSET_);       
652         if (p)  
653         {       
654                 channel = *(p + 2);             
655                 if(padapter->mlmeextpriv.cur_channel >= channel)                
656                 {                       
657                         return (padapter->mlmeextpriv.cur_channel - channel);           
658                 }               
659                 else            
660                 {                       
661                         return (channel-padapter->mlmeextpriv.cur_channel);             
662                 }       
663         }       
664         else
665         {               
666                 return 0;       
667         }
668 }
669
670 static void _mgt_dispatcher(_adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
671 {
672         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
673         u8 *pframe = precv_frame->u.hdr.rx_data; 
674
675           if(ptable->func)
676         {
677          //receive the frames that ra(a1) is my address or ra(a1) is bc address.
678                 if (!_rtw_memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
679                         !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) 
680                 {
681                         return;
682                 }
683                 
684                 ptable->func(padapter, precv_frame);
685         }
686         
687 }
688
689 void mgt_dispatcher(_adapter *padapter, union recv_frame *precv_frame)
690 {
691         int index;
692         struct mlme_handler *ptable;
693 #ifdef CONFIG_AP_MODE
694         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
695 #endif //CONFIG_AP_MODE
696         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
697         u8 *pframe = precv_frame->u.hdr.rx_data;
698         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
699         struct dvobj_priv *psdpriv = padapter->dvobj;
700         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
701
702         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
703                  ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n",
704                   GetFrameType(pframe), GetFrameSubType(pframe)));
705
706 #if 0
707         {
708                 u8 *pbuf;
709                 pbuf = GetAddr1Ptr(pframe);
710                 DBG_871X("A1-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf+1), *(pbuf+2), *(pbuf+3), *(pbuf+4), *(pbuf+5));
711                 pbuf = GetAddr2Ptr(pframe);
712                 DBG_871X("A2-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf+1), *(pbuf+2), *(pbuf+3), *(pbuf+4), *(pbuf+5));
713                 pbuf = GetAddr3Ptr(pframe);
714                 DBG_871X("A3-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf+1), *(pbuf+2), *(pbuf+3), *(pbuf+4), *(pbuf+5));
715         }
716 #endif
717
718         if (GetFrameType(pframe) != WIFI_MGT_TYPE)
719         {
720                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe)));
721                 return;
722         }
723
724         //receive the frames that ra(a1) is my address or ra(a1) is bc address.
725         if (!_rtw_memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
726                 !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
727         {
728                 return;
729         }
730
731         ptable = mlme_sta_tbl;
732
733         index = GetFrameSubType(pframe) >> 4;
734
735 #ifdef CONFIG_TDLS
736         if((index << 4)==WIFI_ACTION){
737                 //category==public (4), action==TDLS_DISCOVERY_RESPONSE
738                 if(*(pframe+24)==0x04 && *(pframe+25)==TDLS_DISCOVERY_RESPONSE){
739                         DBG_871X("recv tdls discovery response frame from "MAC_FMT"\n", MAC_ARG(GetAddr2Ptr(pframe)));
740                         On_TDLS_Dis_Rsp(padapter, precv_frame);
741                 }
742         }
743 #endif //CONFIG_TDLS
744
745         if (index >= (sizeof(mlme_sta_tbl) /sizeof(struct mlme_handler)))
746         {
747                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Currently we do not support reserved sub-fr-type=%d\n", index));
748                 return;
749         }
750         ptable += index;
751
752 #if 1
753         if (psta != NULL)
754         {
755                 if (GetRetry(pframe))
756                 {
757                         if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum)
758                         {
759                                 /* drop the duplicate management frame */
760                                 pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++;
761                                 DBG_871X("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num);
762                                 return;
763                         }
764                 }
765                 psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
766         }
767 #else
768
769         if(GetRetry(pframe))
770         {
771                 //RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("drop due to decache!\n"));
772                 //return;
773         }
774 #endif
775
776 #ifdef CONFIG_AP_MODE
777         switch (GetFrameSubType(pframe)) 
778         {
779                 case WIFI_AUTH:
780                         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
781                                 ptable->func = &OnAuth;
782                         else
783                                 ptable->func = &OnAuthClient;
784                         //pass through
785                 case WIFI_ASSOCREQ:
786                 case WIFI_REASSOCREQ:
787                         _mgt_dispatcher(padapter, ptable, precv_frame); 
788 #ifdef CONFIG_HOSTAPD_MLME                              
789                         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
790                                 rtw_hostapd_mlme_rx(padapter, precv_frame);
791 #endif                  
792                         break;
793                 case WIFI_PROBEREQ:
794                         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
795                         {
796 #ifdef CONFIG_HOSTAPD_MLME              
797                                 rtw_hostapd_mlme_rx(padapter, precv_frame);             
798 #else
799                                 _mgt_dispatcher(padapter, ptable, precv_frame);
800 #endif
801                         }
802                         else
803                                 _mgt_dispatcher(padapter, ptable, precv_frame);
804                         break;
805                 case WIFI_BEACON:                       
806                         _mgt_dispatcher(padapter, ptable, precv_frame);
807                         break;
808                 case WIFI_ACTION:
809                         //if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
810                         _mgt_dispatcher(padapter, ptable, precv_frame);         
811                         break;
812                 default:
813                         _mgt_dispatcher(padapter, ptable, precv_frame); 
814                         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
815                                 rtw_hostapd_mlme_rx(padapter, precv_frame);                     
816                         break;
817         }
818 #else
819
820         _mgt_dispatcher(padapter, ptable, precv_frame); 
821         
822 #endif
823
824 }
825
826 #ifdef CONFIG_P2P
827 u32 p2p_listen_state_process(_adapter *padapter, unsigned char *da)
828 {
829         bool response = _TRUE;
830
831 #ifdef CONFIG_IOCTL_CFG80211
832         if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
833         {
834                 if(padapter->cfg80211_wdinfo.is_ro_ch == _FALSE
835                         || rtw_get_oper_ch(padapter) != padapter->wdinfo.listen_channel
836                         || adapter_wdev_data(padapter)->p2p_enabled == _FALSE
837                         || padapter->mlmepriv.wps_probe_resp_ie == NULL
838                         || padapter->mlmepriv.p2p_probe_resp_ie == NULL
839                 )
840                 {
841 #ifdef CONFIG_DEBUG_CFG80211
842                         DBG_871X("DON'T issue_probersp_p2p: p2p_enabled:%d, wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p, ",
843                                 adapter_wdev_data(padapter)->p2p_enabled,
844                                 padapter->mlmepriv.wps_probe_resp_ie,
845                                 padapter->mlmepriv.p2p_probe_resp_ie);
846                         DBG_871X("is_ro_ch:%d, op_ch:%d, p2p_listen_channel:%d\n", 
847                                 padapter->cfg80211_wdinfo.is_ro_ch,
848                                 rtw_get_oper_ch(padapter),
849                                 padapter->wdinfo.listen_channel);
850 #endif
851                         response = _FALSE;
852                 }
853         }
854         else
855 #endif //CONFIG_IOCTL_CFG80211
856         if( padapter->wdinfo.driver_interface == DRIVER_WEXT )
857         {
858                 //      do nothing if the device name is empty
859                 if ( !padapter->wdinfo.device_name_len )
860                 {
861                         response        = _FALSE;
862                 }
863         }
864
865         if (response == _TRUE)
866                 issue_probersp_p2p( padapter, da);
867         
868         return _SUCCESS;
869 }
870 #endif //CONFIG_P2P
871
872
873 /****************************************************************************
874
875 Following are the callback functions for each subtype of the management frames
876
877 *****************************************************************************/
878
879 unsigned int OnProbeReq(_adapter *padapter, union recv_frame *precv_frame)
880 {
881         unsigned int    ielen;
882         unsigned char   *p;
883         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
884         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
885         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
886         WLAN_BSSID_EX   *cur = &(pmlmeinfo->network);
887         u8 *pframe = precv_frame->u.hdr.rx_data;
888         uint len = precv_frame->u.hdr.len;
889         u8 is_valid_p2p_probereq = _FALSE;
890
891 #ifdef CONFIG_ATMEL_RC_PATCH
892         u8 *target_ie=NULL, *wps_ie=NULL;
893         u8 *start;
894         uint search_len = 0, wps_ielen = 0, target_ielen = 0;
895         struct sta_info *psta;
896         struct sta_priv *pstapriv = &padapter->stapriv;
897 #endif
898
899
900 #ifdef CONFIG_P2P
901         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
902         struct rx_pkt_attrib    *pattrib = &precv_frame->u.hdr.attrib;
903         u8 wifi_test_chk_rate = 1;
904         
905         if (    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && 
906                 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) && 
907                 !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
908                 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
909                 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)
910            )
911         {
912                 //      Commented by Albert 2011/03/17
913                 //      mcs_rate = 0 -> CCK 1M rate
914                 //      mcs_rate = 1 -> CCK 2M rate
915                 //      mcs_rate = 2 -> CCK 5.5M rate
916                 //      mcs_rate = 3 -> CCK 11M rate
917                 //      In the P2P mode, the driver should not support the CCK rate
918
919                 //      Commented by Kurt 2012/10/16
920                 //      IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client
921 #ifdef CONFIG_WIFI_TEST
922                 if ( pattrib->data_rate <= 3 )
923                 {
924                         wifi_test_chk_rate = 0;
925                 }
926 #endif //CONFIG_WIFI_TEST
927
928                 if( wifi_test_chk_rate == 1 )
929                 {
930                         if((is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len)) == _TRUE)
931                         {
932                                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
933                                 {
934                                         // FIXME
935                                         if( padapter->wdinfo.driver_interface == DRIVER_WEXT )
936                                                 report_survey_event(padapter, precv_frame);
937
938                                         p2p_listen_state_process( padapter,  get_sa(pframe));
939
940                                         return _SUCCESS;        
941                                 }
942
943                                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
944                                 {
945                                         goto _continue;
946                                 }
947                         }
948                 }
949         }
950
951 _continue:
952 #endif //CONFIG_P2P
953
954         if(check_fwstate(pmlmepriv, WIFI_STATION_STATE))
955         {
956                 return _SUCCESS;
957         }
958
959         if(check_fwstate(pmlmepriv, _FW_LINKED) == _FALSE && 
960                 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)==_FALSE)
961         {
962                 return _SUCCESS;
963         }
964
965
966         //DBG_871X("+OnProbeReq\n");
967
968
969 #ifdef CONFIG_ATMEL_RC_PATCH
970                 if ((wps_ie = rtw_get_wps_ie(
971                         pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_,
972                         len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_,
973                          NULL, &wps_ielen))) {
974                 
975                         target_ie = rtw_get_wps_attr_content( wps_ie, wps_ielen, WPS_ATTR_MANUFACTURER, NULL, &target_ielen);
976                 }
977                 if ((target_ie && (target_ielen == 4)) && (_TRUE ==_rtw_memcmp((void *)target_ie, "Ozmo",4 ))) {
978                         //psta->flag_atmel_rc = 1;
979                         unsigned char *sa_addr = get_sa(pframe);
980                         printk("%s: Find Ozmo RC -- %02x:%02x:%02x:%02x:%02x:%02x  \n\n",
981                                 __func__, *sa_addr, *(sa_addr+1), *(sa_addr+2), *(sa_addr+3), *(sa_addr+4), *(sa_addr+5));
982                         _rtw_memcpy(  pstapriv->atmel_rc_pattern, get_sa(pframe), ETH_ALEN);
983                 }
984 #endif
985
986
987 #ifdef CONFIG_AUTO_AP_MODE
988         if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&
989                         pmlmepriv->cur_network.join_res == _TRUE)
990         {
991                 _irqL   irqL;
992                 struct sta_info *psta;
993                 u8 *mac_addr, *peer_addr;
994                 struct sta_priv *pstapriv = &padapter->stapriv;
995                 u8 RC_OUI[4]={0x00,0xE0,0x4C,0x0A};
996                 //EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2]
997
998                 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, (int *)&ielen,
999                         len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
1000
1001                 if(!p || ielen !=14)
1002                         goto _non_rc_device;
1003
1004                 if(!_rtw_memcmp(p+2, RC_OUI, sizeof(RC_OUI)))
1005                         goto _non_rc_device;
1006
1007                 if(!_rtw_memcmp(p+6, get_sa(pframe), ETH_ALEN))
1008                 {
1009                         DBG_871X("%s, do rc pairing ("MAC_FMT"), but mac addr mismatch!("MAC_FMT")\n", __FUNCTION__,
1010                                 MAC_ARG(get_sa(pframe)), MAC_ARG(p+6));
1011
1012                         goto _non_rc_device;
1013                 }
1014
1015                 DBG_871X("%s, got the pairing device("MAC_FMT")\n", __FUNCTION__,  MAC_ARG(get_sa(pframe)));
1016
1017                 //new a station
1018                 psta = rtw_get_stainfo(pstapriv, get_sa(pframe));
1019                 if (psta == NULL)
1020                 {
1021                         // allocate a new one
1022                         DBG_871X("going to alloc stainfo for rc="MAC_FMT"\n",  MAC_ARG(get_sa(pframe)));
1023                         psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe));
1024                         if (psta == NULL)
1025                         {
1026                                 //TODO:
1027                                 DBG_871X(" Exceed the upper limit of supported clients...\n");
1028                                 return _SUCCESS;
1029                         }
1030
1031                         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1032                         if (rtw_is_list_empty(&psta->asoc_list))
1033                         {
1034                                 psta->expire_to = pstapriv->expire_to;
1035                                 rtw_list_insert_tail(&psta->asoc_list, &pstapriv->asoc_list);
1036                                 pstapriv->asoc_list_cnt++;
1037                         }
1038                         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1039
1040                         //generate pairing ID
1041                         mac_addr = myid(&(padapter->eeprompriv));
1042                         peer_addr = psta->hwaddr;
1043                         psta->pid = (u16)(((mac_addr[4]<<8) + mac_addr[5]) + ((peer_addr[4]<<8) + peer_addr[5]));
1044
1045                         //update peer stainfo
1046                         psta->isrc = _TRUE;
1047                         //psta->aid = 0;
1048                         //psta->mac_id = 2;
1049
1050                         /* get a unique AID */
1051                         if (psta->aid > 0) {
1052                                 DBG_871X("old AID %d\n", psta->aid);
1053                         } else {
1054                                 for (psta->aid = 1; psta->aid <= NUM_STA; psta->aid++)
1055                                         if (pstapriv->sta_aid[psta->aid - 1] == NULL)
1056                                                 break;
1057
1058                                 if (psta->aid > pstapriv->max_num_sta) {
1059                                         psta->aid = 0;
1060                                         DBG_871X("no room for more AIDs\n");
1061                                         return _SUCCESS;
1062                                 } else {
1063                                         pstapriv->sta_aid[psta->aid - 1] = psta;
1064                                         DBG_871X("allocate new AID = (%d)\n", psta->aid);
1065                                 }
1066                         }
1067                         
1068                         psta->qos_option = 1;
1069                         psta->bw_mode = CHANNEL_WIDTH_20;
1070                         psta->ieee8021x_blocked = _FALSE;
1071 #ifdef CONFIG_80211N_HT
1072                         psta->htpriv.ht_option = _TRUE;
1073                         psta->htpriv.ampdu_enable = _FALSE;
1074                         psta->htpriv.sgi_20m = _FALSE;
1075                         psta->htpriv.sgi_40m = _FALSE;
1076                         psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1077                         psta->htpriv.agg_enable_bitmap = 0x0;//reset
1078                         psta->htpriv.candidate_tid_bitmap = 0x0;//reset
1079 #endif
1080
1081                         rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);
1082
1083                         _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
1084
1085                         _enter_critical_bh(&psta->lock, &irqL);
1086                         psta->state |= _FW_LINKED;
1087                         _exit_critical_bh(&psta->lock, &irqL);
1088
1089                         report_add_sta_event(padapter, psta->hwaddr, psta->aid);
1090
1091                 }
1092
1093                 issue_probersp(padapter, get_sa(pframe), _FALSE);
1094
1095                 return _SUCCESS;
1096
1097         }
1098
1099 _non_rc_device:
1100
1101         return _SUCCESS;
1102
1103 #endif //CONFIG_AUTO_AP_MODE
1104         
1105
1106 #ifdef CONFIG_CONCURRENT_MODE
1107         if(((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
1108                 check_buddy_fwstate(padapter, _FW_UNDER_LINKING|_FW_UNDER_SURVEY))
1109         {
1110                 //don't process probe req
1111                 return _SUCCESS;
1112         }
1113 #endif  
1114
1115         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
1116                         len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
1117
1118
1119         //check (wildcard) SSID 
1120         if (p != NULL)
1121         {
1122                 if(is_valid_p2p_probereq == _TRUE)
1123                 {
1124                         goto _issue_probersp;
1125                 }
1126
1127                 if ( (ielen != 0 && _FALSE ==_rtw_memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength))
1128                         || (ielen == 0 && pmlmeinfo->hidden_ssid_mode)
1129                 )
1130                 {
1131                         return _SUCCESS;
1132                 }
1133
1134 _issue_probersp:
1135                 if(((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE && 
1136                         pmlmepriv->cur_network.join_res == _TRUE)) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
1137                 {
1138                         //DBG_871X("+issue_probersp during ap mode\n");
1139                         issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);                
1140                 }
1141
1142         }
1143
1144         return _SUCCESS;
1145
1146 }
1147
1148 unsigned int OnProbeRsp(_adapter *padapter, union recv_frame *precv_frame)
1149 {
1150         struct sta_info         *psta;
1151         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1152         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1153         struct sta_priv         *pstapriv = &padapter->stapriv;
1154         u8      *pframe = precv_frame->u.hdr.rx_data;
1155 #ifdef CONFIG_P2P
1156         struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
1157 #endif
1158
1159
1160 #ifdef CONFIG_P2P
1161         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
1162         {
1163                 if ( _TRUE == pwdinfo->tx_prov_disc_info.benable )
1164                 {
1165                         if( _rtw_memcmp( pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN ) )
1166                         {
1167                                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
1168                                 {
1169                                         pwdinfo->tx_prov_disc_info.benable = _FALSE;
1170                                         issue_p2p_provision_request( padapter,
1171                                                                                                 pwdinfo->tx_prov_disc_info.ssid.Ssid, 
1172                                                                                                 pwdinfo->tx_prov_disc_info.ssid.SsidLength,
1173                                                                                                 pwdinfo->tx_prov_disc_info.peerDevAddr );
1174                                 }
1175                                 else if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
1176                                 {
1177                                         pwdinfo->tx_prov_disc_info.benable = _FALSE;
1178                                         issue_p2p_provision_request( padapter,
1179                                                                                                 NULL, 
1180                                                                                                 0,
1181                                                                                                 pwdinfo->tx_prov_disc_info.peerDevAddr );
1182                                 }
1183                         }               
1184                 }
1185                 return _SUCCESS;
1186         }
1187         else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
1188         {
1189                 if ( _TRUE == pwdinfo->nego_req_info.benable )
1190                 {
1191                         DBG_871X( "[%s] P2P State is GONEGO ING!\n", __FUNCTION__ );
1192                         if( _rtw_memcmp( pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN ) )
1193                         {
1194                                 pwdinfo->nego_req_info.benable = _FALSE;
1195                                 issue_p2p_GO_request( padapter, pwdinfo->nego_req_info.peerDevAddr);
1196                         }
1197                 }
1198         }
1199         else if( rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ ) )
1200         {
1201                 if ( _TRUE == pwdinfo->invitereq_info.benable )
1202                 {
1203                         DBG_871X( "[%s] P2P_STATE_TX_INVITE_REQ!\n", __FUNCTION__ );
1204                         if( _rtw_memcmp( pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN ) )
1205                         {
1206                                 pwdinfo->invitereq_info.benable = _FALSE;
1207                                 issue_p2p_invitation_request( padapter, pwdinfo->invitereq_info.peer_macaddr );
1208                         }
1209                 }
1210         }
1211 #endif
1212
1213
1214         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
1215         {
1216                 report_survey_event(padapter, precv_frame);     
1217 #ifdef CONFIG_CONCURRENT_MODE
1218                 report_survey_event(padapter->pbuddy_adapter, precv_frame);     
1219 #endif
1220 #ifdef CONFIG_DUALMAC_CONCURRENT
1221                 dc_report_survey_event(padapter, precv_frame);
1222 #endif
1223                 return _SUCCESS;
1224         }
1225
1226         #if 0 //move to validate_recv_mgnt_frame
1227         if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1228         {
1229                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1230                 {
1231                         if ((psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe))) != NULL)
1232                         {
1233                                 psta->sta_stats.rx_mgnt_pkts++;
1234                         }
1235                 }
1236         }
1237         #endif
1238         
1239         return _SUCCESS;
1240         
1241 }
1242
1243 unsigned int OnBeacon(_adapter *padapter, union recv_frame *precv_frame)
1244 {
1245         int cam_idx;
1246         struct sta_info *psta;
1247         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1248         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1249         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1250         struct sta_priv *pstapriv = &padapter->stapriv;
1251         u8 *pframe = precv_frame->u.hdr.rx_data;
1252         uint len = precv_frame->u.hdr.len;
1253         WLAN_BSSID_EX *pbss;
1254         int ret = _SUCCESS;
1255         u8 *p = NULL;
1256         u32 ielen = 0;
1257
1258 #ifdef CONFIG_ATTEMPT_TO_FIX_AP_BEACON_ERROR
1259         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_);
1260         if ((p != NULL) && (ielen > 0))
1261         {
1262                 if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D))
1263                 {
1264                         /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */     
1265                         DBG_871X("[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)));
1266                         *(p + 1) = ielen - 1;
1267                 }
1268         }
1269 #endif
1270
1271         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
1272         {
1273                 report_survey_event(padapter, precv_frame);
1274 #ifdef CONFIG_CONCURRENT_MODE
1275                 report_survey_event(padapter->pbuddy_adapter, precv_frame);     
1276 #endif
1277
1278 #ifdef CONFIG_DUALMAC_CONCURRENT
1279                 dc_report_survey_event(padapter, precv_frame);
1280 #endif
1281
1282                 return _SUCCESS;
1283         }
1284
1285         if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1286         {
1287                 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL)
1288                 {
1289                         //we should update current network before auth, or some IE is wrong
1290                         pbss = (WLAN_BSSID_EX*)rtw_malloc(sizeof(WLAN_BSSID_EX));
1291                         if (pbss) {
1292                                 if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
1293                                         update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE);
1294                                         rtw_get_bcn_info(&(pmlmepriv->cur_network));
1295                                 }
1296                                 rtw_mfree((u8*)pbss, sizeof(WLAN_BSSID_EX));
1297                         }
1298
1299                         //check the vendor of the assoc AP
1300                         pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), len-sizeof(struct rtw_ieee80211_hdr_3addr));                         
1301
1302                         //update TSF Value
1303                         update_TSF(pmlmeext, pframe, len);
1304
1305                         //reset for adaptive_early_32k
1306                         pmlmeext->adaptive_tsf_done = _FALSE;
1307                         pmlmeext->DrvBcnEarly = 0xff;
1308                         pmlmeext->DrvBcnTimeOut = 0xff;
1309                         pmlmeext->bcn_cnt = 0;
1310                         _rtw_memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt));
1311                         _rtw_memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio));
1312
1313 #ifdef CONFIG_P2P_PS
1314                         process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
1315 #endif //CONFIG_P2P_PS
1316
1317                         //start auth
1318                         start_clnt_auth(padapter);
1319
1320                         return _SUCCESS;
1321                 }
1322
1323                 if(((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1324                 {
1325                         if ((psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe))) != NULL)
1326                         {
1327                                 #ifdef CONFIG_PATCH_JOIN_WRONG_CHANNEL        
1328                                 //Merge from 8712 FW code
1329                                 if (cmp_pkt_chnl_diff(padapter,pframe,len) != 0)        
1330                                 {            // join wrong channel, deauth and reconnect           
1331                                         issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
1332
1333                                         report_del_sta_event(padapter,(&(pmlmeinfo->network))->MacAddress, WLAN_REASON_JOIN_WRONG_CHANNEL);             
1334                                         pmlmeinfo->state &= (~WIFI_FW_ASSOC_SUCCESS);                   
1335                                         return _SUCCESS;
1336                                 }        
1337                                 #endif //CONFIG_PATCH_JOIN_WRONG_CHANNEL
1338
1339                                 ret = rtw_check_bcn_info(padapter, pframe, len);
1340                                 if (!ret) {
1341                                                 DBG_871X_LEVEL(_drv_always_, "ap has changed, disconnect now\n ");
1342                                                 receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 0);
1343                                                 return _SUCCESS;
1344                                 }
1345                                 //update WMM, ERP in the beacon
1346                                 //todo: the timer is used instead of the number of the beacon received
1347                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
1348                                 {
1349                                         //DBG_871X("update_bcn_info\n");
1350                                         update_beacon_info(padapter, pframe, len, psta);
1351                                 }
1352
1353                                 adaptive_early_32k(pmlmeext, pframe, len);                              
1354                                 
1355 #ifdef CONFIG_DFS
1356                                 process_csa_ie(padapter, pframe, len);  //channel switch announcement
1357 #endif //CONFIG_DFS
1358
1359 #ifdef CONFIG_P2P_PS
1360                                 process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
1361 #endif //CONFIG_P2P_PS
1362
1363                                 #if 0 //move to validate_recv_mgnt_frame
1364                                 psta->sta_stats.rx_mgnt_pkts++;
1365                                 #endif
1366                         }
1367                 }
1368                 else if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
1369                 {
1370                         if ((psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe))) != NULL)
1371                         {
1372                                 //update WMM, ERP in the beacon
1373                                 //todo: the timer is used instead of the number of the beacon received
1374                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
1375                                 {
1376                                         //DBG_871X("update_bcn_info\n");
1377                                         update_beacon_info(padapter, pframe, len, psta);
1378                                 }
1379
1380                                 #if 0 //move to validate_recv_mgnt_frame
1381                                 psta->sta_stats.rx_mgnt_pkts++;
1382                                 #endif
1383                         }
1384                         else
1385                         {
1386                                 //allocate a new CAM entry for IBSS station
1387                                 if ((cam_idx = allocate_fw_sta_entry(padapter)) == NUM_STA)
1388                                 {
1389                                         goto _END_ONBEACON_;
1390                                 }
1391
1392                                 //get supported rate
1393                                 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)
1394                                 {
1395                                         pmlmeinfo->FW_sta_info[cam_idx].status = 0;
1396                                         goto _END_ONBEACON_;
1397                                 }
1398
1399                                 //update TSF Value
1400                                 update_TSF(pmlmeext, pframe, len);                      
1401
1402                                 //report sta add event
1403                                 report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
1404                         }
1405                 }
1406         }
1407
1408 _END_ONBEACON_:
1409
1410         return _SUCCESS;
1411
1412 }
1413
1414 unsigned int OnAuth(_adapter *padapter, union recv_frame *precv_frame)
1415 {
1416 #ifdef CONFIG_AP_MODE
1417         _irqL irqL;
1418         unsigned int    auth_mode, seq, ie_len;
1419         unsigned char   *sa, *p;        
1420         u16     algorithm;
1421         int     status;
1422         static struct sta_info stat;    
1423         struct  sta_info        *pstat=NULL;    
1424         struct  sta_priv *pstapriv = &padapter->stapriv;
1425         struct security_priv *psecuritypriv = &padapter->securitypriv;
1426         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1427         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1428         u8 *pframe = precv_frame->u.hdr.rx_data; 
1429         uint len = precv_frame->u.hdr.len;
1430         u8      offset = 0;
1431
1432         
1433 #ifdef CONFIG_CONCURRENT_MODE   
1434         if(((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
1435                 check_buddy_fwstate(padapter, _FW_UNDER_LINKING|_FW_UNDER_SURVEY))
1436         {
1437                 //don't process auth request;
1438                 return _SUCCESS;
1439         }
1440 #endif //CONFIG_CONCURRENT_MODE
1441
1442         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1443                 return _FAIL;
1444
1445         DBG_871X("+OnAuth\n");
1446
1447         sa = GetAddr2Ptr(pframe);
1448
1449         auth_mode = psecuritypriv->dot11AuthAlgrthm;
1450
1451         if (GetPrivacy(pframe))
1452         {
1453                 u8      *iv;
1454                 struct rx_pkt_attrib     *prxattrib = &(precv_frame->u.hdr.attrib);
1455
1456                 prxattrib->hdrlen = WLAN_HDR_A3_LEN;
1457                 prxattrib->encrypt = _WEP40_;
1458
1459                 iv = pframe+prxattrib->hdrlen;
1460                 prxattrib->key_index = ((iv[3]>>6)&0x3);
1461
1462                 prxattrib->iv_len = 4;
1463                 prxattrib->icv_len = 4;
1464
1465                 rtw_wep_decrypt(padapter, (u8 *)precv_frame);
1466
1467                 offset = 4;
1468         }
1469
1470         algorithm = le16_to_cpu(*(u16*)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
1471         seq     = le16_to_cpu(*(u16*)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
1472
1473         DBG_871X("auth alg=%x, seq=%X\n", algorithm, seq);
1474
1475         if (auth_mode == 2 &&
1476                         psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
1477                         psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
1478                 auth_mode = 0;
1479
1480         if ((algorithm > 0 && auth_mode == 0) ||        // rx a shared-key auth but shared not enabled
1481                 (algorithm == 0 && auth_mode == 1) )    // rx a open-system auth but shared-key is enabled
1482         {               
1483                 DBG_871X("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",
1484                         algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
1485                 
1486                 status = _STATS_NO_SUPP_ALG_;
1487                 
1488                 goto auth_fail;
1489         }
1490         
1491 #if 0 //ACL control     
1492         phead = &priv->wlan_acl_list;
1493         plist = phead->next;
1494         //check sa
1495         if (acl_mode == 1)              // 1: positive check, only those on acl_list can be connected.
1496                 res = FAIL;
1497         else
1498                 res = SUCCESS;
1499
1500         while(plist != phead)
1501         {
1502                 paclnode = list_entry(plist, struct rtw_wlan_acl_node, list);
1503                 plist = plist->next;
1504                 if (!memcmp((void *)sa, paclnode->addr, 6)) {
1505                         if (paclnode->mode & 2) { // deny
1506                                 res = FAIL;
1507                                 break;
1508                         }
1509                         else {
1510                                 res = SUCCESS;
1511                                 break;
1512                         }
1513                 }
1514         }
1515
1516         if (res != SUCCESS) {
1517                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,"auth abort because ACL!\n");
1518                 return FAIL;
1519         }
1520 #else
1521         if(rtw_access_ctrl(padapter, sa) == _FALSE)
1522         {
1523                 status = _STATS_UNABLE_HANDLE_STA_;
1524                 goto auth_fail;
1525         }       
1526 #endif
1527
1528         pstat = rtw_get_stainfo(pstapriv, sa);
1529         if (pstat == NULL)
1530         {
1531
1532                 // allocate a new one
1533                 DBG_871X("going to alloc stainfo for sa="MAC_FMT"\n",  MAC_ARG(sa));
1534                 pstat = rtw_alloc_stainfo(pstapriv, sa);
1535                 if (pstat == NULL)
1536                 {
1537                         DBG_871X(" Exceed the upper limit of supported clients...\n");
1538                         status = _STATS_UNABLE_HANDLE_STA_;
1539                         goto auth_fail;
1540                 }
1541                 
1542                 pstat->state = WIFI_FW_AUTH_NULL;
1543                 pstat->auth_seq = 0;
1544                 
1545                 //pstat->flags = 0;
1546                 //pstat->capability = 0;
1547         }
1548         else
1549         {               
1550
1551                 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1552                 if(rtw_is_list_empty(&pstat->asoc_list)==_FALSE)
1553                 {                       
1554                         rtw_list_delete(&pstat->asoc_list);
1555                         pstapriv->asoc_list_cnt--;
1556                         if (pstat->expire_to > 0)
1557                         {
1558                                 //TODO: STA re_auth within expire_to
1559                         }
1560                 }
1561                 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1562                 
1563                 if (seq==1) {
1564                         //TODO: STA re_auth and auth timeout 
1565                 }
1566         }
1567
1568         _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
1569         if (rtw_is_list_empty(&pstat->auth_list))
1570         {               
1571
1572                 rtw_list_insert_tail(&pstat->auth_list, &pstapriv->auth_list);
1573                 pstapriv->auth_list_cnt++;
1574         }       
1575         _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
1576
1577         if (pstat->auth_seq == 0)
1578                 pstat->expire_to = pstapriv->auth_to;
1579
1580
1581         if ((pstat->auth_seq + 1) != seq)
1582         {
1583                 DBG_871X("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
1584                         seq, pstat->auth_seq+1);
1585                 status = _STATS_OUT_OF_AUTH_SEQ_;
1586                 goto auth_fail;
1587         }
1588
1589         if (algorithm==0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3))
1590         {
1591                 if (seq == 1)
1592                 {
1593                         pstat->state &= ~WIFI_FW_AUTH_NULL;
1594                         pstat->state |= WIFI_FW_AUTH_SUCCESS;
1595                         pstat->expire_to = pstapriv->assoc_to;
1596                         pstat->authalg = algorithm;
1597                 }
1598                 else
1599                 {
1600                         DBG_871X("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
1601                                 seq, pstat->auth_seq+1);
1602                         status = _STATS_OUT_OF_AUTH_SEQ_;
1603                         goto auth_fail;
1604                 }
1605         }
1606         else // shared system or auto authentication
1607         {
1608                 if (seq == 1)
1609                 {
1610                         //prepare for the challenging txt...
1611
1612                         //get_random_bytes((void *)pstat->chg_txt, 128);//TODO:
1613                         _rtw_memset((void *)pstat->chg_txt, 78, 128);
1614
1615                         pstat->state &= ~WIFI_FW_AUTH_NULL;
1616                         pstat->state |= WIFI_FW_AUTH_STATE;
1617                         pstat->authalg = algorithm;
1618                         pstat->auth_seq = 2;
1619                 }
1620                 else if (seq == 3)
1621                 {
1622                         //checking for challenging txt...
1623                         DBG_871X("checking for challenging txt...\n");
1624                         
1625                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len,
1626                                         len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
1627
1628                         if((p==NULL) || (ie_len<=0))
1629                         {
1630                                 DBG_871X("auth rejected because challenge failure!(1)\n");
1631                                 status = _STATS_CHALLENGE_FAIL_;
1632                                 goto auth_fail;
1633                         }
1634                         
1635                         if (_rtw_memcmp((void *)(p + 2), pstat->chg_txt, 128))
1636                         {
1637                                 pstat->state &= (~WIFI_FW_AUTH_STATE);
1638                                 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1639                                 // challenging txt is correct...
1640                                 pstat->expire_to =  pstapriv->assoc_to;
1641                         }
1642                         else
1643                         {
1644                                 DBG_871X("auth rejected because challenge failure!\n");
1645                                 status = _STATS_CHALLENGE_FAIL_;
1646                                 goto auth_fail;
1647                         }
1648                 }
1649                 else
1650                 {
1651                         DBG_871X("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
1652                                 seq, pstat->auth_seq+1);
1653                         status = _STATS_OUT_OF_AUTH_SEQ_;
1654                         goto auth_fail;
1655                 }
1656         }
1657
1658
1659         // Now, we are going to issue_auth...
1660         pstat->auth_seq = seq + 1;      
1661         
1662 #ifdef CONFIG_NATIVEAP_MLME
1663         issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
1664 #endif
1665
1666         if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1667                 pstat->auth_seq = 0;
1668
1669                 
1670         return _SUCCESS;
1671
1672 auth_fail:
1673
1674         if(pstat)
1675                 rtw_free_stainfo(padapter , pstat);
1676         
1677         pstat = &stat;
1678         _rtw_memset((char *)pstat, '\0', sizeof(stat));
1679         pstat->auth_seq = 2;
1680         _rtw_memcpy(pstat->hwaddr, sa, 6);      
1681         
1682 #ifdef CONFIG_NATIVEAP_MLME
1683         issue_auth(padapter, pstat, (unsigned short)status);    
1684 #endif
1685
1686 #endif
1687         return _FAIL;
1688
1689 }
1690
1691 unsigned int OnAuthClient(_adapter *padapter, union recv_frame *precv_frame)
1692 {
1693         unsigned int    seq, len, status, algthm, offset;
1694         unsigned char   *p;
1695         unsigned int    go2asoc = 0;
1696         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1697         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1698         u8 *pframe = precv_frame->u.hdr.rx_data;
1699         uint pkt_len = precv_frame->u.hdr.len;
1700
1701         DBG_871X("%s\n", __FUNCTION__);
1702
1703         //check A1 matches or not
1704         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1705                 return _SUCCESS;
1706
1707         if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1708                 return _SUCCESS;
1709
1710         offset = (GetPrivacy(pframe))? 4: 0;
1711
1712         algthm  = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
1713         seq     = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
1714         status  = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4));
1715
1716         if (status != 0)
1717         {
1718                 DBG_871X("clnt auth fail, status: %d\n", status);
1719                 if(status == 13)//&& pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto)
1720                 {
1721                         if(pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1722                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
1723                         else
1724                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1725                         //pmlmeinfo->reauth_count = 0;
1726                 }
1727                 
1728                 set_link_timer(pmlmeext, 1);
1729                 goto authclnt_fail;
1730         }
1731
1732         if (seq == 2)
1733         {
1734                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1735                 {
1736                          // legendary shared system
1737                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
1738                                 pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
1739
1740                         if (p == NULL)
1741                         {
1742                                 //DBG_871X("marc: no challenge text?\n");
1743                                 goto authclnt_fail;
1744                         }
1745
1746                         _rtw_memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
1747                         pmlmeinfo->auth_seq = 3;
1748                         issue_auth(padapter, NULL, 0);
1749                         set_link_timer(pmlmeext, REAUTH_TO);
1750
1751                         return _SUCCESS;
1752                 }
1753                 else
1754                 {
1755                         // open system
1756                         go2asoc = 1;
1757                 }
1758         }
1759         else if (seq == 4)
1760         {
1761                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1762                 {
1763                         go2asoc = 1;
1764                 }
1765                 else
1766                 {
1767                         goto authclnt_fail;
1768                 }
1769         }
1770         else
1771         {
1772                 // this is also illegal
1773                 //DBG_871X("marc: clnt auth failed due to illegal seq=%x\n", seq);
1774                 goto authclnt_fail;
1775         }
1776
1777         if (go2asoc)
1778         {
1779                 DBG_871X_LEVEL(_drv_always_, "auth success, start assoc\n");
1780                 start_clnt_assoc(padapter);
1781                 return _SUCCESS;
1782         }
1783
1784 authclnt_fail:
1785
1786         //pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE);
1787
1788         return _FAIL;
1789
1790 }
1791
1792 unsigned int OnAssocReq(_adapter *padapter, union recv_frame *precv_frame)
1793 {
1794 #ifdef CONFIG_AP_MODE
1795         _irqL irqL;
1796         u16 capab_info, listen_interval;
1797         struct rtw_ieee802_11_elems elems;      
1798         struct sta_info *pstat;
1799         unsigned char           reassoc, *p, *pos, *wpa_ie;
1800         unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
1801         int             i, ie_len, wpa_ie_len, left;
1802         unsigned char           supportRate[16];
1803         int                                     supportRateNum;
1804         unsigned short          status = _STATS_SUCCESSFUL_;
1805         unsigned short          frame_type, ie_offset=0;        
1806         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1807         struct security_priv *psecuritypriv = &padapter->securitypriv;
1808         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1809         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);  
1810         WLAN_BSSID_EX   *cur = &(pmlmeinfo->network);
1811         struct sta_priv *pstapriv = &padapter->stapriv;
1812         u8 *pframe = precv_frame->u.hdr.rx_data;
1813         uint pkt_len = precv_frame->u.hdr.len;
1814 #ifdef CONFIG_P2P
1815         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
1816         u8 p2p_status_code = P2P_STATUS_SUCCESS;
1817         u8 *p2pie;
1818         u32 p2pielen = 0;
1819 #ifdef CONFIG_WFD
1820         u8      wfd_ie[ 128 ] = { 0x00 };
1821         u32     wfd_ielen = 0;
1822 #endif // CONFIG_WFD
1823 #endif //CONFIG_P2P
1824
1825 #ifdef CONFIG_CONCURRENT_MODE
1826         if(((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
1827                 check_buddy_fwstate(padapter, _FW_UNDER_LINKING|_FW_UNDER_SURVEY))
1828         {
1829                 //don't process assoc request;
1830                 return _SUCCESS;
1831         }
1832 #endif //CONFIG_CONCURRENT_MODE
1833
1834         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1835                 return _FAIL;
1836         
1837         frame_type = GetFrameSubType(pframe);
1838         if (frame_type == WIFI_ASSOCREQ)
1839         {
1840                 reassoc = 0;
1841                 ie_offset = _ASOCREQ_IE_OFFSET_;
1842         }       
1843         else // WIFI_REASSOCREQ
1844         {
1845                 reassoc = 1;
1846                 ie_offset = _REASOCREQ_IE_OFFSET_;
1847         }
1848         
1849
1850         if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
1851                 DBG_871X("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
1852                        "\n", reassoc, (unsigned long)pkt_len);
1853                 return _FAIL;
1854         }
1855         
1856         pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1857         if (pstat == (struct sta_info *)NULL)
1858         {
1859                 status = _RSON_CLS2_;
1860                 goto asoc_class2_error;
1861         }
1862
1863         capab_info = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN);
1864         //capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));      
1865         //listen_interval = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN+2));
1866         listen_interval = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN+2);
1867
1868         left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
1869         pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
1870         
1871
1872         DBG_871X("%s\n", __FUNCTION__);
1873
1874         // check if this stat has been successfully authenticated/assocated
1875         if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS))
1876         {
1877                 if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS))
1878                 {
1879                         status = _RSON_CLS2_;
1880                         goto asoc_class2_error;
1881                 }
1882                 else
1883                 {
1884                         pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1885                         pstat->state |= WIFI_FW_ASSOC_STATE;                            
1886                 }
1887         }
1888         else
1889         {
1890                 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1891                 pstat->state |= WIFI_FW_ASSOC_STATE;
1892         }
1893
1894
1895 #if 0// todo:tkip_countermeasures
1896         if (hapd->tkip_countermeasures) {
1897                 resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
1898                 goto fail;
1899         }
1900 #endif
1901
1902         pstat->capability = capab_info;
1903
1904 #if 0//todo:
1905         //check listen_interval
1906         if (listen_interval > hapd->conf->max_listen_interval) {
1907                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1908                                HOSTAPD_LEVEL_DEBUG,
1909                                "Too large Listen Interval (%d)",
1910                                listen_interval);
1911                 resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
1912                 goto fail;
1913         }
1914         
1915         pstat->listen_interval = listen_interval;
1916 #endif
1917
1918         //now parse all ieee802_11 ie to point to elems
1919         if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
1920             !elems.ssid) {
1921                 DBG_871X("STA " MAC_FMT " sent invalid association request\n",
1922                        MAC_ARG(pstat->hwaddr));
1923                 status = _STATS_FAILURE_;               
1924                 goto OnAssocReqFail;
1925         }
1926
1927
1928         // now we should check all the fields...
1929         // checking SSID
1930         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
1931                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1932         if (p == NULL)
1933         {
1934                 status = _STATS_FAILURE_;               
1935         }
1936
1937         if (ie_len == 0) // broadcast ssid, however it is not allowed in assocreq
1938                 status = _STATS_FAILURE_;
1939         else
1940         {
1941                 // check if ssid match
1942                 if (!_rtw_memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
1943                         status = _STATS_FAILURE_;
1944
1945                 if (ie_len != cur->Ssid.SsidLength)
1946                         status = _STATS_FAILURE_;
1947         }
1948
1949         if(_STATS_SUCCESSFUL_ != status)
1950                 goto OnAssocReqFail;
1951
1952         // check if the supported rate is ok
1953         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1954         if (p == NULL) {
1955                 DBG_871X("Rx a sta assoc-req which supported rate is empty!\n");
1956                 // use our own rate set as statoin used
1957                 //_rtw_memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN);
1958                 //supportRateNum = AP_BSSRATE_LEN;
1959                 
1960                 status = _STATS_FAILURE_;
1961                 goto OnAssocReqFail;
1962         }
1963         else {
1964                 _rtw_memcpy(supportRate, p+2, ie_len);
1965                 supportRateNum = ie_len;
1966
1967                 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &ie_len,
1968                                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1969                 if (p !=  NULL) {
1970                         
1971                         if(supportRateNum<=sizeof(supportRate))
1972                         {
1973                                 _rtw_memcpy(supportRate+supportRateNum, p+2, ie_len);
1974                                 supportRateNum += ie_len;
1975                         }                       
1976                 }
1977         }
1978
1979         //todo: mask supportRate between AP & STA -> move to update raid
1980         //get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0);
1981
1982         //update station supportRate    
1983         pstat->bssratelen = supportRateNum;
1984         _rtw_memcpy(pstat->bssrateset, supportRate, supportRateNum);
1985         UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1986
1987         //check RSN/WPA/WPS
1988         pstat->dot8021xalg = 0;
1989         pstat->wpa_psk = 0;
1990         pstat->wpa_group_cipher = 0;
1991         pstat->wpa2_group_cipher = 0;
1992         pstat->wpa_pairwise_cipher = 0;
1993         pstat->wpa2_pairwise_cipher = 0;
1994         _rtw_memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1995         if((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1996
1997                 int group_cipher=0, pairwise_cipher=0;  
1998                 
1999                 wpa_ie = elems.rsn_ie;
2000                 wpa_ie_len = elems.rsn_ie_len;
2001
2002                 if(rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
2003                 {
2004                         pstat->dot8021xalg = 1;//psk,  todo:802.1x                                              
2005                         pstat->wpa_psk |= BIT(1);
2006
2007                         pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;                               
2008                         pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
2009                         
2010                         if(!pstat->wpa2_group_cipher)
2011                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
2012
2013                         if(!pstat->wpa2_pairwise_cipher)
2014                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
2015                 }
2016                 else
2017                 {
2018                         status = WLAN_STATUS_INVALID_IE;
2019                 }       
2020                         
2021         } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
2022
2023                 int group_cipher=0, pairwise_cipher=0;  
2024                 
2025                 wpa_ie = elems.wpa_ie;
2026                 wpa_ie_len = elems.wpa_ie_len;
2027
2028                 if(rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
2029                 {
2030                         pstat->dot8021xalg = 1;//psk,  todo:802.1x                                              
2031                         pstat->wpa_psk |= BIT(0);
2032
2033                         pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;                         
2034                         pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
2035                         
2036                         if(!pstat->wpa_group_cipher)
2037                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
2038
2039                         if(!pstat->wpa_pairwise_cipher)
2040                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
2041                 
2042                 }
2043                 else
2044                 {
2045                         status = WLAN_STATUS_INVALID_IE;
2046                 }
2047                 
2048         } else {
2049                 wpa_ie = NULL;
2050                 wpa_ie_len = 0;
2051         }
2052
2053         if(_STATS_SUCCESSFUL_ != status)
2054                 goto OnAssocReqFail;
2055
2056         pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
2057         //if (hapd->conf->wps_state && wpa_ie == NULL) { //todo: to check ap if supporting WPS
2058         if(wpa_ie == NULL) {
2059                 if (elems.wps_ie) {
2060                         DBG_871X("STA included WPS IE in "
2061                                    "(Re)Association Request - assume WPS is "
2062                                    "used\n");
2063                         pstat->flags |= WLAN_STA_WPS;
2064                         //wpabuf_free(sta->wps_ie);
2065                         //sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4,
2066                         //                              elems.wps_ie_len - 4);
2067                 } else {
2068                         DBG_871X("STA did not include WPA/RSN IE "
2069                                    "in (Re)Association Request - possible WPS "
2070                                    "use\n");
2071                         pstat->flags |= WLAN_STA_MAYBE_WPS;
2072                 }
2073
2074
2075                 // AP support WPA/RSN, and sta is going to do WPS, but AP is not ready
2076                 // that the selected registrar of AP is _FLASE
2077                 if((psecuritypriv->wpa_psk >0)  
2078                         && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS)))
2079                 {
2080                         if(pmlmepriv->wps_beacon_ie)
2081                         {       
2082                                 u8 selected_registrar = 0;
2083                                 
2084                                 rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR , &selected_registrar, NULL);
2085
2086                                 if(!selected_registrar)
2087                                 {                                               
2088                                         DBG_871X("selected_registrar is _FALSE , or AP is not ready to do WPS\n");
2089                                                 
2090                                         status = _STATS_UNABLE_HANDLE_STA_;
2091                         
2092                                         goto OnAssocReqFail;
2093                                 }                                               
2094                         }                       
2095                 }
2096                         
2097         }
2098         else
2099         {
2100                 int copy_len;
2101
2102                 if(psecuritypriv->wpa_psk == 0)
2103                 {
2104                         DBG_871X("STA " MAC_FMT ": WPA/RSN IE in association "
2105                         "request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr));
2106                         
2107                         status = WLAN_STATUS_INVALID_IE;
2108                         
2109                         goto OnAssocReqFail;
2110
2111                 }
2112
2113                 if (elems.wps_ie) {
2114                         DBG_871X("STA included WPS IE in "
2115                                    "(Re)Association Request - WPS is "
2116                                    "used\n");
2117                         pstat->flags |= WLAN_STA_WPS;
2118                         copy_len=0;
2119                 }
2120                 else
2121                 {
2122                         copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
2123                 }
2124
2125                 
2126                 if(copy_len>0)
2127                         _rtw_memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
2128                 
2129         }
2130
2131
2132         // check if there is WMM IE & support WWM-PS
2133         pstat->flags &= ~WLAN_STA_WME;
2134         pstat->qos_option = 0;
2135         pstat->qos_info = 0;
2136         pstat->has_legacy_ac = _TRUE;
2137         pstat->uapsd_vo = 0;
2138         pstat->uapsd_vi = 0;
2139         pstat->uapsd_be = 0;
2140         pstat->uapsd_bk = 0;
2141         if (pmlmepriv->qospriv.qos_option) 
2142         {
2143                 p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
2144                 for (;;) 
2145                 {
2146                         p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
2147                         if (p != NULL) {
2148                                 if (_rtw_memcmp(p+2, WMM_IE, 6)) {
2149
2150                                         pstat->flags |= WLAN_STA_WME;
2151                                         
2152                                         pstat->qos_option = 1;                          
2153                                         pstat->qos_info = *(p+8);
2154                                         
2155                                         pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
2156
2157                                         if((pstat->qos_info&0xf) !=0xf)
2158                                                 pstat->has_legacy_ac = _TRUE;
2159                                         else
2160                                                 pstat->has_legacy_ac = _FALSE;
2161                                         
2162                                         if(pstat->qos_info&0xf)
2163                                         {
2164                                                 if(pstat->qos_info&BIT(0))
2165                                                         pstat->uapsd_vo = BIT(0)|BIT(1);
2166                                                 else
2167                                                         pstat->uapsd_vo = 0;
2168                 
2169                                                 if(pstat->qos_info&BIT(1))
2170                                                         pstat->uapsd_vi = BIT(0)|BIT(1);
2171                                                 else
2172                                                         pstat->uapsd_vi = 0;
2173                         
2174                                                 if(pstat->qos_info&BIT(2))
2175                                                         pstat->uapsd_bk = BIT(0)|BIT(1);
2176                                                 else
2177                                                         pstat->uapsd_bk = 0;
2178                         
2179                                                 if(pstat->qos_info&BIT(3))                      
2180                                                         pstat->uapsd_be = BIT(0)|BIT(1);
2181                                                 else
2182                                                         pstat->uapsd_be = 0;
2183                 
2184                                         }
2185         
2186                                         break;
2187                                 }
2188                         }
2189                         else {
2190                                 break;
2191                         }
2192                         p = p + ie_len + 2;
2193                 }
2194         }
2195
2196
2197 #ifdef CONFIG_80211N_HT
2198         /* save HT capabilities in the sta object */
2199         _rtw_memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
2200         if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) 
2201         {
2202                 pstat->flags |= WLAN_STA_HT;
2203                 
2204                 pstat->flags |= WLAN_STA_WME;
2205                 
2206                 _rtw_memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));                 
2207                 
2208         } else
2209                 pstat->flags &= ~WLAN_STA_HT;
2210
2211         
2212         if((pmlmepriv->htpriv.ht_option == _FALSE) && (pstat->flags&WLAN_STA_HT))
2213         {
2214                 status = _STATS_FAILURE_;
2215                 goto OnAssocReqFail;
2216         }
2217                 
2218
2219         if ((pstat->flags & WLAN_STA_HT) &&
2220                     ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
2221                       (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP)))
2222         {                   
2223                 DBG_871X("HT: " MAC_FMT " tried to "
2224                                    "use TKIP with HT association\n", MAC_ARG(pstat->hwaddr));
2225                 
2226                 //status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
2227                 //goto OnAssocReqFail;
2228         }
2229 #endif /* CONFIG_80211N_HT */
2230
2231 #ifdef CONFIG_80211AC_VHT
2232         _rtw_memset(&pstat->vhtpriv, 0, sizeof(struct vht_priv));
2233         if (elems.vht_capabilities && elems.vht_capabilities_len == 12) {
2234                 pstat->flags |= WLAN_STA_VHT;
2235
2236                 _rtw_memcpy(pstat->vhtpriv.vht_cap, elems.vht_capabilities, 12);
2237
2238                 if (elems.vht_op_mode_notify && elems.vht_op_mode_notify_len == 1) {
2239                         _rtw_memcpy(&pstat->vhtpriv.vht_op_mode_notify, elems.vht_op_mode_notify, 1);
2240                 }
2241         }
2242         else {
2243                 pstat->flags &= ~WLAN_STA_VHT;
2244         }
2245
2246         if((pmlmepriv->vhtpriv.vht_option == _FALSE) && (pstat->flags&WLAN_STA_VHT))
2247         {
2248                 status = _STATS_FAILURE_;
2249                 goto OnAssocReqFail;
2250         }
2251 #endif /* CONFIG_80211AC_VHT */
2252
2253        //
2254        //if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)//?
2255         pstat->flags |= WLAN_STA_NONERP;        
2256         for (i = 0; i < pstat->bssratelen; i++) {
2257                 if ((pstat->bssrateset[i] & 0x7f) > 22) {
2258                         pstat->flags &= ~WLAN_STA_NONERP;
2259                         break;
2260                 }
2261         }
2262
2263         if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
2264                 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
2265         else
2266                 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
2267
2268         
2269         
2270         if (status != _STATS_SUCCESSFUL_)
2271                 goto OnAssocReqFail;
2272
2273 #ifdef CONFIG_P2P
2274         pstat->is_p2p_device = _FALSE;
2275         if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2276         {               
2277                 if( (p2pie=rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , NULL, &p2pielen)))
2278                 {
2279                         pstat->is_p2p_device = _TRUE;
2280                         if((p2p_status_code=(u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat))>0)
2281                         {
2282                                 pstat->p2p_status_code = p2p_status_code;
2283                                 status = _STATS_CAP_FAIL_;
2284                                 goto OnAssocReqFail;
2285                         }
2286                 }
2287 #ifdef CONFIG_WFD
2288                 if(rtw_get_wfd_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , wfd_ie, &wfd_ielen ))
2289                 {
2290                         u8      attr_content[ 10 ] = { 0x00 };
2291                         u32     attr_contentlen = 0;
2292
2293                         DBG_8192C( "[%s] WFD IE Found!!\n", __FUNCTION__ );
2294                         rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
2295                         if ( attr_contentlen )
2296                         {
2297                                 pwdinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );
2298                                 DBG_8192C( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_rtsp_ctrlport );
2299                         }
2300                 }
2301 #endif
2302         }
2303         pstat->p2p_status_code = p2p_status_code;
2304 #endif //CONFIG_P2P
2305
2306         //TODO: identify_proprietary_vendor_ie();
2307         // Realtek proprietary IE
2308         // identify if this is Broadcom sta
2309         // identify if this is ralink sta
2310         // Customer proprietary IE
2311
2312         
2313
2314         /* get a unique AID */
2315         if (pstat->aid > 0) {
2316                 DBG_871X("  old AID %d\n", pstat->aid);
2317         } else {
2318                 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
2319                         if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
2320                                 break;
2321                                 
2322                 //if (pstat->aid > NUM_STA) {
2323                 if (pstat->aid > pstapriv->max_num_sta) {
2324                                 
2325                         pstat->aid = 0;
2326                                 
2327                         DBG_871X("  no room for more AIDs\n");
2328
2329                         status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2330                                 
2331                         goto OnAssocReqFail;
2332                                 
2333                         
2334                 } else {
2335                         pstapriv->sta_aid[pstat->aid - 1] = pstat;
2336                         DBG_871X("allocate new AID = (%d)\n", pstat->aid);
2337                 }       
2338         }
2339
2340
2341         pstat->state &= (~WIFI_FW_ASSOC_STATE); 
2342         pstat->state |= WIFI_FW_ASSOC_SUCCESS;
2343         
2344         _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
2345         if (!rtw_is_list_empty(&pstat->auth_list))
2346         {
2347                 rtw_list_delete(&pstat->auth_list);
2348                 pstapriv->auth_list_cnt--;
2349         }
2350         _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
2351
2352         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);   
2353         if (rtw_is_list_empty(&pstat->asoc_list))
2354         {
2355                 pstat->expire_to = pstapriv->expire_to;
2356                 rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list);
2357                 pstapriv->asoc_list_cnt++;
2358         }
2359         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2360
2361         // now the station is qualified to join our BSS...      
2362         if(pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_==status))
2363         {
2364 #ifdef CONFIG_NATIVEAP_MLME
2365                 //.1 bss_cap_update & sta_info_update
2366                 bss_cap_update_on_sta_join(padapter, pstat);
2367                 sta_info_update(padapter, pstat);
2368
2369                 //.2 issue assoc rsp before notify station join event.
2370                 if (frame_type == WIFI_ASSOCREQ)
2371                         issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
2372                 else
2373                         issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
2374
2375 #ifdef CONFIG_IOCTL_CFG80211
2376                 _enter_critical_bh(&pstat->lock, &irqL);
2377                 if(pstat->passoc_req)
2378                 {
2379                         rtw_mfree(pstat->passoc_req, pstat->assoc_req_len);
2380                         pstat->passoc_req = NULL;
2381                         pstat->assoc_req_len = 0;
2382                 }
2383
2384                 pstat->passoc_req =  rtw_zmalloc(pkt_len);
2385                 if(pstat->passoc_req)
2386                 {
2387                         _rtw_memcpy(pstat->passoc_req, pframe, pkt_len);
2388                         pstat->assoc_req_len = pkt_len;
2389                 }
2390                 _exit_critical_bh(&pstat->lock, &irqL);
2391 #endif //CONFIG_IOCTL_CFG80211
2392
2393                 //.3-(1) report sta add event
2394                 report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
2395         
2396 #endif //CONFIG_NATIVEAP_MLME
2397         }
2398
2399         return _SUCCESS;
2400
2401 asoc_class2_error:
2402
2403 #ifdef CONFIG_NATIVEAP_MLME
2404         issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
2405 #endif
2406
2407         return _FAIL;           
2408
2409 OnAssocReqFail:
2410
2411
2412 #ifdef CONFIG_NATIVEAP_MLME
2413         pstat->aid = 0;
2414         if (frame_type == WIFI_ASSOCREQ)
2415                 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
2416         else
2417                 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
2418 #endif
2419
2420
2421 #endif /* CONFIG_AP_MODE */
2422
2423         return _FAIL;           
2424
2425 }
2426
2427 unsigned int OnAssocRsp(_adapter *padapter, union recv_frame *precv_frame)
2428 {
2429         uint i;
2430         int res;
2431         unsigned short  status;
2432         PNDIS_802_11_VARIABLE_IEs       pIE;
2433         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2434         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2435         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2436         //WLAN_BSSID_EX                 *cur_network = &(pmlmeinfo->network);
2437         u8 *pframe = precv_frame->u.hdr.rx_data;
2438         uint pkt_len = precv_frame->u.hdr.len;
2439         PNDIS_802_11_VARIABLE_IEs       pWapiIE = NULL;
2440
2441         DBG_871X("%s\n", __FUNCTION__);
2442         
2443         //check A1 matches or not
2444         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
2445                 return _SUCCESS;
2446
2447         if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
2448                 return _SUCCESS;
2449
2450         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
2451                 return _SUCCESS;
2452
2453         _cancel_timer_ex(&pmlmeext->link_timer);
2454
2455         //status
2456         if ((status = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 2))) > 0)
2457         {
2458                 DBG_871X("assoc reject, status code: %d\n", status);
2459                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
2460                 res = -4;
2461                 goto report_assoc_result;
2462         }
2463
2464         //get capabilities
2465         pmlmeinfo->capability = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
2466
2467         //set slot time
2468         pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
2469
2470         //AID
2471         res = pmlmeinfo->aid = (int)(le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
2472
2473         //following are moved to join event callback function
2474         //to handle HT, WMM, rate adaptive, update MAC reg
2475         //for not to handle the synchronous IO in the tasklet
2476         for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;)
2477         {
2478                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pframe + i);
2479
2480                 switch (pIE->ElementID)
2481                 {
2482                         case _VENDOR_SPECIFIC_IE_:
2483                                 if (_rtw_memcmp(pIE->data, WMM_PARA_OUI, 6))    //WMM
2484                                 {
2485                                         WMM_param_handler(padapter, pIE);
2486                                 }
2487 #if defined(CONFIG_P2P) && defined(CONFIG_WFD)
2488                                 else if ( _rtw_memcmp(pIE->data, WFD_OUI, 4))           //WFD
2489                                 {
2490                                         DBG_871X( "[%s] Found WFD IE\n", __FUNCTION__ );
2491                                         WFD_info_handler( padapter, pIE );
2492                                 }
2493 #endif                          
2494                                 break;
2495
2496 #ifdef CONFIG_WAPI_SUPPORT
2497                         case _WAPI_IE_:
2498                                 pWapiIE = pIE;
2499                                 break;
2500 #endif
2501
2502                         case _HT_CAPABILITY_IE_:        //HT caps
2503                                 HT_caps_handler(padapter, pIE);
2504                                 break;
2505
2506                         case _HT_EXTRA_INFO_IE_:        //HT info
2507                                 HT_info_handler(padapter, pIE);
2508                                 break;
2509
2510 #ifdef CONFIG_80211AC_VHT
2511                         case EID_VHTCapability:
2512                                 VHT_caps_handler(padapter, pIE);
2513                                 break;
2514
2515                         case EID_VHTOperation:
2516                                 VHT_operation_handler(padapter, pIE);
2517                                 break;
2518 #endif
2519
2520                         case _ERPINFO_IE_:
2521                                 ERP_IE_handler(padapter, pIE);
2522
2523                         default:
2524                                 break;
2525                 }
2526
2527                 i += (pIE->Length + 2);
2528         }
2529
2530 #ifdef CONFIG_WAPI_SUPPORT
2531         rtw_wapi_on_assoc_ok(padapter, pIE);
2532 #endif
2533
2534         pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
2535         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
2536
2537         //Update Basic Rate Table for spec, 2010-12-28 , by thomas
2538         UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
2539
2540 report_assoc_result:
2541         if (res > 0) {
2542                 rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
2543         } else {
2544                 rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
2545         }
2546
2547         report_join_res(padapter, res);
2548
2549         return _SUCCESS;
2550 }
2551
2552 unsigned int OnDeAuth(_adapter *padapter, union recv_frame *precv_frame)
2553 {
2554         unsigned short  reason;
2555         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2556         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2557         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2558         u8 *pframe = precv_frame->u.hdr.rx_data;
2559 #ifdef CONFIG_P2P
2560         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
2561 #endif //CONFIG_P2P
2562
2563         //check A3
2564         if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
2565                 return _SUCCESS;
2566
2567 #ifdef CONFIG_P2P
2568         if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
2569         {
2570                 _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
2571                 _set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
2572         }
2573 #endif //CONFIG_P2P
2574
2575         reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
2576
2577         rtw_lock_rx_suspend_timeout(8000);
2578
2579 #ifdef CONFIG_AP_MODE
2580         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
2581         {               
2582                 _irqL irqL;
2583                 struct sta_info *psta;
2584                 struct sta_priv *pstapriv = &padapter->stapriv;
2585                 
2586                 //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);                
2587                 //rtw_free_stainfo(padapter, psta);
2588                 //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);         
2589
2590                 DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" reason=%u, ta=%pM\n"
2591                         , FUNC_ADPT_ARG(padapter), reason, GetAddr2Ptr(pframe));
2592
2593                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));  
2594                 if(psta)
2595                 {
2596                         u8 updated = _FALSE;
2597                 
2598                         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2599                         if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
2600                         {                       
2601                                 rtw_list_delete(&psta->asoc_list);
2602                                 pstapriv->asoc_list_cnt--;
2603                                 updated = ap_free_sta(padapter, psta, _FALSE, reason);
2604
2605                         }
2606                         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2607
2608                         associated_clients_update(padapter, updated);
2609                 }
2610                 
2611
2612                 return _SUCCESS;
2613         }
2614         else
2615 #endif
2616         {
2617                 int     ignore_received_deauth = 0;
2618
2619                 //      Commented by Albert 20130604
2620                 //      Before sending the auth frame to start the STA/GC mode connection with AP/GO, 
2621                 //      we will send the deauth first.
2622                 //      However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth.
2623                 //      Added the following code to avoid this case.
2624                 if ( ( pmlmeinfo->state & WIFI_FW_AUTH_STATE ) ||
2625                         ( pmlmeinfo->state & WIFI_FW_ASSOC_STATE ) )
2626                 {
2627                         if ( reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA )
2628                         {
2629                                 ignore_received_deauth = 1;
2630                         } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) {
2631                                 // TODO: 802.11r
2632                                 ignore_received_deauth = 1;
2633                         }
2634                 }
2635
2636                 DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" reason=%u, ta=%pM, ignore=%d\n"
2637                         , FUNC_ADPT_ARG(padapter), reason, GetAddr2Ptr(pframe), ignore_received_deauth);
2638
2639                 if ( 0 == ignore_received_deauth )
2640                 {
2641                         receive_disconnect(padapter, GetAddr2Ptr(pframe), reason);
2642                 }
2643         }       
2644         pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
2645         return _SUCCESS;
2646
2647 }
2648
2649 unsigned int OnDisassoc(_adapter *padapter, union recv_frame *precv_frame)
2650 {
2651         unsigned short  reason;
2652         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2653         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2654         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2655         u8 *pframe = precv_frame->u.hdr.rx_data;
2656 #ifdef CONFIG_P2P
2657         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
2658 #endif //CONFIG_P2P
2659
2660         //check A3
2661         if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
2662                 return _SUCCESS;
2663
2664 #ifdef CONFIG_P2P
2665         if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
2666         {
2667                 _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
2668                 _set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
2669         }
2670 #endif //CONFIG_P2P
2671
2672         reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
2673
2674         rtw_lock_rx_suspend_timeout(8000);
2675         
2676 #ifdef CONFIG_AP_MODE
2677         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
2678         {       
2679                 _irqL irqL;
2680                 struct sta_info *psta;
2681                 struct sta_priv *pstapriv = &padapter->stapriv;
2682                 
2683                 //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);        
2684                 //rtw_free_stainfo(padapter, psta);
2685                 //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);         
2686
2687                 DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" reason=%u, ta=%pM\n"
2688                         , FUNC_ADPT_ARG(padapter), reason, GetAddr2Ptr(pframe));
2689
2690                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));  
2691                 if(psta)
2692                 {
2693                         u8 updated = _FALSE;
2694                         
2695                         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2696                         if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
2697                         {
2698                                 rtw_list_delete(&psta->asoc_list);
2699                                 pstapriv->asoc_list_cnt--;
2700                                 updated = ap_free_sta(padapter, psta, _FALSE, reason);
2701                         
2702                         }
2703                         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2704
2705                         associated_clients_update(padapter, updated);
2706                 }
2707
2708                 return _SUCCESS;
2709         }
2710         else
2711 #endif
2712         {
2713                 DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" reason=%u, ta=%pM\n"
2714                         , FUNC_ADPT_ARG(padapter), reason, GetAddr2Ptr(pframe));
2715
2716                 receive_disconnect(padapter, GetAddr2Ptr(pframe), reason);
2717         }       
2718         pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
2719         return _SUCCESS;
2720
2721 }
2722
2723 unsigned int OnAtim(_adapter *padapter, union recv_frame *precv_frame)
2724 {
2725         DBG_871X("%s\n", __FUNCTION__);
2726         return _SUCCESS;
2727 }
2728
2729 unsigned int on_action_spct_ch_switch(_adapter *padapter, struct sta_info *psta, u8 *ies, uint ies_len)
2730 {
2731         unsigned int ret = _FAIL;
2732         struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv;
2733         struct mlme_ext_info    *pmlmeinfo = &(mlmeext->mlmext_info);
2734
2735         if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
2736                 ret = _SUCCESS; 
2737                 goto exit;
2738         }
2739
2740         if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
2741                 
2742                 int ch_switch_mode = -1, ch = -1, ch_switch_cnt = -1;
2743                 int ch_offset = -1;
2744                 u8 bwmode;
2745                 struct ieee80211_info_element *ie;
2746
2747                 DBG_871X(FUNC_NDEV_FMT" from "MAC_FMT"\n",
2748                         FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(psta->hwaddr));
2749
2750                 for_each_ie(ie, ies, ies_len) {
2751                         if (ie->id == WLAN_EID_CHANNEL_SWITCH) {
2752                                 ch_switch_mode = ie->data[0];
2753                                 ch = ie->data[1];
2754                                 ch_switch_cnt = ie->data[2];
2755                                 DBG_871X("ch_switch_mode:%d, ch:%d, ch_switch_cnt:%d\n",
2756                                         ch_switch_mode, ch, ch_switch_cnt);
2757                         }
2758                         else if (ie->id == WLAN_EID_SECONDARY_CHANNEL_OFFSET) {
2759                                 ch_offset = secondary_ch_offset_to_hal_ch_offset(ie->data[0]);
2760                                 DBG_871X("ch_offset:%d\n", ch_offset);
2761                         }
2762                 }
2763
2764                 if (ch == -1)
2765                         return _SUCCESS;
2766
2767                 if (ch_offset == -1)
2768                         bwmode = mlmeext->cur_bwmode;
2769                 else
2770                         bwmode = (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) ?
2771                                 CHANNEL_WIDTH_20 : CHANNEL_WIDTH_40;
2772
2773                 ch_offset = (ch_offset == -1) ? mlmeext->cur_ch_offset : ch_offset;
2774
2775                 /* todo:
2776                  * 1. the decision of channel switching
2777                  * 2. things after channel switching
2778                  */
2779
2780                 ret = rtw_set_ch_cmd(padapter, ch, bwmode, ch_offset, _TRUE);
2781         }
2782
2783 exit:
2784         return ret;
2785 }
2786
2787 unsigned int on_action_spct(_adapter *padapter, union recv_frame *precv_frame)
2788 {
2789         unsigned int ret = _FAIL;
2790         struct sta_info *psta = NULL;
2791         struct sta_priv *pstapriv = &padapter->stapriv;
2792         u8 *pframe = precv_frame->u.hdr.rx_data;
2793         uint frame_len = precv_frame->u.hdr.len;
2794         u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2795         u8 category;
2796         u8 action;
2797
2798         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
2799
2800         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
2801
2802         if (!psta)
2803                 goto exit;
2804
2805         category = frame_body[0];
2806         if(category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
2807                 goto exit;
2808
2809         action = frame_body[1];
2810         switch (action) {
2811         case RTW_WLAN_ACTION_SPCT_MSR_REQ:
2812         case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
2813         case RTW_WLAN_ACTION_SPCT_TPC_REQ:
2814         case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
2815                 break;
2816         case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
2817                 #ifdef CONFIG_SPCT_CH_SWITCH
2818                 ret = on_action_spct_ch_switch(padapter, psta, &frame_body[2],
2819                         frame_len-(frame_body-pframe)-2);
2820                 #endif
2821                 break;
2822         default:
2823                 break;
2824         }
2825
2826 exit:
2827         return ret;
2828 }
2829
2830 unsigned int OnAction_qos(_adapter *padapter, union recv_frame *precv_frame)
2831 {
2832         return _SUCCESS;
2833 }
2834
2835 unsigned int OnAction_dls(_adapter *padapter, union recv_frame *precv_frame)
2836 {
2837         return _SUCCESS;
2838 }
2839
2840 unsigned int OnAction_back(_adapter *padapter, union recv_frame *precv_frame)
2841 {
2842         u8 *addr;
2843         struct sta_info *psta=NULL;
2844         struct recv_reorder_ctrl *preorder_ctrl;
2845         unsigned char           *frame_body;
2846         unsigned char           category, action;
2847         unsigned short  tid, status, reason_code = 0;
2848         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2849         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2850         u8 *pframe = precv_frame->u.hdr.rx_data;
2851         struct sta_priv *pstapriv = &padapter->stapriv;
2852 #ifdef CONFIG_80211N_HT
2853
2854         DBG_871X("%s\n", __FUNCTION__);
2855
2856         //check RA matches or not       
2857         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))//for if1, sta/ap mode
2858                 return _SUCCESS;
2859
2860 /*
2861         //check A1 matches or not
2862         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
2863                 return _SUCCESS;
2864 */
2865
2866         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 
2867                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2868                         return _SUCCESS;
2869
2870         addr = GetAddr2Ptr(pframe);
2871         psta = rtw_get_stainfo(pstapriv, addr);
2872
2873         if(psta==NULL)
2874                 return _SUCCESS;
2875
2876         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2877
2878         category = frame_body[0];
2879         if (category == RTW_WLAN_CATEGORY_BACK)// representing Block Ack
2880         {
2881 #ifdef CONFIG_TDLS
2882                 if((psta->tdls_sta_state & TDLS_LINKED_STATE) && 
2883                         (psta->htpriv.ht_option==_TRUE) &&
2884                         (psta->htpriv.ampdu_enable==_TRUE))
2885                 {
2886                         DBG_871X("Recv [%s] from direc link\n", __FUNCTION__);
2887                 }
2888                 else
2889 #endif //CONFIG_TDLS
2890                 if (!pmlmeinfo->HT_enable)
2891                 {
2892                         return _SUCCESS;
2893                 }
2894
2895                 action = frame_body[1];
2896                 DBG_871X("%s, action=%d\n", __FUNCTION__, action);
2897                 switch (action)
2898                 {
2899                         case RTW_WLAN_ACTION_ADDBA_REQ: //ADDBA request
2900
2901                                 _rtw_memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
2902                                 //process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe));
2903                                 process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), addr);
2904                                 
2905                                 if(pmlmeinfo->bAcceptAddbaReq == _TRUE)
2906                                 {
2907                                         issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
2908                                 }
2909                                 else
2910                                 {
2911                                         issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);//reject ADDBA Req
2912                                 }
2913                                                                 
2914                                 break;
2915
2916                         case RTW_WLAN_ACTION_ADDBA_RESP: //ADDBA response
2917
2918                                 //status = frame_body[3] | (frame_body[4] << 8); //endian issue
2919                                 status = RTW_GET_LE16(&frame_body[3]);
2920                                 tid = ((frame_body[5] >> 2) & 0x7);
2921
2922                                 if (status == 0)
2923                                 {       //successful                                    
2924                                         DBG_871X("agg_enable for TID=%d\n", tid);
2925                                         psta->htpriv.agg_enable_bitmap |= 1 << tid;                                     
2926                                         psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);                         
2927                                 }
2928                                 else
2929                                 {                                       
2930                                         psta->htpriv.agg_enable_bitmap &= ~BIT(tid);                                    
2931                                 }
2932
2933                                 if(psta->state & WIFI_STA_ALIVE_CHK_STATE)
2934                                 {
2935                                         DBG_871X("%s alive check - rx ADDBA response\n", __func__);
2936                                         psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2937                                         psta->expire_to = pstapriv->expire_to;
2938                                         psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
2939                                 }
2940
2941                                 //DBG_871X("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap);
2942                                 break;
2943
2944                         case RTW_WLAN_ACTION_DELBA: //DELBA
2945                                 if ((frame_body[3] & BIT(3)) == 0)
2946                                 {
2947                                         psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
2948                                         psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
2949                                         
2950                                         //reason_code = frame_body[4] | (frame_body[5] << 8);
2951                                         reason_code = RTW_GET_LE16(&frame_body[4]);
2952                                 }
2953                                 else if((frame_body[3] & BIT(3)) == BIT(3))
2954                                 {                                               
2955                                         tid = (frame_body[3] >> 4) & 0x0F;
2956                                 
2957                                         preorder_ctrl =  &psta->recvreorder_ctrl[tid];
2958                                         preorder_ctrl->enable = _FALSE;
2959                                         preorder_ctrl->indicate_seq = 0xffff;
2960                                         #ifdef DBG_RX_SEQ
2961                                         DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u \n", __FUNCTION__, __LINE__,
2962                                                 preorder_ctrl->indicate_seq);
2963                                         #endif
2964                                 }
2965                                 
2966                                 DBG_871X("%s(): DELBA: %x(%x)\n", __FUNCTION__,pmlmeinfo->agg_enable_bitmap, reason_code);
2967                                 //todo: how to notify the host while receiving DELETE BA
2968                                 break;
2969
2970                         default:
2971                                 break;
2972                 }
2973         }
2974 #endif //CONFIG_80211N_HT
2975         return _SUCCESS;
2976 }
2977
2978 #ifdef CONFIG_P2P
2979
2980 static int get_reg_classes_full_count(struct p2p_channels channel_list) {
2981         int cnt = 0;
2982         int i;
2983
2984         for (i = 0; i < channel_list.reg_classes; i++) {
2985                 cnt += channel_list.reg_class[i].channels;
2986         }
2987
2988         return cnt;
2989 }
2990
2991 static void get_channel_cnt_24g_5gl_5gh(  struct mlme_ext_priv *pmlmeext, u8* p24g_cnt, u8* p5gl_cnt, u8* p5gh_cnt )
2992 {
2993         int     i = 0;
2994
2995         *p24g_cnt = 0;
2996         *p5gl_cnt = 0;
2997         *p5gh_cnt = 0;  
2998         
2999         for( i = 0; i < pmlmeext->max_chan_nums; i++ )
3000         {
3001                 if ( pmlmeext->channel_set[ i ].ChannelNum <= 14 )
3002                 {
3003                         (*p24g_cnt)++;
3004                 }
3005                 else if ( ( pmlmeext->channel_set[ i ].ChannelNum > 14 ) && ( pmlmeext->channel_set[ i ].ChannelNum <= 48 ) )
3006                 {
3007                         //      Just include the channel 36, 40, 44, 48 channels for 5G low
3008                         (*p5gl_cnt)++;
3009                 }
3010                 else if ( ( pmlmeext->channel_set[ i ].ChannelNum >= 149 ) && ( pmlmeext->channel_set[ i ].ChannelNum <= 161 ) )
3011                 {
3012                         //      Just include the channel 149, 153, 157, 161 channels for 5G high
3013                         (*p5gh_cnt)++;
3014                 }
3015         }
3016 }
3017
3018 void issue_p2p_GO_request(_adapter *padapter, u8* raddr)
3019 {
3020
3021         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3022         u8                      action = P2P_PUB_ACTION_ACTION;
3023         u32                     p2poui = cpu_to_be32(P2POUI);
3024         u8                      oui_subtype = P2P_GO_NEGO_REQ;
3025         u8                      wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
3026         u8                      wpsielen = 0, p2pielen = 0, i;
3027         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
3028         u16                     len_channellist_attr = 0;
3029 #ifdef CONFIG_WFD
3030         u32                                     wfdielen = 0;
3031 #endif //CONFIG_WFD             
3032         
3033         struct xmit_frame                       *pmgntframe;
3034         struct pkt_attrib                       *pattrib;
3035         unsigned char                                   *pframe;
3036         struct rtw_ieee80211_hdr        *pwlanhdr;
3037         unsigned short                          *fctrl;
3038         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3039         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3040         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3041         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
3042
3043
3044         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
3045         {
3046                 return;
3047         }
3048
3049         DBG_871X( "[%s] In\n", __FUNCTION__ );
3050         //update attribute
3051         pattrib = &pmgntframe->attrib;
3052         update_mgntframe_attrib(padapter, pattrib);
3053
3054         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3055
3056         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3057         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3058
3059         fctrl = &(pwlanhdr->frame_ctl);
3060         *(fctrl) = 0;
3061
3062         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3063         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3064         _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
3065
3066         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3067         pmlmeext->mgnt_seq++;
3068         SetFrameSubType(pframe, WIFI_ACTION);
3069
3070         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3071         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3072
3073         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3074         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3075         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
3076         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
3077         pwdinfo->negotiation_dialog_token = 1;  //      Initialize the dialog value
3078         pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &(pattrib->pktlen));
3079
3080         
3081
3082         //      WPS Section
3083         wpsielen = 0;
3084         //      WPS OUI
3085         *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
3086         wpsielen += 4;
3087
3088         //      WPS version
3089         //      Type:
3090         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
3091         wpsielen += 2;
3092
3093         //      Length:
3094         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
3095         wpsielen += 2;
3096
3097         //      Value:
3098         wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0
3099
3100         //      Device Password ID
3101         //      Type:
3102         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
3103         wpsielen += 2;
3104
3105         //      Length:
3106         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
3107         wpsielen += 2;
3108
3109         //      Value:
3110
3111         if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN )
3112         {
3113                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_USER_SPEC );
3114         }
3115         else if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN )
3116         {
3117                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );
3118         }
3119         else if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC )
3120         {
3121                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_PBC );
3122         }
3123
3124         wpsielen += 2;
3125
3126         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
3127
3128
3129         //      P2P IE Section.
3130
3131         //      P2P OUI
3132         p2pielen = 0;
3133         p2pie[ p2pielen++ ] = 0x50;
3134         p2pie[ p2pielen++ ] = 0x6F;
3135         p2pie[ p2pielen++ ] = 0x9A;
3136         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
3137
3138         //      Commented by Albert 20110306
3139         //      According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes
3140         //      1. P2P Capability
3141         //      2. Group Owner Intent
3142         //      3. Configuration Timeout
3143         //      4. Listen Channel
3144         //      5. Extended Listen Timing
3145         //      6. Intended P2P Interface Address
3146         //      7. Channel List
3147         //      8. P2P Device Info
3148         //      9. Operating Channel
3149
3150
3151         //      P2P Capability
3152         //      Type:
3153         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
3154
3155         //      Length:
3156         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3157         p2pielen += 2;
3158
3159         //      Value:
3160         //      Device Capability Bitmap, 1 byte
3161         p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
3162
3163         //      Group Capability Bitmap, 1 byte
3164         if ( pwdinfo->persistent_supported )
3165         {
3166                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
3167         }
3168         else
3169         {
3170                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
3171         }
3172
3173
3174         //      Group Owner Intent
3175         //      Type:
3176         p2pie[ p2pielen++ ] = P2P_ATTR_GO_INTENT;
3177
3178         //      Length:
3179         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
3180         p2pielen += 2;
3181
3182         //      Value:
3183         //      Todo the tie breaker bit.
3184         p2pie[ p2pielen++ ] = ( ( pwdinfo->intent << 1 ) | BIT(0) );
3185
3186         //      Configuration Timeout
3187         //      Type:
3188         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
3189
3190         //      Length:
3191         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3192         p2pielen += 2;
3193
3194         //      Value:
3195         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P GO
3196         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P Client
3197
3198
3199         //      Listen Channel
3200         //      Type:
3201         p2pie[ p2pielen++ ] = P2P_ATTR_LISTEN_CH;
3202
3203         //      Length:
3204         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
3205         p2pielen += 2;
3206
3207         //      Value:
3208         //      Country String
3209         p2pie[ p2pielen++ ] = 'X';
3210         p2pie[ p2pielen++ ] = 'X';
3211         
3212         //      The third byte should be set to 0x04.
3213         //      Described in the "Operating Channel Attribute" section.
3214         p2pie[ p2pielen++ ] = 0x04;
3215
3216         //      Operating Class
3217         p2pie[ p2pielen++ ] = 0x51;     //      Copy from SD7
3218         
3219         //      Channel Number
3220         p2pie[ p2pielen++ ] = pwdinfo->listen_channel;  //      listening channel number
3221         
3222
3223         //      Extended Listen Timing ATTR
3224         //      Type:
3225         p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
3226
3227         //      Length:
3228         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
3229         p2pielen += 2;
3230
3231         //      Value:
3232         //      Availability Period
3233         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
3234         p2pielen += 2;
3235
3236         //      Availability Interval
3237         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
3238         p2pielen += 2;
3239
3240
3241         //      Intended P2P Interface Address
3242         //      Type:
3243         p2pie[ p2pielen++ ] = P2P_ATTR_INTENTED_IF_ADDR;
3244
3245         //      Length:
3246         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
3247         p2pielen += 2;
3248
3249         //      Value:
3250         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3251         p2pielen += ETH_ALEN;
3252
3253
3254         //      Channel List
3255         //      Type:
3256         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
3257
3258         // Length:
3259         // Country String(3)
3260         // + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
3261         // + number of channels in all classes
3262         len_channellist_attr = 3
3263            + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
3264            + get_reg_classes_full_count(pmlmeext->channel_list);
3265
3266 #ifdef CONFIG_CONCURRENT_MODE
3267         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3268         {
3269                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
3270         }
3271         else
3272         {
3273                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3274         }
3275 #else
3276
3277         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3278
3279 #endif
3280         p2pielen += 2;
3281
3282         //      Value:
3283         //      Country String
3284         p2pie[ p2pielen++ ] = 'X';
3285         p2pie[ p2pielen++ ] = 'X';
3286         
3287         //      The third byte should be set to 0x04.
3288         //      Described in the "Operating Channel Attribute" section.
3289         p2pie[ p2pielen++ ] = 0x04;
3290
3291         //      Channel Entry List
3292
3293 #ifdef CONFIG_CONCURRENT_MODE
3294         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3295         {
3296                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;    
3297                 struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3298
3299                 //      Operating Class
3300                 if ( pbuddy_mlmeext->cur_channel > 14 )
3301                 {
3302                         if ( pbuddy_mlmeext->cur_channel >= 149 )
3303                         {
3304                                 p2pie[ p2pielen++ ] = 0x7c;
3305                         }
3306                         else
3307                         {
3308                                 p2pie[ p2pielen++ ] = 0x73;
3309                         }
3310                 }
3311                 else
3312                 {
3313                         p2pie[ p2pielen++ ] = 0x51;
3314                 }
3315
3316                 //      Number of Channels
3317                 //      Just support 1 channel and this channel is AP's channel
3318                 p2pie[ p2pielen++ ] = 1;
3319
3320                 //      Channel List
3321                 p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
3322         }
3323         else
3324         {
3325                 int i,j;
3326                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3327                         //      Operating Class
3328                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3329
3330                         //      Number of Channels
3331                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3332
3333                         //      Channel List
3334                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3335                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3336                         }
3337                 }
3338         }
3339 #else // CONFIG_CONCURRENT_MODE
3340         {
3341                 int i,j;
3342                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3343                         //      Operating Class
3344                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3345
3346                         //      Number of Channels
3347                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3348
3349                         //      Channel List
3350                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3351                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3352                         }
3353                 }
3354         }
3355 #endif // CONFIG_CONCURRENT_MODE
3356
3357         //      Device Info
3358         //      Type:
3359         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
3360
3361         //      Length:
3362         //      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
3363         //      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
3364         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
3365         p2pielen += 2;
3366
3367         //      Value:
3368         //      P2P Device Address
3369         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3370         p2pielen += ETH_ALEN;
3371
3372         //      Config Method
3373         //      This field should be big endian. Noted by P2P specification.
3374
3375         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
3376
3377         p2pielen += 2;
3378
3379         //      Primary Device Type
3380         //      Category ID
3381         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
3382         p2pielen += 2;
3383
3384         //      OUI
3385         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
3386         p2pielen += 4;
3387
3388         //      Sub Category ID
3389         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
3390         p2pielen += 2;
3391
3392         //      Number of Secondary Device Types
3393         p2pie[ p2pielen++ ] = 0x00;     //      No Secondary Device Type List
3394
3395         //      Device Name
3396         //      Type:
3397         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
3398         p2pielen += 2;
3399
3400         //      Length:
3401         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
3402         p2pielen += 2;
3403
3404         //      Value:
3405         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len );
3406         p2pielen += pwdinfo->device_name_len;   
3407         
3408
3409         //      Operating Channel
3410         //      Type:
3411         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
3412
3413         //      Length:
3414         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
3415         p2pielen += 2;
3416
3417         //      Value:
3418         //      Country String
3419         p2pie[ p2pielen++ ] = 'X';
3420         p2pie[ p2pielen++ ] = 'X';
3421         
3422         //      The third byte should be set to 0x04.
3423         //      Described in the "Operating Channel Attribute" section.
3424         p2pie[ p2pielen++ ] = 0x04;
3425
3426         //      Operating Class
3427         if ( pwdinfo->operating_channel <= 14 )
3428         {
3429                 //      Operating Class
3430                 p2pie[ p2pielen++ ] = 0x51;
3431         }
3432         else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
3433         {
3434                 //      Operating Class
3435                 p2pie[ p2pielen++ ] = 0x73;
3436         }
3437         else
3438         {
3439                 //      Operating Class
3440                 p2pie[ p2pielen++ ] = 0x7c;
3441         }
3442
3443         //      Channel Number
3444         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       //      operating channel number
3445
3446         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );                
3447
3448 #ifdef CONFIG_WFD
3449         wfdielen = build_nego_req_wfd_ie(pwdinfo, pframe);
3450         pframe += wfdielen;
3451         pattrib->pktlen += wfdielen;
3452 #endif //CONFIG_WFD
3453
3454         pattrib->last_txcmdsz = pattrib->pktlen;
3455
3456         dump_mgntframe(padapter, pmgntframe);
3457
3458         return;
3459
3460 }
3461
3462
3463 void issue_p2p_GO_response(_adapter *padapter, u8* raddr, u8* frame_body,uint len, u8 result)
3464 {
3465
3466         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3467         u8                      action = P2P_PUB_ACTION_ACTION;
3468         u32                     p2poui = cpu_to_be32(P2POUI);
3469         u8                      oui_subtype = P2P_GO_NEGO_RESP;
3470         u8                      wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
3471         u8                      p2pielen = 0, i;
3472         uint                    wpsielen = 0;
3473         u16                     wps_devicepassword_id = 0x0000;
3474         uint                    wps_devicepassword_id_len = 0;
3475         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh;
3476         u16                     len_channellist_attr = 0;
3477         
3478         struct xmit_frame                       *pmgntframe;
3479         struct pkt_attrib                       *pattrib;
3480         unsigned char                                   *pframe;
3481         struct rtw_ieee80211_hdr        *pwlanhdr;
3482         unsigned short                          *fctrl;
3483         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3484         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3485         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3486         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
3487
3488 #ifdef CONFIG_WFD
3489         u32                                     wfdielen = 0;
3490 #endif //CONFIG_WFD
3491
3492         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
3493         {
3494                 return;
3495         }
3496
3497         DBG_871X( "[%s] In, result = %d\n", __FUNCTION__,  result );
3498         //update attribute
3499         pattrib = &pmgntframe->attrib;
3500         update_mgntframe_attrib(padapter, pattrib);
3501
3502         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3503
3504         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3505         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3506
3507         fctrl = &(pwlanhdr->frame_ctl);
3508         *(fctrl) = 0;
3509
3510         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3511         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3512         _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
3513
3514         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3515         pmlmeext->mgnt_seq++;
3516         SetFrameSubType(pframe, WIFI_ACTION);
3517
3518         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3519         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3520
3521         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3522         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3523         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
3524         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
3525         pwdinfo->negotiation_dialog_token = frame_body[7];      //      The Dialog Token of provisioning discovery request frame.
3526         pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
3527
3528         //      Commented by Albert 20110328
3529         //      Try to get the device password ID from the WPS IE of group negotiation request frame
3530         //      WiFi Direct test plan 5.1.15
3531         rtw_get_wps_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
3532         rtw_get_wps_attr_content( wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
3533         wps_devicepassword_id = be16_to_cpu( wps_devicepassword_id );
3534
3535         _rtw_memset( wpsie, 0x00, 255 );
3536         wpsielen = 0;
3537
3538         //      WPS Section
3539         wpsielen = 0;
3540         //      WPS OUI
3541         *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
3542         wpsielen += 4;
3543
3544         //      WPS version
3545         //      Type:
3546         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
3547         wpsielen += 2;
3548
3549         //      Length:
3550         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
3551         wpsielen += 2;
3552
3553         //      Value:
3554         wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0
3555
3556         //      Device Password ID
3557         //      Type:
3558         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
3559         wpsielen += 2;
3560
3561         //      Length:
3562         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
3563         wpsielen += 2;
3564
3565         //      Value:
3566         if ( wps_devicepassword_id == WPS_DPID_USER_SPEC )
3567         {
3568                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );
3569         }
3570         else if ( wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC )
3571         {
3572                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_USER_SPEC );
3573         }
3574         else
3575         {
3576                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_PBC );
3577         }
3578         wpsielen += 2;
3579
3580         //      Commented by Kurt 20120113
3581         //      If some device wants to do p2p handshake without sending prov_disc_req
3582         //      We have to get peer_req_cm from here.
3583         if(_rtw_memcmp( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3) )
3584         {
3585                 if ( wps_devicepassword_id == WPS_DPID_USER_SPEC )
3586                 {
3587                         _rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3 );
3588                 }
3589                 else if ( wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC )
3590                 {
3591                         _rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3 );     
3592                 }
3593                 else
3594                 {
3595                         _rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3 );     
3596                 }
3597         }
3598
3599         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
3600
3601
3602         //      P2P IE Section.
3603
3604         //      P2P OUI
3605         p2pielen = 0;
3606         p2pie[ p2pielen++ ] = 0x50;
3607         p2pie[ p2pielen++ ] = 0x6F;
3608         p2pie[ p2pielen++ ] = 0x9A;
3609         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
3610
3611         //      Commented by Albert 20100908
3612         //      According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes
3613         //      1. Status
3614         //      2. P2P Capability
3615         //      3. Group Owner Intent
3616         //      4. Configuration Timeout
3617         //      5. Operating Channel
3618         //      6. Intended P2P Interface Address
3619         //      7. Channel List
3620         //      8. Device Info
3621         //      9. Group ID     ( Only GO )
3622
3623
3624         //      ToDo:
3625
3626         //      P2P Status
3627         //      Type:
3628         p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
3629
3630         //      Length:
3631         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
3632         p2pielen += 2;
3633
3634         //      Value:
3635         p2pie[ p2pielen++ ] = result;
3636         
3637         //      P2P Capability
3638         //      Type:
3639         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
3640
3641         //      Length:
3642         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3643         p2pielen += 2;
3644
3645         //      Value:
3646         //      Device Capability Bitmap, 1 byte
3647
3648         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
3649         {
3650                 //      Commented by Albert 2011/03/08
3651                 //      According to the P2P specification
3652                 //      if the sending device will be client, the P2P Capability should be reserved of group negotation response frame
3653                 p2pie[ p2pielen++ ] = 0;
3654         }
3655         else
3656         {
3657                 //      Be group owner or meet the error case
3658                 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
3659         }
3660         
3661         //      Group Capability Bitmap, 1 byte
3662         if ( pwdinfo->persistent_supported )
3663         {
3664                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
3665         }
3666         else
3667         {
3668                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
3669         }
3670
3671         //      Group Owner Intent
3672         //      Type:
3673         p2pie[ p2pielen++ ] = P2P_ATTR_GO_INTENT;
3674
3675         //      Length:
3676         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
3677         p2pielen += 2;
3678
3679         //      Value:
3680         if ( pwdinfo->peer_intent & 0x01 )
3681         {
3682                 //      Peer's tie breaker bit is 1, our tie breaker bit should be 0
3683                 p2pie[ p2pielen++ ] = ( pwdinfo->intent << 1 );
3684         }
3685         else
3686         {
3687                 //      Peer's tie breaker bit is 0, our tie breaker bit should be 1
3688                 p2pie[ p2pielen++ ] = ( ( pwdinfo->intent << 1 ) | BIT(0) );
3689         }
3690
3691
3692         //      Configuration Timeout
3693         //      Type:
3694         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
3695
3696         //      Length:
3697         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3698         p2pielen += 2;
3699
3700         //      Value:
3701         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P GO
3702         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P Client
3703
3704         //      Operating Channel
3705         //      Type:
3706         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
3707
3708         //      Length:
3709         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
3710         p2pielen += 2;
3711
3712         //      Value:
3713         //      Country String
3714         p2pie[ p2pielen++ ] = 'X';
3715         p2pie[ p2pielen++ ] = 'X';
3716         
3717         //      The third byte should be set to 0x04.
3718         //      Described in the "Operating Channel Attribute" section.
3719         p2pie[ p2pielen++ ] = 0x04;
3720
3721         //      Operating Class
3722         if ( pwdinfo->operating_channel <= 14 )
3723         {
3724                 //      Operating Class
3725                 p2pie[ p2pielen++ ] = 0x51;
3726         }
3727         else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
3728         {
3729                 //      Operating Class
3730                 p2pie[ p2pielen++ ] = 0x73;
3731         }
3732         else
3733         {
3734                 //      Operating Class
3735                 p2pie[ p2pielen++ ] = 0x7c;
3736         }
3737         
3738         //      Channel Number
3739         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       //      operating channel number
3740
3741         //      Intended P2P Interface Address  
3742         //      Type:
3743         p2pie[ p2pielen++ ] = P2P_ATTR_INTENTED_IF_ADDR;
3744
3745         //      Length:
3746         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
3747         p2pielen += 2;
3748
3749         //      Value:
3750         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3751         p2pielen += ETH_ALEN;
3752
3753         //      Channel List
3754         //      Type:
3755         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
3756
3757         // Country String(3)
3758         // + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
3759         // + number of channels in all classes
3760         len_channellist_attr = 3
3761            + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
3762            + get_reg_classes_full_count(pmlmeext->channel_list);
3763
3764 #ifdef CONFIG_CONCURRENT_MODE
3765         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3766         {
3767                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
3768         }
3769         else
3770         {
3771                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3772         }
3773 #else
3774
3775         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3776
3777  #endif
3778         p2pielen += 2;
3779
3780         //      Value:
3781         //      Country String
3782         p2pie[ p2pielen++ ] = 'X';
3783         p2pie[ p2pielen++ ] = 'X';
3784         
3785         //      The third byte should be set to 0x04.
3786         //      Described in the "Operating Channel Attribute" section.
3787         p2pie[ p2pielen++ ] = 0x04;
3788
3789         //      Channel Entry List
3790
3791 #ifdef CONFIG_CONCURRENT_MODE
3792         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3793         {
3794                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;    
3795                 struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3796
3797                 //      Operating Class
3798                 if ( pbuddy_mlmeext->cur_channel > 14 )
3799                 {
3800                         if ( pbuddy_mlmeext->cur_channel >= 149 )
3801                         {
3802                                 p2pie[ p2pielen++ ] = 0x7c;
3803                         }
3804                         else
3805                         {
3806                                 p2pie[ p2pielen++ ] = 0x73;
3807                         }
3808                 }
3809                 else
3810                 {
3811                         p2pie[ p2pielen++ ] = 0x51;
3812                 }
3813
3814                 //      Number of Channels
3815                 //      Just support 1 channel and this channel is AP's channel
3816                 p2pie[ p2pielen++ ] = 1;
3817
3818                 //      Channel List
3819                 p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
3820         }
3821         else
3822         {
3823                 int i, j;
3824                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3825                         //      Operating Class
3826                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3827
3828                         //      Number of Channels
3829                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3830
3831                         //      Channel List
3832                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3833                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3834                         }
3835                 }
3836         }
3837 #else // CONFIG_CONCURRENT_MODE
3838         {
3839                 int i, j;
3840                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3841                         //      Operating Class
3842                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3843
3844                         //      Number of Channels
3845                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3846
3847                         //      Channel List
3848                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3849                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3850                         }
3851                 }
3852         }
3853 #endif // CONFIG_CONCURRENT_MODE
3854
3855         
3856         //      Device Info
3857         //      Type:
3858         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
3859
3860         //      Length:
3861         //      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
3862         //      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
3863         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
3864         p2pielen += 2;
3865
3866         //      Value:
3867         //      P2P Device Address
3868         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3869         p2pielen += ETH_ALEN;
3870
3871         //      Config Method
3872         //      This field should be big endian. Noted by P2P specification.
3873
3874         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
3875
3876         p2pielen += 2;
3877
3878         //      Primary Device Type
3879         //      Category ID
3880         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
3881         p2pielen += 2;
3882
3883         //      OUI
3884         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
3885         p2pielen += 4;
3886
3887         //      Sub Category ID
3888         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
3889         p2pielen += 2;
3890
3891         //      Number of Secondary Device Types
3892         p2pie[ p2pielen++ ] = 0x00;     //      No Secondary Device Type List
3893
3894         //      Device Name
3895         //      Type:
3896         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
3897         p2pielen += 2;
3898
3899         //      Length:
3900         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
3901         p2pielen += 2;
3902
3903         //      Value:
3904         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len );
3905         p2pielen += pwdinfo->device_name_len;   
3906         
3907         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
3908         {
3909                 //      Group ID Attribute
3910                 //      Type:
3911                 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
3912
3913                 //      Length:
3914                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + pwdinfo->nego_ssidlen );
3915                 p2pielen += 2;
3916
3917                 //      Value:
3918                 //      p2P Device Address
3919                 _rtw_memcpy( p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN );
3920                 p2pielen += ETH_ALEN;
3921
3922                 //      SSID
3923                 _rtw_memcpy( p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
3924                 p2pielen += pwdinfo->nego_ssidlen;
3925                 
3926         }
3927         
3928         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );        
3929         
3930 #ifdef CONFIG_WFD
3931         wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe);
3932         pframe += wfdielen;
3933         pattrib->pktlen += wfdielen;
3934 #endif //CONFIG_WFD
3935
3936         pattrib->last_txcmdsz = pattrib->pktlen;
3937
3938         dump_mgntframe(padapter, pmgntframe);
3939
3940         return;
3941
3942 }
3943
3944 void issue_p2p_GO_confirm(_adapter *padapter, u8* raddr, u8 result)
3945 {
3946
3947         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3948         u8                      action = P2P_PUB_ACTION_ACTION;
3949         u32                     p2poui = cpu_to_be32(P2POUI);
3950         u8                      oui_subtype = P2P_GO_NEGO_CONF;
3951         u8                      wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
3952         u8                      wpsielen = 0, p2pielen = 0;
3953         
3954         struct xmit_frame                       *pmgntframe;
3955         struct pkt_attrib                       *pattrib;
3956         unsigned char                                   *pframe;
3957         struct rtw_ieee80211_hdr        *pwlanhdr;
3958         unsigned short                          *fctrl;
3959         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3960         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3961         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3962         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
3963 #ifdef CONFIG_WFD
3964         u32                                     wfdielen = 0;
3965 #endif //CONFIG_WFD
3966
3967         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
3968         {
3969                 return;
3970         }
3971
3972         DBG_871X( "[%s] In\n", __FUNCTION__ );
3973         //update attribute
3974         pattrib = &pmgntframe->attrib;
3975         update_mgntframe_attrib(padapter, pattrib);
3976
3977         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3978
3979         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3980         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3981
3982         fctrl = &(pwlanhdr->frame_ctl);
3983         *(fctrl) = 0;
3984
3985         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3986         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3987         _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
3988
3989         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3990         pmlmeext->mgnt_seq++;
3991         SetFrameSubType(pframe, WIFI_ACTION);
3992
3993         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3994         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3995
3996         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3997         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3998         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
3999         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
4000         pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
4001
4002         
4003
4004         //      P2P IE Section.
4005
4006         //      P2P OUI
4007         p2pielen = 0;
4008         p2pie[ p2pielen++ ] = 0x50;
4009         p2pie[ p2pielen++ ] = 0x6F;
4010         p2pie[ p2pielen++ ] = 0x9A;
4011         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
4012
4013         //      Commented by Albert 20110306
4014         //      According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes
4015         //      1. Status
4016         //      2. P2P Capability
4017         //      3. Operating Channel
4018         //      4. Channel List
4019         //      5. Group ID     ( if this WiFi is GO )
4020
4021         //      P2P Status
4022         //      Type:
4023         p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
4024
4025         //      Length:
4026         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
4027         p2pielen += 2;
4028
4029         //      Value:
4030         p2pie[ p2pielen++ ] = result;
4031
4032         //      P2P Capability
4033         //      Type:
4034         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
4035
4036         //      Length:
4037         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
4038         p2pielen += 2;
4039
4040         //      Value:
4041         //      Device Capability Bitmap, 1 byte
4042         p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
4043         
4044         //      Group Capability Bitmap, 1 byte
4045         if ( pwdinfo->persistent_supported )
4046         {
4047                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
4048         }
4049         else
4050         {
4051                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
4052         }
4053
4054
4055         //      Operating Channel
4056         //      Type:
4057         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
4058
4059         //      Length:
4060         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
4061         p2pielen += 2;
4062
4063         //      Value:
4064         //      Country String
4065         p2pie[ p2pielen++ ] = 'X';
4066         p2pie[ p2pielen++ ] = 'X';
4067         
4068         //      The third byte should be set to 0x04.
4069         //      Described in the "Operating Channel Attribute" section.
4070         p2pie[ p2pielen++ ] = 0x04;
4071
4072
4073         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
4074         {
4075                 if ( pwdinfo->peer_operating_ch <= 14 )
4076                 {
4077                         //      Operating Class
4078                         p2pie[ p2pielen++ ] = 0x51;
4079                 }
4080                 else if ( ( pwdinfo->peer_operating_ch >= 36 ) && ( pwdinfo->peer_operating_ch <= 48 ) )
4081                 {
4082                         //      Operating Class
4083                         p2pie[ p2pielen++ ] = 0x73;
4084                 }
4085                 else
4086                 {
4087                         //      Operating Class
4088                         p2pie[ p2pielen++ ] = 0x7c;
4089                 }
4090                 
4091                 p2pie[ p2pielen++ ] = pwdinfo->peer_operating_ch;
4092         }
4093         else
4094         {
4095                 if ( pwdinfo->operating_channel <= 14 )
4096                 {
4097                         //      Operating Class
4098                         p2pie[ p2pielen++ ] = 0x51;
4099                 }
4100                 else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
4101                 {
4102                         //      Operating Class
4103                         p2pie[ p2pielen++ ] = 0x73;
4104                 }
4105                 else
4106                 {
4107                         //      Operating Class
4108                         p2pie[ p2pielen++ ] = 0x7c;
4109                 }
4110                 
4111                 //      Channel Number
4112                 p2pie[ p2pielen++ ] = pwdinfo->operating_channel;               //      Use the listen channel as the operating channel
4113         }
4114
4115
4116         //      Channel List
4117         //      Type:
4118         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
4119
4120         *(u16*) ( p2pie + p2pielen ) = 6;
4121         p2pielen += 2;
4122
4123         //      Country String
4124         p2pie[ p2pielen++ ] = 'X';
4125         p2pie[ p2pielen++ ] = 'X';
4126         
4127         //      The third byte should be set to 0x04.
4128         //      Described in the "Operating Channel Attribute" section.
4129         p2pie[ p2pielen++ ] = 0x04;
4130
4131         //      Value:
4132         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
4133         {
4134                 if ( pwdinfo->peer_operating_ch <= 14 )
4135                 {
4136                         //      Operating Class
4137                         p2pie[ p2pielen++ ] = 0x51;
4138                 }
4139                 else if ( ( pwdinfo->peer_operating_ch >= 36 ) && ( pwdinfo->peer_operating_ch <= 48 ) )
4140                 {
4141                         //      Operating Class
4142                         p2pie[ p2pielen++ ] = 0x73;
4143                 }
4144                 else
4145                 {
4146                         //      Operating Class
4147                         p2pie[ p2pielen++ ] = 0x7c;
4148                 }
4149                 p2pie[ p2pielen++ ] = 1;
4150                 p2pie[ p2pielen++ ] = pwdinfo->peer_operating_ch;
4151         }
4152         else
4153         {
4154                 if ( pwdinfo->operating_channel <= 14 )
4155                 {
4156                         //      Operating Class
4157                         p2pie[ p2pielen++ ] = 0x51;
4158                 }
4159                 else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
4160                 {
4161                         //      Operating Class
4162                         p2pie[ p2pielen++ ] = 0x73;
4163                 }
4164                 else
4165                 {
4166                         //      Operating Class
4167                         p2pie[ p2pielen++ ] = 0x7c;
4168                 }
4169                 
4170                 //      Channel Number
4171                 p2pie[ p2pielen++ ] = 1;
4172                 p2pie[ p2pielen++ ] = pwdinfo->operating_channel;               //      Use the listen channel as the operating channel
4173         }
4174
4175         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
4176         {
4177                 //      Group ID Attribute
4178                 //      Type:
4179                 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
4180
4181                 //      Length:
4182                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + pwdinfo->nego_ssidlen );
4183                 p2pielen += 2;
4184
4185                 //      Value:
4186                 //      p2P Device Address
4187                 _rtw_memcpy( p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN );
4188                 p2pielen += ETH_ALEN;
4189
4190                 //      SSID
4191                 _rtw_memcpy( p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
4192                 p2pielen += pwdinfo->nego_ssidlen;
4193         }
4194         
4195         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
4196         
4197 #ifdef CONFIG_WFD
4198         wfdielen = build_nego_confirm_wfd_ie(pwdinfo, pframe);
4199         pframe += wfdielen;
4200         pattrib->pktlen += wfdielen;
4201 #endif //CONFIG_WFD
4202
4203         pattrib->last_txcmdsz = pattrib->pktlen;
4204
4205         dump_mgntframe(padapter, pmgntframe);
4206
4207         return;
4208
4209 }
4210
4211 void issue_p2p_invitation_request(_adapter *padapter, u8* raddr )
4212 {
4213
4214         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
4215         u8                      action = P2P_PUB_ACTION_ACTION;
4216         u32                     p2poui = cpu_to_be32(P2POUI);
4217         u8                      oui_subtype = P2P_INVIT_REQ;
4218         u8                      p2pie[ 255 ] = { 0x00 };
4219         u8                      p2pielen = 0, i;
4220         u8                      dialogToken = 3;
4221         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
4222         u16                     len_channellist_attr = 0;       
4223 #ifdef CONFIG_WFD
4224         u32                                     wfdielen = 0;
4225 #endif //CONFIG_WFD
4226 #ifdef CONFIG_CONCURRENT_MODE
4227         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
4228         struct wifidirect_info  *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
4229         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
4230         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4231 #endif
4232
4233         struct xmit_frame                       *pmgntframe;
4234         struct pkt_attrib                       *pattrib;
4235         unsigned char                                   *pframe;
4236         struct rtw_ieee80211_hdr        *pwlanhdr;
4237         unsigned short                          *fctrl;
4238         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
4239         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4240         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4241         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
4242
4243
4244         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
4245         {
4246                 return;
4247         }
4248
4249         //update attribute
4250         pattrib = &pmgntframe->attrib;
4251         update_mgntframe_attrib(padapter, pattrib);
4252
4253         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4254
4255         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4256         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4257
4258         fctrl = &(pwlanhdr->frame_ctl);
4259         *(fctrl) = 0;
4260
4261         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
4262         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4263         _rtw_memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
4264
4265         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4266         pmlmeext->mgnt_seq++;
4267         SetFrameSubType(pframe, WIFI_ACTION);
4268
4269         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4270         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4271
4272         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4273         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4274         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
4275         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
4276         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
4277
4278         //      P2P IE Section.
4279
4280         //      P2P OUI
4281         p2pielen = 0;
4282         p2pie[ p2pielen++ ] = 0x50;
4283         p2pie[ p2pielen++ ] = 0x6F;
4284         p2pie[ p2pielen++ ] = 0x9A;
4285         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
4286
4287         //      Commented by Albert 20101011
4288         //      According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes
4289         //      1. Configuration Timeout
4290         //      2. Invitation Flags
4291         //      3. Operating Channel    ( Only GO )
4292         //      4. P2P Group BSSID      ( Should be included if I am the GO )
4293         //      5. Channel List
4294         //      6. P2P Group ID
4295         //      7. P2P Device Info
4296
4297         //      Configuration Timeout
4298         //      Type:
4299         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
4300
4301         //      Length:
4302         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
4303         p2pielen += 2;
4304
4305         //      Value:
4306         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P GO
4307         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P Client
4308
4309         //      Invitation Flags
4310         //      Type:
4311         p2pie[ p2pielen++ ] = P2P_ATTR_INVITATION_FLAGS;
4312
4313         //      Length:
4314         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
4315         p2pielen += 2;
4316
4317         //      Value:
4318         p2pie[ p2pielen++ ] = P2P_INVITATION_FLAGS_PERSISTENT;
4319
4320
4321         //      Operating Channel
4322         //      Type:
4323         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
4324
4325         //      Length:
4326         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
4327         p2pielen += 2;
4328
4329         //      Value:
4330         //      Country String
4331         p2pie[ p2pielen++ ] = 'X';
4332         p2pie[ p2pielen++ ] = 'X';
4333         
4334         //      The third byte should be set to 0x04.
4335         //      Described in the "Operating Channel Attribute" section.
4336         p2pie[ p2pielen++ ] = 0x04;
4337
4338         //      Operating Class
4339         if ( pwdinfo->invitereq_info.operating_ch <= 14 )
4340                 p2pie[ p2pielen++ ] = 0x51;
4341         else if ( ( pwdinfo->invitereq_info.operating_ch >= 36 ) && ( pwdinfo->invitereq_info.operating_ch <= 48 ) )
4342                 p2pie[ p2pielen++ ] = 0x73;
4343         else
4344                 p2pie[ p2pielen++ ] = 0x7c;
4345         
4346         //      Channel Number
4347         p2pie[ p2pielen++ ] = pwdinfo->invitereq_info.operating_ch;     //      operating channel number
4348
4349         if ( _rtw_memcmp( myid( &padapter->eeprompriv ), pwdinfo->invitereq_info.go_bssid, ETH_ALEN ) )
4350         {
4351                 //      P2P Group BSSID
4352                 //      Type:
4353                 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_BSSID;
4354
4355                 //      Length:
4356                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
4357                 p2pielen += 2;
4358
4359                 //      Value:
4360                 //      P2P Device Address for GO
4361                 _rtw_memcpy( p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN );
4362                 p2pielen += ETH_ALEN;
4363         }
4364
4365         //      Channel List
4366         //      Type:
4367         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
4368
4369         
4370         //      Length:
4371         // Country String(3)
4372         // + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
4373         // + number of channels in all classes
4374         len_channellist_attr = 3
4375            + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
4376            + get_reg_classes_full_count(pmlmeext->channel_list);
4377
4378 #ifdef CONFIG_CONCURRENT_MODE
4379         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4380         {
4381                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
4382         }
4383         else
4384         {
4385                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
4386         }
4387 #else
4388
4389         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
4390
4391  #endif
4392         p2pielen += 2;
4393
4394         //      Value:
4395         //      Country String
4396         p2pie[ p2pielen++ ] = 'X';
4397         p2pie[ p2pielen++ ] = 'X';
4398         
4399         //      The third byte should be set to 0x04.
4400         //      Described in the "Operating Channel Attribute" section.
4401         p2pie[ p2pielen++ ] = 0x04;
4402
4403         //      Channel Entry List
4404 #ifdef CONFIG_CONCURRENT_MODE
4405         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4406         {
4407                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;    
4408                 struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4409
4410                 //      Operating Class
4411                 if ( pbuddy_mlmeext->cur_channel > 14 )
4412                 {
4413                         if ( pbuddy_mlmeext->cur_channel >= 149 )
4414                         {
4415                                 p2pie[ p2pielen++ ] = 0x7c;
4416                         }
4417                         else
4418                         {
4419                                 p2pie[ p2pielen++ ] = 0x73;
4420                         }
4421                 }
4422                 else
4423                 {
4424                         p2pie[ p2pielen++ ] = 0x51;
4425                 }
4426
4427                 //      Number of Channels
4428                 //      Just support 1 channel and this channel is AP's channel
4429                 p2pie[ p2pielen++ ] = 1;
4430
4431                 //      Channel List
4432                 p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
4433         }
4434         else
4435         {
4436                 int i, j;
4437                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
4438                         //      Operating Class
4439                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
4440
4441                         //      Number of Channels
4442                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
4443
4444                         //      Channel List
4445                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
4446                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
4447                         }
4448                 }
4449         }
4450 #else // CONFIG_CONCURRENT_MODE
4451         {
4452                 int i, j;
4453                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
4454                         //      Operating Class
4455                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
4456
4457                         //      Number of Channels
4458                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
4459
4460                         //      Channel List
4461                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
4462                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
4463                         }
4464                 }
4465         }
4466 #endif // CONFIG_CONCURRENT_MODE
4467
4468
4469         //      P2P Group ID
4470         //      Type:
4471         p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
4472
4473         //      Length:
4474         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 6 + pwdinfo->invitereq_info.ssidlen );
4475         p2pielen += 2;
4476
4477         //      Value:
4478         //      P2P Device Address for GO
4479         _rtw_memcpy( p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN );
4480         p2pielen += ETH_ALEN;
4481
4482         //      SSID
4483         _rtw_memcpy( p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen );
4484         p2pielen += pwdinfo->invitereq_info.ssidlen;
4485         
4486
4487         //      Device Info
4488         //      Type:
4489         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
4490
4491         //      Length:
4492         //      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
4493         //      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
4494         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
4495         p2pielen += 2;
4496         
4497         //      Value:
4498         //      P2P Device Address
4499         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
4500         p2pielen += ETH_ALEN;
4501
4502         //      Config Method
4503         //      This field should be big endian. Noted by P2P specification.
4504         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY );
4505         p2pielen += 2;
4506
4507         //      Primary Device Type
4508         //      Category ID
4509         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
4510         p2pielen += 2;
4511
4512         //      OUI
4513         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
4514         p2pielen += 4;
4515
4516         //      Sub Category ID
4517         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
4518         p2pielen += 2;
4519
4520         //      Number of Secondary Device Types
4521         p2pie[ p2pielen++ ] = 0x00;     //      No Secondary Device Type List
4522
4523         //      Device Name
4524         //      Type:
4525         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
4526         p2pielen += 2;
4527
4528         //      Length:
4529         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
4530         p2pielen += 2;
4531
4532         //      Value:
4533         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
4534         p2pielen += pwdinfo->device_name_len;
4535                 
4536         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );        
4537
4538 #ifdef CONFIG_WFD
4539         wfdielen = build_invitation_req_wfd_ie(pwdinfo, pframe);
4540         pframe += wfdielen;
4541         pattrib->pktlen += wfdielen;
4542 #endif //CONFIG_WFD     
4543
4544         pattrib->last_txcmdsz = pattrib->pktlen;
4545
4546         dump_mgntframe(padapter, pmgntframe);
4547
4548         return;
4549
4550 }
4551
4552 void issue_p2p_invitation_response(_adapter *padapter, u8* raddr, u8 dialogToken, u8 status_code)
4553 {
4554
4555         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
4556         u8                      action = P2P_PUB_ACTION_ACTION;
4557         u32                     p2poui = cpu_to_be32(P2POUI);
4558         u8                      oui_subtype = P2P_INVIT_RESP;
4559         u8                      p2pie[ 255 ] = { 0x00 };
4560         u8                      p2pielen = 0, i;
4561         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
4562         u16                     len_channellist_attr = 0;
4563 #ifdef CONFIG_CONCURRENT_MODE
4564         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
4565         struct wifidirect_info  *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
4566         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
4567         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4568 #endif  
4569 #ifdef CONFIG_WFD
4570         u32                                     wfdielen = 0;
4571 #endif //CONFIG_WFD
4572         
4573         struct xmit_frame                       *pmgntframe;
4574         struct pkt_attrib                       *pattrib;
4575         unsigned char                                   *pframe;
4576         struct rtw_ieee80211_hdr        *pwlanhdr;
4577         unsigned short                          *fctrl;
4578         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
4579         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4580         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4581         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
4582
4583
4584         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
4585         {
4586                 return;
4587         }
4588
4589         //update attribute
4590         pattrib = &pmgntframe->attrib;
4591         update_mgntframe_attrib(padapter, pattrib);
4592
4593         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4594
4595         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4596         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4597
4598         fctrl = &(pwlanhdr->frame_ctl);
4599         *(fctrl) = 0;
4600
4601         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
4602         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4603         _rtw_memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
4604
4605         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4606         pmlmeext->mgnt_seq++;
4607         SetFrameSubType(pframe, WIFI_ACTION);
4608
4609         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4610         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4611
4612         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4613         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4614         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
4615         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
4616         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
4617
4618         //      P2P IE Section.
4619
4620         //      P2P OUI
4621         p2pielen = 0;
4622         p2pie[ p2pielen++ ] = 0x50;
4623         p2pie[ p2pielen++ ] = 0x6F;
4624         p2pie[ p2pielen++ ] = 0x9A;
4625         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
4626
4627         //      Commented by Albert 20101005
4628         //      According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes
4629         //      1. Status
4630         //      2. Configuration Timeout
4631         //      3. Operating Channel    ( Only GO )
4632         //      4. P2P Group BSSID      ( Only GO )
4633         //      5. Channel List
4634
4635         //      P2P Status
4636         //      Type:
4637         p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
4638
4639         //      Length:
4640         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
4641         p2pielen += 2;
4642
4643         //      Value:
4644         //      When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE.
4645         //      Sent the event receiving the P2P Invitation Req frame to DMP UI.
4646         //      DMP had to compare the MAC address to find out the profile.
4647         //      So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB.
4648         //      If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req
4649         //      to NB to rebuild the persistent group.
4650         p2pie[ p2pielen++ ] = status_code;
4651         
4652         //      Configuration Timeout
4653         //      Type:
4654         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
4655
4656         //      Length:
4657         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
4658         p2pielen += 2;
4659
4660         //      Value:
4661         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P GO
4662         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P Client
4663
4664         if( status_code == P2P_STATUS_SUCCESS )
4665         {
4666                 if( rtw_p2p_chk_role( pwdinfo, P2P_ROLE_GO ) )
4667                 {
4668                         //      The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO
4669                         //      In this case, the P2P Invitation response frame should carry the two more P2P attributes.
4670                         //      First one is operating channel attribute.
4671                         //      Second one is P2P Group BSSID attribute.
4672
4673                         //      Operating Channel
4674                         //      Type:
4675                         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
4676
4677                         //      Length:
4678                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
4679                         p2pielen += 2;
4680
4681                         //      Value:
4682                         //      Country String
4683                         p2pie[ p2pielen++ ] = 'X';
4684                         p2pie[ p2pielen++ ] = 'X';
4685                 
4686                         //      The third byte should be set to 0x04.
4687                         //      Described in the "Operating Channel Attribute" section.
4688                         p2pie[ p2pielen++ ] = 0x04;
4689
4690                         //      Operating Class
4691                         p2pie[ p2pielen++ ] = 0x51;     //      Copy from SD7
4692                 
4693                         //      Channel Number
4694                         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       //      operating channel number
4695                         
4696
4697                         //      P2P Group BSSID
4698                         //      Type:
4699                         p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_BSSID;
4700
4701                         //      Length:
4702                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
4703                         p2pielen += 2;
4704
4705                         //      Value:
4706                         //      P2P Device Address for GO
4707                         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
4708                         p2pielen += ETH_ALEN;
4709
4710                 }
4711
4712                 //      Channel List
4713                 //      Type:
4714                 p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
4715
4716                 //      Length:
4717                 // Country String(3)
4718                 // + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
4719                 // + number of channels in all classes
4720                 len_channellist_attr = 3
4721                         + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
4722                         + get_reg_classes_full_count(pmlmeext->channel_list);
4723
4724 #ifdef CONFIG_CONCURRENT_MODE
4725                 if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4726                 {
4727                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
4728                 }
4729                 else
4730                 {
4731                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
4732                 }
4733 #else
4734
4735                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
4736
4737 #endif
4738                 p2pielen += 2;
4739
4740                 //      Value:
4741                 //      Country String
4742                 p2pie[ p2pielen++ ] = 'X';
4743                 p2pie[ p2pielen++ ] = 'X';
4744
4745                 //      The third byte should be set to 0x04.
4746                 //      Described in the "Operating Channel Attribute" section.
4747                 p2pie[ p2pielen++ ] = 0x04;
4748
4749                 //      Channel Entry List
4750 #ifdef CONFIG_CONCURRENT_MODE
4751                 if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4752                 {
4753                         _adapter *pbuddy_adapter = padapter->pbuddy_adapter;    
4754                         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4755
4756                         //      Operating Class
4757                         if ( pbuddy_mlmeext->cur_channel > 14 )
4758                         {
4759                                 if ( pbuddy_mlmeext->cur_channel >= 149 )
4760                                 {
4761                                         p2pie[ p2pielen++ ] = 0x7c;
4762                                 }
4763                                 else
4764                                 {
4765                                         p2pie[ p2pielen++ ] = 0x73;
4766                                 }
4767                         }
4768                         else
4769                         {
4770                                 p2pie[ p2pielen++ ] = 0x51;
4771                         }
4772
4773                         //      Number of Channels
4774                         //      Just support 1 channel and this channel is AP's channel
4775                         p2pie[ p2pielen++ ] = 1;
4776
4777                         //      Channel List
4778                         p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
4779                 }
4780                 else
4781                 {
4782                         int i, j;
4783                         for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
4784                                 //      Operating Class
4785                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
4786
4787                                 //      Number of Channels
4788                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
4789
4790                                 //      Channel List
4791                                 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
4792                                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
4793                                 }
4794                         }
4795                 }
4796 #else // CONFIG_CONCURRENT_MODE
4797                 {
4798                         int i, j;
4799                         for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
4800                                 //      Operating Class
4801                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
4802
4803                                 //      Number of Channels
4804                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
4805
4806                                 //      Channel List
4807                                 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
4808                                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
4809                                 }
4810                         }
4811                 }
4812 #endif // CONFIG_CONCURRENT_MODE
4813         }
4814                 
4815         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );        
4816         
4817 #ifdef CONFIG_WFD
4818         wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe);
4819         pframe += wfdielen;
4820         pattrib->pktlen += wfdielen;
4821 #endif //CONFIG_WFD
4822
4823         pattrib->last_txcmdsz = pattrib->pktlen;
4824
4825         dump_mgntframe(padapter, pmgntframe);
4826
4827         return;
4828
4829 }
4830
4831 void issue_p2p_provision_request(_adapter *padapter, u8* pssid, u8 ussidlen, u8* pdev_raddr )
4832 {
4833         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
4834         u8                      action = P2P_PUB_ACTION_ACTION;
4835         u8                      dialogToken = 1;
4836         u32                     p2poui = cpu_to_be32(P2POUI);
4837         u8                      oui_subtype = P2P_PROVISION_DISC_REQ;
4838         u8                      wpsie[ 100 ] = { 0x00 };
4839         u8                      wpsielen = 0;
4840         u32                     p2pielen = 0;
4841 #ifdef CONFIG_WFD
4842         u32                                     wfdielen = 0;
4843 #endif //CONFIG_WFD             
4844         
4845         struct xmit_frame                       *pmgntframe;
4846         struct pkt_attrib                       *pattrib;
4847         unsigned char                                   *pframe;
4848         struct rtw_ieee80211_hdr        *pwlanhdr;
4849         unsigned short                          *fctrl;
4850         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
4851         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4852         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4853         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4854
4855
4856         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
4857         {
4858                 return;
4859         }
4860
4861         DBG_871X( "[%s] In\n", __FUNCTION__ );
4862         //update attribute
4863         pattrib = &pmgntframe->attrib;
4864         update_mgntframe_attrib(padapter, pattrib);
4865
4866         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4867
4868         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4869         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4870
4871         fctrl = &(pwlanhdr->frame_ctl);
4872         *(fctrl) = 0;
4873
4874         _rtw_memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
4875         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4876         _rtw_memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
4877
4878         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4879         pmlmeext->mgnt_seq++;
4880         SetFrameSubType(pframe, WIFI_ACTION);
4881
4882         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4883         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4884
4885         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4886         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4887         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
4888         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
4889         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));               
4890
4891         p2pielen = build_prov_disc_request_p2p_ie( pwdinfo, pframe, pssid, ussidlen, pdev_raddr );
4892
4893         pframe += p2pielen;
4894         pattrib->pktlen += p2pielen;
4895
4896         wpsielen = 0;
4897         //      WPS OUI
4898         *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
4899         wpsielen += 4;
4900
4901         //      WPS version
4902         //      Type:
4903         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
4904         wpsielen += 2;
4905
4906         //      Length:
4907         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
4908         wpsielen += 2;
4909
4910         //      Value:
4911         wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0
4912
4913         //      Config Method
4914         //      Type:
4915         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
4916         wpsielen += 2;
4917
4918         //      Length:
4919         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
4920         wpsielen += 2;
4921
4922         //      Value:
4923         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->tx_prov_disc_info.wps_config_method_request );
4924         wpsielen += 2;
4925
4926         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
4927
4928
4929 #ifdef CONFIG_WFD
4930         wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
4931         pframe += wfdielen;
4932         pattrib->pktlen += wfdielen;
4933 #endif //CONFIG_WFD
4934
4935         pattrib->last_txcmdsz = pattrib->pktlen;
4936
4937         dump_mgntframe(padapter, pmgntframe);
4938
4939         return;
4940
4941 }
4942
4943
4944 u8 is_matched_in_profilelist( u8* peermacaddr, struct profile_info* profileinfo )
4945 {
4946         u8 i, match_result = 0;
4947
4948         DBG_871X( "[%s] peermac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
4949                     peermacaddr[0], peermacaddr[1],peermacaddr[2],peermacaddr[3],peermacaddr[4],peermacaddr[5]);
4950         
4951         for( i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++ )
4952         {
4953                DBG_871X( "[%s] profileinfo_mac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
4954                             profileinfo->peermac[0], profileinfo->peermac[1],profileinfo->peermac[2],profileinfo->peermac[3],profileinfo->peermac[4],profileinfo->peermac[5]);             
4955                 if ( _rtw_memcmp( peermacaddr, profileinfo->peermac, ETH_ALEN ) )
4956                 {
4957                         match_result = 1;
4958                         DBG_871X( "[%s] Match!\n", __FUNCTION__ );
4959                         break;
4960                 }
4961         }
4962         
4963         return (match_result );
4964 }
4965
4966 void issue_probersp_p2p(_adapter *padapter, unsigned char *da)
4967 {
4968         struct xmit_frame                       *pmgntframe;
4969         struct pkt_attrib                       *pattrib;
4970         unsigned char                                   *pframe;
4971         struct rtw_ieee80211_hdr        *pwlanhdr;
4972         unsigned short                          *fctrl; 
4973         unsigned char                                   *mac;
4974         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
4975         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4976         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4977         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4978         //WLAN_BSSID_EX                 *cur_network = &(pmlmeinfo->network);
4979         u16                                     beacon_interval = 100;
4980         u16                                     capInfo = 0;
4981         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4982         u8                                      wpsie[255] = { 0x00 };
4983         u32                                     wpsielen = 0, p2pielen = 0;
4984 #ifdef CONFIG_WFD
4985         u32                                     wfdielen = 0;
4986 #endif //CONFIG_WFD
4987 #ifdef CONFIG_INTEL_WIDI
4988         u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 };
4989 #endif //CONFIG_INTEL_WIDI
4990
4991         //DBG_871X("%s\n", __FUNCTION__);
4992         
4993         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
4994         {
4995                 return;
4996         }
4997         
4998         //update attribute
4999         pattrib = &pmgntframe->attrib;
5000         update_mgntframe_attrib(padapter, pattrib);     
5001         
5002         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5003                 
5004         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5005         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;  
5006         
5007         mac = myid(&(padapter->eeprompriv));
5008         
5009         fctrl = &(pwlanhdr->frame_ctl);
5010         *(fctrl) = 0;
5011         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5012         _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
5013         
5014         //      Use the device address for BSSID field. 
5015         _rtw_memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
5016
5017         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5018         pmlmeext->mgnt_seq++;
5019         SetFrameSubType(fctrl, WIFI_PROBERSP);
5020         
5021         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5022         pattrib->pktlen = pattrib->hdrlen;
5023         pframe += pattrib->hdrlen;
5024
5025         //timestamp will be inserted by hardware
5026         pframe += 8;
5027         pattrib->pktlen += 8;
5028
5029         // beacon interval: 2 bytes
5030         _rtw_memcpy(pframe, (unsigned char *) &beacon_interval, 2); 
5031         pframe += 2;
5032         pattrib->pktlen += 2;
5033
5034         //      capability info: 2 bytes
5035         //      ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec)
5036         capInfo |= cap_ShortPremble;
5037         capInfo |= cap_ShortSlot;
5038         
5039         _rtw_memcpy(pframe, (unsigned char *) &capInfo, 2);
5040         pframe += 2;
5041         pattrib->pktlen += 2;
5042
5043
5044         // SSID
5045         pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
5046
5047         // supported rates...
5048         //      Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 )
5049         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
5050
5051         // DS parameter set
5052         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
5053
5054 #ifdef CONFIG_IOCTL_CFG80211
5055         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
5056         {
5057                 if( pmlmepriv->wps_probe_resp_ie != NULL && pmlmepriv->p2p_probe_resp_ie != NULL )
5058                 {
5059                         //WPS IE
5060                         _rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
5061                         pattrib->pktlen += pmlmepriv->wps_probe_resp_ie_len;
5062                         pframe += pmlmepriv->wps_probe_resp_ie_len;
5063
5064                         //P2P IE
5065                         _rtw_memcpy(pframe, pmlmepriv->p2p_probe_resp_ie, pmlmepriv->p2p_probe_resp_ie_len);
5066                         pattrib->pktlen += pmlmepriv->p2p_probe_resp_ie_len;
5067                         pframe += pmlmepriv->p2p_probe_resp_ie_len;
5068                 }
5069         }
5070         else
5071 #endif //CONFIG_IOCTL_CFG80211          
5072         {
5073
5074                 //      Todo: WPS IE
5075                 //      Noted by Albert 20100907
5076                 //      According to the WPS specification, all the WPS attribute is presented by Big Endian.
5077
5078                 wpsielen = 0;
5079                 //      WPS OUI
5080                 *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
5081                 wpsielen += 4;
5082
5083                 //      WPS version
5084                 //      Type:
5085                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
5086                 wpsielen += 2;
5087
5088                 //      Length:
5089                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
5090                 wpsielen += 2;
5091
5092                 //      Value:
5093                 wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0
5094
5095 #ifdef CONFIG_INTEL_WIDI
5096                 //      Commented by Kurt
5097                 //      Appended WiDi info. only if we did issued_probereq_widi(), and then we saved ven. ext. in pmlmepriv->sa_ext.
5098                 if(  _rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE 
5099                         || pmlmepriv->num_p2p_sdt != 0 )
5100                 {
5101                         //Sec dev type
5102                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SEC_DEV_TYPE_LIST );
5103                         wpsielen += 2;
5104
5105                         //      Length:
5106                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
5107                         wpsielen += 2;
5108
5109                         //      Value:
5110                         //      Category ID
5111                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_DISPLAYS );
5112                         wpsielen += 2;
5113
5114                         //      OUI
5115                         *(u32*) ( wpsie + wpsielen ) = cpu_to_be32( INTEL_DEV_TYPE_OUI );
5116                         wpsielen += 4;
5117
5118                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_WIDI_CONSUMER_SINK );
5119                         wpsielen += 2;
5120
5121                         if(  _rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE )
5122                         {
5123                                 //      Vendor Extension
5124                                 _rtw_memcpy( wpsie + wpsielen, pmlmepriv->sa_ext, L2SDTA_SERVICE_VE_LEN );
5125                                 wpsielen += L2SDTA_SERVICE_VE_LEN;
5126                         }
5127                 }
5128 #endif //CONFIG_INTEL_WIDI
5129
5130                 //      WiFi Simple Config State
5131                 //      Type:
5132                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SIMPLE_CONF_STATE );
5133                 wpsielen += 2;
5134
5135                 //      Length:
5136                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
5137                 wpsielen += 2;
5138
5139                 //      Value:
5140                 wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;   //      Not Configured.
5141
5142                 //      Response Type
5143                 //      Type:
5144                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_RESP_TYPE );
5145                 wpsielen += 2;
5146
5147                 //      Length:
5148                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
5149                 wpsielen += 2;
5150
5151                 //      Value:
5152                 wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
5153
5154                 //      UUID-E
5155                 //      Type:
5156                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_UUID_E );
5157                 wpsielen += 2;
5158
5159                 //      Length:
5160                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0010 );
5161                 wpsielen += 2;
5162
5163                 //      Value:
5164                 if (pwdinfo->external_uuid == 0) {
5165                         _rtw_memset( wpsie + wpsielen, 0x0, 16 );
5166                         _rtw_memcpy( wpsie + wpsielen, myid( &padapter->eeprompriv ), ETH_ALEN );
5167                 } else {
5168                         _rtw_memcpy( wpsie + wpsielen, pwdinfo->uuid, 0x10 );
5169                 }
5170                 wpsielen += 0x10;
5171
5172                 //      Manufacturer
5173                 //      Type:
5174                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MANUFACTURER );
5175                 wpsielen += 2;
5176
5177                 //      Length:
5178                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0007 );
5179                 wpsielen += 2;
5180
5181                 //      Value:
5182                 _rtw_memcpy( wpsie + wpsielen, "Realtek", 7 );
5183                 wpsielen += 7;
5184
5185                 //      Model Name
5186                 //      Type:
5187                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MODEL_NAME );
5188                 wpsielen += 2;
5189
5190                 //      Length:
5191                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0006 );
5192                 wpsielen += 2;  
5193
5194                 //      Value:
5195                 _rtw_memcpy( wpsie + wpsielen, "8192CU", 6 );
5196                 wpsielen += 6;
5197
5198                 //      Model Number
5199                 //      Type:
5200                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MODEL_NUMBER );
5201                 wpsielen += 2;
5202
5203                 //      Length:
5204                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
5205                 wpsielen += 2;
5206
5207                 //      Value:
5208                 wpsie[ wpsielen++ ] = 0x31;             //      character 1
5209
5210                 //      Serial Number
5211                 //      Type:
5212                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SERIAL_NUMBER );
5213                 wpsielen += 2;
5214
5215                 //      Length:
5216                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( ETH_ALEN );
5217                 wpsielen += 2;
5218
5219                 //      Value:
5220                 _rtw_memcpy( wpsie + wpsielen, "123456" , ETH_ALEN );
5221                 wpsielen += ETH_ALEN;
5222
5223                 //      Primary Device Type
5224                 //      Type:
5225                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
5226                 wpsielen += 2;
5227
5228                 //      Length:
5229                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
5230                 wpsielen += 2;
5231
5232                 //      Value:
5233                 //      Category ID
5234                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
5235                 wpsielen += 2;
5236
5237                 //      OUI
5238                 *(u32*) ( wpsie + wpsielen ) = cpu_to_be32( WPSOUI );
5239                 wpsielen += 4;
5240
5241                 //      Sub Category ID
5242                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
5243                 wpsielen += 2;
5244
5245                 //      Device Name
5246                 //      Type:
5247                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
5248                 wpsielen += 2;
5249
5250                 //      Length:
5251                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->device_name_len );
5252                 wpsielen += 2;
5253
5254                 //      Value:
5255                 _rtw_memcpy( wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len );
5256                 wpsielen += pwdinfo->device_name_len;
5257
5258                 //      Config Method
5259                 //      Type:
5260                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
5261                 wpsielen += 2;
5262
5263                 //      Length:
5264                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
5265                 wpsielen += 2;
5266
5267                 //      Value:
5268                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
5269                 wpsielen += 2;
5270                 
5271
5272                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
5273                 
5274
5275                 p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
5276                 pframe += p2pielen;
5277                 pattrib->pktlen += p2pielen;
5278         }
5279
5280 #ifdef CONFIG_WFD
5281 #ifdef CONFIG_IOCTL_CFG80211
5282         if ( _TRUE == pwdinfo->wfd_info->wfd_enable )
5283 #endif //CONFIG_IOCTL_CFG80211
5284         {
5285                 wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
5286                 pframe += wfdielen;
5287                 pattrib->pktlen += wfdielen;
5288         }
5289 #ifdef CONFIG_IOCTL_CFG80211
5290         else if (pmlmepriv->wfd_probe_resp_ie != NULL && pmlmepriv->wfd_probe_resp_ie_len>0)
5291         {
5292                 //WFD IE
5293                 _rtw_memcpy(pframe, pmlmepriv->wfd_probe_resp_ie, pmlmepriv->wfd_probe_resp_ie_len);
5294                 pattrib->pktlen += pmlmepriv->wfd_probe_resp_ie_len;
5295                 pframe += pmlmepriv->wfd_probe_resp_ie_len;             
5296         }
5297 #endif //CONFIG_IOCTL_CFG80211
5298 #endif //CONFIG_WFD     
5299
5300         pattrib->last_txcmdsz = pattrib->pktlen;
5301         
5302
5303         dump_mgntframe(padapter, pmgntframe);
5304         
5305         return;
5306
5307 }
5308
5309 int _issue_probereq_p2p(_adapter *padapter, u8 *da, int wait_ack)
5310 {
5311         int ret = _FAIL;
5312         struct xmit_frame               *pmgntframe;
5313         struct pkt_attrib               *pattrib;
5314         unsigned char                   *pframe;
5315         struct rtw_ieee80211_hdr        *pwlanhdr;
5316         unsigned short          *fctrl;
5317         unsigned char                   *mac;
5318         unsigned char                   bssrate[NumRates];
5319         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
5320         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5321         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5322         int     bssrate_len = 0;
5323         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
5324         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo); 
5325         u8                                      wpsie[255] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
5326         u16                                     wpsielen = 0, p2pielen = 0;
5327 #ifdef CONFIG_WFD
5328         u32                                     wfdielen = 0;
5329 #endif //CONFIG_WFD
5330
5331         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5332
5333
5334         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
5335         {
5336                 goto exit;
5337         }
5338
5339         //update attribute
5340         pattrib = &pmgntframe->attrib;
5341         update_mgntframe_attrib(padapter, pattrib);
5342
5343
5344         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5345
5346         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5347         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5348
5349         mac = myid(&(padapter->eeprompriv));
5350
5351         fctrl = &(pwlanhdr->frame_ctl);
5352         *(fctrl) = 0;
5353
5354         if (da) {
5355                 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5356                 _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);
5357         } else {
5358                 if ( ( pwdinfo->p2p_info.scan_op_ch_only ) || ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) )
5359                 {
5360                         //      This two flags will be set when this is only the P2P client mode.
5361                         _rtw_memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
5362                         _rtw_memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
5363                 }
5364                 else
5365                 {
5366                         //      broadcast probe request frame
5367                         _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
5368                         _rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
5369                 }
5370         }
5371         _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
5372
5373         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5374         pmlmeext->mgnt_seq++;
5375         SetFrameSubType(pframe, WIFI_PROBEREQ);
5376
5377         pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
5378         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
5379
5380         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
5381         {
5382                 pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &(pattrib->pktlen));
5383         }
5384         else
5385         {
5386                 pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &(pattrib->pktlen));
5387         }
5388         //      Use the OFDM rate in the P2P probe request frame. ( 6(B), 9(B), 12(B), 24(B), 36, 48, 54 )
5389         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
5390
5391 #ifdef CONFIG_IOCTL_CFG80211
5392         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
5393         {
5394                 if( pmlmepriv->wps_probe_req_ie != NULL && pmlmepriv->p2p_probe_req_ie != NULL )
5395                 {
5396                         //WPS IE
5397                         _rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
5398                         pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
5399                         pframe += pmlmepriv->wps_probe_req_ie_len;
5400
5401                         //P2P IE
5402                         _rtw_memcpy(pframe, pmlmepriv->p2p_probe_req_ie, pmlmepriv->p2p_probe_req_ie_len);
5403                         pattrib->pktlen += pmlmepriv->p2p_probe_req_ie_len;
5404                         pframe += pmlmepriv->p2p_probe_req_ie_len;
5405                 }
5406         }
5407         else
5408 #endif //CONFIG_IOCTL_CFG80211
5409         {
5410
5411                 //      WPS IE
5412                 //      Noted by Albert 20110221
5413                 //      According to the WPS specification, all the WPS attribute is presented by Big Endian.
5414
5415                 wpsielen = 0;
5416                 //      WPS OUI
5417                 *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
5418                 wpsielen += 4;
5419
5420                 //      WPS version
5421                 //      Type:
5422                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
5423                 wpsielen += 2;
5424
5425                 //      Length:
5426                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
5427                 wpsielen += 2;
5428
5429                 //      Value:
5430                 wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0
5431
5432                 if( pmlmepriv->wps_probe_req_ie == NULL )
5433                 {
5434                         //      UUID-E
5435                         //      Type:
5436                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_UUID_E );
5437                         wpsielen += 2;
5438
5439                         //      Length:
5440                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0010 );
5441                         wpsielen += 2;
5442
5443                         //      Value:
5444                         if (pwdinfo->external_uuid == 0) {
5445                                 _rtw_memset( wpsie + wpsielen, 0x0, 16 );
5446                                 _rtw_memcpy( wpsie + wpsielen, myid( &padapter->eeprompriv ), ETH_ALEN );
5447                         } else {
5448                                 _rtw_memcpy( wpsie + wpsielen, pwdinfo->uuid, 0x10 );
5449                         }
5450                         wpsielen += 0x10;
5451
5452                         //      Config Method
5453                         //      Type:
5454                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
5455                         wpsielen += 2;
5456
5457                         //      Length:
5458                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
5459                         wpsielen += 2;
5460
5461                         //      Value:
5462                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
5463                         wpsielen += 2;
5464                 }
5465
5466                 //      Device Name
5467                 //      Type:
5468                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
5469                 wpsielen += 2;
5470
5471                 //      Length:
5472                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->device_name_len );
5473                 wpsielen += 2;
5474
5475                 //      Value:
5476                 _rtw_memcpy( wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len );
5477                 wpsielen += pwdinfo->device_name_len;
5478
5479                 //      Primary Device Type
5480                 //      Type:
5481                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
5482                 wpsielen += 2;
5483
5484                 //      Length:
5485                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
5486                 wpsielen += 2;
5487
5488                 //      Value:
5489                 //      Category ID
5490                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_RTK_WIDI );
5491                 wpsielen += 2;
5492
5493                 //      OUI
5494                 *(u32*) ( wpsie + wpsielen ) = cpu_to_be32( WPSOUI );
5495                 wpsielen += 4;
5496
5497                 //      Sub Category ID
5498                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_RTK_DMP );
5499                 wpsielen += 2;
5500
5501                 //      Device Password ID
5502                 //      Type:
5503                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
5504                 wpsielen += 2;
5505
5506                 //      Length:
5507                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
5508                 wpsielen += 2;
5509
5510                 //      Value:
5511                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );  //      Registrar-specified
5512                 wpsielen += 2;  
5513
5514                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
5515                 
5516                 //      P2P OUI
5517                 p2pielen = 0;
5518                 p2pie[ p2pielen++ ] = 0x50;
5519                 p2pie[ p2pielen++ ] = 0x6F;
5520                 p2pie[ p2pielen++ ] = 0x9A;
5521                 p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
5522
5523                 //      Commented by Albert 20110221
5524                 //      According to the P2P Specification, the probe request frame should contain 5 P2P attributes
5525                 //      1. P2P Capability
5526                 //      2. P2P Device ID if this probe request wants to find the specific P2P device
5527                 //      3. Listen Channel
5528                 //      4. Extended Listen Timing
5529                 //      5. Operating Channel if this WiFi is working as the group owner now
5530
5531                 //      P2P Capability
5532                 //      Type:
5533                 p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
5534
5535                 //      Length:
5536                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
5537                 p2pielen += 2;
5538
5539                 //      Value:
5540                 //      Device Capability Bitmap, 1 byte
5541                 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
5542                 
5543                 //      Group Capability Bitmap, 1 byte
5544                 if ( pwdinfo->persistent_supported )
5545                         p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
5546                 else
5547                         p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
5548
5549                 //      Listen Channel
5550                 //      Type:
5551                 p2pie[ p2pielen++ ] = P2P_ATTR_LISTEN_CH;
5552
5553                 //      Length:
5554                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
5555                 p2pielen += 2;
5556
5557                 //      Value:
5558                 //      Country String
5559                 p2pie[ p2pielen++ ] = 'X';
5560                 p2pie[ p2pielen++ ] = 'X';
5561                 
5562                 //      The third byte should be set to 0x04.
5563                 //      Described in the "Operating Channel Attribute" section.
5564                 p2pie[ p2pielen++ ] = 0x04;
5565
5566                 //      Operating Class
5567                 p2pie[ p2pielen++ ] = 0x51;     //      Copy from SD7
5568                 
5569                 //      Channel Number
5570                 p2pie[ p2pielen++ ] = pwdinfo->listen_channel;  //      listen channel
5571                 
5572
5573                 //      Extended Listen Timing
5574                 //      Type:
5575                 p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
5576
5577                 //      Length:
5578                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
5579                 p2pielen += 2;
5580
5581                 //      Value:
5582                 //      Availability Period
5583                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
5584                 p2pielen += 2;
5585
5586                 //      Availability Interval
5587                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
5588                 p2pielen += 2;
5589
5590                 if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
5591                 {
5592                         //      Operating Channel (if this WiFi is working as the group owner now)
5593                         //      Type:
5594                         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
5595
5596                         //      Length:
5597                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
5598                         p2pielen += 2;
5599
5600                         //      Value:
5601                         //      Country String
5602                         p2pie[ p2pielen++ ] = 'X';
5603                         p2pie[ p2pielen++ ] = 'X';
5604                 
5605                         //      The third byte should be set to 0x04.
5606                         //      Described in the "Operating Channel Attribute" section.
5607                         p2pie[ p2pielen++ ] = 0x04;
5608
5609                         //      Operating Class
5610                         p2pie[ p2pielen++ ] = 0x51;     //      Copy from SD7
5611                 
5612                         //      Channel Number
5613                         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       //      operating channel number
5614                         
5615                 }
5616                 
5617                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );        
5618
5619         }
5620
5621 #ifdef CONFIG_WFD
5622 #ifdef CONFIG_IOCTL_CFG80211
5623         if ( _TRUE == pwdinfo->wfd_info->wfd_enable )
5624 #endif
5625         {
5626                 wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
5627                 pframe += wfdielen;
5628                 pattrib->pktlen += wfdielen;
5629         }
5630 #ifdef CONFIG_IOCTL_CFG80211
5631         else if (pmlmepriv->wfd_probe_req_ie != NULL && pmlmepriv->wfd_probe_req_ie_len>0)              
5632         {
5633                 //WFD IE
5634                 _rtw_memcpy(pframe, pmlmepriv->wfd_probe_req_ie, pmlmepriv->wfd_probe_req_ie_len);
5635                 pattrib->pktlen += pmlmepriv->wfd_probe_req_ie_len;
5636                 pframe += pmlmepriv->wfd_probe_req_ie_len;              
5637         }
5638 #endif //CONFIG_IOCTL_CFG80211
5639 #endif //CONFIG_WFD     
5640
5641         pattrib->last_txcmdsz = pattrib->pktlen;
5642
5643         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
5644
5645         if (wait_ack) {
5646                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5647         } else {
5648                 dump_mgntframe(padapter, pmgntframe);
5649                 ret = _SUCCESS;
5650         }
5651
5652 exit:
5653         return ret;
5654 }
5655
5656 inline void issue_probereq_p2p(_adapter *adapter, u8 *da)
5657 {
5658         _issue_probereq_p2p(adapter, da, _FALSE);
5659 }
5660
5661 int issue_probereq_p2p_ex(_adapter *adapter, u8 *da, int try_cnt, int wait_ms)
5662 {
5663         int ret;
5664         int i = 0;
5665         u32 start = rtw_get_current_time();
5666
5667         do
5668         {
5669                 ret = _issue_probereq_p2p(adapter, da, wait_ms>0?_TRUE:_FALSE);
5670
5671                 i++;
5672
5673                 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
5674                         break;
5675
5676                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
5677                         rtw_msleep_os(wait_ms);
5678
5679         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
5680
5681         if (ret != _FAIL) {
5682                 ret = _SUCCESS;
5683                 #ifndef DBG_XMIT_ACK
5684                 goto exit;
5685                 #endif
5686         }
5687
5688         if (try_cnt && wait_ms) {
5689                 if (da)
5690                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
5691                                 FUNC_ADPT_ARG(adapter), MAC_ARG(da), rtw_get_oper_ch(adapter),
5692                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
5693                 else
5694                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5695                                 FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter),
5696                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
5697         }
5698 exit:
5699         return ret;
5700 }
5701
5702 #endif //CONFIG_P2P
5703
5704 s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
5705 {
5706         _adapter *adapter = recv_frame->u.hdr.adapter;
5707         struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
5708         u8 *frame = recv_frame->u.hdr.rx_data;
5709         u16 seq_ctrl = ( (recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
5710                 (recv_frame->u.hdr.attrib.frag_num & 0xf);
5711         
5712         if (GetRetry(frame)) {
5713                 if (token >= 0) {
5714                         if ((seq_ctrl == mlmeext->action_public_rxseq)
5715                                 && (token == mlmeext->action_public_dialog_token))
5716                         {
5717                                 DBG_871X(FUNC_ADPT_FMT" seq_ctrl=0x%x, rxseq=0x%x, token:%d\n",
5718                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
5719                                 return _FAIL;
5720                         }
5721                 } else {
5722                         if (seq_ctrl == mlmeext->action_public_rxseq) {
5723                                 DBG_871X(FUNC_ADPT_FMT" seq_ctrl=0x%x, rxseq=0x%x\n",
5724                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
5725                                 return _FAIL;
5726                         }
5727                 }
5728         }
5729         
5730         mlmeext->action_public_rxseq = seq_ctrl;
5731         
5732         if (token >= 0)
5733                 mlmeext->action_public_dialog_token = token;
5734
5735         return _SUCCESS;
5736 }
5737
5738 unsigned int on_action_public_p2p(union recv_frame *precv_frame)
5739 {
5740         _adapter *padapter = precv_frame->u.hdr.adapter;
5741         u8 *pframe = precv_frame->u.hdr.rx_data;
5742         uint len = precv_frame->u.hdr.len;
5743         u8 *frame_body;
5744         u8 dialogToken=0;
5745 #ifdef CONFIG_P2P
5746         u8 *p2p_ie;
5747         u32     p2p_ielen, wps_ielen;
5748         struct  wifidirect_info *pwdinfo = &( padapter->wdinfo );
5749         u8      result = P2P_STATUS_SUCCESS;
5750         u8      empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
5751         u8 *merged_p2pie = NULL;
5752         u32 merged_p2p_ielen= 0;
5753 #endif //CONFIG_P2P
5754
5755         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
5756
5757         dialogToken = frame_body[7];
5758
5759         if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
5760                 return _FAIL;
5761         
5762 #ifdef CONFIG_P2P
5763         _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
5764 #ifdef CONFIG_IOCTL_CFG80211
5765         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211)
5766         {
5767                 rtw_cfg80211_rx_p2p_action_public(padapter, pframe, len);
5768         }
5769         else
5770 #endif //CONFIG_IOCTL_CFG80211
5771         {
5772                 //      Do nothing if the driver doesn't enable the P2P function.
5773                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
5774                         return _SUCCESS;
5775
5776                 len -= sizeof(struct rtw_ieee80211_hdr_3addr);
5777
5778                 switch( frame_body[ 6 ] )//OUI Subtype
5779                 {
5780                         case P2P_GO_NEGO_REQ:
5781                         {
5782                                 DBG_871X( "[%s] Got GO Nego Req Frame\n", __FUNCTION__);
5783                                 _rtw_memset( &pwdinfo->groupid_info, 0x00, sizeof( struct group_id_info ) );
5784
5785                                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
5786                                 {
5787                                         rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
5788                                 }
5789
5790                                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
5791                                 {
5792                                         //      Commented by Albert 20110526
5793                                         //      In this case, this means the previous nego fail doesn't be reset yet.
5794                                         _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5795                                         //      Restore the previous p2p state
5796                                         rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
5797                                         DBG_871X( "[%s] Restore the previous p2p state to %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo) );                                                
5798                                 }                                       
5799 #ifdef CONFIG_CONCURRENT_MODE
5800                                 if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
5801                                 {
5802                                         _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
5803                                 }
5804 #endif // CONFIG_CONCURRENT_MODE
5805
5806                                 //      Commented by Kurt 20110902
5807                                 //Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered.
5808                                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
5809                                         rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
5810
5811                                 //      Commented by Kurt 20120113
5812                                 //      Get peer_dev_addr here if peer doesn't issue prov_disc frame.
5813                                 if( _rtw_memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN) )
5814                                         _rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
5815
5816                                 result = process_p2p_group_negotation_req( pwdinfo, frame_body, len );
5817                                 issue_p2p_GO_response( padapter, GetAddr2Ptr(pframe), frame_body, len, result );
5818 #ifdef CONFIG_INTEL_WIDI
5819                                 if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) )
5820                                 {
5821                                         padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
5822                                         _cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
5823                                         intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
5824                                 }
5825 #endif //CONFIG_INTEL_WIDI
5826
5827                                 //      Commented by Albert 20110718
5828                                 //      No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer.
5829 #ifdef CONFIG_CONCURRENT_MODE
5830                                 //      Commented by Albert 20120107
5831                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
5832 #else // CONFIG_CONCURRENT_MODE
5833                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
5834 #endif // CONFIG_CONCURRENT_MODE
5835                                 break;                                  
5836                         }
5837                         case P2P_GO_NEGO_RESP:
5838                         {
5839                                 DBG_871X( "[%s] Got GO Nego Resp Frame\n", __FUNCTION__);
5840
5841                                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
5842                                 {
5843                                         //      Commented by Albert 20110425
5844                                         //      The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function.
5845                                         _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5846                                         pwdinfo->nego_req_info.benable = _FALSE;
5847                                         result = process_p2p_group_negotation_resp( pwdinfo, frame_body, len);
5848                                         issue_p2p_GO_confirm( pwdinfo->padapter, GetAddr2Ptr(pframe), result);
5849                                         if ( P2P_STATUS_SUCCESS == result )
5850                                         {
5851                                                 if ( rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT )
5852                                                 {
5853                                                         pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
5854                                                         #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5855                                                         pwdinfo->p2p_info.operation_ch[ 1 ] = 1;        //Check whether GO is operating in channel 1;
5856                                                         pwdinfo->p2p_info.operation_ch[ 2 ] = 6;        //Check whether GO is operating in channel 6;
5857                                                         pwdinfo->p2p_info.operation_ch[ 3 ] = 11;       //Check whether GO is operating in channel 11;
5858                                                         #endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
5859                                                         pwdinfo->p2p_info.scan_op_ch_only = 1;
5860                                                         _set_timer( &pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH );
5861                                                 }
5862                                         }
5863
5864                                         //      Reset the dialog token for group negotiation frames.
5865                                         pwdinfo->negotiation_dialog_token = 1;
5866
5867                                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
5868                                         {
5869                                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
5870                                         }
5871                                 }
5872                                 else
5873                                 {
5874                                         DBG_871X( "[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __FUNCTION__);
5875                                 }
5876                                 
5877                                 break;
5878                         }
5879                         case P2P_GO_NEGO_CONF:
5880                         {
5881                                 DBG_871X( "[%s] Got GO Nego Confirm Frame\n", __FUNCTION__);
5882                                 result = process_p2p_group_negotation_confirm( pwdinfo, frame_body, len);
5883                                 if ( P2P_STATUS_SUCCESS == result )
5884                                 {
5885                                         if ( rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT )
5886                                         {
5887                                                 pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
5888                                                 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5889                                                 pwdinfo->p2p_info.operation_ch[ 1 ] = 1;        //Check whether GO is operating in channel 1;
5890                                                 pwdinfo->p2p_info.operation_ch[ 2 ] = 6;        //Check whether GO is operating in channel 6;
5891                                                 pwdinfo->p2p_info.operation_ch[ 3 ] = 11;       //Check whether GO is operating in channel 11;
5892                                                 #endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
5893                                                 pwdinfo->p2p_info.scan_op_ch_only = 1;
5894                                                 _set_timer( &pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH );
5895                                         }
5896                                 }
5897                                 break;
5898                         }
5899                         case P2P_INVIT_REQ:
5900                         {
5901                                 //      Added by Albert 2010/10/05
5902                                 //      Received the P2P Invite Request frame.
5903                                 
5904                                 DBG_871X( "[%s] Got invite request frame!\n", __FUNCTION__ );
5905                                 if ( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)) )
5906                                 {
5907                                         //      Parse the necessary information from the P2P Invitation Request frame.
5908                                         //      For example: The MAC address of sending this P2P Invitation Request frame.
5909                                         u32     attr_contentlen = 0;
5910                                         u8      status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
5911                                         struct group_id_info group_id;
5912                                         u8      invitation_flag = 0;
5913                                         int j=0;
5914
5915                                         merged_p2p_ielen = rtw_get_p2p_merged_ies_len(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_);
5916
5917                                         merged_p2pie = rtw_zmalloc(merged_p2p_ielen + 2);       // 2 is for EID and Length
5918                                         if (merged_p2pie == NULL)
5919                                         {
5920                                                 DBG_871X( "[%s] Malloc p2p ie fail\n", __FUNCTION__);
5921                                                 goto exit;
5922                                         }
5923                                         _rtw_memset(merged_p2pie, 0x00, merged_p2p_ielen);                                      
5924
5925                                         merged_p2p_ielen = rtw_p2p_merge_ies(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, merged_p2pie);
5926
5927                                         rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
5928                                         if ( attr_contentlen )
5929                                         {
5930
5931                                                 rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
5932                                                 //      Commented by Albert 20120510
5933                                                 //      Copy to the pwdinfo->p2p_peer_interface_addr.
5934                                                 //      So that the WFD UI ( or Sigma ) can get the peer interface address by using the following command.
5935                                                 //      #> iwpriv wlan0 p2p_get peer_ifa
5936                                                 //      After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant.
5937
5938                                                 if ( attr_contentlen )
5939                                                 {
5940                                                         DBG_871X( "[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
5941                                                                         pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
5942                                                                         pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
5943                                                                         pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5] );
5944                                                 }                                                               
5945
5946                                                 if ( invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT )
5947                                                 {
5948                                                         //      Re-invoke the persistent group.
5949                                                         
5950                                                         _rtw_memset( &group_id, 0x00, sizeof( struct group_id_info ) );
5951                                                         rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen);
5952                                                         if ( attr_contentlen )
5953                                                         {
5954                                                                 if ( _rtw_memcmp( group_id.go_device_addr, myid( &padapter->eeprompriv ), ETH_ALEN ) )
5955                                                                 {
5956                                                                         //      The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO.
5957                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO );
5958                                                                         rtw_p2p_set_role( pwdinfo, P2P_ROLE_GO );
5959                                                                         status_code = P2P_STATUS_SUCCESS;
5960                                                                 }
5961                                                                 else
5962                                                                 {
5963                                                                         //      The p2p device sending this p2p invitation request wants to be the persistent GO.
5964                                                                         if ( is_matched_in_profilelist( pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[ 0 ] ) )
5965                                                                         {
5966                                                                                 u8 operatingch_info[5] = { 0x00 };
5967                                                                                 if ( rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) )
5968                                                                                 {
5969                                                                                         if( rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4] ) >= 0 )
5970                                                                                         {
5971                                                                                                 //      The operating channel is acceptable for this device.
5972                                                                                                 pwdinfo->rx_invitereq_info.operation_ch[0]= operatingch_info[4];
5973                                                                                                 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5974                                                                                                 pwdinfo->rx_invitereq_info.operation_ch[1]= 1;          //Check whether GO is operating in channel 1;
5975                                                                                                 pwdinfo->rx_invitereq_info.operation_ch[2]= 6;          //Check whether GO is operating in channel 6;
5976                                                                                                 pwdinfo->rx_invitereq_info.operation_ch[3]= 11;         //Check whether GO is operating in channel 11;
5977                                                                                                 #endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
5978                                                                                                 pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
5979                                                                                                 _set_timer( &pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH );
5980                                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH );
5981                                                                                                 rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
5982                                                                                                 status_code = P2P_STATUS_SUCCESS;
5983                                                                                         }
5984                                                                                         else
5985                                                                                         {
5986                                                                                                 //      The operating channel isn't supported by this device.
5987                                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
5988                                                                                                 rtw_p2p_set_role( pwdinfo, P2P_ROLE_DEVICE );
5989                                                                                                 status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
5990                                                                                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
5991                                                                                         }
5992                                                                                 }
5993                                                                                 else
5994                                                                                 {
5995                                                                                         //      Commented by Albert 20121130
5996                                                                                         //      Intel will use the different P2P IE to store the operating channel information
5997                                                                                         //      Workaround for Intel WiDi 3.5
5998                                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH );
5999                                                                                         rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
6000                                                                                         status_code = P2P_STATUS_SUCCESS;
6001                                                                                 }                                                               
6002                                                                         }
6003                                                                         else
6004                                                                         {
6005                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
6006                                                                                 #ifdef CONFIG_INTEL_WIDI
6007                                                                                 _rtw_memcpy( pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN );
6008                                                                                 rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
6009                                                                                 #endif //CONFIG_INTEL_WIDI
6010
6011                                                                                 status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
6012                                                                         }
6013                                                                 }
6014                                                         }
6015                                                         else
6016                                                         {
6017                                                                 DBG_871X( "[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__ );
6018                                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
6019                                                         }                                                                       
6020                                                 }
6021                                                 else
6022                                                 {
6023                                                         //      Received the invitation to join a P2P group.
6024
6025                                                         _rtw_memset( &group_id, 0x00, sizeof( struct group_id_info ) );
6026                                                         rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen);
6027                                                         if ( attr_contentlen )
6028                                                         {
6029                                                                 if ( _rtw_memcmp( group_id.go_device_addr, myid( &padapter->eeprompriv ), ETH_ALEN ) )
6030                                                                 {
6031                                                                         //      In this case, the GO can't be myself.
6032                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
6033                                                                         status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
6034                                                                 }
6035                                                                 else
6036                                                                 {
6037                                                                         //      The p2p device sending this p2p invitation request wants to join an existing P2P group
6038                                                                         //      Commented by Albert 2012/06/28
6039                                                                         //      In this case, this Wi-Fi device should use the iwpriv command to get the peer device address.
6040                                                                         //      The peer device address should be the destination address for the provisioning discovery request.
6041                                                                         //      Then, this Wi-Fi device should use the iwpriv command to get the peer interface address.
6042                                                                         //      The peer interface address should be the address for WPS mac address
6043                                                                         _rtw_memcpy( pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN );                                                                                       
6044                                                                         rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
6045                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN );
6046                                                                         status_code = P2P_STATUS_SUCCESS;
6047                                                                 }
6048                                                         }
6049                                                         else
6050                                                         {
6051                                                                 DBG_871X( "[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__ );
6052                                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
6053                                                         }
6054                                                 }
6055                                         }
6056                                         else
6057                                         {
6058                                                 DBG_871X( "[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __FUNCTION__ );
6059                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
6060                                         }                                                       
6061
6062                                         DBG_871X( "[%s] status_code = %d\n", __FUNCTION__, status_code );
6063
6064                                         pwdinfo->inviteresp_info.token = frame_body[ 7 ];
6065                                         issue_p2p_invitation_response( padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code );
6066                                         _set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
6067                                 }
6068 #ifdef CONFIG_INTEL_WIDI
6069                                 if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) )
6070                                 {
6071                                         padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
6072                                         _cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
6073                                         intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
6074                                 }
6075 #endif //CONFIG_INTEL_WIDI
6076                                 break;
6077                         }
6078                         case P2P_INVIT_RESP:
6079                         {
6080                                 u8      attr_content = 0x00;
6081                                 u32     attr_contentlen = 0;
6082                                 
6083                                 DBG_871X( "[%s] Got invite response frame!\n", __FUNCTION__ );
6084                                 _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
6085                                 if ( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)) )
6086                                 {
6087                                         rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
6088                                                                         
6089                                         if ( attr_contentlen == 1 )
6090                                         {
6091                                                 DBG_871X( "[%s] Status = %d\n", __FUNCTION__, attr_content );
6092                                                 pwdinfo->invitereq_info.benable = _FALSE;
6093
6094                                                 if ( attr_content == P2P_STATUS_SUCCESS )
6095                                                 {
6096                                                         if ( _rtw_memcmp( pwdinfo->invitereq_info.go_bssid, myid( &padapter->eeprompriv ), ETH_ALEN ))
6097                                                         {
6098                                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO );
6099                                                         }
6100                                                         else
6101                                                         {
6102                                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
6103                                                         }
6104                                                         rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_OK );
6105                                                 }
6106                                                 else
6107                                                 {
6108                                                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
6109                                                         rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
6110                                                 }
6111                                         }
6112                                         else
6113                                         {
6114                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
6115                                                 rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
6116                                         }
6117                                 }
6118                                 else
6119                                 {
6120                                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
6121                                         rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
6122                                 }
6123
6124                                 if ( rtw_p2p_chk_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL ) )
6125                                 {
6126                                         _set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
6127                                 }
6128                                 break;
6129                         }
6130                         case P2P_DEVDISC_REQ:
6131
6132                                 process_p2p_devdisc_req(pwdinfo, pframe, len);
6133
6134                                 break;
6135
6136                         case P2P_DEVDISC_RESP:
6137
6138                                 process_p2p_devdisc_resp(pwdinfo, pframe, len);
6139
6140                                 break;
6141
6142                         case P2P_PROVISION_DISC_REQ:
6143                                 DBG_871X( "[%s] Got Provisioning Discovery Request Frame\n", __FUNCTION__ );
6144                                 process_p2p_provdisc_req(pwdinfo, pframe, len);
6145                                 _rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
6146
6147                                 //20110902 Kurt
6148                                 //Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered.
6149                                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
6150                                         rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
6151                                 
6152                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
6153                                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
6154 #ifdef CONFIG_INTEL_WIDI
6155                                 if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) )
6156                                 {
6157                                         padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
6158                                         _cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
6159                                         intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
6160                                 }
6161 #endif //CONFIG_INTEL_WIDI
6162                                 break;
6163
6164                         case P2P_PROVISION_DISC_RESP:
6165                                 //      Commented by Albert 20110707
6166                                 //      Should we check the pwdinfo->tx_prov_disc_info.bsent flag here??
6167                                 DBG_871X( "[%s] Got Provisioning Discovery Response Frame\n", __FUNCTION__ );
6168                                 //      Commented by Albert 20110426
6169                                 //      The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function.
6170                                 _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
6171                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
6172                                 process_p2p_provdisc_resp(pwdinfo, pframe);
6173                                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
6174                                 break;
6175
6176                 }
6177         }
6178
6179
6180 exit:
6181
6182         if(merged_p2pie)
6183         {
6184                 rtw_mfree(merged_p2pie, merged_p2p_ielen + 2);
6185         }
6186 #endif //CONFIG_P2P
6187         return _SUCCESS;
6188 }
6189
6190 unsigned int on_action_public_vendor(union recv_frame *precv_frame)
6191 {
6192         unsigned int ret = _FAIL;
6193         u8 *pframe = precv_frame->u.hdr.rx_data;
6194         uint frame_len = precv_frame->u.hdr.len;
6195         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
6196
6197         if (_rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE) {
6198                 ret = on_action_public_p2p(precv_frame);
6199         }
6200
6201         return ret;
6202 }
6203
6204 unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
6205 {
6206         unsigned int ret = _FAIL;
6207         u8 *pframe = precv_frame->u.hdr.rx_data;
6208         uint frame_len = precv_frame->u.hdr.len;
6209         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
6210         u8 token;
6211         _adapter *adapter = precv_frame->u.hdr.adapter;
6212         int cnt = 0;
6213         char msg[64];
6214
6215         token = frame_body[2];
6216
6217         if (rtw_action_public_decache(precv_frame, token) == _FAIL)
6218                 goto exit;
6219
6220         #ifdef CONFIG_IOCTL_CFG80211
6221         cnt += sprintf((msg+cnt), "%s(token:%u)", action_public_str(action), token);
6222         rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
6223         #endif
6224
6225         ret = _SUCCESS;
6226         
6227 exit:
6228         return ret;
6229 }
6230
6231 unsigned int on_action_public(_adapter *padapter, union recv_frame *precv_frame)
6232 {
6233         unsigned int ret = _FAIL;
6234         u8 *pframe = precv_frame->u.hdr.rx_data;
6235         uint frame_len = precv_frame->u.hdr.len;
6236         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
6237         u8 category, action;
6238
6239         /* check RA matches or not */
6240         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
6241                 goto exit;
6242
6243         category = frame_body[0];
6244         if(category != RTW_WLAN_CATEGORY_PUBLIC)
6245                 goto exit;
6246
6247         action = frame_body[1];
6248         switch (action) {
6249         case ACT_PUBLIC_VENDOR:
6250                 ret = on_action_public_vendor(precv_frame);
6251                 break;
6252         default:
6253                 ret = on_action_public_default(precv_frame, action);
6254                 break;
6255         }
6256
6257 exit:
6258         return ret;
6259 }
6260
6261 unsigned int OnAction_ht(_adapter *padapter, union recv_frame *precv_frame)
6262 {
6263         u8 *pframe = precv_frame->u.hdr.rx_data;
6264         uint frame_len = precv_frame->u.hdr.len;
6265         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
6266         u8 category, action;
6267
6268         /* check RA matches or not */
6269         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
6270                 goto exit;
6271
6272         category = frame_body[0];
6273         if(category != RTW_WLAN_CATEGORY_HT)
6274                 goto exit;
6275
6276         action = frame_body[1];
6277         switch (action) {
6278         case RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING:
6279 #ifdef CONFIG_BEAMFORMING
6280                 //DBG_871X("RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING\n");
6281                 beamforming_get_report_frame(padapter, precv_frame);
6282 #endif //CONFIG_BEAMFORMING
6283                 break;
6284         default:
6285                 break;
6286         }
6287
6288 exit:
6289
6290         return _SUCCESS;
6291 }
6292
6293 #ifdef CONFIG_IEEE80211W
6294 unsigned int OnAction_sa_query(_adapter *padapter, union recv_frame *precv_frame)
6295 {
6296         u8 *pframe = precv_frame->u.hdr.rx_data;
6297         struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
6298         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6299         unsigned short tid;
6300         //Baron
6301         
6302         DBG_871X("OnAction_sa_query\n");
6303         
6304         switch (pframe[WLAN_HDR_A3_LEN+1])
6305         {
6306                 case 0: //SA Query req
6307                         _rtw_memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short));
6308                         DBG_871X("OnAction_sa_query request,action=%d, tid=%04x\n", pframe[WLAN_HDR_A3_LEN+1], tid);
6309                         issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid);
6310                         break;
6311
6312                 case 1: //SA Query rsp
6313                         _cancel_timer_ex(&pmlmeext->sa_query_timer);
6314                         DBG_871X("OnAction_sa_query response,action=%d, tid=%04x, cancel timer\n", pframe[WLAN_HDR_A3_LEN+1], pframe[WLAN_HDR_A3_LEN+2]);
6315                         break;
6316                 default:
6317                         break;
6318         }
6319         if(0)
6320         {
6321                 int pp;
6322                 printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
6323                 for(pp=0;pp< pattrib->pkt_len; pp++)
6324                         printk(" %02x ", pframe[pp]);
6325                 printk("\n");
6326         }       
6327         
6328         return _SUCCESS;
6329 }
6330 #endif //CONFIG_IEEE80211W
6331
6332 unsigned int OnAction_wmm(_adapter *padapter, union recv_frame *precv_frame)
6333 {
6334         return _SUCCESS;
6335 }
6336
6337 unsigned int OnAction_vht(_adapter *padapter, union recv_frame *precv_frame)
6338 {
6339 #ifdef CONFIG_80211AC_VHT
6340         struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
6341         u8 *pframe = precv_frame->u.hdr.rx_data;
6342         uint frame_len = precv_frame->u.hdr.len;
6343         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
6344         u8 category, action;
6345         struct sta_info *psta = NULL;
6346
6347         /* check RA matches or not */
6348         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
6349                 goto exit;
6350
6351         category = frame_body[0];
6352         if(category != RTW_WLAN_CATEGORY_VHT)
6353                 goto exit;
6354
6355         action = frame_body[1];
6356         switch (action) {
6357         case RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING:
6358 #ifdef CONFIG_BEAMFORMING
6359                 //DBG_871X("RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING\n");
6360                 beamforming_get_report_frame(padapter, precv_frame);
6361 #endif //CONFIG_BEAMFORMING
6362                 break;
6363         case RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION:
6364                 // CategoryCode(1) + ActionCode(1) + OpModeNotification(1)
6365                 //DBG_871X("RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION\n");
6366                 psta = rtw_get_stainfo(&padapter->stapriv, prxattrib->ta);
6367                 if (psta)
6368                         rtw_process_vht_op_mode_notify(padapter, &frame_body[2], psta);
6369                 break;
6370         default:
6371                 break;
6372         }
6373
6374 exit:
6375 #endif //CONFIG_80211AC_VHT
6376
6377         return _SUCCESS;
6378 }
6379
6380 unsigned int OnAction_p2p(_adapter *padapter, union recv_frame *precv_frame)
6381 {
6382 #ifdef CONFIG_P2P
6383         u8 *frame_body;
6384         u8 category, OUI_Subtype, dialogToken=0;
6385         u8 *pframe = precv_frame->u.hdr.rx_data;
6386         uint len = precv_frame->u.hdr.len;
6387         struct  wifidirect_info *pwdinfo = &( padapter->wdinfo );
6388
6389         //check RA matches or not
6390         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))//for if1, sta/ap mode
6391                 return _SUCCESS;
6392
6393         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
6394
6395         category = frame_body[0];
6396         if(category != RTW_WLAN_CATEGORY_P2P)
6397                 return _SUCCESS;
6398
6399         if ( cpu_to_be32( *( ( u32* ) ( frame_body + 1 ) ) ) != P2POUI )
6400                 return _SUCCESS;
6401
6402 #ifdef CONFIG_IOCTL_CFG80211
6403         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
6404         {
6405                 rtw_cfg80211_rx_action_p2p(padapter, pframe, len);
6406                 return _SUCCESS;
6407         }
6408         else
6409 #endif //CONFIG_IOCTL_CFG80211
6410         {
6411                 len -= sizeof(struct rtw_ieee80211_hdr_3addr);
6412                 OUI_Subtype = frame_body[5];
6413                 dialogToken = frame_body[6];
6414
6415                 switch(OUI_Subtype)
6416                 {
6417                         case P2P_NOTICE_OF_ABSENCE:
6418                                 
6419                                 break;
6420                                 
6421                         case P2P_PRESENCE_REQUEST:
6422
6423                                 process_p2p_presence_req(pwdinfo, pframe, len);                 
6424                                 
6425                                 break;
6426                                 
6427                         case P2P_PRESENCE_RESPONSE:
6428                                 
6429                                 break;
6430                                 
6431                         case P2P_GO_DISC_REQUEST:
6432                                 
6433                                 break;
6434                                 
6435                         default:
6436                                 break;
6437                                 
6438                 }
6439         }
6440 #endif //CONFIG_P2P
6441
6442         return _SUCCESS;
6443
6444 }
6445
6446 unsigned int OnAction(_adapter *padapter, union recv_frame *precv_frame)
6447 {
6448         int i;
6449         unsigned char   category;
6450         struct action_handler *ptable;
6451         unsigned char   *frame_body;
6452         u8 *pframe = precv_frame->u.hdr.rx_data; 
6453
6454         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
6455         
6456         category = frame_body[0];
6457         
6458         for(i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++) 
6459         {
6460                 ptable = &OnAction_tbl[i];
6461                 
6462                 if(category == ptable->num)
6463                         ptable->func(padapter, precv_frame);
6464         
6465         }
6466
6467         return _SUCCESS;
6468
6469 }
6470
6471 unsigned int DoReserved(_adapter *padapter, union recv_frame *precv_frame)
6472 {
6473
6474         //DBG_871X("rcvd mgt frame(%x, %x)\n", (GetFrameSubType(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe));
6475         return _SUCCESS;
6476 }
6477
6478 struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
6479 {
6480         struct xmit_frame *pmgntframe;
6481         struct xmit_buf *pxmitbuf;
6482
6483         if (once)
6484                 pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
6485         else
6486                 pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
6487
6488         if (pmgntframe == NULL) {
6489                 DBG_871X(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once);
6490                 goto exit;
6491         }
6492
6493         if ((pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv)) == NULL) {
6494                 DBG_871X(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter));
6495                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
6496                 pmgntframe = NULL;
6497                 goto exit;
6498         }
6499
6500         pmgntframe->frame_tag = MGNT_FRAMETAG;
6501         pmgntframe->pxmitbuf = pxmitbuf;
6502         pmgntframe->buf_addr = pxmitbuf->pbuf;
6503         pxmitbuf->priv_data = pmgntframe;
6504
6505 exit:
6506         return pmgntframe;
6507
6508 }
6509
6510 inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
6511 {
6512         return _alloc_mgtxmitframe(pxmitpriv, _FALSE);
6513 }
6514
6515 inline struct xmit_frame *alloc_mgtxmitframe_once(struct xmit_priv *pxmitpriv)
6516 {
6517         return _alloc_mgtxmitframe(pxmitpriv, _TRUE);
6518 }
6519
6520
6521 /****************************************************************************
6522
6523 Following are some TX fuctions for WiFi MLME
6524
6525 *****************************************************************************/
6526
6527 void update_mgnt_tx_rate(_adapter *padapter, u8 rate)
6528 {
6529         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6530
6531         pmlmeext->tx_rate = rate;
6532         //DBG_871X("%s(): rate = %x\n",__FUNCTION__, rate);
6533 }
6534
6535 void update_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
6536 {
6537         u8      wireless_mode;
6538         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6539
6540         //_rtw_memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
6541
6542         pattrib->hdrlen = 24;
6543         pattrib->nr_frags = 1;
6544         pattrib->priority = 7;
6545         pattrib->mac_id = 0;
6546         pattrib->qsel = 0x12;
6547
6548         pattrib->pktlen = 0;
6549
6550         if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
6551                 wireless_mode = WIRELESS_11B;
6552         else
6553                 wireless_mode = WIRELESS_11G;
6554         pattrib->raid =  rtw_get_mgntframe_raid(padapter, wireless_mode);
6555         pattrib->rate = pmlmeext->tx_rate;
6556
6557         pattrib->encrypt = _NO_PRIVACY_;
6558         pattrib->bswenc = _FALSE;       
6559
6560         pattrib->qos_en = _FALSE;
6561         pattrib->ht_en = _FALSE;
6562         pattrib->bwmode = CHANNEL_WIDTH_20;
6563         pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6564         pattrib->sgi = _FALSE;
6565
6566         pattrib->seqnum = pmlmeext->mgnt_seq;
6567
6568         pattrib->retry_ctrl = _TRUE;
6569
6570         pattrib->mbssid = 0;
6571
6572 }
6573
6574 void update_mgntframe_attrib_addr(_adapter *padapter, struct xmit_frame *pmgntframe)
6575 {
6576         u8      *pframe;
6577         struct pkt_attrib       *pattrib = &pmgntframe->attrib;
6578
6579         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6580
6581         _rtw_memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);
6582         _rtw_memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN);
6583 }
6584
6585 void dump_mgntframe(_adapter *padapter, struct xmit_frame *pmgntframe)
6586 {
6587         if(padapter->bSurpriseRemoved == _TRUE ||
6588                 padapter->bDriverStopped == _TRUE)
6589         {
6590                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
6591                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
6592                 return;
6593         }
6594
6595         rtw_hal_mgnt_xmit(padapter, pmgntframe);
6596 }
6597
6598 s32 dump_mgntframe_and_wait(_adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
6599 {
6600         s32 ret = _FAIL;
6601         _irqL irqL;
6602         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;      
6603         struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
6604         struct submit_ctx sctx;
6605
6606         if(padapter->bSurpriseRemoved == _TRUE ||
6607                 padapter->bDriverStopped == _TRUE)
6608         {
6609                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
6610                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
6611                 return ret;
6612         }
6613
6614         rtw_sctx_init(&sctx, timeout_ms);
6615         pxmitbuf->sctx = &sctx;
6616
6617         ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
6618
6619         if (ret == _SUCCESS)
6620                 ret = rtw_sctx_wait(&sctx, __func__);
6621
6622         _enter_critical(&pxmitpriv->lock_sctx, &irqL);
6623         pxmitbuf->sctx = NULL;
6624         _exit_critical(&pxmitpriv->lock_sctx, &irqL);
6625
6626          return ret;
6627 }
6628
6629 s32 dump_mgntframe_and_wait_ack(_adapter *padapter, struct xmit_frame *pmgntframe)
6630 {
6631 #ifdef CONFIG_XMIT_ACK
6632         static u8 seq_no = 0;
6633         s32 ret = _FAIL;
6634         u32 timeout_ms = 500;//  500ms
6635         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
6636         #ifdef CONFIG_CONCURRENT_MODE
6637         if (padapter->pbuddy_adapter && !padapter->isprimary)
6638                 pxmitpriv = &(padapter->pbuddy_adapter->xmitpriv);
6639         #endif
6640
6641         if(padapter->bSurpriseRemoved == _TRUE ||
6642                 padapter->bDriverStopped == _TRUE)
6643         {
6644                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
6645                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
6646                 return -1;
6647         }
6648
6649         _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
6650         pxmitpriv->ack_tx = _TRUE;
6651         pxmitpriv->seq_no = seq_no++;
6652         pmgntframe->ack_report = 1;
6653         if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
6654                 ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
6655         }
6656
6657         pxmitpriv->ack_tx = _FALSE;
6658         _exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
6659
6660          return ret;
6661 #else //!CONFIG_XMIT_ACK
6662         dump_mgntframe(padapter, pmgntframe);
6663         rtw_msleep_os(50);
6664         return _SUCCESS;
6665 #endif //!CONFIG_XMIT_ACK        
6666 }
6667
6668 int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
6669 {
6670         u8 *ssid_ie;
6671         sint ssid_len_ori;
6672         int len_diff = 0;
6673         
6674         ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
6675
6676         //DBG_871X("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __FUNCTION__, hidden_ssid_mode, ssid_ie, ssid_len_ori);
6677         
6678         if(ssid_ie && ssid_len_ori>0)
6679         {
6680                 switch(hidden_ssid_mode)
6681                 {
6682                         case 1:
6683                         {
6684                                 u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
6685                                 u32 remain_len = 0;
6686                                 
6687                                 remain_len = ies_len -(next_ie-ies);
6688                                 
6689                                 ssid_ie[1] = 0;                         
6690                                 _rtw_memcpy(ssid_ie+2, next_ie, remain_len);
6691                                 len_diff -= ssid_len_ori;
6692                                 
6693                                 break;
6694                         }               
6695                         case 2:
6696                                 _rtw_memset(&ssid_ie[2], 0, ssid_len_ori);
6697                                 break;
6698                         default:
6699                                 break;
6700                 }
6701         }
6702
6703         return len_diff;
6704 }
6705
6706 void issue_beacon(_adapter *padapter, int timeout_ms)
6707 {
6708         struct xmit_frame       *pmgntframe;
6709         struct pkt_attrib       *pattrib;
6710         unsigned char   *pframe;
6711         struct rtw_ieee80211_hdr *pwlanhdr;
6712         unsigned short *fctrl;
6713         unsigned int    rate_len;
6714         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
6715 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6716         _irqL irqL;
6717         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6718 #endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6719         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6720         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6721         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
6722         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
6723 #ifdef CONFIG_P2P
6724         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
6725 #endif //CONFIG_P2P
6726
6727
6728         //DBG_871X("%s\n", __FUNCTION__);
6729
6730         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
6731         {
6732                 DBG_871X("%s, alloc mgnt frame fail\n", __FUNCTION__);
6733                 return;
6734         }
6735 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6736         _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
6737 #endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6738
6739         //update attribute
6740         pattrib = &pmgntframe->attrib;
6741         update_mgntframe_attrib(padapter, pattrib);
6742         pattrib->qsel = 0x10;
6743         #ifdef CONFIG_CONCURRENT_MODE
6744         if(padapter->iface_type == IFACE_PORT1) 
6745                 pattrib->mbssid = 1;
6746         #endif  
6747         
6748         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6749                 
6750         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6751         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;  
6752         
6753         
6754         fctrl = &(pwlanhdr->frame_ctl);
6755         *(fctrl) = 0;
6756         
6757         _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
6758         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
6759         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
6760
6761         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
6762         //pmlmeext->mgnt_seq++;
6763         SetFrameSubType(pframe, WIFI_BEACON);
6764         
6765         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);       
6766         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
6767         
6768         if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
6769         {
6770                 //DBG_871X("ie len=%d\n", cur_network->IELength);
6771 #ifdef CONFIG_P2P
6772                 // for P2P : Primary Device Type & Device Name
6773                 u32 wpsielen=0, insert_len=0;
6774                 u8 *wpsie=NULL;         
6775                 wpsie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wpsielen);
6776                 
6777                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen>0)
6778                 {
6779                         uint wps_offset, remainder_ielen;
6780                         u8 *premainder_ie, *pframe_wscie;
6781         
6782                         wps_offset = (uint)(wpsie - cur_network->IEs);
6783
6784                         premainder_ie = wpsie + wpsielen;
6785
6786                         remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
6787
6788 #ifdef CONFIG_IOCTL_CFG80211
6789                         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
6790                         {
6791                                 if(pmlmepriv->wps_beacon_ie && pmlmepriv->wps_beacon_ie_len>0)
6792                                 {
6793                                         _rtw_memcpy(pframe, cur_network->IEs, wps_offset);
6794                                         pframe += wps_offset;
6795                                         pattrib->pktlen += wps_offset;
6796
6797                                         _rtw_memcpy(pframe, pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
6798                                         pframe += pmlmepriv->wps_beacon_ie_len;
6799                                         pattrib->pktlen += pmlmepriv->wps_beacon_ie_len;
6800
6801                                         //copy remainder_ie to pframe
6802                                         _rtw_memcpy(pframe, premainder_ie, remainder_ielen);
6803                                         pframe += remainder_ielen;              
6804                                         pattrib->pktlen += remainder_ielen;
6805                                 }
6806                                 else
6807                                 {
6808                                         _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
6809                                         pframe += cur_network->IELength;
6810                                         pattrib->pktlen += cur_network->IELength;
6811                                 }
6812                         }
6813                         else
6814 #endif //CONFIG_IOCTL_CFG80211
6815                         {
6816                                 pframe_wscie = pframe + wps_offset;
6817                                 _rtw_memcpy(pframe, cur_network->IEs, wps_offset+wpsielen);                     
6818                                 pframe += (wps_offset + wpsielen);              
6819                                 pattrib->pktlen += (wps_offset + wpsielen);
6820
6821                                 //now pframe is end of wsc ie, insert Primary Device Type & Device Name
6822                                 //      Primary Device Type
6823                                 //      Type:
6824                                 *(u16*) ( pframe + insert_len) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
6825                                 insert_len += 2;
6826                                 
6827                                 //      Length:
6828                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( 0x0008 );
6829                                 insert_len += 2;
6830                                 
6831                                 //      Value:
6832                                 //      Category ID
6833                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
6834                                 insert_len += 2;
6835
6836                                 //      OUI
6837                                 *(u32*) ( pframe + insert_len ) = cpu_to_be32( WPSOUI );
6838                                 insert_len += 4;
6839
6840                                 //      Sub Category ID
6841                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
6842                                 insert_len += 2;
6843
6844
6845                                 //      Device Name
6846                                 //      Type:
6847                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
6848                                 insert_len += 2;
6849
6850                                 //      Length:
6851                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( pwdinfo->device_name_len );
6852                                 insert_len += 2;
6853
6854                                 //      Value:
6855                                 _rtw_memcpy( pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len );
6856                                 insert_len += pwdinfo->device_name_len;
6857
6858
6859                                 //update wsc ie length
6860                                 *(pframe_wscie+1) = (wpsielen -2) + insert_len;
6861
6862                                 //pframe move to end
6863                                 pframe+=insert_len;
6864                                 pattrib->pktlen += insert_len;
6865
6866                                 //copy remainder_ie to pframe
6867                                 _rtw_memcpy(pframe, premainder_ie, remainder_ielen);
6868                                 pframe += remainder_ielen;              
6869                                 pattrib->pktlen += remainder_ielen;
6870                         }
6871                 }
6872                 else
6873 #endif //CONFIG_P2P
6874                 {
6875                         int len_diff;
6876                         _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
6877                         len_diff = update_hidden_ssid(
6878                                 pframe+_BEACON_IE_OFFSET_
6879                                 , cur_network->IELength-_BEACON_IE_OFFSET_
6880                                 , pmlmeinfo->hidden_ssid_mode
6881                         );
6882                         pframe += (cur_network->IELength+len_diff);
6883                         pattrib->pktlen += (cur_network->IELength+len_diff);
6884                 }
6885
6886                 {
6887                         u8 *wps_ie;
6888                         uint wps_ielen;
6889                         u8 sr = 0;
6890                         wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof (struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
6891                                 pattrib->pktlen-sizeof (struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
6892                         if (wps_ie && wps_ielen>0) {
6893                                 rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8*)(&sr), NULL);
6894                         }
6895                         if (sr != 0)
6896                                 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
6897                         else
6898                                 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
6899                 }
6900
6901 #ifdef CONFIG_P2P
6902                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
6903                 {
6904                         u32 len;
6905 #ifdef CONFIG_IOCTL_CFG80211
6906                         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
6907                         {
6908                                 len = pmlmepriv->p2p_beacon_ie_len;
6909                                 if(pmlmepriv->p2p_beacon_ie && len>0)                           
6910                                         _rtw_memcpy(pframe, pmlmepriv->p2p_beacon_ie, len);
6911                         }
6912                         else
6913 #endif //CONFIG_IOCTL_CFG80211
6914                         {
6915                                 len = build_beacon_p2p_ie(pwdinfo, pframe);
6916                         }
6917
6918                         pframe += len;
6919                         pattrib->pktlen += len;
6920 #ifdef CONFIG_WFD
6921 #ifdef CONFIG_IOCTL_CFG80211
6922                         if(_TRUE == pwdinfo->wfd_info->wfd_enable)
6923 #endif //CONFIG_IOCTL_CFG80211
6924                         {
6925                         len = build_beacon_wfd_ie( pwdinfo, pframe );
6926                         }
6927 #ifdef CONFIG_IOCTL_CFG80211
6928                         else
6929                         {       
6930                                 len = 0;
6931                                 if(pmlmepriv->wfd_beacon_ie && pmlmepriv->wfd_beacon_ie_len>0)
6932                                 {
6933                                         len = pmlmepriv->wfd_beacon_ie_len;
6934                                         _rtw_memcpy(pframe, pmlmepriv->wfd_beacon_ie, len);     
6935                                 }
6936                         }               
6937 #endif //CONFIG_IOCTL_CFG80211
6938                         pframe += len;
6939                         pattrib->pktlen += len;
6940 #endif //CONFIG_WFD
6941                 }
6942 #endif //CONFIG_P2P
6943
6944                 goto _issue_bcn;
6945
6946         }
6947
6948         //below for ad-hoc mode
6949
6950         //timestamp will be inserted by hardware
6951         pframe += 8;
6952         pattrib->pktlen += 8;
6953
6954         // beacon interval: 2 bytes
6955
6956         _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 
6957
6958         pframe += 2;
6959         pattrib->pktlen += 2;
6960
6961         // capability info: 2 bytes
6962
6963         _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
6964
6965         pframe += 2;
6966         pattrib->pktlen += 2;
6967
6968         // SSID
6969         pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
6970
6971         // supported rates...
6972         rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
6973         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pattrib->pktlen);
6974
6975         // DS parameter set
6976         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
6977
6978         //if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
6979         {
6980                 u8 erpinfo=0;
6981                 u32 ATIMWindow;
6982                 // IBSS Parameter Set...
6983                 //ATIMWindow = cur->Configuration.ATIMWindow;
6984                 ATIMWindow = 0;
6985                 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
6986
6987                 //ERP IE
6988                 pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
6989         }       
6990
6991
6992         // EXTERNDED SUPPORTED RATE
6993         if (rate_len > 8)
6994         {
6995                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
6996         }
6997
6998
6999         //todo:HT for adhoc
7000
7001 _issue_bcn:
7002
7003 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
7004         pmlmepriv->update_bcn = _FALSE;
7005         
7006         _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);  
7007 #endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
7008
7009         if ((pattrib->pktlen + TXDESC_SIZE) > 512)
7010         {
7011                 DBG_871X("beacon frame too large\n");
7012                 return;
7013         }
7014         
7015         pattrib->last_txcmdsz = pattrib->pktlen;
7016
7017         //DBG_871X("issue bcn_sz=%d\n", pattrib->last_txcmdsz);
7018         if(timeout_ms > 0)
7019                 dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
7020         else
7021                 dump_mgntframe(padapter, pmgntframe);
7022
7023 }
7024
7025 void issue_probersp(_adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
7026 {
7027         struct xmit_frame                       *pmgntframe;
7028         struct pkt_attrib                       *pattrib;
7029         unsigned char                                   *pframe;
7030         struct rtw_ieee80211_hdr        *pwlanhdr;
7031         unsigned short                          *fctrl; 
7032         unsigned char                                   *mac, *bssid;
7033         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
7034 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
7035         u8 *pwps_ie;
7036         uint wps_ielen;
7037         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
7038 #endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
7039         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7040         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7041         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
7042         unsigned int    rate_len;
7043 #ifdef CONFIG_P2P
7044         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
7045 #ifdef CONFIG_WFD
7046         u32                                     wfdielen = 0;
7047 #endif //CONFIG_WFD
7048 #endif //CONFIG_P2P
7049
7050         //DBG_871X("%s\n", __FUNCTION__);
7051
7052         if(da == NULL)
7053                 return;
7054
7055         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7056         {
7057                 DBG_871X("%s, alloc mgnt frame fail\n", __FUNCTION__);
7058                 return;
7059         }
7060
7061
7062         //update attribute
7063         pattrib = &pmgntframe->attrib;
7064         update_mgntframe_attrib(padapter, pattrib);     
7065         
7066         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7067                 
7068         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7069         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;  
7070         
7071         mac = myid(&(padapter->eeprompriv));
7072         bssid = cur_network->MacAddress;
7073         
7074         fctrl = &(pwlanhdr->frame_ctl);
7075         *(fctrl) = 0;
7076         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
7077         _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
7078         _rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
7079
7080         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7081         pmlmeext->mgnt_seq++;
7082         SetFrameSubType(fctrl, WIFI_PROBERSP);
7083         
7084         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7085         pattrib->pktlen = pattrib->hdrlen;
7086         pframe += pattrib->hdrlen;
7087
7088
7089         if(cur_network->IELength>MAX_IE_SZ)
7090                 return;
7091         
7092 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
7093         if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
7094         {
7095                 pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
7096         
7097                 //inerset & update wps_probe_resp_ie
7098                 if((pmlmepriv->wps_probe_resp_ie!=NULL) && pwps_ie && (wps_ielen>0))
7099                 {
7100                         uint wps_offset, remainder_ielen;
7101                         u8 *premainder_ie;              
7102         
7103                         wps_offset = (uint)(pwps_ie - cur_network->IEs);
7104
7105                         premainder_ie = pwps_ie + wps_ielen;
7106
7107                         remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
7108
7109                         _rtw_memcpy(pframe, cur_network->IEs, wps_offset);              
7110                         pframe += wps_offset;           
7111                         pattrib->pktlen += wps_offset;          
7112
7113                         wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];//to get ie data len
7114                         if((wps_offset+wps_ielen+2)<=MAX_IE_SZ)
7115                         {
7116                                 _rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
7117                                 pframe += wps_ielen+2;          
7118                                 pattrib->pktlen += wps_ielen+2; 
7119                         }
7120
7121                         if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)
7122                         {
7123                                 _rtw_memcpy(pframe, premainder_ie, remainder_ielen);
7124                                 pframe += remainder_ielen;              
7125                                 pattrib->pktlen += remainder_ielen;     
7126                         }
7127                 }
7128                 else
7129                 {
7130                         _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
7131                         pframe += cur_network->IELength;
7132                         pattrib->pktlen += cur_network->IELength;
7133                 }
7134
7135                 /* retrieve SSID IE from cur_network->Ssid */
7136                 {
7137                         u8 *ssid_ie;
7138                         sint ssid_ielen;
7139                         sint ssid_ielen_diff;
7140                         u8 buf[MAX_IE_SZ];
7141                         u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct rtw_ieee80211_hdr_3addr);
7142
7143                         ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
7144                                 (pframe-ies)-_FIXED_IE_LENGTH_);
7145
7146                         ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
7147
7148                         if (ssid_ie &&  cur_network->Ssid.SsidLength) {
7149                                 uint remainder_ielen;
7150                                 u8 *remainder_ie;
7151                                 remainder_ie = ssid_ie+2;
7152                                 remainder_ielen = (pframe-remainder_ie);
7153
7154                                 if (remainder_ielen > MAX_IE_SZ) {
7155                                         DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));
7156                                         remainder_ielen = MAX_IE_SZ;
7157                                 }
7158
7159                                 _rtw_memcpy(buf, remainder_ie, remainder_ielen);
7160                                 _rtw_memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
7161                                 *(ssid_ie+1) = cur_network->Ssid.SsidLength;
7162                                 _rtw_memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
7163
7164                                 pframe += ssid_ielen_diff;
7165                                 pattrib->pktlen += ssid_ielen_diff;
7166                         }
7167                 }
7168         }       
7169         else            
7170 #endif          
7171         {
7172         
7173                 //timestamp will be inserted by hardware
7174                 pframe += 8;
7175                 pattrib->pktlen += 8;
7176
7177                 // beacon interval: 2 bytes
7178
7179                 _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 
7180
7181                 pframe += 2;
7182                 pattrib->pktlen += 2;
7183
7184                 // capability info: 2 bytes
7185
7186                 _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
7187
7188                 pframe += 2;
7189                 pattrib->pktlen += 2;
7190
7191                 //below for ad-hoc mode
7192
7193                 // SSID
7194                 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
7195
7196                 // supported rates...
7197                 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
7198                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pattrib->pktlen);
7199
7200                 // DS parameter set
7201                 pframe =rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
7202
7203                 if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
7204                 {
7205                         u8 erpinfo=0;
7206                         u32 ATIMWindow;
7207                         // IBSS Parameter Set...
7208                         //ATIMWindow = cur->Configuration.ATIMWindow;
7209                         ATIMWindow = 0;
7210                         pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
7211
7212                         //ERP IE
7213                         pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
7214                 }
7215
7216                 
7217                 // EXTERNDED SUPPORTED RATE
7218                 if (rate_len > 8)
7219                 {
7220                         pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
7221                 }
7222
7223
7224                 //todo:HT for adhoc
7225
7226         }       
7227
7228 #ifdef CONFIG_P2P
7229         if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)
7230                 /* IOT issue, When wifi_spec is not set, send probe_resp with P2P IE even if probe_req has no P2P IE */
7231                 && (is_valid_p2p_probereq || !padapter->registrypriv.wifi_spec))
7232         {
7233                 u32 len;
7234 #ifdef CONFIG_IOCTL_CFG80211
7235                 if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
7236                 {
7237                         //if pwdinfo->role == P2P_ROLE_DEVICE will call issue_probersp_p2p()
7238                         len = pmlmepriv->p2p_go_probe_resp_ie_len;
7239                         if(pmlmepriv->p2p_go_probe_resp_ie && len>0)
7240                                 _rtw_memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie, len);
7241                 }
7242                 else
7243 #endif //CONFIG_IOCTL_CFG80211
7244                 {
7245                         len = build_probe_resp_p2p_ie(pwdinfo, pframe);
7246                 }
7247
7248                 pframe += len;
7249                 pattrib->pktlen += len;
7250                 
7251 #ifdef CONFIG_WFD
7252 #ifdef CONFIG_IOCTL_CFG80211
7253                 if(_TRUE == pwdinfo->wfd_info->wfd_enable)
7254 #endif //CONFIG_IOCTL_CFG80211
7255                 {
7256                         len = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
7257                 }
7258 #ifdef CONFIG_IOCTL_CFG80211
7259                 else
7260                 {       
7261                         len = 0;
7262                         if(pmlmepriv->wfd_probe_resp_ie && pmlmepriv->wfd_probe_resp_ie_len>0)
7263                         {
7264                                 len = pmlmepriv->wfd_probe_resp_ie_len;
7265                                 _rtw_memcpy(pframe, pmlmepriv->wfd_probe_resp_ie, len); 
7266                         }       
7267                 }
7268 #endif //CONFIG_IOCTL_CFG80211          
7269                 pframe += len;
7270                 pattrib->pktlen += len;
7271 #endif //CONFIG_WFD
7272
7273         }
7274 #endif //CONFIG_P2P
7275
7276
7277 #ifdef CONFIG_AUTO_AP_MODE
7278 {
7279         struct sta_info *psta;
7280         struct sta_priv *pstapriv = &padapter->stapriv;
7281
7282         DBG_871X("(%s)\n", __FUNCTION__);
7283
7284         //check rc station
7285         psta = rtw_get_stainfo(pstapriv, da);
7286         if (psta && psta->isrc && psta->pid>0)
7287         {
7288                 u8 RC_OUI[4]={0x00,0xE0,0x4C,0x0A};
7289                 u8 RC_INFO[14] = {0};
7290                 //EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2]
7291                 u16 cu_ch = (u16)cur_network->Configuration.DSConfig;
7292
7293                 DBG_871X("%s, reply rc(pid=0x%x) device "MAC_FMT" in ch=%d\n", __FUNCTION__,
7294                         psta->pid, MAC_ARG(psta->hwaddr), cu_ch);
7295
7296                 //append vendor specific ie
7297                 _rtw_memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI));
7298                 _rtw_memcpy(&RC_INFO[4], mac, ETH_ALEN);
7299                 _rtw_memcpy(&RC_INFO[10], (u8*)&psta->pid, 2);
7300                 _rtw_memcpy(&RC_INFO[12], (u8*)&cu_ch, 2);
7301
7302                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen);
7303         }
7304 }
7305 #endif //CONFIG_AUTO_AP_MODE
7306
7307
7308         pattrib->last_txcmdsz = pattrib->pktlen;
7309         
7310
7311         dump_mgntframe(padapter, pmgntframe);
7312         
7313         return;
7314
7315 }
7316
7317 int _issue_probereq(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da, u8 ch, bool append_wps, int wait_ack)
7318 {
7319         int ret = _FAIL;
7320         struct xmit_frame               *pmgntframe;
7321         struct pkt_attrib               *pattrib;
7322         unsigned char                   *pframe;
7323         struct rtw_ieee80211_hdr        *pwlanhdr;
7324         unsigned short          *fctrl;
7325         unsigned char                   *mac;
7326         unsigned char                   bssrate[NumRates];
7327         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
7328         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7329         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7330         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7331         int     bssrate_len = 0;
7332         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
7333
7334         RT_TRACE(_module_rtl871x_mlme_c_,_drv_notice_,("+issue_probereq\n"));
7335
7336         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7337         {
7338                 goto exit;
7339         }
7340
7341         //update attribute
7342         pattrib = &pmgntframe->attrib;
7343         update_mgntframe_attrib(padapter, pattrib);
7344
7345
7346         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7347
7348         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7349         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7350
7351         mac = myid(&(padapter->eeprompriv));
7352
7353         fctrl = &(pwlanhdr->frame_ctl);
7354         *(fctrl) = 0;
7355
7356         if (da)
7357         {
7358                 //      unicast probe request frame
7359                 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
7360                 _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);
7361         }
7362         else
7363         {
7364                 //      broadcast probe request frame
7365                 _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
7366                 _rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
7367         }
7368
7369         _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
7370
7371         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7372         pmlmeext->mgnt_seq++;
7373         SetFrameSubType(pframe, WIFI_PROBEREQ);
7374
7375         pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
7376         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
7377
7378         if(pssid)
7379                 pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
7380         else
7381                 pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
7382
7383         get_rate_set(padapter, bssrate, &bssrate_len);
7384
7385         if (bssrate_len > 8)
7386         {
7387                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
7388                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
7389         }
7390         else
7391         {
7392                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
7393         }
7394
7395         if (ch)
7396                 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, &ch, &pattrib->pktlen);
7397
7398         if (append_wps) {
7399                 //add wps_ie for wps2.0
7400                 if(pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie)
7401                 {
7402                         _rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
7403                         pframe += pmlmepriv->wps_probe_req_ie_len;
7404                         pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
7405                         //pmlmepriv->wps_probe_req_ie_len = 0 ;//reset to zero
7406                 }
7407         }
7408
7409         pattrib->last_txcmdsz = pattrib->pktlen;
7410
7411         RT_TRACE(_module_rtl871x_mlme_c_,_drv_notice_,("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
7412
7413         if (wait_ack) {
7414                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
7415         } else {
7416                 dump_mgntframe(padapter, pmgntframe);
7417                 ret = _SUCCESS;
7418         }
7419
7420 exit:
7421         return ret;
7422 }
7423
7424 inline void issue_probereq(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da)
7425 {
7426         _issue_probereq(padapter, pssid, da, 0, 1, _FALSE);
7427 }
7428
7429 int issue_probereq_ex(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da, u8 ch, bool append_wps,
7430         int try_cnt, int wait_ms)
7431 {
7432         int ret;
7433         int i = 0;
7434         u32 start = rtw_get_current_time();
7435
7436         do
7437         {
7438                 ret = _issue_probereq(padapter, pssid, da, ch, append_wps, wait_ms>0?_TRUE:_FALSE);
7439
7440                 i++;
7441
7442                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
7443                         break;
7444
7445                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
7446                         rtw_msleep_os(wait_ms);
7447
7448         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
7449
7450         if (ret != _FAIL) {
7451                 ret = _SUCCESS;
7452                 #ifndef DBG_XMIT_ACK
7453                 goto exit;
7454                 #endif
7455         }
7456
7457         if (try_cnt && wait_ms) {
7458                 if (da)
7459                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
7460                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
7461                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
7462                 else
7463                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
7464                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
7465                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
7466         }
7467 exit:
7468         return ret;
7469 }
7470
7471 // if psta == NULL, indiate we are station(client) now...
7472 void issue_auth(_adapter *padapter, struct sta_info *psta, unsigned short status)
7473 {
7474         struct xmit_frame                       *pmgntframe;
7475         struct pkt_attrib                       *pattrib;
7476         unsigned char                                   *pframe;
7477         struct rtw_ieee80211_hdr        *pwlanhdr;
7478         unsigned short                          *fctrl;
7479         unsigned int                                    val32;
7480         unsigned short                          val16;
7481         int use_shared_key = 0;
7482         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
7483         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7484         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7485
7486         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7487         {
7488                 return;
7489         }
7490
7491         //update attribute
7492         pattrib = &pmgntframe->attrib;
7493         update_mgntframe_attrib(padapter, pattrib);
7494
7495         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7496
7497         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7498         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7499
7500         fctrl = &(pwlanhdr->frame_ctl);
7501         *(fctrl) = 0;
7502
7503         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7504         pmlmeext->mgnt_seq++;
7505         SetFrameSubType(pframe, WIFI_AUTH);
7506
7507         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
7508         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7509
7510
7511         if(psta)// for AP mode
7512         {
7513 #ifdef CONFIG_NATIVEAP_MLME
7514
7515                 _rtw_memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);           
7516                 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
7517                 _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
7518
7519         
7520                 // setting auth algo number
7521                 val16 = (u16)psta->authalg;
7522
7523                 if(status != _STATS_SUCCESSFUL_)
7524                         val16 = 0;
7525
7526                 if (val16)      {
7527                         val16 = cpu_to_le16(val16);     
7528                         use_shared_key = 1;
7529                 }
7530
7531                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
7532
7533                 // setting auth seq number
7534                 val16 =(u16)psta->auth_seq;
7535                 val16 = cpu_to_le16(val16);     
7536                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
7537
7538                 // setting status code...
7539                 val16 = status;
7540                 val16 = cpu_to_le16(val16);     
7541                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));
7542
7543                 // added challenging text...
7544                 if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
7545                 {
7546                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
7547                 }
7548 #endif
7549         }
7550         else
7551         {               
7552                 _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
7553                 _rtw_memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
7554                 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
7555         
7556                 // setting auth algo number             
7557                 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)? 1: 0;// 0:OPEN System, 1:Shared key
7558                 if (val16)      {
7559                         val16 = cpu_to_le16(val16);     
7560                         use_shared_key = 1;
7561                 }       
7562                 //DBG_871X("%s auth_algo= %s auth_seq=%d\n",__FUNCTION__,(pmlmeinfo->auth_algo==0)?"OPEN":"SHARED",pmlmeinfo->auth_seq);
7563                 
7564                 //setting IV for auth seq #3
7565                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
7566                 {
7567                         //DBG_871X("==> iv(%d),key_index(%d)\n",pmlmeinfo->iv,pmlmeinfo->key_index);
7568                         val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
7569                         val32 = cpu_to_le32(val32);
7570                         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&val32, &(pattrib->pktlen));
7571
7572                         pattrib->iv_len = 4;
7573                 }
7574
7575                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
7576                 
7577                 // setting auth seq number
7578                 val16 = pmlmeinfo->auth_seq;
7579                 val16 = cpu_to_le16(val16);     
7580                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
7581
7582                 
7583                 // setting status code...
7584                 val16 = status;
7585                 val16 = cpu_to_le16(val16);     
7586                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));
7587
7588                 // then checking to see if sending challenging text...
7589                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
7590                 {
7591                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
7592
7593                         SetPrivacy(fctrl);
7594                         
7595                         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);                       
7596                         
7597                         pattrib->encrypt = _WEP40_;
7598
7599                         pattrib->icv_len = 4;
7600                         
7601                         pattrib->pktlen += pattrib->icv_len;                    
7602                         
7603                 }
7604                 
7605         }
7606
7607         pattrib->last_txcmdsz = pattrib->pktlen;
7608
7609         rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
7610         DBG_871X("%s\n", __FUNCTION__);
7611         dump_mgntframe(padapter, pmgntframe);
7612
7613         return;
7614 }
7615
7616
7617 void issue_asocrsp(_adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
7618 {
7619 #ifdef CONFIG_AP_MODE
7620         struct xmit_frame       *pmgntframe;
7621         struct rtw_ieee80211_hdr        *pwlanhdr;
7622         struct pkt_attrib *pattrib;
7623         unsigned char   *pbuf, *pframe;
7624         unsigned short val;             
7625         unsigned short *fctrl;
7626         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
7627         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7628         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7629         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);  
7630         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
7631         u8 *ie = pnetwork->IEs; 
7632 #ifdef CONFIG_P2P
7633         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
7634 #ifdef CONFIG_WFD
7635         u32                                     wfdielen = 0;
7636 #endif //CONFIG_WFD
7637
7638 #endif //CONFIG_P2P
7639
7640         DBG_871X("%s\n", __FUNCTION__);
7641
7642         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7643         {
7644                 return;
7645         }
7646
7647         //update attribute
7648         pattrib = &pmgntframe->attrib;
7649         update_mgntframe_attrib(padapter, pattrib);
7650
7651
7652         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7653
7654         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7655         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7656
7657         fctrl = &(pwlanhdr->frame_ctl);
7658         *(fctrl) = 0;
7659
7660         _rtw_memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
7661         _rtw_memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
7662         _rtw_memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7663
7664
7665         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7666         pmlmeext->mgnt_seq++;
7667         if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
7668                 SetFrameSubType(pwlanhdr, pkt_type);            
7669         else
7670                 return;
7671
7672         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7673         pattrib->pktlen += pattrib->hdrlen;
7674         pframe += pattrib->hdrlen;
7675
7676         //capability
7677         val = *(unsigned short *)rtw_get_capability_from_ie(ie);
7678
7679         pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_ , (unsigned char *)&val, &(pattrib->pktlen));
7680
7681         status = cpu_to_le16(status);
7682         pframe = rtw_set_fixed_ie(pframe , _STATUS_CODE_ , (unsigned char *)&status, &(pattrib->pktlen));
7683         
7684         val = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
7685         pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_ , (unsigned char *)&val, &(pattrib->pktlen));
7686
7687         if (pstat->bssratelen <= 8)
7688         {
7689                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
7690         }       
7691         else 
7692         {
7693                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
7694                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
7695         }
7696
7697 #ifdef CONFIG_80211N_HT
7698         if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option))
7699         {
7700                 uint ie_len=0;
7701                 
7702                 //FILL HT CAP INFO IE
7703                 //p = hostapd_eid_ht_capabilities_info(hapd, p);
7704                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
7705                 if(pbuf && ie_len>0)
7706                 {
7707                         _rtw_memcpy(pframe, pbuf, ie_len+2);
7708                         pframe += (ie_len+2);
7709                         pattrib->pktlen +=(ie_len+2);
7710                 }
7711
7712                 //FILL HT ADD INFO IE
7713                 //p = hostapd_eid_ht_operation(hapd, p);
7714                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
7715                 if(pbuf && ie_len>0)
7716                 {
7717                         _rtw_memcpy(pframe, pbuf, ie_len+2);
7718                         pframe += (ie_len+2);
7719                         pattrib->pktlen +=(ie_len+2);
7720                 }
7721                 
7722         }       
7723 #endif
7724
7725 #ifdef CONFIG_80211AC_VHT
7726         if ((pstat->flags & WLAN_STA_VHT) && (pmlmepriv->vhtpriv.vht_option))
7727         {
7728                 u32 ie_len=0;
7729
7730                 //FILL VHT CAP IE
7731                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
7732                 if(pbuf && ie_len>0)
7733                 {
7734                         _rtw_memcpy(pframe, pbuf, ie_len+2);
7735                         pframe += (ie_len+2);
7736                         pattrib->pktlen +=(ie_len+2);
7737                 }
7738
7739                 //FILL VHT OPERATION IE
7740                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTOperation, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
7741                 if(pbuf && ie_len>0)
7742                 {
7743                         _rtw_memcpy(pframe, pbuf, ie_len+2);
7744                         pframe += (ie_len+2);
7745                         pattrib->pktlen +=(ie_len+2);
7746                 }
7747         }
7748 #endif //CONFIG_80211AC_VHT
7749
7750         //FILL WMM IE
7751         if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option))
7752         {
7753                 uint ie_len=0;
7754                 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};     
7755                 
7756                 for (pbuf = ie + _BEACON_IE_OFFSET_; ;pbuf+= (ie_len + 2))
7757                 {                       
7758                         pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));       
7759                         if(pbuf && _rtw_memcmp(pbuf+2, WMM_PARA_IE, 6)) 
7760                         {                               
7761                                 _rtw_memcpy(pframe, pbuf, ie_len+2);
7762                                 pframe += (ie_len+2);
7763                                 pattrib->pktlen +=(ie_len+2);
7764                                 
7765                                 break;                          
7766                         }
7767                         
7768                         if ((pbuf == NULL) || (ie_len == 0))
7769                         {
7770                                 break;
7771                         }                       
7772                 }
7773                 
7774         }
7775
7776
7777         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
7778         {
7779                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
7780         }
7781
7782         //add WPS IE ie for wps 2.0
7783         if(pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len>0)
7784         {
7785                 _rtw_memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
7786                 
7787                 pframe += pmlmepriv->wps_assoc_resp_ie_len;
7788                 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
7789         }
7790
7791 #ifdef CONFIG_P2P
7792         if( padapter->wdinfo.driver_interface == DRIVER_WEXT )
7793         {
7794                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device == _TRUE))
7795                 {
7796                         u32 len;
7797
7798                         len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
7799
7800                         pframe += len;
7801                         pattrib->pktlen += len;
7802                 }
7803         }
7804 #ifdef CONFIG_WFD
7805         if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)
7806 #ifdef CONFIG_IOCTL_CFG80211            
7807                 && (_TRUE == pwdinfo->wfd_info->wfd_enable)
7808 #endif //CONFIG_IOCTL_CFG80211  
7809         )
7810         {
7811                 wfdielen = build_assoc_resp_wfd_ie(pwdinfo, pframe);
7812                 pframe += wfdielen;
7813                 pattrib->pktlen += wfdielen;
7814         }
7815 #endif //CONFIG_WFD
7816 #endif //CONFIG_P2P
7817
7818         pattrib->last_txcmdsz = pattrib->pktlen;
7819         
7820         dump_mgntframe(padapter, pmgntframe);
7821         
7822 #endif
7823 }
7824
7825 void issue_assocreq(_adapter *padapter)
7826 {
7827         int ret = _FAIL;
7828         struct xmit_frame                               *pmgntframe;
7829         struct pkt_attrib                               *pattrib;
7830         unsigned char                                   *pframe, *p;
7831         struct rtw_ieee80211_hdr                        *pwlanhdr;
7832         unsigned short                          *fctrl;
7833         unsigned short                          val16;
7834         unsigned int                                    i, j, ie_len, index=0;
7835         unsigned char                                   rf_type, bssrate[NumRates], sta_bssrate[NumRates];
7836         PNDIS_802_11_VARIABLE_IEs       pIE;
7837         struct registry_priv    *pregpriv = &padapter->registrypriv;
7838         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
7839         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7840         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7841         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7842         int     bssrate_len = 0, sta_bssrate_len = 0;
7843         u8      vs_ie_length = 0;
7844 #ifdef CONFIG_P2P
7845         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
7846         u8                                      p2pie[ 255 ] = { 0x00 };
7847         u16                                     p2pielen = 0;   
7848 #ifdef CONFIG_WFD
7849         u32                                     wfdielen = 0;
7850 #endif //CONFIG_WFD
7851 #endif //CONFIG_P2P
7852
7853 #ifdef CONFIG_DFS
7854         u16     cap;
7855
7856         /* Dot H */
7857         u8 pow_cap_ele[2] = { 0x00 };
7858         u8 sup_ch[ 30 * 2 ] = {0x00 }, sup_ch_idx = 0, idx_5g = 2;      //For supported channel
7859 #endif //CONFIG_DFS
7860
7861         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7862                 goto exit;
7863
7864         //update attribute
7865         pattrib = &pmgntframe->attrib;
7866         update_mgntframe_attrib(padapter, pattrib);
7867
7868
7869         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7870
7871         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7872         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7873
7874         fctrl = &(pwlanhdr->frame_ctl);
7875         *(fctrl) = 0;
7876         _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7877         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
7878         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7879
7880         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7881         pmlmeext->mgnt_seq++;
7882         SetFrameSubType(pframe, WIFI_ASSOCREQ);
7883
7884         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
7885         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7886
7887         //caps
7888
7889 #ifdef CONFIG_DFS
7890         _rtw_memcpy(&cap, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
7891         cap |= cap_SpecMgmt;
7892         _rtw_memcpy(pframe, &cap, 2);
7893 #else
7894         _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
7895 #endif //CONFIG_DFS
7896
7897         pframe += 2;
7898         pattrib->pktlen += 2;
7899
7900         //listen interval
7901         //todo: listen interval for power saving
7902         val16 = cpu_to_le16(3);
7903         _rtw_memcpy(pframe ,(unsigned char *)&val16, 2);
7904         pframe += 2;
7905         pattrib->pktlen += 2;
7906
7907         //SSID
7908         pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
7909
7910 #ifdef CONFIG_DFS
7911         /* Dot H */
7912         if(pmlmeext->cur_channel > 14)
7913         {
7914                 pow_cap_ele[0] = 13;    // Minimum transmit power capability
7915                 pow_cap_ele[1] = 21;    // Maximum transmit power capability
7916                 pframe = rtw_set_ie(pframe, EID_PowerCap, 2, pow_cap_ele, &(pattrib->pktlen));
7917
7918                 //supported channels
7919                 do{
7920                         if( pmlmeext->channel_set[sup_ch_idx].ChannelNum <= 14 )
7921                         {
7922                                 sup_ch[0] = 1;  //First channel number
7923                                 sup_ch[1] = pmlmeext->channel_set[sup_ch_idx].ChannelNum;       //Number of channel
7924                         }
7925                         else
7926                         {
7927                                 sup_ch[idx_5g++] = pmlmeext->channel_set[sup_ch_idx].ChannelNum;
7928                                 sup_ch[idx_5g++] = 1;
7929                         }
7930                         sup_ch_idx++;
7931                 }
7932                 while( pmlmeext->channel_set[sup_ch_idx].ChannelNum != 0 );
7933                 pframe = rtw_set_ie(pframe, EID_SupportedChannels, idx_5g, sup_ch, &(pattrib->pktlen));
7934         }
7935 #endif //CONFIG_DFS
7936
7937         //supported rate & extended supported rate
7938
7939 #if 1   // Check if the AP's supported rates are also supported by STA.
7940         get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
7941         //DBG_871X("sta_bssrate_len=%d\n", sta_bssrate_len);
7942         
7943         if(pmlmeext->cur_channel == 14)// for JAPAN, channel 14 can only uses B Mode(CCK) 
7944         {
7945                 sta_bssrate_len = 4;
7946         }
7947
7948         
7949         //for (i = 0; i < sta_bssrate_len; i++) {
7950         //      DBG_871X("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]);
7951         //}
7952
7953         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
7954                 if (pmlmeinfo->network.SupportedRates[i] == 0) break;
7955                 DBG_871X("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
7956         }
7957         
7958
7959         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
7960                 if (pmlmeinfo->network.SupportedRates[i] == 0) break;
7961
7962                 
7963                 // Check if the AP's supported rates are also supported by STA.
7964                 for (j=0; j < sta_bssrate_len; j++) {
7965                          // Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP
7966                         if ( (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK) 
7967                                         == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) {
7968                                 //DBG_871X("match i = %d, j=%d\n", i, j);
7969                                 break;
7970                         } else {
7971                                 //DBG_871X("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK));
7972                         }
7973                 }
7974                 
7975                 if (j == sta_bssrate_len) {
7976                         // the rate is not supported by STA
7977                         DBG_871X("%s(): the rate[%d]=%02X is not supported by STA!\n",__FUNCTION__, i, pmlmeinfo->network.SupportedRates[i]);
7978                 } else {
7979                         // the rate is supported by STA
7980                         bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
7981                 }
7982         }
7983         
7984         bssrate_len = index;
7985         DBG_871X("bssrate_len = %d\n", bssrate_len);
7986
7987 #else   // Check if the AP's supported rates are also supported by STA.
7988 #if 0
7989         get_rate_set(padapter, bssrate, &bssrate_len);
7990 #else
7991         for (bssrate_len = 0; bssrate_len < NumRates; bssrate_len++) {
7992                 if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0) break;
7993
7994                 if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0x2C) // Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP
7995                         break;
7996
7997                 bssrate[bssrate_len] = pmlmeinfo->network.SupportedRates[bssrate_len];
7998         }
7999 #endif
8000 #endif  // Check if the AP's supported rates are also supported by STA.
8001
8002         if (bssrate_len == 0) {
8003                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
8004                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
8005                 goto exit; //don't connect to AP if no joint supported rate
8006         }
8007
8008
8009         if (bssrate_len > 8)
8010         {
8011                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
8012                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
8013         }
8014         else
8015         {
8016                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
8017         }
8018
8019         //vendor specific IE, such as WPA, WMM, WPS
8020         for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pmlmeinfo->network.IELength;)
8021         {
8022                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pmlmeinfo->network.IEs + i);
8023
8024                 switch (pIE->ElementID)
8025                 {
8026                         case _VENDOR_SPECIFIC_IE_:
8027                                 if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
8028                                                 (_rtw_memcmp(pIE->data, WMM_OUI, 4)) ||
8029                                                 (_rtw_memcmp(pIE->data, WPS_OUI, 4)))
8030                                 {       
8031                                         vs_ie_length = pIE->Length;
8032                                         if((!padapter->registrypriv.wifi_spec) && (_rtw_memcmp(pIE->data, WPS_OUI, 4)))
8033                                         {
8034                                                 //Commented by Kurt 20110629
8035                                                 //In some older APs, WPS handshake
8036                                                 //would be fail if we append vender extensions informations to AP
8037
8038                                                 vs_ie_length = 14;
8039                                         }
8040                                         
8041                                         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, vs_ie_length, pIE->data, &(pattrib->pktlen));
8042                                 }
8043                                 break;
8044
8045                         case EID_WPA2:
8046                                 pframe = rtw_set_ie(pframe, EID_WPA2, pIE->Length, pIE->data, &(pattrib->pktlen));
8047                                 break;
8048 #ifdef CONFIG_80211N_HT
8049                         case EID_HTCapability:
8050                                 if(padapter->mlmepriv.htpriv.ht_option==_TRUE) {
8051                                         if (!(is_ap_in_tkip(padapter)))
8052                                         {
8053                                                 _rtw_memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
8054
8055                                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
8056
8057                                                 pframe = rtw_set_ie(pframe, EID_HTCapability, pIE->Length , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
8058                                         }
8059                                 }
8060                                 break;
8061
8062                         case EID_EXTCapability:
8063                                 if(padapter->mlmepriv.htpriv.ht_option==_TRUE) {
8064                                         pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
8065                                 }
8066                                 break;
8067 #endif //CONFIG_80211N_HT
8068 #ifdef CONFIG_80211AC_VHT
8069                         case EID_VHTCapability:
8070                                 if (padapter->mlmepriv.vhtpriv.vht_option ==_TRUE) {
8071                                         pframe = rtw_set_ie(pframe, EID_VHTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
8072                                 }
8073                                 break;
8074
8075                         case EID_OpModeNotification:
8076                                 if (padapter->mlmepriv.vhtpriv.vht_option ==_TRUE) {
8077                                         pframe = rtw_set_ie(pframe, EID_OpModeNotification, pIE->Length, pIE->data, &(pattrib->pktlen));
8078                                 }
8079                                 break;
8080 #endif // CONFIG_80211AC_VHT
8081                         default:
8082                                 break;
8083                 }
8084
8085                 i += (pIE->Length + 2);
8086         }
8087
8088         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
8089         {
8090                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
8091         }
8092
8093
8094 #ifdef CONFIG_WAPI_SUPPORT
8095         rtw_build_assoc_req_wapi_ie(padapter, pframe, pattrib);
8096 #endif
8097
8098
8099 #ifdef CONFIG_P2P
8100
8101 #ifdef CONFIG_IOCTL_CFG80211
8102         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
8103         {
8104                 if(pmlmepriv->p2p_assoc_req_ie && pmlmepriv->p2p_assoc_req_ie_len>0)
8105                 {
8106                         _rtw_memcpy(pframe, pmlmepriv->p2p_assoc_req_ie, pmlmepriv->p2p_assoc_req_ie_len);
8107                         pframe += pmlmepriv->p2p_assoc_req_ie_len;
8108                         pattrib->pktlen += pmlmepriv->p2p_assoc_req_ie_len;
8109                 }
8110         }
8111         else
8112 #endif //CONFIG_IOCTL_CFG80211
8113         {
8114                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
8115                 {
8116                         //      Should add the P2P IE in the association request frame. 
8117                         //      P2P OUI
8118                         
8119                         p2pielen = 0;
8120                         p2pie[ p2pielen++ ] = 0x50;
8121                         p2pie[ p2pielen++ ] = 0x6F;
8122                         p2pie[ p2pielen++ ] = 0x9A;
8123                         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
8124
8125                         //      Commented by Albert 20101109
8126                         //      According to the P2P Specification, the association request frame should contain 3 P2P attributes
8127                         //      1. P2P Capability
8128                         //      2. Extended Listen Timing
8129                         //      3. Device Info
8130                         //      Commented by Albert 20110516
8131                         //      4. P2P Interface
8132
8133                         //      P2P Capability
8134                         //      Type:
8135                         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
8136
8137                         //      Length:
8138                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
8139                         p2pielen += 2;
8140
8141                         //      Value:
8142                         //      Device Capability Bitmap, 1 byte
8143                         p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
8144
8145                         //      Group Capability Bitmap, 1 byte
8146                         if ( pwdinfo->persistent_supported )
8147                                 p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
8148                         else
8149                                 p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
8150
8151                         //      Extended Listen Timing
8152                         //      Type:
8153                         p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
8154
8155                         //      Length:
8156                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
8157                         p2pielen += 2;
8158
8159                         //      Value:
8160                         //      Availability Period
8161                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
8162                         p2pielen += 2;
8163
8164                         //      Availability Interval
8165                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
8166                         p2pielen += 2;
8167
8168                         //      Device Info
8169                         //      Type:
8170                         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
8171
8172                         //      Length:
8173                         //      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
8174                         //      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
8175                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
8176                         p2pielen += 2;
8177
8178                         //      Value:
8179                         //      P2P Device Address
8180                         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
8181                         p2pielen += ETH_ALEN;
8182
8183                         //      Config Method
8184                         //      This field should be big endian. Noted by P2P specification.
8185                         if ( ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN ) ||
8186                                 ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN ) )
8187                         {
8188                                 *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY );
8189                         }
8190                         else
8191                         {
8192                                 *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_PBC );
8193                         }
8194
8195                         p2pielen += 2;
8196
8197                         //      Primary Device Type
8198                         //      Category ID
8199                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
8200                         p2pielen += 2;
8201
8202                         //      OUI
8203                         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
8204                         p2pielen += 4;
8205
8206                         //      Sub Category ID
8207                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
8208                         p2pielen += 2;
8209
8210                         //      Number of Secondary Device Types
8211                         p2pie[ p2pielen++ ] = 0x00;     //      No Secondary Device Type List
8212
8213                         //      Device Name
8214                         //      Type:
8215                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
8216                         p2pielen += 2;
8217
8218                         //      Length:
8219                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
8220                         p2pielen += 2;
8221
8222                         //      Value:
8223                         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
8224                         p2pielen += pwdinfo->device_name_len;
8225                 
8226                         //      P2P Interface
8227                         //      Type:
8228                         p2pie[ p2pielen++ ] = P2P_ATTR_INTERFACE;
8229                         
8230                         //      Length:
8231                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x000D );
8232                         p2pielen += 2;
8233                         
8234                         //      Value:
8235                         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );        //      P2P Device Address
8236                         p2pielen += ETH_ALEN;
8237
8238                         p2pie[ p2pielen++ ] = 1;        //      P2P Interface Address Count
8239                         
8240                         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );        //      P2P Interface Address List
8241                         p2pielen += ETH_ALEN;
8242                 
8243                         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
8244
8245 #ifdef CONFIG_WFD
8246                         //wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);
8247                         //pframe += wfdielen;
8248                         //pattrib->pktlen += wfdielen;
8249 #endif //CONFIG_WFD
8250                 }
8251         }
8252
8253 #endif //CONFIG_P2P
8254
8255 #ifdef CONFIG_WFD
8256 #ifdef CONFIG_IOCTL_CFG80211
8257         if ( _TRUE == pwdinfo->wfd_info->wfd_enable )
8258 #endif //CONFIG_IOCTL_CFG80211
8259         {
8260                 wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);
8261                 pframe += wfdielen;
8262                 pattrib->pktlen += wfdielen;
8263         }
8264 #ifdef CONFIG_IOCTL_CFG80211
8265         else if (pmlmepriv->wfd_assoc_req_ie != NULL && pmlmepriv->wfd_assoc_req_ie_len>0)              
8266         {
8267                 //WFD IE
8268                 _rtw_memcpy(pframe, pmlmepriv->wfd_assoc_req_ie, pmlmepriv->wfd_assoc_req_ie_len);
8269                 pattrib->pktlen += pmlmepriv->wfd_assoc_req_ie_len;
8270                 pframe += pmlmepriv->wfd_assoc_req_ie_len;              
8271         }
8272 #endif //CONFIG_IOCTL_CFG80211
8273 #endif //CONFIG_WFD     
8274
8275         pattrib->last_txcmdsz = pattrib->pktlen;
8276         dump_mgntframe(padapter, pmgntframe);
8277
8278         ret = _SUCCESS;
8279
8280 exit:
8281         if (ret == _SUCCESS)
8282                 rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
8283         else
8284                 rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
8285
8286         return;
8287 }
8288
8289 //when wait_ack is ture, this function shoule be called at process context
8290 static int _issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
8291 {
8292         int ret = _FAIL;
8293         struct xmit_frame                       *pmgntframe;
8294         struct pkt_attrib                       *pattrib;
8295         unsigned char                                   *pframe;
8296         struct rtw_ieee80211_hdr        *pwlanhdr;
8297         unsigned short                          *fctrl;
8298         struct xmit_priv        *pxmitpriv;
8299         struct mlme_ext_priv    *pmlmeext;
8300         struct mlme_ext_info    *pmlmeinfo;
8301
8302         //DBG_871X("%s:%d\n", __FUNCTION__, power_mode);
8303
8304         if(!padapter)
8305                 goto exit;
8306
8307         pxmitpriv = &(padapter->xmitpriv);
8308         pmlmeext = &(padapter->mlmeextpriv);
8309         pmlmeinfo = &(pmlmeext->mlmext_info);
8310
8311         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8312         {
8313                 goto exit;
8314         }
8315
8316         //update attribute
8317         pattrib = &pmgntframe->attrib;
8318         update_mgntframe_attrib(padapter, pattrib);
8319         pattrib->retry_ctrl = _FALSE;
8320
8321         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8322
8323         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8324         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8325
8326         fctrl = &(pwlanhdr->frame_ctl);
8327         *(fctrl) = 0;
8328
8329         if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
8330         {
8331                 SetFrDs(fctrl);
8332         }
8333         else if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
8334         {
8335                 SetToDs(fctrl);
8336         }
8337         
8338         if (power_mode)
8339         {
8340                 SetPwrMgt(fctrl);
8341         }
8342
8343         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
8344         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8345         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8346
8347         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8348         pmlmeext->mgnt_seq++;
8349         SetFrameSubType(pframe, WIFI_DATA_NULL);
8350
8351         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8352         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8353
8354         pattrib->last_txcmdsz = pattrib->pktlen;
8355
8356         if(wait_ack)
8357         {
8358                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
8359         }
8360         else
8361         {
8362                 dump_mgntframe(padapter, pmgntframe);
8363                 ret = _SUCCESS;
8364         }
8365
8366 exit:
8367         return ret;
8368 }
8369
8370 /*
8371  * [IMPORTANT] Don't call this function in interrupt context
8372  *
8373  * When wait_ms > 0, this function shoule be called at process context
8374  * da == NULL for station mode
8375  */
8376 int issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
8377 {
8378         int ret;
8379         int i = 0;
8380         u32 start = rtw_get_current_time();
8381         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8382         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8383         struct sta_info *psta;
8384
8385
8386         /* da == NULL, assum it's null data for sta to ap*/
8387         if (da == NULL)
8388                 da = get_my_bssid(&(pmlmeinfo->network));
8389
8390         psta = rtw_get_stainfo(&padapter->stapriv, da);
8391         if (psta) {
8392                 if (power_mode)
8393                         rtw_hal_macid_sleep(padapter, psta->mac_id);
8394                 else
8395                         rtw_hal_macid_wakeup(padapter, psta->mac_id);
8396         } else {
8397                 DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",
8398                         FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup");
8399                 rtw_warn_on(1);
8400         }
8401
8402         do {
8403                 ret = _issue_nulldata(padapter, da, power_mode, wait_ms>0?_TRUE:_FALSE);
8404
8405                 i++;
8406
8407                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
8408                         break;
8409
8410                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
8411                         rtw_msleep_os(wait_ms);
8412
8413         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
8414
8415         if (ret != _FAIL) {
8416                 ret = _SUCCESS;
8417                 #ifndef DBG_XMIT_ACK
8418                 goto exit;
8419                 #endif
8420         }
8421
8422         if (try_cnt && wait_ms) {
8423                 if (da)
8424                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
8425                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
8426                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8427                 else
8428                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
8429                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
8430                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8431         }
8432 exit:
8433         return ret;
8434 }
8435
8436 /*
8437  * [IMPORTANT] This function run in interrupt context
8438  *
8439  * The null data packet would be sent without power bit,
8440  * and not guarantee success.
8441  */
8442 s32 issue_nulldata_in_interrupt(PADAPTER padapter, u8 *da)
8443 {
8444         int ret;
8445         struct mlme_ext_priv *pmlmeext;
8446         struct mlme_ext_info *pmlmeinfo;
8447
8448
8449         pmlmeext = &padapter->mlmeextpriv;
8450         pmlmeinfo = &pmlmeext->mlmext_info;
8451
8452         /* da == NULL, assum it's null data for sta to ap*/
8453         if (da == NULL)
8454                 da = get_my_bssid(&(pmlmeinfo->network));
8455
8456         ret = _issue_nulldata(padapter, da, 0, _FALSE);
8457
8458         return ret;
8459 }
8460
8461 //when wait_ack is ture, this function shoule be called at process context
8462 static int _issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
8463 {
8464         int ret = _FAIL;
8465         struct xmit_frame                       *pmgntframe;
8466         struct pkt_attrib                       *pattrib;
8467         unsigned char                                   *pframe;
8468         struct rtw_ieee80211_hdr        *pwlanhdr;
8469         unsigned short                          *fctrl, *qc;
8470         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
8471         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8472         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8473
8474         DBG_871X("%s\n", __FUNCTION__);
8475
8476         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8477         {
8478                 goto exit;
8479         }
8480
8481         //update attribute
8482         pattrib = &pmgntframe->attrib;
8483         update_mgntframe_attrib(padapter, pattrib);
8484
8485         pattrib->hdrlen +=2;
8486         pattrib->qos_en = _TRUE;
8487         pattrib->eosp = 1;
8488         pattrib->ack_policy = 0;
8489         pattrib->mdata = 0;
8490
8491         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8492
8493         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8494         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8495
8496         fctrl = &(pwlanhdr->frame_ctl);
8497         *(fctrl) = 0;
8498
8499         if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
8500         {
8501                 SetFrDs(fctrl);
8502         }
8503         else if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
8504         {
8505                 SetToDs(fctrl);
8506         }
8507
8508         if(pattrib->mdata)
8509                 SetMData(fctrl);
8510
8511         qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
8512         
8513         SetPriority(qc, tid);
8514
8515         SetEOSP(qc, pattrib->eosp);
8516
8517         SetAckpolicy(qc, pattrib->ack_policy);
8518
8519         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
8520         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8521         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8522
8523         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8524         pmlmeext->mgnt_seq++;
8525         SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
8526
8527         pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
8528         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
8529
8530         pattrib->last_txcmdsz = pattrib->pktlen;
8531         
8532         if(wait_ack)
8533         {
8534                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
8535         }
8536         else
8537         {
8538                 dump_mgntframe(padapter, pmgntframe);
8539                 ret = _SUCCESS;
8540         }
8541
8542 exit:
8543         return ret;
8544 }
8545
8546 //when wait_ms >0 , this function shoule be called at process context
8547 //da == NULL for station mode
8548 int issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
8549 {
8550         int ret;
8551         int i = 0;
8552         u32 start = rtw_get_current_time();
8553         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8554         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8555
8556         /* da == NULL, assum it's null data for sta to ap*/
8557         if (da == NULL)
8558                 da = get_my_bssid(&(pmlmeinfo->network));
8559         
8560         do
8561         {
8562                 ret = _issue_qos_nulldata(padapter, da, tid, wait_ms>0?_TRUE:_FALSE);
8563
8564                 i++;
8565
8566                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
8567                         break;
8568
8569                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
8570                         rtw_msleep_os(wait_ms);
8571
8572         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
8573
8574         if (ret != _FAIL) {
8575                 ret = _SUCCESS;
8576                 #ifndef DBG_XMIT_ACK
8577                 goto exit;
8578                 #endif
8579         }
8580
8581         if (try_cnt && wait_ms) {
8582                 if (da)
8583                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
8584                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
8585                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8586                 else
8587                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
8588                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
8589                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8590         }
8591 exit:
8592         return ret;
8593 }
8594
8595 static int _issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
8596 {
8597         struct xmit_frame                       *pmgntframe;
8598         struct pkt_attrib                       *pattrib;
8599         unsigned char                                   *pframe;
8600         struct rtw_ieee80211_hdr        *pwlanhdr;
8601         unsigned short                          *fctrl;
8602         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
8603         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8604         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8605         int ret = _FAIL;
8606 #ifdef CONFIG_P2P
8607         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
8608 #endif //CONFIG_P2P     
8609
8610         //DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
8611
8612 #ifdef CONFIG_P2P
8613         if ( !( rtw_p2p_chk_state( pwdinfo, P2P_STATE_NONE ) ) && ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) )
8614         {
8615                 _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
8616                 _set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
8617         }
8618 #endif //CONFIG_P2P
8619
8620         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8621         {
8622                 goto exit;
8623         }
8624
8625         //update attribute
8626         pattrib = &pmgntframe->attrib;
8627         update_mgntframe_attrib(padapter, pattrib);
8628         pattrib->retry_ctrl = _FALSE;
8629
8630         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8631
8632         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8633         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8634
8635         fctrl = &(pwlanhdr->frame_ctl);
8636         *(fctrl) = 0;
8637
8638         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
8639         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8640         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8641
8642         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8643         pmlmeext->mgnt_seq++;
8644         SetFrameSubType(pframe, WIFI_DEAUTH);
8645
8646         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8647         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8648
8649         reason = cpu_to_le16(reason);
8650         pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_ , (unsigned char *)&reason, &(pattrib->pktlen));
8651
8652         pattrib->last_txcmdsz = pattrib->pktlen;
8653
8654
8655         if(wait_ack)
8656         {
8657                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
8658         }
8659         else
8660         {
8661                 dump_mgntframe(padapter, pmgntframe);
8662                 ret = _SUCCESS;
8663         }
8664
8665 exit:
8666         return ret;
8667 }
8668
8669 int issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason)
8670 {
8671         DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
8672         return _issue_deauth(padapter, da, reason, _FALSE);
8673 }
8674
8675 int issue_deauth_ex(_adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
8676         int wait_ms)
8677 {
8678         int ret;
8679         int i = 0;
8680         u32 start = rtw_get_current_time();
8681
8682         do
8683         {
8684                 ret = _issue_deauth(padapter, da, reason, wait_ms>0?_TRUE:_FALSE);
8685
8686                 i++;
8687
8688                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
8689                         break;
8690
8691                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
8692                         rtw_msleep_os(wait_ms);
8693
8694         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
8695
8696         if (ret != _FAIL) {
8697                 ret = _SUCCESS;
8698                 #ifndef DBG_XMIT_ACK
8699                 goto exit;
8700                 #endif
8701         }
8702
8703         if (try_cnt && wait_ms) {
8704                 if (da)
8705                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
8706                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
8707                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8708                 else
8709                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
8710                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
8711                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8712         }
8713 exit:
8714         return ret;
8715 }
8716
8717 void issue_action_spct_ch_switch(_adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)
8718 {       
8719         _irqL   irqL;
8720         _list           *plist, *phead;
8721         struct xmit_frame                       *pmgntframe;
8722         struct pkt_attrib                       *pattrib;
8723         unsigned char                           *pframe;
8724         struct rtw_ieee80211_hdr        *pwlanhdr;
8725         unsigned short                  *fctrl;
8726         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
8727         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8728         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8729         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8730
8731
8732         DBG_871X(FUNC_NDEV_FMT" ra="MAC_FMT", ch:%u, offset:%u\n",
8733                 FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(ra), new_ch, ch_offset);
8734
8735         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8736                 return;
8737
8738         //update attribute
8739         pattrib = &pmgntframe->attrib;
8740         update_mgntframe_attrib(padapter, pattrib);
8741
8742         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8743
8744         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8745         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8746
8747         fctrl = &(pwlanhdr->frame_ctl);
8748         *(fctrl) = 0;
8749
8750         _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */
8751         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); /* TA */
8752         _rtw_memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */
8753
8754         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8755         pmlmeext->mgnt_seq++;
8756         SetFrameSubType(pframe, WIFI_ACTION);
8757
8758         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8759         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8760
8761         /* category, action */
8762         {
8763                 u8 category, action;
8764                 category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;
8765                 action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;
8766
8767                 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
8768                 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
8769         }
8770
8771         pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0);
8772         pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen),
8773                 hal_ch_offset_to_secondary_ch_offset(ch_offset));
8774
8775         pattrib->last_txcmdsz = pattrib->pktlen;
8776
8777         dump_mgntframe(padapter, pmgntframe);
8778
8779 }
8780
8781 #ifdef CONFIG_IEEE80211W
8782 void issue_action_SA_Query(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid)
8783 {
8784         u8      category = RTW_WLAN_CATEGORY_SA_QUERY;
8785         u16     reason_code;
8786         struct xmit_frame               *pmgntframe;
8787         struct pkt_attrib               *pattrib;
8788         u8                                      *pframe;
8789         struct rtw_ieee80211_hdr        *pwlanhdr;
8790         u16                                     *fctrl;
8791         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
8792         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8793         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8794         struct sta_info         *psta;
8795         struct sta_priv         *pstapriv = &padapter->stapriv;
8796         struct registry_priv            *pregpriv = &padapter->registrypriv;
8797
8798
8799         DBG_871X("%s\n", __FUNCTION__);
8800
8801         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8802         {
8803                 DBG_871X("%s: alloc_mgtxmitframe fail\n", __FUNCTION__);
8804                 return;
8805         }
8806
8807         //update attribute
8808         pattrib = &pmgntframe->attrib;
8809         update_mgntframe_attrib(padapter, pattrib);
8810
8811         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8812
8813         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8814         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8815
8816         fctrl = &(pwlanhdr->frame_ctl);
8817         *(fctrl) = 0;
8818
8819         if(raddr)
8820                 _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
8821         else
8822                 _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8823         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8824         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8825
8826         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8827         pmlmeext->mgnt_seq++;
8828         SetFrameSubType(pframe, WIFI_ACTION);
8829
8830         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8831         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8832
8833         pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
8834         pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
8835
8836         switch (action)
8837         {
8838                 case 0: //SA Query req
8839                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);
8840                         pmlmeext->sa_query_seq++;
8841                         //send sa query request to AP, AP should reply sa query response in 1 second
8842                         set_sa_query_timer(pmlmeext, 1000);
8843                         break;
8844
8845                 case 1: //SA Query rsp
8846                         tid = cpu_to_le16(tid);
8847                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&tid, &pattrib->pktlen);
8848                         break;
8849                 default:
8850                         break;
8851         }
8852
8853         pattrib->last_txcmdsz = pattrib->pktlen;
8854
8855         dump_mgntframe(padapter, pmgntframe);
8856 }
8857 #endif //CONFIG_IEEE80211W
8858
8859 void issue_action_BA(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
8860 {
8861         u8      category = RTW_WLAN_CATEGORY_BACK;
8862         u16     start_seq;
8863         u16     BA_para_set;
8864         u16     reason_code;
8865         u16     BA_timeout_value;
8866         u16     BA_starting_seqctrl;
8867         u32 max_rx_ampdu_factor;
8868         struct xmit_frame               *pmgntframe;
8869         struct pkt_attrib               *pattrib;
8870         u8                                      *pframe;
8871         struct rtw_ieee80211_hdr        *pwlanhdr;
8872         u16                                     *fctrl;
8873         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
8874         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8875         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8876         struct sta_info         *psta;
8877         struct sta_priv         *pstapriv = &padapter->stapriv;
8878         struct registry_priv            *pregpriv = &padapter->registrypriv;
8879
8880 #ifdef CONFIG_80211N_HT
8881         DBG_871X("%s, category=%d, action=%d, status=%d\n", __FUNCTION__, category, action, status);
8882
8883         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8884         {
8885                 return;
8886         }
8887
8888         //update attribute
8889         pattrib = &pmgntframe->attrib;
8890         update_mgntframe_attrib(padapter, pattrib);
8891
8892         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8893
8894         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8895         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8896
8897         fctrl = &(pwlanhdr->frame_ctl);
8898         *(fctrl) = 0;
8899
8900         //_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8901         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
8902         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8903         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8904
8905         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8906         pmlmeext->mgnt_seq++;
8907         SetFrameSubType(pframe, WIFI_ACTION);
8908
8909         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8910         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8911
8912         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
8913         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
8914
8915       status = cpu_to_le16(status);
8916         
8917
8918         if (category == 3)
8919         {
8920                 switch (action)
8921                 {
8922                         case 0: //ADDBA req
8923                                 do {
8924                                         pmlmeinfo->dialogToken++;
8925                                 } while (pmlmeinfo->dialogToken == 0);
8926                                 pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
8927
8928 #ifdef CONFIG_BT_COEXIST
8929                                 if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(padapter) == _TRUE)
8930                                 {
8931                                         // A-MSDU NOT Supported
8932                                         BA_para_set = 0;
8933                                         // immediate Block Ack
8934                                         BA_para_set |= (1 << 1) & IEEE80211_ADDBA_PARAM_POLICY_MASK;
8935                                         // TID
8936                                         BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
8937                                         // max buffer size is 8 MSDU
8938                                         BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
8939                                 }
8940                                 else
8941 #endif
8942                                 {
8943                                         #if defined(CONFIG_RTL8188E) && defined(CONFIG_SDIO_HCI)
8944                                         BA_para_set = (0x0802 | ((status & 0xf) << 2)); //immediate ack & 16 buffer size
8945                                         #else
8946                                         BA_para_set = (0x1002 | ((status & 0xf) << 2)); //immediate ack & 64 buffer size
8947                                         #endif
8948                                 }
8949                                 //sys_mib.BA_para_set = 0x0802; //immediate ack & 32 buffer size
8950                                 BA_para_set = cpu_to_le16(BA_para_set);
8951                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
8952
8953                                 //BA_timeout_value = 0xffff;//max: 65535 TUs(~ 65 ms)
8954                                 BA_timeout_value = 5000;//~ 5ms
8955                                 BA_timeout_value = cpu_to_le16(BA_timeout_value);
8956                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_timeout_value)), &(pattrib->pktlen));
8957
8958                                 //if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
8959                                 if ((psta = rtw_get_stainfo(pstapriv, raddr)) != NULL)
8960                                 {
8961                                         start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
8962
8963                                         DBG_871X("BA_starting_seqctrl = %d for TID=%d\n", start_seq, status & 0x07);
8964                                         
8965                                         psta->BA_starting_seqctrl[status & 0x07] = start_seq;
8966                                         
8967                                         BA_starting_seqctrl = start_seq << 4;
8968                                 }
8969                                 
8970                                 BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl);
8971                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_starting_seqctrl)), &(pattrib->pktlen));
8972                                 break;
8973
8974                         case 1: //ADDBA rsp
8975                                 pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
8976                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
8977                                 /*
8978                                 //BA_para_set = cpu_to_le16((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); //64 buffer size
8979                                 #if defined(CONFIG_RTL8188E )&& defined (CONFIG_SDIO_HCI)
8980                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); //32buffer size
8981                                 #else
8982                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); //64 buffer size
8983                                 #endif
8984                                 */
8985                                 rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
8986                                 if(MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)
8987                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); //64 buffer size
8988                                 else if(MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)
8989                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); //32 buffer size
8990                                 else if(MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)
8991                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); //16 buffer size
8992                                 else if(MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)
8993                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); //8 buffer size
8994                                 else
8995                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); //64 buffer size       
8996
8997 #ifdef CONFIG_BT_COEXIST
8998                                 if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(padapter) == _TRUE)
8999                                 {
9000                                         // max buffer size is 8 MSDU
9001                                         BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
9002                                         BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
9003                                 }
9004 #endif
9005
9006                                 if(pregpriv->ampdu_amsdu==0)//disabled
9007                                         BA_para_set = cpu_to_le16(BA_para_set & ~BIT(0));
9008                                 else if(pregpriv->ampdu_amsdu==1)//enabled
9009                                         BA_para_set = cpu_to_le16(BA_para_set | BIT(0));
9010                                 else //auto
9011                                         BA_para_set = cpu_to_le16(BA_para_set);
9012                                 
9013                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
9014                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
9015                                 break;
9016                         case 2://DELBA
9017                                 BA_para_set = (status & 0x1F) << 3;
9018                                 BA_para_set = cpu_to_le16(BA_para_set);                         
9019                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
9020
9021                                 reason_code = 37;//Requested from peer STA as it does not want to use the mechanism
9022                                 reason_code = cpu_to_le16(reason_code);
9023                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(reason_code)), &(pattrib->pktlen));
9024                                 break;
9025                         default:
9026                                 break;
9027                 }
9028         }
9029
9030         pattrib->last_txcmdsz = pattrib->pktlen;
9031
9032         dump_mgntframe(padapter, pmgntframe);
9033 #endif //CONFIG_80211N_HT
9034 }
9035
9036 static void issue_action_BSSCoexistPacket(_adapter *padapter)
9037 {       
9038         _irqL   irqL;
9039         _list           *plist, *phead;
9040         unsigned char category, action;
9041         struct xmit_frame                       *pmgntframe;
9042         struct pkt_attrib                       *pattrib;
9043         unsigned char                           *pframe;
9044         struct rtw_ieee80211_hdr        *pwlanhdr;
9045         unsigned short                  *fctrl;
9046         struct  wlan_network    *pnetwork = NULL;
9047         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
9048         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
9049         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
9050         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9051         _queue          *queue  = &(pmlmepriv->scanned_queue);
9052         u8 InfoContent[16] = {0};
9053         u8 ICS[8][15];
9054 #ifdef CONFIG_80211N_HT 
9055         if((pmlmepriv->num_FortyMHzIntolerant==0) || (pmlmepriv->num_sta_no_ht==0))
9056                 return;
9057
9058         if(_TRUE == pmlmeinfo->bwmode_updated)
9059                 return;
9060         
9061
9062         DBG_871X("%s\n", __FUNCTION__);
9063
9064
9065         category = RTW_WLAN_CATEGORY_PUBLIC;
9066         action = ACT_PUBLIC_BSSCOEXIST;
9067
9068         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
9069         {
9070                 return;
9071         }
9072
9073         //update attribute
9074         pattrib = &pmgntframe->attrib;
9075         update_mgntframe_attrib(padapter, pattrib);
9076
9077         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
9078
9079         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
9080         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
9081
9082         fctrl = &(pwlanhdr->frame_ctl);
9083         *(fctrl) = 0;
9084
9085         _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
9086         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
9087         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
9088
9089         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
9090         pmlmeext->mgnt_seq++;
9091         SetFrameSubType(pframe, WIFI_ACTION);
9092
9093         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
9094         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
9095
9096         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
9097         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
9098
9099
9100         //
9101         if(pmlmepriv->num_FortyMHzIntolerant>0)
9102         {
9103                 u8 iedata=0;
9104                 
9105                 iedata |= BIT(2);//20 MHz BSS Width Request
9106
9107                 pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));
9108                 
9109         }
9110         
9111
9112         //
9113         _rtw_memset(ICS, 0, sizeof(ICS));
9114         if(pmlmepriv->num_sta_no_ht>0)
9115         {       
9116                 int i;
9117         
9118                 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
9119
9120                 phead = get_list_head(queue);
9121                 plist = get_next(phead);
9122        
9123                 while(1)
9124                 {
9125                         int len;
9126                         u8 *p;
9127                         WLAN_BSSID_EX *pbss_network;
9128         
9129                         if (rtw_end_of_queue_search(phead,plist)== _TRUE)
9130                                 break;          
9131
9132                         pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);      
9133                 
9134                         plist = get_next(plist);
9135
9136                         pbss_network = (WLAN_BSSID_EX *)&pnetwork->network;
9137
9138                         p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
9139                         if((p==NULL) || (len==0))//non-HT
9140                         {
9141                                 if((pbss_network->Configuration.DSConfig<=0) || (pbss_network->Configuration.DSConfig>14))
9142                                         continue;
9143                                 
9144                                 ICS[0][pbss_network->Configuration.DSConfig]=1;
9145                                 
9146                                 if(ICS[0][0] == 0)
9147                                         ICS[0][0] = 1;          
9148                         }               
9149         
9150                 }        
9151
9152                 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
9153
9154
9155                 for(i= 0;i<8;i++)
9156                 {
9157                         if(ICS[i][0] == 1)
9158                         {
9159                                 int j, k = 0;
9160                                 
9161                                 InfoContent[k] = i;                             
9162                                 //SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent,i);
9163                                 k++;
9164                                 
9165                                 for(j=1;j<=14;j++)
9166                                 {
9167                                         if(ICS[i][j]==1)
9168                                         {
9169                                                 if(k<16)
9170                                                 {
9171                                                         InfoContent[k] = j; //channel number
9172                                                         //SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j);
9173                                                         k++;
9174                                                 }       
9175                                         }       
9176                                 }       
9177
9178                                 pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
9179                                 
9180                         }
9181                         
9182                 }
9183                 
9184
9185         }
9186                 
9187
9188         pattrib->last_txcmdsz = pattrib->pktlen;
9189
9190         dump_mgntframe(padapter, pmgntframe);
9191 #endif //CONFIG_80211N_HT
9192 }
9193
9194 unsigned int send_delba(_adapter *padapter, u8 initiator, u8 *addr)
9195 {
9196         struct sta_priv *pstapriv = &padapter->stapriv;
9197         struct sta_info *psta = NULL;
9198         //struct recv_reorder_ctrl *preorder_ctrl;
9199         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9200         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9201         u16 tid;
9202
9203         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 
9204                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
9205                         return _SUCCESS;
9206         
9207         psta = rtw_get_stainfo(pstapriv, addr);
9208         if(psta==NULL)
9209                 return _SUCCESS;
9210
9211         //DBG_871X("%s:%s\n", __FUNCTION__, (initiator==0)?"RX_DIR":"TX_DIR");
9212         
9213         if(initiator==0) // recipient
9214         {
9215                 for(tid = 0;tid<MAXTID;tid++)
9216                 {
9217                         if(psta->recvreorder_ctrl[tid].enable == _TRUE)
9218                         {
9219                                 DBG_871X("rx agg disable tid(%d)\n",tid);
9220                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
9221                                 psta->recvreorder_ctrl[tid].enable = _FALSE;
9222                                 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
9223                                 #ifdef DBG_RX_SEQ
9224                                 DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u \n", __FUNCTION__, __LINE__,
9225                                         psta->recvreorder_ctrl[tid].indicate_seq);
9226                                 #endif
9227                         }               
9228                 }
9229         }
9230         else if(initiator == 1)// originator
9231         {
9232 #ifdef CONFIG_80211N_HT
9233                 //DBG_871X("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap);
9234                 for(tid = 0;tid<MAXTID;tid++)
9235                 {
9236                         if(psta->htpriv.agg_enable_bitmap & BIT(tid))
9237                         {
9238                                 DBG_871X("tx agg disable tid(%d)\n",tid);
9239                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F) );
9240                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
9241                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
9242                                 
9243                         }                       
9244                 }
9245 #endif //CONFIG_80211N_HT
9246         }
9247         
9248         return _SUCCESS;
9249         
9250 }
9251
9252 unsigned int send_beacon(_adapter *padapter)
9253 {
9254         u8      bxmitok = _FALSE;
9255         int     issue=0;
9256         int poll = 0;
9257 //#ifdef CONFIG_CONCURRENT_MODE
9258         //struct mlme_ext_priv  *pmlmeext = &(padapter->mlmeextpriv);
9259         //struct mlme_ext_info  *pmlmeinfo = &(pmlmeext->mlmext_info);
9260         //_adapter *pbuddy_adapter = padapter->pbuddy_adapter;
9261         //struct mlme_priv *pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
9262 //#endif                
9263
9264 #ifdef CONFIG_PCI_HCI
9265
9266         //DBG_871X("%s\n", __FUNCTION__);
9267
9268         issue_beacon(padapter, 0);
9269
9270         return _SUCCESS;
9271
9272 #endif
9273
9274 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
9275         u32 start = rtw_get_current_time();
9276
9277         rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
9278         rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
9279         do{
9280                 issue_beacon(padapter, 100);
9281                 issue++;
9282                 do {
9283                         rtw_yield_os();
9284                         rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
9285                         poll++;
9286                 }while((poll%10)!=0 && _FALSE == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
9287
9288         }while(_FALSE == bxmitok && issue<100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
9289
9290         if(padapter->bSurpriseRemoved || padapter->bDriverStopped)
9291         {
9292                 return _FAIL;
9293         }
9294
9295         
9296         if(_FALSE == bxmitok)
9297         {
9298                 DBG_871X("%s fail! %u ms\n", __FUNCTION__, rtw_get_passing_time_ms(start));
9299                 return _FAIL;
9300         }
9301         else
9302         {
9303                 u32 passing_time = rtw_get_passing_time_ms(start);
9304
9305                 if(passing_time > 100 || issue > 3)
9306                         DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));
9307                 //else
9308                 //      DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));
9309                 
9310                 return _SUCCESS;
9311         }
9312
9313 #endif
9314
9315 }
9316
9317 /****************************************************************************
9318
9319 Following are some utitity fuctions for WiFi MLME
9320
9321 *****************************************************************************/
9322
9323 BOOLEAN IsLegal5GChannel(
9324         IN PADAPTER                     Adapter,
9325         IN u8                   channel)
9326 {
9327         
9328         int i=0;
9329         u8 Channel_5G[45] = {36,38,40,42,44,46,48,50,52,54,56,58,
9330                 60,62,64,100,102,104,106,108,110,112,114,116,118,120,122,
9331                 124,126,128,130,132,134,136,138,140,149,151,153,155,157,159,
9332                 161,163,165};
9333         for(i=0;i<sizeof(Channel_5G);i++)
9334                 if(channel == Channel_5G[i])
9335                         return _TRUE;
9336         return _FALSE;
9337 }
9338
9339 void site_survey(_adapter *padapter)
9340 {
9341         unsigned char           survey_channel = 0, val8;
9342         RT_SCAN_TYPE    ScanType = SCAN_PASSIVE;
9343         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9344         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9345         u32 initialgain = 0;
9346
9347 #ifdef CONFIG_P2P
9348
9349 #ifdef CONFIG_CONCURRENT_MODE
9350
9351 #if defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE) || defined(CONFIG_ATMEL_RC_PATCH) 
9352         u8 stay_buddy_ch = 0;
9353 #endif
9354         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
9355         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;                     
9356         struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
9357
9358 #endif //CONFIG_CONCURRENT_MODE
9359         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
9360         static unsigned char  prev_survey_channel = 0;
9361         static unsigned int p2p_scan_count = 0; 
9362         
9363         if ( ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) || ( pwdinfo->p2p_info.scan_op_ch_only ) )
9364         {
9365                 if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
9366                 {
9367                         survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
9368                 }
9369                 else
9370                 {
9371                         survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
9372                 }
9373                 ScanType = SCAN_ACTIVE;
9374         }
9375         else if(rtw_p2p_findphase_ex_is_social(pwdinfo))
9376         {
9377                 //      Commented by Albert 2011/06/03
9378                 //      The driver is in the find phase, it should go through the social channel.
9379                 int ch_set_idx;
9380                 survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
9381                 ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, survey_channel);
9382                 if (ch_set_idx >= 0)
9383                         ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
9384                 else
9385                         ScanType = SCAN_ACTIVE;
9386         }
9387         else
9388 #endif //CONFIG_P2P
9389         {
9390                 struct rtw_ieee80211_channel *ch;
9391                 if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
9392                         ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
9393                         survey_channel = ch->hw_value;
9394                         ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
9395                 }
9396         }
9397         
9398         if (0){
9399 #ifdef CONFIG_P2P
9400                 DBG_871X(FUNC_ADPT_FMT" ch:%u (cnt:%u,idx:%d) at %dms, %c%c%c\n"
9401                 , FUNC_ADPT_ARG(padapter)
9402                 , survey_channel
9403                 , pwdinfo->find_phase_state_exchange_cnt, pmlmeext->sitesurvey_res.channel_idx
9404                 , rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
9405                 , ScanType?'A':'P', pmlmeext->sitesurvey_res.scan_mode?'A':'P'
9406                 , pmlmeext->sitesurvey_res.ssid[0].SsidLength?'S':' ' 
9407                 );
9408 #else
9409                 DBG_871X(FUNC_ADPT_FMT" ch:%u (cnt:%u) at %dms, %c%c%c\n"
9410                 , FUNC_ADPT_ARG(padapter)
9411                 , survey_channel
9412                 , pmlmeext->sitesurvey_res.channel_idx
9413                 , rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
9414                 , ScanType?'A':'P', pmlmeext->sitesurvey_res.scan_mode?'A':'P'
9415                 , pmlmeext->sitesurvey_res.ssid[0].SsidLength?'S':' '
9416                 );
9417 #endif // CONFIG_P2P
9418                 #ifdef DBG_FIXED_CHAN
9419                 DBG_871X(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan);
9420                 #endif
9421         }
9422
9423         if(survey_channel != 0)
9424         {
9425                 //PAUSE 4-AC Queue when site_survey
9426                 //rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8));
9427                 //val8 |= 0x0f;
9428                 //rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8));
9429 #if defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE) || defined(CONFIG_ATMEL_RC_PATCH)
9430                 if ((padapter->pbuddy_adapter->mlmeextpriv.mlmext_info.state&0x03) == WIFI_FW_AP_STATE) {
9431                         if (pmlmeinfo->scan_cnt == RTW_SCAN_NUM_OF_CH) {
9432                                 if (pmlmeinfo->backop_cnt == 0)
9433                                         stay_buddy_ch = 1;
9434                                 else if (pmlmeinfo->backop_cnt == RTW_STAY_AP_CH_MILLISECOND)
9435                                         stay_buddy_ch = 2;
9436
9437                                 if (stay_buddy_ch == 2) {
9438                                         pmlmeinfo->scan_cnt = 1;
9439                                         pmlmeinfo->backop_cnt = 0;
9440                                 } else if (stay_buddy_ch == 1) {
9441                                         pmlmeinfo->backop_cnt++;
9442                                         survey_channel = pbuddy_mlmeext->cur_channel;
9443                                 } else {
9444                                         pmlmeinfo->backop_cnt++;
9445                                         set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
9446                                         return; 
9447                                 }
9448                         } else {
9449                                 pmlmeinfo->scan_cnt++;
9450                         }
9451                 }
9452 #endif
9453                 if(pmlmeext->sitesurvey_res.channel_idx == 0)
9454                 {
9455 #ifdef DBG_FIXED_CHAN
9456                         if(pmlmeext->fixed_chan !=0xff)
9457                                 set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
9458                         else    
9459 #endif
9460                                 set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
9461                 }
9462                 else
9463                 {
9464 #ifdef DBG_FIXED_CHAN
9465                         if(pmlmeext->fixed_chan!=0xff)
9466                                 SelectChannel(padapter, pmlmeext->fixed_chan);
9467                         else    
9468 #endif
9469                                 SelectChannel(padapter, survey_channel);
9470                 }
9471
9472 #if defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE) || defined(CONFIG_ATMEL_RC_PATCH) 
9473                 if( stay_buddy_ch == 1 )
9474                 {
9475                         val8 = 0; //survey done
9476                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
9477
9478                         if(check_buddy_mlmeinfo_state(padapter, WIFI_FW_AP_STATE) &&
9479                                 check_buddy_fwstate(padapter, _FW_LINKED))
9480                         {
9481                                 update_beacon(padapter->pbuddy_adapter, 0, NULL, _TRUE);
9482                         }
9483                 }
9484                 else if( stay_buddy_ch == 2 )
9485                 {
9486                         val8 = 1; //under site survey
9487                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
9488                 }
9489 #endif
9490
9491                 if(ScanType == SCAN_ACTIVE) //obey the channel plan setting...
9492                 {
9493                         #ifdef CONFIG_P2P
9494                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || 
9495                                 rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)
9496                         )
9497                         {
9498                                 issue_probereq_p2p(padapter, NULL);
9499                                 issue_probereq_p2p(padapter, NULL);
9500                                 issue_probereq_p2p(padapter, NULL);
9501                         }
9502                         else
9503                         #endif //CONFIG_P2P
9504                         {
9505                                 int i;
9506                                 for(i=0;i<RTW_SSID_SCAN_AMOUNT;i++){
9507                                         if(pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
9508                                                 /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
9509                                                 if (padapter->registrypriv.wifi_spec)
9510                                                         issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
9511                                                 else
9512                                                         issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
9513                                                 issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
9514                                         }
9515                                 }
9516
9517                                 if(pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
9518                                         /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
9519                                         if (padapter->registrypriv.wifi_spec)
9520                                                 issue_probereq(padapter, NULL, NULL);
9521                                         else
9522                                                 issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
9523                                         issue_probereq(padapter, NULL, NULL);
9524                                 }
9525                         }
9526                 }
9527 #if  defined(CONFIG_ATMEL_RC_PATCH)
9528                 // treat wlan0 & p2p0 in same way, may be changed in near feature.
9529                 // assume home channel is 6, channel switch sequence will be 
9530                 //      1,2-6-3,4-6-5,6-6-7,8-6-9,10-6-11,12-6-13,14
9531                 //if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)==_TRUE)
9532
9533                 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
9534                         set_survey_timer(pmlmeext, 20);
9535                 else
9536                         set_survey_timer(pmlmeext, 40);
9537 #else
9538                 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
9539 #endif
9540         }
9541         else
9542         {
9543
9544                 //      channel number is 0 or this channel is not valid.
9545
9546 #ifdef CONFIG_CONCURRENT_MODE
9547                 u8 cur_channel;
9548                 u8 cur_bwmode;
9549                 u8 cur_ch_offset;
9550
9551                 if (rtw_get_ch_setting_union(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset) != 0)
9552                 {
9553                         if (0)
9554                         DBG_871X(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
9555                                 FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
9556                 }
9557                 #ifdef CONFIG_IOCTL_CFG80211
9558                 else if(padapter->pbuddy_adapter
9559                         && pbuddy_adapter->wdinfo.driver_interface == DRIVER_CFG80211
9560                         && adapter_wdev_data(pbuddy_adapter)->p2p_enabled
9561                         && rtw_p2p_chk_state(&pbuddy_adapter->wdinfo, P2P_STATE_LISTEN)
9562                         )
9563                 {
9564                         cur_channel = pbuddy_adapter->wdinfo.listen_channel;
9565                         cur_bwmode = pbuddy_mlmeext->cur_bwmode;
9566                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
9567                 }
9568                 #endif
9569                 else
9570                 {
9571                         cur_channel = pmlmeext->cur_channel;
9572                         cur_bwmode = pmlmeext->cur_bwmode;
9573                         cur_ch_offset = pmlmeext->cur_ch_offset;
9574                 }               
9575 #endif
9576
9577         
9578 #ifdef CONFIG_P2P
9579                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
9580                 {
9581                         if( ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) || ( pwdinfo->p2p_info.scan_op_ch_only ) )
9582                         {
9583                                 //      Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT.
9584                                 //      This will let the following flow to run the scanning end.
9585                                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
9586                         }
9587                         #ifdef CONFIG_DBG_P2P
9588                         DBG_871X( "[%s] find phase exchange cnt = %d\n", __FUNCTION__, pwdinfo->find_phase_state_exchange_cnt );
9589                         #endif
9590                 }
9591
9592                 if(rtw_p2p_findphase_ex_is_needed(pwdinfo))
9593                 {
9594                         //      Set the P2P State to the listen state of find phase and set the current channel to the listen channel
9595                         set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
9596                         rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
9597                         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
9598
9599                         initialgain = 0xff; //restore RX GAIN
9600                         rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 
9601                         //turn on dynamic functions
9602                         Restore_DM_Func_Flag(padapter);
9603                         //Switch_DM_Func(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, _TRUE);
9604                         
9605                         _set_timer( &pwdinfo->find_phase_timer, ( u32 ) ( ( u32 ) ( pwdinfo->listen_dwell ) * 100 ) );
9606                 }
9607                 else
9608 #endif //CONFIG_P2P
9609                 {
9610
9611 #if defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE) || defined(CONFIG_ATMEL_RC_PATCH) 
9612                         pmlmeinfo->scan_cnt = 0;
9613                         pmlmeinfo->backop_cnt = 0;
9614 #endif
9615
9616 #ifdef CONFIG_ANTENNA_DIVERSITY
9617                         // 20100721:Interrupt scan operation here.
9618                         // For SW antenna diversity before link, it needs to switch to another antenna and scan again.
9619                         // It compares the scan result and select beter one to do connection.
9620                         if(rtw_hal_antdiv_before_linked(padapter))
9621                         {                               
9622                                 pmlmeext->sitesurvey_res.bss_cnt = 0;
9623                                 pmlmeext->sitesurvey_res.channel_idx = -1;
9624                                 pmlmeext->chan_scan_time = SURVEY_TO /2;                        
9625                                 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
9626                                 return;
9627                         }
9628 #endif
9629
9630 #ifdef CONFIG_P2P
9631                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
9632                         {
9633                         #ifdef CONFIG_CONCURRENT_MODE
9634                                 if( pwdinfo->driver_interface == DRIVER_WEXT )
9635                                 {
9636                                         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
9637                                         {
9638                                                 _set_timer( &pwdinfo->ap_p2p_switch_timer, 500 );
9639                                         }
9640                                 }               
9641                                 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
9642                         #else
9643                                 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
9644                         #endif
9645                         }
9646                         rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
9647 #endif //CONFIG_P2P
9648                         
9649                         pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
9650
9651                         //switch back to the original channel
9652                         //SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset);
9653
9654                         {
9655 #ifdef CONFIG_CONCURRENT_MODE
9656                                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
9657 #else
9658 #ifdef CONFIG_DUALMAC_CONCURRENT
9659                                 dc_set_channel_bwmode_survey_done(padapter);
9660 #else
9661
9662 #ifdef CONFIG_P2P
9663                         if( (pwdinfo->driver_interface == DRIVER_WEXT) && (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) )
9664                                 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
9665                         else
9666 #endif //CONFIG_P2P
9667                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
9668
9669 #endif //CONFIG_DUALMAC_CONCURRENT
9670 #endif //CONFIG_CONCURRENT_MODE
9671                         }
9672
9673                         //flush 4-AC Queue after site_survey
9674                         //val8 = 0;
9675                         //rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8));
9676
9677                         //config MSR
9678                         Set_MSR(padapter, (pmlmeinfo->state & 0x3));
9679
9680                         initialgain = 0xff; //restore RX GAIN
9681                         rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 
9682                         //turn on dynamic functions
9683                         Restore_DM_Func_Flag(padapter);
9684                         //Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);
9685
9686                         if (is_client_associated_to_ap(padapter) == _TRUE)
9687                         {
9688                                 issue_nulldata(padapter, NULL, 0, 3, 500);
9689                                 
9690 #ifdef CONFIG_CONCURRENT_MODE
9691                                 if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
9692                                 {
9693                                         DBG_871X("adapter is surveydone(buddy_adapter is linked), issue nulldata(pwrbit=0)\n");
9694                                         
9695                                         issue_nulldata(padapter->pbuddy_adapter, NULL, 0, 3, 500);
9696                                 }
9697 #endif  
9698                         }
9699 #ifdef CONFIG_CONCURRENT_MODE
9700                         else if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
9701                         {
9702                                 issue_nulldata(padapter->pbuddy_adapter, NULL, 0, 3, 500);
9703                         }
9704 #endif  
9705
9706                         val8 = 0; //survey done
9707                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
9708
9709                         report_surveydone_event(padapter);
9710
9711                         pmlmeext->chan_scan_time = SURVEY_TO;
9712                         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
9713
9714                         issue_action_BSSCoexistPacket(padapter);
9715                         issue_action_BSSCoexistPacket(padapter);
9716                         issue_action_BSSCoexistPacket(padapter);
9717
9718                 }
9719
9720 #ifdef CONFIG_CONCURRENT_MODE
9721                 if(check_buddy_mlmeinfo_state(padapter, WIFI_FW_AP_STATE) &&
9722                         check_buddy_fwstate(padapter, _FW_LINKED))
9723                 {
9724
9725                         DBG_871X("survey done, current CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
9726
9727                         DBG_871X("restart pbuddy_adapter's beacon\n");
9728                 
9729                         update_beacon(padapter->pbuddy_adapter, 0, NULL, _TRUE);
9730                 }
9731 #endif
9732
9733         }
9734
9735         return;
9736
9737 }
9738
9739 //collect bss info from Beacon and Probe request/response frames.
9740 u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSID_EX *bssid)
9741 {
9742         int     i;
9743         u32     len;
9744         u8      *p;
9745         u16     val16, subtype;
9746         u8      *pframe = precv_frame->u.hdr.rx_data;
9747         u32     packet_len = precv_frame->u.hdr.len;
9748         u8 ie_offset;
9749         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
9750         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9751         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9752
9753         len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
9754
9755         if (len > MAX_IE_SZ)
9756         {
9757                 //DBG_871X("IE too long for survey event\n");
9758                 return _FAIL;
9759         }
9760
9761         _rtw_memset(bssid, 0, sizeof(WLAN_BSSID_EX));
9762
9763         subtype = GetFrameSubType(pframe);
9764
9765         if(subtype==WIFI_BEACON) {
9766                 bssid->Reserved[0] = 1;
9767                 ie_offset = _BEACON_IE_OFFSET_;
9768         } else {
9769                 // FIXME : more type
9770                 if (subtype == WIFI_PROBERSP) {
9771                         ie_offset = _PROBERSP_IE_OFFSET_;
9772                         bssid->Reserved[0] = 3;
9773                 }
9774                 else if (subtype == WIFI_PROBEREQ) {
9775                         ie_offset = _PROBEREQ_IE_OFFSET_;
9776                         bssid->Reserved[0] = 2;
9777                 }
9778                 else {
9779                         bssid->Reserved[0] = 0;
9780                         ie_offset = _FIXED_IE_LENGTH_;
9781                 }
9782         }
9783                 
9784         bssid->Length = sizeof(WLAN_BSSID_EX) - MAX_IE_SZ + len;
9785
9786         //below is to copy the information element
9787         bssid->IELength = len;
9788         _rtw_memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
9789
9790         //get the signal strength
9791         //bssid->Rssi = precv_frame->u.hdr.attrib.SignalStrength; // 0-100 index.
9792         bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; // in dBM.raw data    
9793         bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;//in percentage 
9794         bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;//in percentage
9795 #ifdef CONFIG_ANTENNA_DIVERSITY
9796         //rtw_hal_get_hwreg(padapter, HW_VAR_CURRENT_ANTENNA, (u8 *)(&bssid->PhyInfo.Optimum_antenna));
9797         rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA,  &bssid->PhyInfo.Optimum_antenna);
9798 #endif
9799
9800         // checking SSID
9801         if ((p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset)) == NULL)
9802         {
9803                 DBG_871X("marc: cannot find SSID for survey event\n");
9804                 return _FAIL;
9805         }
9806
9807         if (*(p + 1))
9808         {
9809                 if (len > NDIS_802_11_LENGTH_SSID)
9810                 {
9811                         DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
9812                         return _FAIL;
9813                 }
9814                 _rtw_memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
9815                 bssid->Ssid.SsidLength = *(p + 1);
9816         }
9817         else
9818         {
9819                 bssid->Ssid.SsidLength = 0;
9820         }
9821
9822         _rtw_memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
9823
9824         //checking rate info...
9825         i = 0;
9826         p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
9827         if (p != NULL)
9828         {
9829                 if (len > NDIS_802_11_LENGTH_RATES_EX)
9830                 {
9831                         DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
9832                         return _FAIL;
9833                 }
9834                 _rtw_memcpy(bssid->SupportedRates, (p + 2), len);
9835                 i = len;
9836         }
9837
9838         p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
9839         if (p != NULL)
9840         {
9841                 if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
9842                 {
9843                         DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
9844                         return _FAIL;
9845                 }
9846                 _rtw_memcpy(bssid->SupportedRates + i, (p + 2), len);
9847         }
9848
9849         //todo:
9850 #if 0
9851         if (judge_network_type(bssid->SupportedRates, (len + i)) == WIRELESS_11B)
9852         {
9853                 bssid->NetworkTypeInUse = Ndis802_11DS;
9854         }
9855         else
9856 #endif
9857         {
9858                 bssid->NetworkTypeInUse = Ndis802_11OFDM24;
9859         }
9860
9861 #ifdef CONFIG_P2P
9862         if (subtype == WIFI_PROBEREQ)
9863         {
9864                 u8 *p2p_ie;
9865                 u32     p2p_ielen;
9866                 // Set Listion Channel
9867                 if ((p2p_ie = rtw_get_p2p_ie(bssid->IEs, bssid->IELength, NULL, &p2p_ielen)))
9868                 {
9869                         u32     attr_contentlen = 0;
9870                         u8 listen_ch[5] = { 0x00 };
9871
9872                         if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, listen_ch, &attr_contentlen) != NULL)
9873                                 bssid->Configuration.DSConfig = listen_ch[4];
9874                         else
9875                                 return _FALSE; // Intel device maybe no bring Listen Channel
9876                 } else
9877                 { // use current channel
9878                         bssid->Configuration.DSConfig = padapter->mlmeextpriv.cur_channel;
9879                         DBG_871X("%s()-%d: Cannot get p2p_ie. set DSconfig to op_ch(%d)\n", __FUNCTION__, __LINE__, bssid->Configuration.DSConfig);
9880                 }
9881
9882                 // FIXME
9883                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
9884                 _rtw_memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
9885                 bssid->Privacy = 1;
9886                 return _SUCCESS;
9887         }
9888 #endif //CONFIG_P2P
9889
9890         if (bssid->IELength < 12)
9891                 return _FAIL;
9892
9893         // Checking for DSConfig
9894         p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
9895
9896         bssid->Configuration.DSConfig = 0;
9897         bssid->Configuration.Length = 0;
9898
9899         if (p)
9900         {
9901                 bssid->Configuration.DSConfig = *(p + 2);
9902         }
9903         else
9904         {// In 5G, some ap do not have DSSET IE
9905                 // checking HT info for channel
9906                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
9907                 if(p)
9908                 {
9909                         struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
9910                         bssid->Configuration.DSConfig = HT_info->primary_channel;
9911                 }
9912                 else
9913                 { // use current channel
9914                         bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
9915                 }
9916         }
9917
9918         _rtw_memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
9919         bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod);
9920
9921         val16 = rtw_get_capability((WLAN_BSSID_EX *)bssid);
9922
9923         if (val16 & BIT(0))
9924         {
9925                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
9926                 _rtw_memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
9927         }
9928         else
9929         {
9930                 bssid->InfrastructureMode = Ndis802_11IBSS;
9931                 _rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
9932         }
9933
9934         if (val16 & BIT(4))
9935                 bssid->Privacy = 1;
9936         else
9937                 bssid->Privacy = 0;
9938
9939         bssid->Configuration.ATIMWindow = 0;
9940
9941         //20/40 BSS Coexistence check
9942         if((pregistrypriv->wifi_spec==1) && (_FALSE == pmlmeinfo->bwmode_updated))
9943         {       
9944                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
9945 #ifdef CONFIG_80211N_HT
9946                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
9947                 if(p && len>0)
9948                 {
9949                         struct HT_caps_element  *pHT_caps;
9950                         pHT_caps = (struct HT_caps_element      *)(p + 2);
9951                         
9952                         if(pHT_caps->u.HT_cap_element.HT_caps_info&BIT(14))
9953                         {                               
9954                                 pmlmepriv->num_FortyMHzIntolerant++;
9955                         }
9956                 }
9957                 else
9958                 {
9959                         pmlmepriv->num_sta_no_ht++;
9960                 }
9961 #endif //CONFIG_80211N_HT
9962                 
9963         }
9964
9965 #ifdef CONFIG_INTEL_WIDI
9966         //process_intel_widi_query_or_tigger(padapter, bssid);
9967         if(process_intel_widi_query_or_tigger(padapter, bssid))
9968         {
9969                 return _FAIL;
9970         }
9971 #endif // CONFIG_INTEL_WIDI
9972
9973         #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1
9974         if(strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
9975                 DBG_871X("Receiving %s("MAC_FMT", DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n"
9976                         , bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig
9977                         , rtw_get_oper_ch(padapter)
9978                         , bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi
9979                 );
9980         }
9981         #endif
9982
9983         // mark bss info receving from nearby channel as SignalQuality 101
9984         if(bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
9985         {
9986                 bssid->PhyInfo.SignalQuality= 101;
9987         }
9988
9989         return _SUCCESS;
9990 }
9991
9992 void start_create_ibss(_adapter* padapter)
9993 {
9994         unsigned short  caps;
9995         u8      val8;
9996         u8      join_type;
9997         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9998         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9999         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
10000         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
10001         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
10002
10003         //update wireless mode
10004         update_wireless_mode(padapter);
10005
10006         //udpate capability
10007         caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);
10008         update_capinfo(padapter, caps);
10009         if(caps&cap_IBSS)//adhoc master
10010         {
10011                 //set_opmode_cmd(padapter, adhoc);//removed
10012
10013                 val8 = 0xcf;
10014                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
10015
10016                 rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
10017
10018                 //switch channel
10019                 //SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE);
10020                 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
10021
10022                 beacon_timing_control(padapter);
10023
10024                 //set msr to WIFI_FW_ADHOC_STATE
10025                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
10026                 Set_MSR(padapter, (pmlmeinfo->state & 0x3));
10027
10028                 //issue beacon
10029                 if(send_beacon(padapter)==_FAIL)
10030                 {
10031                         RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("issuing beacon frame fail....\n"));
10032
10033                         report_join_res(padapter, -1);
10034                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
10035                 }
10036                 else
10037                 {
10038                         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
10039                         join_type = 0;
10040                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
10041
10042                         report_join_res(padapter, 1);
10043                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
10044                         rtw_indicate_connect(padapter);
10045                 }
10046         }
10047         else
10048         {
10049                 DBG_871X("start_create_ibss, invalid cap:%x\n", caps);
10050                 return;
10051         }
10052         //update bc/mc sta_info
10053         update_bmc_sta(padapter);
10054
10055 }
10056
10057 void start_clnt_join(_adapter* padapter)
10058 {
10059         unsigned short  caps;
10060         u8      val8;
10061         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10062         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10063         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
10064         int beacon_timeout;
10065
10066         //update wireless mode
10067         update_wireless_mode(padapter);
10068
10069         //udpate capability
10070         caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);
10071         update_capinfo(padapter, caps);
10072         if (caps&cap_ESS)
10073         {
10074                 Set_MSR(padapter, WIFI_FW_STATION_STATE);
10075
10076                 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
10077
10078 #ifdef CONFIG_WAPI_SUPPORT
10079                 if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI)
10080                 {
10081                         //Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey.
10082                         val8 = 0x4c;
10083                 }
10084 #endif
10085                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
10086
10087                 #ifdef CONFIG_DEAUTH_BEFORE_CONNECT
10088                 // Because of AP's not receiving deauth before
10089                 // AP may: 1)not response auth or 2)deauth us after link is complete
10090                 // issue deauth before issuing auth to deal with the situation
10091
10092                 //      Commented by Albert 2012/07/21
10093                 //      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it.
10094                 {
10095                         #ifdef CONFIG_P2P
10096                         _queue *queue = &(padapter->mlmepriv.scanned_queue);
10097                         _list   *head = get_list_head(queue);
10098                         _list *pos = get_next(head);
10099                         struct wlan_network *scanned = NULL;
10100                         u8 ie_offset = 0;
10101                         _irqL irqL;
10102                         bool has_p2p_ie = _FALSE;
10103
10104                         _enter_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL);
10105
10106                         for (pos = get_next(head);!rtw_end_of_queue_search(head, pos); pos = get_next(pos)) {
10107                                 
10108                                 scanned = LIST_CONTAINOR(pos, struct wlan_network, list);
10109                                 if(scanned==NULL)
10110                                         rtw_warn_on(1);
10111
10112                                 if (_rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE
10113                                         && _rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE
10114                                 ) {
10115                                         ie_offset = (scanned->network.Reserved[0] == 2? 0:12);
10116                                         if (rtw_get_p2p_ie(scanned->network.IEs+ie_offset, scanned->network.IELength-ie_offset, NULL, NULL))
10117                                                 has_p2p_ie = _TRUE;
10118                                         break;
10119                                 }
10120                         }
10121         
10122                         _exit_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL);
10123
10124                         if (scanned == NULL || rtw_end_of_queue_search(head, pos) || has_p2p_ie == _FALSE)
10125                         #endif /* CONFIG_P2P */
10126                                 //To avoid connecting to AP fail during resume process, change retry count from 5 to 1
10127                                 issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
10128                 }
10129                 #endif /* CONFIG_DEAUTH_BEFORE_CONNECT */
10130
10131                 //here wait for receiving the beacon to start auth
10132                 //and enable a timer
10133                 beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
10134                 set_link_timer(pmlmeext, beacon_timeout);       
10135                 _set_timer( &padapter->mlmepriv.assoc_timer, 
10136                         (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) +beacon_timeout);
10137                 
10138                 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
10139         }
10140         else if (caps&cap_IBSS) //adhoc client
10141         {
10142                 Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
10143
10144                 val8 = 0xcf;
10145                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
10146
10147                 beacon_timing_control(padapter);
10148
10149                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
10150
10151                 report_join_res(padapter, 1);
10152         }
10153         else
10154         {
10155                 //DBG_871X("marc: invalid cap:%x\n", caps);
10156                 return;
10157         }
10158
10159 }
10160
10161 void start_clnt_auth(_adapter* padapter)
10162 {
10163         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10164         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10165
10166         _cancel_timer_ex(&pmlmeext->link_timer);
10167
10168         pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
10169         pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
10170
10171         pmlmeinfo->auth_seq = 1;
10172         pmlmeinfo->reauth_count = 0;
10173         pmlmeinfo->reassoc_count = 0;
10174         pmlmeinfo->link_count = 0;
10175         pmlmeext->retry = 0;
10176
10177
10178         DBG_871X_LEVEL(_drv_always_, "start auth\n");
10179         issue_auth(padapter, NULL, 0);
10180
10181         set_link_timer(pmlmeext, REAUTH_TO);
10182
10183 }
10184
10185
10186 void start_clnt_assoc(_adapter* padapter)
10187 {
10188         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10189         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10190
10191         _cancel_timer_ex(&pmlmeext->link_timer);
10192
10193         pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
10194         pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
10195
10196         issue_assocreq(padapter);
10197
10198         set_link_timer(pmlmeext, REASSOC_TO);
10199 }
10200
10201 unsigned int receive_disconnect(_adapter *padapter, unsigned char *MacAddr, unsigned short reason)
10202 {
10203         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10204         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10205
10206         if (!(_rtw_memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
10207                 return _SUCCESS;
10208
10209         DBG_871X("%s\n", __FUNCTION__);
10210
10211         if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
10212         {
10213                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
10214                 {
10215                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
10216                         report_del_sta_event(padapter, MacAddr, reason);
10217
10218                 }
10219                 else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE)
10220                 {
10221                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
10222                         report_join_res(padapter, -2);
10223                 }
10224         }
10225
10226         return _SUCCESS;
10227 }
10228
10229 #ifdef CONFIG_80211D
10230 static void process_80211d(PADAPTER padapter, WLAN_BSSID_EX *bssid)
10231 {
10232         struct registry_priv *pregistrypriv;
10233         struct mlme_ext_priv *pmlmeext;
10234         RT_CHANNEL_INFO *chplan_new;
10235         u8 channel;
10236         u8 i;
10237
10238
10239         pregistrypriv = &padapter->registrypriv;
10240         pmlmeext = &padapter->mlmeextpriv;
10241
10242         // Adjust channel plan by AP Country IE
10243         if (pregistrypriv->enable80211d &&
10244                 (!pmlmeext->update_channel_plan_by_ap_done))
10245         {
10246                 u8 *ie, *p;
10247                 u32 len;
10248                 RT_CHANNEL_PLAN chplan_ap;
10249                 RT_CHANNEL_INFO chplan_sta[MAX_CHANNEL_NUM];
10250                 u8 country[4];
10251                 u8 fcn; // first channel number
10252                 u8 noc; // number of channel
10253                 u8 j, k;
10254
10255                 ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
10256                 if (!ie) return;
10257                 if (len < 6) return;
10258
10259                 ie += 2;
10260                 p = ie;
10261                 ie += len;
10262
10263                 _rtw_memset(country, 0, 4);
10264                 _rtw_memcpy(country, p, 3);
10265                 p += 3;
10266                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
10267                                 ("%s: 802.11d country=%s\n", __FUNCTION__, country));
10268
10269                 i = 0;
10270                 while ((ie - p) >= 3)
10271                 {
10272                         fcn = *(p++);
10273                         noc = *(p++);
10274                         p++;
10275
10276                         for (j = 0; j < noc; j++)
10277                         {
10278                                 if (fcn <= 14) channel = fcn + j; // 2.4 GHz
10279                                 else channel = fcn + j*4; // 5 GHz
10280
10281                                 chplan_ap.Channel[i++] = channel;
10282                         }
10283                 }
10284                 chplan_ap.Len = i;
10285
10286 #ifdef CONFIG_DEBUG_RTL871X
10287                 i = 0;
10288                 DBG_871X("%s: AP[%s] channel plan {", __FUNCTION__, bssid->Ssid.Ssid);
10289                 while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0))
10290                 {
10291                         DBG_8192C("%02d,", chplan_ap.Channel[i]);
10292                         i++;
10293                 }
10294                 DBG_871X("}\n");
10295 #endif
10296
10297                 _rtw_memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
10298 #ifdef CONFIG_DEBUG_RTL871X
10299                 i = 0;
10300                 DBG_871X("%s: STA channel plan {", __FUNCTION__);
10301                 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0))
10302                 {
10303                         DBG_871X("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType==SCAN_PASSIVE?'p':'a');
10304                         i++;
10305                 }
10306                 DBG_871X("}\n");
10307 #endif
10308
10309                 _rtw_memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
10310                 chplan_new = pmlmeext->channel_set;
10311
10312                 i = j = k = 0;
10313                 if (pregistrypriv->wireless_mode & WIRELESS_11G)
10314                 {
10315                         do {
10316                                 if ((i == MAX_CHANNEL_NUM) ||
10317                                         (chplan_sta[i].ChannelNum == 0) ||
10318                                         (chplan_sta[i].ChannelNum > 14))
10319                                         break;
10320
10321                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
10322                                         break;
10323
10324                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j])
10325                                 {
10326                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10327                                         chplan_new[k].ScanType = SCAN_ACTIVE;
10328                                         i++;
10329                                         j++;
10330                                         k++;
10331                                 }
10332                                 else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j])
10333                                 {
10334                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10335 //                                      chplan_new[k].ScanType = chplan_sta[i].ScanType;
10336                                         chplan_new[k].ScanType = SCAN_PASSIVE;
10337                                         i++;
10338                                         k++;
10339                                 }
10340                                 else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j])
10341                                 {
10342                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10343                                         chplan_new[k].ScanType = SCAN_ACTIVE;
10344                                         j++;
10345                                         k++;
10346                                 }
10347                         } while (1);
10348
10349                         // change AP not support channel to Passive scan
10350                         while ((i < MAX_CHANNEL_NUM) &&
10351                                 (chplan_sta[i].ChannelNum != 0) &&
10352                                 (chplan_sta[i].ChannelNum <= 14))
10353                         {
10354                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10355 //                              chplan_new[k].ScanType = chplan_sta[i].ScanType;
10356                                 chplan_new[k].ScanType = SCAN_PASSIVE;
10357                                 i++;
10358                                 k++;
10359                         }
10360
10361                         // add channel AP supported
10362                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
10363                         {
10364                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10365                                 chplan_new[k].ScanType = SCAN_ACTIVE;
10366                                 j++;
10367                                 k++;
10368                         }
10369                 }
10370                 else
10371                 {
10372                         // keep original STA 2.4G channel plan
10373                         while ((i < MAX_CHANNEL_NUM) &&
10374                                 (chplan_sta[i].ChannelNum != 0) &&
10375                                 (chplan_sta[i].ChannelNum <= 14))
10376                         {
10377                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10378                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
10379                                 i++;
10380                                 k++;
10381                         }
10382
10383                         // skip AP 2.4G channel plan
10384                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
10385                         {
10386                                 j++;
10387                         }
10388                 }
10389
10390                 if (pregistrypriv->wireless_mode & WIRELESS_11A)
10391                 {
10392                         do {
10393                                 if ((i == MAX_CHANNEL_NUM) ||
10394                                         (chplan_sta[i].ChannelNum == 0))
10395                                         break;
10396
10397                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
10398                                         break;
10399
10400                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j])
10401                                 {
10402                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10403                                         chplan_new[k].ScanType = SCAN_ACTIVE;
10404                                         i++;
10405                                         j++;
10406                                         k++;
10407                                 }
10408                                 else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j])
10409                                 {
10410                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10411 //                                      chplan_new[k].ScanType = chplan_sta[i].ScanType;
10412                                         chplan_new[k].ScanType = SCAN_PASSIVE;
10413                                         i++;
10414                                         k++;
10415                                 }
10416                                 else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j])
10417                                 {
10418                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10419                                         chplan_new[k].ScanType = SCAN_ACTIVE;
10420                                         j++;
10421                                         k++;
10422                                 }
10423                         } while (1);
10424
10425                         // change AP not support channel to Passive scan
10426                         while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0))
10427                         {
10428                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10429 //                              chplan_new[k].ScanType = chplan_sta[i].ScanType;
10430                                 chplan_new[k].ScanType = SCAN_PASSIVE;
10431                                 i++;
10432                                 k++;
10433                         }
10434
10435                         // add channel AP supported
10436                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0))
10437                         {
10438                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10439                                 chplan_new[k].ScanType = SCAN_ACTIVE;
10440                                 j++;
10441                                 k++;
10442                         }
10443                 }
10444                 else
10445                 {
10446                         // keep original STA 5G channel plan
10447                         while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0))
10448                         {
10449                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10450                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
10451                                 i++;
10452                                 k++;
10453                         }
10454                 }
10455
10456                 pmlmeext->update_channel_plan_by_ap_done = 1;
10457
10458 #ifdef CONFIG_DEBUG_RTL871X
10459                 k = 0;
10460                 DBG_871X("%s: new STA channel plan {", __FUNCTION__);
10461                 while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0))
10462                 {
10463                         DBG_871X("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType==SCAN_PASSIVE?'p':'c');
10464                         k++;
10465                 }
10466                 DBG_871X("}\n");
10467 #endif
10468
10469 #if 0
10470                 // recover the right channel index
10471                 channel = chplan_sta[pmlmeext->sitesurvey_res.channel_idx].ChannelNum;
10472                 k = 0;
10473                 while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0))
10474                 {
10475                         if (chplan_new[k].ChannelNum == channel) {
10476                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
10477                                                  ("%s: change mlme_ext sitesurvey channel index from %d to %d\n",
10478                                                   __FUNCTION__, pmlmeext->sitesurvey_res.channel_idx, k));
10479                                 pmlmeext->sitesurvey_res.channel_idx = k;
10480                                 break;
10481                         }
10482                         k++;
10483                 }
10484 #endif
10485         }
10486
10487         // If channel is used by AP, set channel scan type to active
10488         channel = bssid->Configuration.DSConfig;
10489         chplan_new = pmlmeext->channel_set;
10490         i = 0;
10491         while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0))
10492         {
10493                 if (chplan_new[i].ChannelNum == channel)
10494                 {
10495                         if (chplan_new[i].ScanType == SCAN_PASSIVE)
10496                         {
10497                                 //5G Bnad 2, 3 (DFS) doesn't change to active scan
10498                                 if(channel >= 52 && channel <= 144)
10499                                         break;
10500                                 
10501                                 chplan_new[i].ScanType = SCAN_ACTIVE;
10502                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
10503                                                  ("%s: change channel %d scan type from passive to active\n",
10504                                                   __FUNCTION__, channel));
10505                         }
10506                         break;
10507                 }
10508                 i++;
10509         }
10510 }
10511 #endif
10512
10513 /****************************************************************************
10514
10515 Following are the functions to report events
10516
10517 *****************************************************************************/
10518
10519 void report_survey_event(_adapter *padapter, union recv_frame *precv_frame)
10520 {
10521         struct cmd_obj *pcmd_obj;
10522         u8      *pevtcmd;
10523         u32 cmdsz;
10524         struct survey_event     *psurvey_evt;
10525         struct C2HEvent_Header *pc2h_evt_hdr;
10526         struct mlme_ext_priv *pmlmeext;
10527         struct cmd_priv *pcmdpriv;
10528         //u8 *pframe = precv_frame->u.hdr.rx_data;
10529         //uint len = precv_frame->u.hdr.len;
10530
10531         if(!padapter)
10532                 return;
10533
10534         pmlmeext = &padapter->mlmeextpriv;
10535         pcmdpriv = &padapter->cmdpriv;
10536         
10537
10538         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10539         {
10540                 return;
10541         }
10542
10543         cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
10544         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
10545         {
10546                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10547                 return;
10548         }
10549
10550         _rtw_init_listhead(&pcmd_obj->list);
10551
10552         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
10553         pcmd_obj->cmdsz = cmdsz;
10554         pcmd_obj->parmbuf = pevtcmd;
10555
10556         pcmd_obj->rsp = NULL;
10557         pcmd_obj->rspsz  = 0;
10558
10559         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
10560         pc2h_evt_hdr->len = sizeof(struct survey_event);
10561         pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
10562         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
10563
10564         psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
10565
10566         if (collect_bss_info(padapter, precv_frame, (WLAN_BSSID_EX *)&psurvey_evt->bss) == _FAIL)
10567         {
10568                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10569                 rtw_mfree((u8 *)pevtcmd, cmdsz);
10570                 return;
10571         }
10572
10573 #ifdef CONFIG_80211D
10574         process_80211d(padapter, &psurvey_evt->bss);
10575 #endif
10576
10577         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
10578
10579         pmlmeext->sitesurvey_res.bss_cnt++;
10580
10581         return;
10582
10583 }
10584
10585 void report_surveydone_event(_adapter *padapter)
10586 {
10587         struct cmd_obj *pcmd_obj;
10588         u8      *pevtcmd;
10589         u32 cmdsz;
10590         struct surveydone_event *psurveydone_evt;
10591         struct C2HEvent_Header  *pc2h_evt_hdr;
10592         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
10593         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
10594
10595         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10596         {
10597                 return;
10598         }
10599
10600         cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
10601         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
10602         {
10603                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10604                 return;
10605         }
10606
10607         _rtw_init_listhead(&pcmd_obj->list);
10608
10609         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
10610         pcmd_obj->cmdsz = cmdsz;
10611         pcmd_obj->parmbuf = pevtcmd;
10612
10613         pcmd_obj->rsp = NULL;
10614         pcmd_obj->rspsz  = 0;
10615
10616         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
10617         pc2h_evt_hdr->len = sizeof(struct surveydone_event);
10618         pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
10619         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
10620
10621         psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
10622         psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
10623
10624         DBG_871X("survey done event(%x) band:%d for "ADPT_FMT"\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter));
10625
10626         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
10627
10628         return;
10629
10630 }
10631
10632 void report_join_res(_adapter *padapter, int res)
10633 {
10634         struct cmd_obj *pcmd_obj;
10635         u8      *pevtcmd;
10636         u32 cmdsz;
10637         struct joinbss_event            *pjoinbss_evt;
10638         struct C2HEvent_Header  *pc2h_evt_hdr;
10639         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
10640         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10641         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
10642
10643         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10644         {
10645                 return;
10646         }
10647
10648         cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
10649         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
10650         {
10651                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10652                 return;
10653         }
10654
10655         _rtw_init_listhead(&pcmd_obj->list);
10656
10657         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
10658         pcmd_obj->cmdsz = cmdsz;
10659         pcmd_obj->parmbuf = pevtcmd;
10660
10661         pcmd_obj->rsp = NULL;
10662         pcmd_obj->rspsz  = 0;
10663
10664         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
10665         pc2h_evt_hdr->len = sizeof(struct joinbss_event);
10666         pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
10667         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
10668
10669         pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
10670         _rtw_memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));
10671         pjoinbss_evt->network.join_res  = pjoinbss_evt->network.aid = res;
10672
10673         DBG_871X("report_join_res(%d)\n", res);
10674         
10675         
10676         rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
10677         
10678         
10679         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
10680
10681         return;
10682
10683 }
10684
10685 void report_del_sta_event(_adapter *padapter, unsigned char* MacAddr, unsigned short reason)
10686 {
10687         struct cmd_obj *pcmd_obj;
10688         u8      *pevtcmd;
10689         u32 cmdsz;
10690         struct sta_info *psta;
10691         int     mac_id;
10692         struct stadel_event                     *pdel_sta_evt;
10693         struct C2HEvent_Header  *pc2h_evt_hdr;
10694         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
10695         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
10696
10697         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10698         {
10699                 return;
10700         }
10701
10702         cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
10703         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
10704         {
10705                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10706                 return;
10707         }
10708
10709         _rtw_init_listhead(&pcmd_obj->list);
10710
10711         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
10712         pcmd_obj->cmdsz = cmdsz;
10713         pcmd_obj->parmbuf = pevtcmd;
10714
10715         pcmd_obj->rsp = NULL;
10716         pcmd_obj->rspsz  = 0;
10717
10718         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
10719         pc2h_evt_hdr->len = sizeof(struct stadel_event);
10720         pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
10721         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
10722
10723         pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
10724         _rtw_memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
10725         _rtw_memcpy((unsigned char *)(pdel_sta_evt->rsvd),(unsigned char *)(&reason),2);
10726
10727
10728         psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
10729         if(psta)
10730                 mac_id = (int)psta->mac_id;     
10731         else
10732                 mac_id = (-1);
10733
10734         pdel_sta_evt->mac_id = mac_id;
10735
10736         DBG_871X("report_del_sta_event: delete STA, mac_id=%d\n", mac_id);
10737
10738         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
10739
10740         return;
10741 }
10742
10743 void report_add_sta_event(_adapter *padapter, unsigned char* MacAddr, int cam_idx)
10744 {
10745         struct cmd_obj *pcmd_obj;
10746         u8      *pevtcmd;
10747         u32 cmdsz;
10748         struct stassoc_event            *padd_sta_evt;
10749         struct C2HEvent_Header  *pc2h_evt_hdr;
10750         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
10751         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
10752
10753         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10754         {
10755                 return;
10756         }
10757
10758         cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
10759         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
10760         {
10761                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10762                 return;
10763         }
10764
10765         _rtw_init_listhead(&pcmd_obj->list);
10766
10767         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
10768         pcmd_obj->cmdsz = cmdsz;
10769         pcmd_obj->parmbuf = pevtcmd;
10770
10771         pcmd_obj->rsp = NULL;
10772         pcmd_obj->rspsz  = 0;
10773
10774         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
10775         pc2h_evt_hdr->len = sizeof(struct stassoc_event);
10776         pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
10777         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
10778
10779         padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
10780         _rtw_memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
10781         padd_sta_evt->cam_id = cam_idx;
10782
10783         DBG_871X("report_add_sta_event: add STA\n");
10784
10785         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
10786
10787         return;
10788 }
10789
10790
10791 bool rtw_port_switch_chk(_adapter *adapter)
10792 {
10793         bool switch_needed = _FALSE;
10794 #ifdef CONFIG_CONCURRENT_MODE
10795 #ifdef CONFIG_RUNTIME_PORT_SWITCH
10796         struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
10797         struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(dvobj);
10798         _adapter *if_port0 = NULL;
10799         _adapter *if_port1 = NULL;
10800         struct mlme_ext_info *if_port0_mlmeinfo = NULL;
10801         struct mlme_ext_info *if_port1_mlmeinfo = NULL;
10802         int i;
10803
10804         for (i = 0; i < dvobj->iface_nums; i++) {
10805                 if (get_iface_type(dvobj->padapters[i]) == IFACE_PORT0) {
10806                         if_port0 = dvobj->padapters[i];
10807                         if_port0_mlmeinfo = &(if_port0->mlmeextpriv.mlmext_info);
10808                 }
10809                 else if (get_iface_type(dvobj->padapters[i]) == IFACE_PORT1) {
10810                         if_port1 = dvobj->padapters[i];
10811                         if_port1_mlmeinfo = &(if_port1->mlmeextpriv.mlmext_info);
10812                 }
10813         }
10814
10815         if (if_port0 == NULL) {
10816                 rtw_warn_on(1);
10817                 goto exit;
10818         }
10819
10820         if (if_port1 == NULL) {
10821                 rtw_warn_on(1);
10822                 goto exit;
10823         }
10824
10825 #ifdef DBG_RUNTIME_PORT_SWITCH
10826         DBG_871X(FUNC_ADPT_FMT" wowlan_mode:%u\n"
10827                 ADPT_FMT", port0, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n"
10828                 ADPT_FMT", port1, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n",
10829                 FUNC_ADPT_ARG(adapter), pwrctl->wowlan_mode,
10830                 ADPT_ARG(if_port0), if_port0_mlmeinfo->state, rtw_p2p_state(&if_port0->wdinfo), rtw_p2p_chk_state(&if_port0->wdinfo, P2P_STATE_NONE),
10831                 ADPT_ARG(if_port1), if_port1_mlmeinfo->state, rtw_p2p_state(&if_port1->wdinfo), rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE));
10832 #endif /* DBG_RUNTIME_PORT_SWITCH */
10833
10834 #ifdef CONFIG_WOWLAN
10835         /* WOWLAN interface(primary, for now) should be port0 */
10836         if (pwrctl->wowlan_mode == _TRUE) {
10837                 if(!is_primary_adapter(if_port0)) {
10838                         DBG_871X("%s "ADPT_FMT" enable WOWLAN\n", __func__, ADPT_ARG(if_port1));
10839                         switch_needed = _TRUE;
10840                 }
10841                 goto exit;
10842         }
10843 #endif /* CONFIG_WOWLAN */
10844
10845         /* AP should use port0 for ctl frame's ack */
10846         if ((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
10847                 DBG_871X("%s "ADPT_FMT" is AP/GO\n", __func__, ADPT_ARG(if_port1));
10848                 switch_needed = _TRUE;
10849                 goto exit;
10850         }
10851
10852         /* GC should use port0 for p2p ps */    
10853         if (((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
10854                 && (if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
10855                 && !rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE)
10856                 && !check_fwstate(&if_port1->mlmepriv, WIFI_UNDER_WPS)
10857         ) {
10858                 DBG_871X("%s "ADPT_FMT" is GC\n", __func__, ADPT_ARG(if_port1));
10859                 switch_needed = _TRUE;
10860                 goto exit;
10861         }
10862
10863         /* port1 linked, but port0 not linked */
10864         if ((if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
10865                 && !(if_port0_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
10866                 && ((if_port0_mlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
10867         ) {
10868                 DBG_871X("%s "ADPT_FMT" is SINGLE_LINK\n", __func__, ADPT_ARG(if_port1));
10869                 switch_needed = _TRUE;
10870                 goto exit;
10871         }
10872
10873 exit:
10874 #ifdef DBG_RUNTIME_PORT_SWITCH
10875         DBG_871X(FUNC_ADPT_FMT" ret:%d\n", FUNC_ADPT_ARG(adapter), switch_needed);
10876 #endif /* DBG_RUNTIME_PORT_SWITCH */
10877 #endif /* CONFIG_RUNTIME_PORT_SWITCH */
10878 #endif /* CONFIG_CONCURRENT_MODE */
10879         return switch_needed;
10880 }
10881
10882 /****************************************************************************
10883
10884 Following are the event callback functions
10885
10886 *****************************************************************************/
10887
10888 //for sta/adhoc mode
10889 void update_sta_info(_adapter *padapter, struct sta_info *psta)
10890 {
10891         _irqL   irqL;
10892         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
10893         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10894         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10895
10896         //ERP
10897         VCS_update(padapter, psta);
10898
10899 #ifdef CONFIG_80211N_HT
10900         //HT
10901         if(pmlmepriv->htpriv.ht_option)
10902         {
10903                 psta->htpriv.ht_option = _TRUE;
10904
10905                 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
10906
10907                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))
10908                         psta->htpriv.sgi_20m = _TRUE;
10909
10910                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))
10911                         psta->htpriv.sgi_40m = _TRUE;
10912
10913                 psta->qos_option = _TRUE;
10914
10915                 psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;
10916                 psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;
10917                 psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
10918
10919                 _rtw_memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct rtw_ieee80211_ht_cap));
10920         }
10921         else
10922 #endif //CONFIG_80211N_HT
10923         {
10924 #ifdef CONFIG_80211N_HT
10925                 psta->htpriv.ht_option = _FALSE;
10926
10927                 psta->htpriv.ampdu_enable = _FALSE;
10928                 
10929                 psta->htpriv.sgi_20m = _FALSE;
10930                 psta->htpriv.sgi_40m = _FALSE;
10931 #endif //CONFIG_80211N_HT
10932                 psta->qos_option = _FALSE;
10933
10934         }
10935
10936 #ifdef CONFIG_80211N_HT
10937         psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
10938         
10939         psta->htpriv.agg_enable_bitmap = 0x0;//reset
10940         psta->htpriv.candidate_tid_bitmap = 0x0;//reset
10941 #endif //CONFIG_80211N_HT
10942
10943         psta->bw_mode = pmlmeext->cur_bwmode;
10944
10945         //QoS
10946         if(pmlmepriv->qospriv.qos_option)
10947                 psta->qos_option = _TRUE;
10948
10949 #ifdef CONFIG_80211AC_VHT
10950         _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));
10951 #endif //CONFIG_80211AC_VHT
10952
10953         update_ldpc_stbc_cap(psta);
10954
10955         _enter_critical_bh(&psta->lock, &irqL);
10956         psta->state = _FW_LINKED;
10957         _exit_critical_bh(&psta->lock, &irqL);
10958
10959 }
10960
10961 static void rtw_mlmeext_disconnect(_adapter *padapter)
10962 {
10963         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
10964         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10965         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10966         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
10967         u8 state_backup = (pmlmeinfo->state&0x03);
10968
10969         //set_opmode_cmd(padapter, infra_client_with_mlme);
10970
10971 #if 1
10972         /*
10973          * For safety, prevent from keeping macid sleep.
10974          * If we can sure all power mode enter/leave are paired,
10975          * this check can be removed.
10976          * Lucas@20131113
10977          */
10978         /* wakeup macid after disconnect. */
10979         {
10980                 struct sta_info *psta;
10981                 psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
10982                 if (psta)
10983                         rtw_hal_macid_wakeup(padapter, psta->mac_id);
10984         }
10985 #endif
10986
10987         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
10988         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
10989
10990         //set MSR to no link state -> infra. mode
10991         Set_MSR(padapter, _HW_STATE_STATION_);
10992
10993         pmlmeinfo->state = WIFI_FW_NULL_STATE;
10994
10995         if(state_backup == WIFI_FW_STATION_STATE)
10996         {
10997                 if (rtw_port_switch_chk(padapter) == _TRUE) {
10998                         rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
10999                         #ifdef CONFIG_LPS
11000                         {
11001                                 _adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
11002                                 if (port0_iface)
11003                                         rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
11004                         }
11005                         #endif
11006                 }
11007         }
11008
11009 #ifdef CONFIG_DUALMAC_CONCURRENT
11010         dc_set_channel_bwmode_disconnect(padapter);
11011 #else //!CONFIG_DUALMAC_CONCURRENT
11012 #ifdef CONFIG_CONCURRENT_MODE
11013         if((check_buddy_fwstate(padapter, _FW_LINKED)) != _TRUE)
11014         {
11015 #endif //CONFIG_CONCURRENT_MODE
11016                 //switch to the 20M Hz mode after disconnect
11017                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
11018                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
11019
11020                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
11021 #ifdef CONFIG_CONCURRENT_MODE
11022         }
11023 #endif //CONFIG_CONCURRENT_MODE
11024 #ifdef CONFIG_FCS_MODE
11025         else
11026         {
11027                 PADAPTER pbuddy_adapter;        
11028                 struct mlme_ext_priv *pbuddy_mlmeext;
11029
11030                 if(EN_FCS(padapter))
11031                 {                       
11032                         pbuddy_adapter = padapter->pbuddy_adapter;
11033                         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
11034                 
11035                         rtw_hal_set_hwreg(padapter, HW_VAR_STOP_FCS_MODE, NULL);
11036
11037                         //switch to buddy's channel setting if buddy is linked
11038                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
11039                 }       
11040         }
11041 #endif //!CONFIG_FCS_MODE
11042 #endif //!CONFIG_DUALMAC_CONCURRENT
11043
11044
11045         flush_all_cam_entry(padapter);
11046
11047         _cancel_timer_ex(&pmlmeext->link_timer);
11048
11049         //pmlmepriv->LinkDetectInfo.TrafficBusyState = _FALSE;
11050         pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
11051         pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
11052
11053 }
11054
11055 void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res)
11056 {
11057         struct sta_info         *psta, *psta_bmc;
11058         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11059         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11060         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
11061         struct sta_priv         *pstapriv = &padapter->stapriv;
11062         u8      join_type;
11063
11064         if(join_res < 0)
11065         {
11066                 join_type = 1;
11067                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
11068                 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
11069
11070                 goto exit_mlmeext_joinbss_event_callback;
11071         }
11072
11073         if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
11074         {
11075                 //update bc/mc sta_info
11076                 update_bmc_sta(padapter);
11077         }
11078
11079
11080         //turn on dynamic functions
11081         Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);
11082
11083         // update IOT-releated issue
11084         update_IOT_info(padapter);
11085
11086         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
11087
11088         //BCN interval
11089         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
11090
11091         //udpate capability
11092         update_capinfo(padapter, pmlmeinfo->capability);
11093
11094         //WMM, Update EDCA param
11095         WMMOnAssocRsp(padapter);
11096
11097         //HT
11098         HTOnAssocRsp(padapter);
11099
11100 #ifdef CONFIG_80211AC_VHT
11101         //VHT
11102         VHTOnAssocRsp(padapter);
11103 #endif
11104
11105 #ifndef CONFIG_CONCURRENT_MODE
11106         //      Call set_channel_bwmode when the CONFIG_CONCURRENT_MODE doesn't be defined.
11107         //Set cur_channel&cur_bwmode&cur_ch_offset
11108         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
11109 #endif
11110
11111         psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
11112         if (psta) //only for infra. mode
11113         {
11114                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
11115
11116                 //DBG_871X("set_sta_rate\n");
11117
11118                 psta->wireless_mode = pmlmeext->cur_wireless_mode;
11119         
11120                 //set per sta rate after updating HT cap.
11121                 set_sta_rate(padapter, psta);
11122                 
11123                 rtw_sta_media_status_rpt(padapter, psta, 1);
11124
11125                 /* wakeup macid after join bss successfully to ensure 
11126                         the subsequent data frames can be sent out normally */
11127                 rtw_hal_macid_wakeup(padapter, psta->mac_id);
11128         }
11129
11130         if (rtw_port_switch_chk(padapter) == _TRUE)
11131                 rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
11132
11133         join_type = 2;
11134         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
11135
11136         if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
11137         {
11138                 // correcting TSF
11139                 correct_TSF(padapter, pmlmeext);
11140         
11141                 //set_link_timer(pmlmeext, DISCONNECT_TO);
11142         }
11143
11144 #ifdef CONFIG_LPS
11145         if(get_iface_type(padapter) == IFACE_PORT0)
11146                 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
11147 #endif
11148
11149 #ifdef CONFIG_BEAMFORMING
11150         if (psta)
11151                 beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_ENTER, (u8 *)psta, sizeof(struct sta_info), 0);
11152 #endif
11153
11154 exit_mlmeext_joinbss_event_callback:
11155
11156 #ifdef CONFIG_DUALMAC_CONCURRENT
11157         dc_handle_join_done(padapter, join_res);
11158 #endif
11159 #ifdef CONFIG_CONCURRENT_MODE
11160         concurrent_chk_joinbss_done(padapter, join_res);
11161 #endif
11162
11163         DBG_871X("=>%s\n", __FUNCTION__);
11164
11165 }
11166
11167 //currently only adhoc mode will go here
11168 void mlmeext_sta_add_event_callback(_adapter *padapter, struct sta_info *psta)
11169 {
11170         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
11171         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11172         u8      join_type;
11173
11174         DBG_871X("%s\n", __FUNCTION__);
11175
11176         if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
11177         {
11178                 if(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)//adhoc master or sta_count>1
11179                 {
11180                         //nothing to do
11181                 }
11182                 else//adhoc client
11183                 {
11184                         //update TSF Value
11185                         //update_TSF(pmlmeext, pframe, len);                    
11186
11187                         // correcting TSF
11188                         correct_TSF(padapter, pmlmeext);
11189
11190                         //start beacon
11191                         if(send_beacon(padapter)==_FAIL)
11192                         {
11193                                 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
11194
11195                                 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
11196
11197                                 return;
11198                         }
11199
11200                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
11201                                 
11202                 }
11203
11204                 join_type = 2;
11205                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
11206         }
11207
11208         pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
11209
11210         psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates);
11211         _rtw_memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen);
11212
11213         //update adhoc sta_info
11214         update_sta_info(padapter, psta);
11215
11216         rtw_hal_update_sta_rate_mask(padapter, psta);
11217
11218         // ToDo: HT for Ad-hoc 
11219         psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);
11220         psta->raid = rtw_hal_networktype_to_raid(padapter, psta);
11221
11222         //rate radaptive
11223         Update_RA_Entry(padapter, psta);
11224 }
11225
11226 void mlmeext_sta_del_event_callback(_adapter *padapter)
11227 {
11228         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11229         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11230
11231         if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
11232         {
11233                 rtw_mlmeext_disconnect(padapter);
11234         }
11235
11236 }
11237
11238 /****************************************************************************
11239
11240 Following are the functions for the timer handlers
11241
11242 *****************************************************************************/
11243 void _linked_info_dump(_adapter *padapter)
11244 {
11245         int i;
11246         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11247       struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11248         u8 mac_id;
11249         int UndecoratedSmoothedPWDB;
11250         struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
11251         
11252         if(padapter->bLinkInfoDump){
11253
11254                 DBG_871X("\n============["ADPT_FMT"] linked status check ===================\n",ADPT_ARG(padapter));    
11255
11256                 if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
11257                 {
11258                         rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);      
11259                 
11260                         DBG_871X("AP[" MAC_FMT "] - UndecoratedSmoothedPWDB:%d\n",
11261                                 MAC_ARG(padapter->mlmepriv.cur_network.network.MacAddress),UndecoratedSmoothedPWDB);
11262                 }
11263                 else if((pmlmeinfo->state&0x03) == _HW_STATE_AP_)
11264                 {
11265                         _irqL irqL;
11266                         _list   *phead, *plist;
11267         
11268                         struct sta_info *psta=NULL;     
11269                         struct sta_priv *pstapriv = &padapter->stapriv;
11270                         
11271                         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);   
11272                         phead = &pstapriv->asoc_list;
11273                         plist = get_next(phead);
11274                         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
11275                         {
11276                                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
11277                                 plist = get_next(plist);                        
11278                                 
11279                                 DBG_871X("STA[" MAC_FMT "]:UndecoratedSmoothedPWDB:%d\n", 
11280                                         MAC_ARG(psta->hwaddr),psta->rssi_stat.UndecoratedSmoothedPWDB);
11281                         }
11282                         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);            
11283                         
11284                 }
11285                 for(i=0; i<NUM_STA; i++)
11286                 {
11287                         if(pdvobj->macid[i] == _TRUE)
11288                         {
11289                                 if(i !=1) //skip bc/mc sta
11290                                         //============  tx info ============    
11291                                         rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i);                 
11292                         }
11293                 }
11294                 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL);
11295                         
11296                 
11297         }
11298               
11299
11300 }
11301
11302 u8 chk_ap_is_alive(_adapter *padapter, struct sta_info *psta)
11303 {
11304         u8 ret = _FALSE;
11305         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11306         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11307
11308         #ifdef DBG_EXPIRATION_CHK
11309         DBG_871X(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"
11310                                 /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/
11311                                 ", retry:%u\n"
11312                 , FUNC_ADPT_ARG(padapter)
11313                 , STA_RX_PKTS_DIFF_ARG(psta)
11314                 , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts
11315                 , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts
11316                 /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts
11317                 , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts
11318                 , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts
11319                 , pmlmeinfo->bcn_interval*/
11320                 , pmlmeext->retry
11321         );
11322
11323         DBG_871X(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter)
11324                 , padapter->xmitpriv.tx_pkts
11325                 , pmlmeinfo->link_count
11326         );
11327         #endif
11328
11329         if((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
11330                 && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
11331                 && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
11332         )
11333         {
11334                 ret = _FALSE;
11335         }
11336         else
11337         {
11338                 ret = _TRUE;
11339         }
11340
11341         sta_update_last_rx_pkts(psta);
11342
11343         return ret;
11344 }
11345
11346 #ifdef CONFIG_TDLS
11347 void linked_status_chk_tdls(_adapter *padapter)
11348 {
11349 struct candidate_pool{
11350         struct sta_info *psta;
11351         u8 addr[ETH_ALEN];
11352 };
11353         struct sta_priv *pstapriv = &padapter->stapriv;
11354         _irqL irqL;
11355         u8 ack_chk;
11356         struct sta_info *psta;
11357         int i, num_teardown=0, num_checkalive=0;
11358         _list   *plist, *phead;
11359         struct tdls_txmgmt txmgmt;
11360         struct candidate_pool checkalive[NUM_STA];
11361         struct candidate_pool teardown[NUM_STA];
11362 #define ALIVE_MIN 2
11363 #define ALIVE_MAX 5
11364
11365         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
11366         _rtw_memset(checkalive, 0x00, sizeof(checkalive));
11367         _rtw_memset(teardown, 0x00, sizeof(teardown));
11368
11369         if((padapter->tdlsinfo.link_established == _TRUE)){
11370                 _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
11371                 for(i=0; i< NUM_STA; i++)
11372                 {
11373                         phead = &(pstapriv->sta_hash[i]);
11374                         plist = get_next(phead);
11375                         
11376                         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
11377                         {
11378                                 psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
11379                                 plist = get_next(plist);
11380
11381                                 if(psta->tdls_sta_state & TDLS_LINKED_STATE)
11382                                 {
11383                                         psta->alive_count++;
11384                                         if(psta->alive_count >= ALIVE_MIN)
11385                                         {
11386 #ifdef CONFIG_XMIT_ACK
11387                                                 if(psta->sta_stats.last_rx_data_pkts >= psta->sta_stats.rx_data_pkts)
11388 #else
11389                                                 if((psta->sta_stats.last_rx_data_pkts >= psta->sta_stats.rx_data_pkts) &&
11390                                                         (!(psta->tdls_sta_state & TDLS_ALIVE_STATE)) )
11391 #endif
11392                                                 {
11393                                                         if(psta->alive_count < ALIVE_MAX)
11394                                                         {
11395                                                                 _rtw_memcpy(checkalive[num_checkalive].addr, psta->hwaddr, ETH_ALEN);
11396                                                                 checkalive[num_checkalive].psta = psta;
11397                                                                 num_checkalive++;
11398                                                         }
11399                                                         else
11400                                                         {
11401                                                                 _rtw_memcpy(teardown[num_teardown].addr, psta->hwaddr, ETH_ALEN);
11402                                                                 teardown[num_teardown].psta = psta;
11403                                                                 num_teardown++;
11404                                                         }
11405                                                 }
11406                                                 else
11407                                                 {
11408                                                         psta->tdls_sta_state &= (~TDLS_ALIVE_STATE);
11409                                                         psta->alive_count = 0;
11410                                                 }
11411                                         }
11412                                         psta->sta_stats.last_rx_data_pkts = psta->sta_stats.rx_data_pkts;
11413                                 }
11414                         }
11415                 }
11416                 _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
11417
11418                 if(num_checkalive > 0)
11419                 {
11420                         for(i=0; i< num_checkalive; i++)
11421                         {
11422 #ifdef CONFIG_XMIT_ACK
11423                                 //TDLS: Should we set wait_ms to 300 for keeping alive?
11424                                 ack_chk = issue_nulldata_to_TDLS_peer_STA(padapter,     checkalive[i].addr, 0, 3, 300);
11425
11426                                 if(ack_chk == _SUCCESS)
11427                                 {
11428                                         checkalive[i].psta->alive_count = 0;
11429                                 }
11430 #else
11431                                 checkalive[i].psta->tdls_sta_state &= (~TDLS_ALIVE_STATE);
11432                                 _rtw_memcpy(txmgmt.peer, checkalive[i].addr, ETH_ALEN);
11433                                 issue_tdls_dis_req(padapter, &txmgmt);
11434                                 issue_tdls_dis_req(padapter, &txmgmt);
11435                                 issue_tdls_dis_req(padapter, &txmgmt);
11436 #endif //CONFIG_XMIT_ACK
11437                         }
11438                 }
11439
11440                 if(num_teardown > 0)
11441                 {
11442                         for(i=0; i< num_teardown; i++)
11443                         {
11444                                 DBG_871X("[%s %d] Send teardown to "MAC_FMT" \n", __FUNCTION__, __LINE__, MAC_ARG(teardown[i].addr));
11445                                 txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_;
11446                                 _rtw_memcpy(txmgmt.peer, teardown[i].addr, ETH_ALEN);
11447                                 issue_tdls_teardown(padapter, &txmgmt, _FALSE);
11448                         }
11449                 }
11450         }
11451
11452 }
11453 #endif //CONFIG_TDLS
11454
11455 void linked_status_chk(_adapter *padapter)
11456 {
11457         u32     i;
11458         struct sta_info         *psta;
11459         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
11460         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11461         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11462         struct sta_priv         *pstapriv = &padapter->stapriv;
11463         
11464
11465         if (is_client_associated_to_ap(padapter))
11466         {
11467                 //linked infrastructure client mode
11468
11469                 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
11470                 int rx_chk_limit;
11471                 int link_count_limit;
11472
11473                 #if defined(DBG_ROAMING_TEST)
11474                 rx_chk_limit = 1;
11475                 #elif defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && !defined(CONFIG_LPS_LCLK_WD_TIMER)
11476                 rx_chk_limit = 4;
11477                 #else
11478                 rx_chk_limit = 8;
11479                 #endif
11480 #ifdef CONFIG_P2P
11481                 if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE))
11482                         link_count_limit = 3; // 8 sec
11483                 else
11484 #endif // CONFIG_P2P
11485                         link_count_limit = 7; // 16 sec
11486
11487                 // Marked by Kurt 20130715
11488                 // For WiDi 3.5 and latered on, they don't ask WiDi sink to do roaming, so we could not check rx limit that strictly.
11489                 // todo: To check why we under miracast session, rx_chk would be _FALSE
11490                 //#ifdef CONFIG_INTEL_WIDI
11491                 //if (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_NONE)
11492                 //      rx_chk_limit = 1;
11493                 //#endif
11494
11495                 if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
11496                 {
11497                         bool is_p2p_enable = _FALSE;
11498                         #ifdef CONFIG_P2P
11499                         is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
11500                         #endif
11501                         
11502                         if (chk_ap_is_alive(padapter, psta) == _FALSE)
11503                                 rx_chk = _FAIL;
11504
11505                         if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
11506                                 tx_chk = _FAIL;
11507
11508                         #if defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && !defined(CONFIG_LPS_LCLK_WD_TIMER)
11509                         if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
11510                                 u8 backup_oper_channel=0;
11511
11512                                 /* switch to correct channel of current network  before issue keep-alive frames */
11513                                 if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
11514                                         backup_oper_channel = rtw_get_oper_ch(padapter);
11515                                         SelectChannel(padapter, pmlmeext->cur_channel);
11516                                 }
11517
11518                                 if (rx_chk != _SUCCESS)
11519                                         issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 0, 0, 3, 1);
11520
11521                                 if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) || rx_chk != _SUCCESS) {
11522                                         tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
11523                                         /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
11524                                         if (tx_chk == _SUCCESS && !is_p2p_enable)
11525                                                 rx_chk = _SUCCESS;
11526                                 }
11527
11528                                 /* back to the original operation channel */
11529                                 if(backup_oper_channel>0)
11530                                         SelectChannel(padapter, backup_oper_channel);
11531
11532                         }
11533                         else
11534                         #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
11535                         {
11536                                 if (rx_chk != _SUCCESS) {
11537                                         if (pmlmeext->retry == 0) {
11538                                                 #ifdef DBG_EXPIRATION_CHK
11539                                                 DBG_871X("issue_probereq to trigger probersp, retry=%d\n", pmlmeext->retry);
11540                                                 #endif
11541                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
11542                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
11543                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
11544                                         }
11545                                 }
11546
11547                                 if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) {
11548                                         #ifdef DBG_EXPIRATION_CHK
11549                                         DBG_871X("%s issue_nulldata 0\n", __FUNCTION__);
11550                                         #endif
11551                                         tx_chk = issue_nulldata_in_interrupt(padapter, NULL);
11552                                 }
11553                         }
11554
11555                         if (rx_chk == _FAIL) {
11556                                 pmlmeext->retry++;
11557                                 if (pmlmeext->retry > rx_chk_limit) {
11558                                         DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
11559                                                 FUNC_ADPT_ARG(padapter));
11560                                         receive_disconnect(padapter, pmlmeinfo->network.MacAddress
11561                                                 , WLAN_REASON_EXPIRATION_CHK);
11562                                         return;
11563                                 }
11564                         } else {
11565                                 pmlmeext->retry = 0;
11566                         }
11567
11568                         if (tx_chk == _FAIL) {
11569                                 pmlmeinfo->link_count %= (link_count_limit+1);
11570                         } else {
11571                                 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
11572                                 pmlmeinfo->link_count = 0;
11573                         }
11574
11575                 } //end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL)
11576
11577 #if defined (CONFIG_TDLS) && defined (CONFIG_TDLS_AUTOCHECKALIVE)
11578                 linked_status_chk_tdls(padapter);
11579 #endif //CONFIG_TDLS
11580
11581         }
11582         else if (is_client_associated_to_ibss(padapter))
11583         {
11584                 //linked IBSS mode
11585                 //for each assoc list entry to check the rx pkt counter
11586                 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
11587                 {
11588                         if (pmlmeinfo->FW_sta_info[i].status == 1)
11589                         {
11590                                 psta = pmlmeinfo->FW_sta_info[i].psta;
11591
11592                                 if(NULL==psta) continue;
11593
11594                                 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta))
11595                                 {
11596
11597                                         if(pmlmeinfo->FW_sta_info[i].retry<3)
11598                                         {
11599                                                 pmlmeinfo->FW_sta_info[i].retry++;
11600                                         }
11601                                         else
11602                                         {
11603                                                 pmlmeinfo->FW_sta_info[i].retry = 0;
11604                                                 pmlmeinfo->FW_sta_info[i].status = 0;
11605                                                 report_del_sta_event(padapter, psta->hwaddr
11606                                                         , 65535// indicate disconnect caused by no rx
11607                                                 );
11608                                         }       
11609                                 }
11610                                 else
11611                                 {
11612                                         pmlmeinfo->FW_sta_info[i].retry = 0;
11613                                         pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
11614                                 }
11615                         }
11616                 }
11617
11618                 //set_link_timer(pmlmeext, DISCONNECT_TO);
11619
11620         }
11621
11622 }
11623
11624 void survey_timer_hdl(_adapter *padapter)
11625 {
11626         struct cmd_obj  *ph2c;
11627         struct sitesurvey_parm  *psurveyPara;
11628         struct cmd_priv                                 *pcmdpriv=&padapter->cmdpriv;
11629         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
11630 #ifdef CONFIG_P2P
11631         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
11632 #endif
11633
11634         //DBG_871X("marc: survey timer\n");
11635
11636         //issue rtw_sitesurvey_cmd
11637         if (pmlmeext->sitesurvey_res.state > SCAN_START)
11638         {
11639                 if(pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
11640                 {
11641 #if defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE) || defined(CONFIG_ATMEL_RC_PATCH) 
11642                         if (padapter->mlmeextpriv.mlmext_info.scan_cnt != RTW_SCAN_NUM_OF_CH
11643                                 || padapter->mlmeextpriv.mlmext_info.backop_cnt == RTW_STAY_AP_CH_MILLISECOND)
11644 #endif
11645                                 pmlmeext->sitesurvey_res.channel_idx++;
11646                 }
11647
11648                 if(pmlmeext->scan_abort == _TRUE)
11649                 {
11650                         #ifdef CONFIG_P2P
11651                         if(!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE))
11652                         {
11653                                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
11654                                 pmlmeext->sitesurvey_res.channel_idx = 3;
11655                                 DBG_871X("%s idx:%d, cnt:%u\n", __FUNCTION__
11656                                         , pmlmeext->sitesurvey_res.channel_idx
11657                                         , pwdinfo->find_phase_state_exchange_cnt
11658                                 );
11659                         }
11660                         else
11661                         #endif
11662                         {
11663                                 pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
11664                                 DBG_871X("%s idx:%d\n", __FUNCTION__
11665                                         , pmlmeext->sitesurvey_res.channel_idx
11666                                 );
11667                         }
11668
11669                         pmlmeext->scan_abort = _FALSE;//reset
11670                 }
11671
11672                 if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
11673                 {
11674                         goto exit_survey_timer_hdl;
11675                 }
11676
11677                 if ((psurveyPara = (struct sitesurvey_parm*)rtw_zmalloc(sizeof(struct sitesurvey_parm))) == NULL)
11678                 {
11679                         rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
11680                         goto exit_survey_timer_hdl;
11681                 }
11682
11683                 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
11684                 rtw_enqueue_cmd(pcmdpriv, ph2c);
11685         }
11686
11687
11688 exit_survey_timer_hdl:
11689
11690         return;
11691 }
11692
11693 void link_timer_hdl(_adapter *padapter)
11694 {
11695         //static unsigned int           rx_pkt = 0;
11696         //static u64                            tx_cnt = 0;
11697         //struct xmit_priv              *pxmitpriv = &(padapter->xmitpriv);
11698         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11699         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11700         //struct sta_priv               *pstapriv = &padapter->stapriv;
11701
11702
11703         if (pmlmeinfo->state & WIFI_FW_AUTH_NULL)
11704         {
11705                 DBG_871X("link_timer_hdl:no beacon while connecting\n");
11706                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
11707                 report_join_res(padapter, -3);
11708         }
11709         else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE)
11710         {
11711                 //re-auth timer
11712                 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT)
11713                 {
11714                         //if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto)
11715                         //{
11716                                 pmlmeinfo->state = 0;
11717                                 report_join_res(padapter, -1);
11718                                 return;
11719                         //}
11720                         //else
11721                         //{
11722                         //      pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
11723                         //      pmlmeinfo->reauth_count = 0;
11724                         //}
11725                 }
11726                 
11727                 DBG_871X("link_timer_hdl: auth timeout and try again\n");
11728                 pmlmeinfo->auth_seq = 1;
11729                 issue_auth(padapter, NULL, 0);
11730                 set_link_timer(pmlmeext, REAUTH_TO);
11731         }
11732         else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)
11733         {
11734                 //re-assoc timer
11735                 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT)
11736                 {
11737                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
11738                         report_join_res(padapter, -2);
11739                         return;
11740                 }
11741
11742                 DBG_871X("link_timer_hdl: assoc timeout and try again\n");
11743                 issue_assocreq(padapter);
11744                 set_link_timer(pmlmeext, REASSOC_TO);
11745         }
11746 #if 0
11747         else if (is_client_associated_to_ap(padapter))
11748         {
11749                 //linked infrastructure client mode
11750                 if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
11751                 {
11752                         /*to monitor whether the AP is alive or not*/
11753                         if (rx_pkt == psta->sta_stats.rx_pkts)
11754                         {
11755                                 receive_disconnect(padapter, pmlmeinfo->network.MacAddress);
11756                                 return;
11757                         }
11758                         else
11759                         {
11760                                 rx_pkt = psta->sta_stats.rx_pkts;
11761                                 set_link_timer(pmlmeext, DISCONNECT_TO);
11762                         }
11763
11764                         //update the EDCA paramter according to the Tx/RX mode
11765                         update_EDCA_param(padapter);
11766
11767                         /*to send the AP a nulldata if no frame is xmitted in order to keep alive*/
11768                         if (pmlmeinfo->link_count++ == 0)
11769                         {
11770                                 tx_cnt = pxmitpriv->tx_pkts;
11771                         }
11772                         else if ((pmlmeinfo->link_count & 0xf) == 0)
11773                         {
11774                                 if (tx_cnt == pxmitpriv->tx_pkts)
11775                                 {
11776                                         issue_nulldata_in_interrupt(padapter, NULL);
11777                                 }
11778
11779                                 tx_cnt = pxmitpriv->tx_pkts;
11780                         }
11781                 } //end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL)
11782         }
11783         else if (is_client_associated_to_ibss(padapter))
11784         {
11785                 //linked IBSS mode
11786                 //for each assoc list entry to check the rx pkt counter
11787                 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
11788                 {
11789                         if (pmlmeinfo->FW_sta_info[i].status == 1)
11790                         {
11791                                 psta = pmlmeinfo->FW_sta_info[i].psta;
11792
11793                                 if (pmlmeinfo->FW_sta_info[i].rx_pkt == psta->sta_stats.rx_pkts)
11794                                 {
11795                                         pmlmeinfo->FW_sta_info[i].status = 0;
11796                                         report_del_sta_event(padapter, psta->hwaddr);
11797                                 }
11798                                 else
11799                                 {
11800                                         pmlmeinfo->FW_sta_info[i].rx_pkt = psta->sta_stats.rx_pkts;
11801                                 }
11802                         }
11803                 }
11804
11805                 set_link_timer(pmlmeext, DISCONNECT_TO);
11806         }
11807 #endif
11808
11809         return;
11810 }
11811
11812 void addba_timer_hdl(struct sta_info *psta)
11813 {
11814 #ifdef CONFIG_80211N_HT
11815         struct ht_priv  *phtpriv;
11816
11817         if(!psta)
11818                 return;
11819         
11820         phtpriv = &psta->htpriv;
11821
11822         if((phtpriv->ht_option==_TRUE) && (phtpriv->ampdu_enable==_TRUE)) 
11823         {
11824                 if(phtpriv->candidate_tid_bitmap)
11825                         phtpriv->candidate_tid_bitmap=0x0;
11826                 
11827         }
11828 #endif //CONFIG_80211N_HT
11829 }
11830
11831 #ifdef CONFIG_IEEE80211W
11832 void sa_query_timer_hdl(_adapter *padapter)
11833 {
11834         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11835         struct mlme_priv * pmlmepriv = &padapter->mlmepriv;
11836         _irqL irqL;
11837         //disconnect
11838         _enter_critical_bh(&pmlmepriv->lock, &irqL);
11839
11840         if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
11841         {
11842                 rtw_disassoc_cmd(padapter, 0, _TRUE);
11843                 rtw_indicate_disconnect(padapter);
11844                 rtw_free_assoc_resources(padapter, 1);  
11845         }
11846
11847         _exit_critical_bh(&pmlmepriv->lock, &irqL);
11848         DBG_871X("SA query timeout disconnect\n");
11849 }
11850 #endif //CONFIG_IEEE80211W
11851
11852 u8 NULL_hdl(_adapter *padapter, u8 *pbuf)
11853 {
11854         return H2C_SUCCESS;
11855 }
11856
11857 #ifdef CONFIG_AUTO_AP_MODE
11858 void rtw_start_auto_ap(_adapter *adapter)
11859 {
11860         DBG_871X("%s\n", __FUNCTION__);
11861
11862         rtw_set_802_11_infrastructure_mode(adapter, Ndis802_11APMode);
11863
11864         rtw_setopmode_cmd(adapter, Ndis802_11APMode,_TRUE);
11865 }
11866
11867 static int rtw_auto_ap_start_beacon(_adapter *adapter)
11868 {
11869         int ret=0;
11870         u8 *pbuf = NULL;
11871         uint len;
11872         u8      supportRate[16];
11873         int     sz = 0, rateLen;
11874         u8 *    ie;
11875         u8      wireless_mode, oper_channel;
11876         u8 ssid[3] = {0}; //hidden ssid
11877         u32 ssid_len = sizeof(ssid);
11878         struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
11879
11880
11881         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
11882                 return -EINVAL;
11883
11884
11885         len = 128;
11886         pbuf = rtw_zmalloc(len);
11887         if(!pbuf)
11888                 return -ENOMEM;
11889
11890
11891         //generate beacon
11892         ie = pbuf;
11893
11894         //timestamp will be inserted by hardware
11895         sz += 8;
11896         ie += sz;
11897
11898         //beacon interval : 2bytes
11899         *(u16*)ie = cpu_to_le16((u16)100);//BCN_INTERVAL=100;
11900         sz += 2;
11901         ie += 2;
11902
11903         //capability info
11904         *(u16*)ie = 0;
11905         *(u16*)ie |= cpu_to_le16(cap_ESS);
11906         *(u16*)ie |= cpu_to_le16(cap_ShortPremble);
11907         //*(u16*)ie |= cpu_to_le16(cap_Privacy);
11908         sz += 2;
11909         ie += 2;
11910
11911         //SSID
11912         ie = rtw_set_ie(ie, _SSID_IE_, ssid_len, ssid, &sz);
11913
11914         //supported rates
11915         wireless_mode = WIRELESS_11BG_24N;
11916         rtw_set_supported_rate(supportRate, wireless_mode) ;
11917         rateLen = rtw_get_rateset_len(supportRate);
11918         if (rateLen > 8)
11919         {
11920                 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, supportRate, &sz);
11921         }
11922         else
11923         {
11924                 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, supportRate, &sz);
11925         }
11926
11927
11928         //DS parameter set
11929         if(check_buddy_fwstate(adapter, _FW_LINKED) &&
11930                 check_buddy_fwstate(adapter, WIFI_STATION_STATE))
11931         {
11932                 PADAPTER pbuddy_adapter = adapter->pbuddy_adapter;
11933                 struct mlme_ext_priv *pbuddy_mlmeext  = &pbuddy_adapter->mlmeextpriv;
11934
11935                 oper_channel = pbuddy_mlmeext->cur_channel;
11936         }
11937         else
11938         {
11939                 oper_channel = adapter_to_dvobj(adapter)->oper_channel;
11940         }
11941         ie = rtw_set_ie(ie, _DSSET_IE_, 1, &oper_channel, &sz);
11942
11943         //ext supported rates
11944         if (rateLen > 8)
11945         {
11946                 ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz);
11947         }
11948
11949         DBG_871X("%s, start auto ap beacon sz=%d\n", __FUNCTION__, sz);
11950
11951         //lunch ap mode & start to issue beacon
11952         if(rtw_check_beacon_data(adapter, pbuf,  sz) == _SUCCESS)
11953         {
11954
11955         }
11956         else
11957         {
11958                 ret = -EINVAL;
11959         }
11960
11961
11962         rtw_mfree(pbuf, len);
11963
11964         return ret;
11965
11966 }
11967 #endif//CONFIG_AUTO_AP_MODE
11968
11969 u8 setopmode_hdl(_adapter *padapter, u8 *pbuf)
11970 {
11971         u8      type;
11972         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11973         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11974         struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
11975
11976         if(psetop->mode == Ndis802_11APMode)
11977         {
11978                 pmlmeinfo->state = WIFI_FW_AP_STATE;
11979                 type = _HW_STATE_AP_;
11980 #ifdef CONFIG_NATIVEAP_MLME
11981                 //start_ap_mode(padapter);
11982 #endif
11983         }
11984         else if(psetop->mode == Ndis802_11Infrastructure)
11985         {
11986                 pmlmeinfo->state &= ~(BIT(0)|BIT(1));// clear state
11987                 pmlmeinfo->state |= WIFI_FW_STATION_STATE;//set to      STATION_STATE
11988                 type = _HW_STATE_STATION_;
11989         }
11990         else if(psetop->mode == Ndis802_11IBSS)
11991         {
11992                 type = _HW_STATE_ADHOC_;
11993         }
11994         else
11995         {
11996                 type = _HW_STATE_NOLINK_;
11997         }
11998
11999         rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
12000         //Set_NETYPE0_MSR(padapter, type);
12001
12002
12003 #ifdef CONFIG_AUTO_AP_MODE
12004         if(psetop->mode == Ndis802_11APMode)
12005                 rtw_auto_ap_start_beacon(padapter);
12006 #endif
12007
12008         if (rtw_port_switch_chk(padapter) == _TRUE)
12009         {
12010                 rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
12011
12012                 if(psetop->mode == Ndis802_11APMode)
12013                         adapter_to_pwrctl(padapter)->fw_psmode_iface_id = 0xff; //ap mode won't dowload rsvd pages
12014                 else if (psetop->mode == Ndis802_11Infrastructure) {
12015                         #ifdef CONFIG_LPS
12016                         _adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
12017                         if (port0_iface)
12018                                 rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
12019                         #endif  
12020                 }
12021         }       
12022
12023 #ifdef CONFIG_BT_COEXIST
12024         if (psetop->mode == Ndis802_11APMode)
12025         {
12026                 // Do this after port switch to
12027                 // prevent from downloading rsvd page to wrong port
12028                 rtw_btcoex_MediaStatusNotify(padapter, 1); //connect 
12029         }
12030 #endif // CONFIG_BT_COEXIST
12031
12032         return H2C_SUCCESS;
12033         
12034 }
12035
12036 u8 createbss_hdl(_adapter *padapter, u8 *pbuf)
12037 {
12038         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12039         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12040         WLAN_BSSID_EX   *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
12041         struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
12042         //u32   initialgain;
12043         
12044 #ifdef CONFIG_AP_MODE
12045         if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
12046                 WLAN_BSSID_EX *network = &padapter->mlmepriv.cur_network.network;
12047                 start_bss_network(padapter, (u8*)network);
12048                 return H2C_SUCCESS;
12049         }
12050 #endif
12051
12052         //below is for ad-hoc master
12053         if(pparm->network.InfrastructureMode == Ndis802_11IBSS)
12054         {
12055                 rtw_joinbss_reset(padapter);
12056         
12057                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
12058                 pmlmeext->cur_ch_offset= HAL_PRIME_CHNL_OFFSET_DONT_CARE;       
12059                 pmlmeinfo->ERP_enable = 0;
12060                 pmlmeinfo->WMM_enable = 0;
12061                 pmlmeinfo->HT_enable = 0;
12062                 pmlmeinfo->HT_caps_enable = 0;
12063                 pmlmeinfo->HT_info_enable = 0;
12064                 pmlmeinfo->agg_enable_bitmap = 0;
12065                 pmlmeinfo->candidate_tid_bitmap = 0;
12066
12067                 //disable dynamic functions, such as high power, DIG
12068                 Save_DM_Func_Flag(padapter);
12069                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
12070
12071                 //config the initial gain under linking, need to write the BB registers
12072                 //initialgain = 0x1E;
12073                 //rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
12074
12075                 //cancel link timer 
12076                 _cancel_timer_ex(&pmlmeext->link_timer);
12077
12078                 //clear CAM
12079                 flush_all_cam_entry(padapter);  
12080
12081                 _rtw_memcpy(pnetwork, pbuf, FIELD_OFFSET(WLAN_BSSID_EX, IELength)); 
12082                 pnetwork->IELength = ((WLAN_BSSID_EX *)pbuf)->IELength;
12083
12084                 if(pnetwork->IELength>MAX_IE_SZ)//Check pbuf->IELength
12085                         return H2C_PARAMETERS_ERROR;
12086
12087                 _rtw_memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength);
12088         
12089                 start_create_ibss(padapter);
12090
12091         }       
12092
12093         return H2C_SUCCESS;
12094
12095 }
12096
12097 u8 join_cmd_hdl(_adapter *padapter, u8 *pbuf)
12098 {
12099         u8      join_type;
12100         PNDIS_802_11_VARIABLE_IEs       pIE;
12101         struct registry_priv    *pregpriv = &padapter->registrypriv;
12102         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12103         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12104         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
12105 #ifdef CONFIG_ANTENNA_DIVERSITY
12106         struct joinbss_parm     *pparm = (struct joinbss_parm *)pbuf;
12107 #endif //CONFIG_ANTENNA_DIVERSITY
12108         u32 i;
12109         u8      cbw40_enable=0;
12110         //u32   initialgain;
12111         //u32   acparm;
12112         u8 ch, bw, offset;
12113
12114 #if 1
12115         /*
12116          * For safety, prevent from keeping macid sleep.
12117          * If we can sure all power mode enter/leave are paired,
12118          * this check can be removed.
12119          * Lucas@20131113
12120          */
12121         {
12122         struct sta_info *psta;
12123         psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
12124         if (psta)
12125                 rtw_hal_macid_wakeup(padapter, psta->mac_id);
12126         }
12127 #endif
12128
12129 #ifdef CONFIG_BT_COEXIST
12130 {
12131         static u8 bw_mode = 0;
12132
12133         if (0 == bw_mode)
12134         {
12135                 bw_mode = pregpriv->bw_mode; // keep original bw_mode
12136                 DBG_871X(FUNC_ADPT_FMT ": [BTCOEX] Save bw_mode(0x%02x)\n",
12137                         FUNC_ADPT_ARG(padapter), pregpriv->bw_mode);
12138         }
12139
12140         if ((rtw_btcoex_1Ant(padapter) == _TRUE)
12141                 && (rtw_btcoex_IsBtLinkExist(padapter) == _TRUE))
12142         {
12143                 pregpriv->bw_mode = 0x00;
12144                 DBG_871X(FUNC_ADPT_FMT ": [BTCOEX] Change bw_mode to 20MHz(0x%02x)\n",
12145                         FUNC_ADPT_ARG(padapter), pregpriv->bw_mode);
12146         }
12147         else
12148         {
12149                 pregpriv->bw_mode = bw_mode;
12150                 DBG_871X(FUNC_ADPT_FMT ": [BTCOEX] Restore bw_mode(0x%02x)\n",
12151                         FUNC_ADPT_ARG(padapter), pregpriv->bw_mode);
12152         }
12153 }
12154 #endif // CONFIG_BT_COEXIST
12155
12156         //check already connecting to AP or not
12157         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
12158         {
12159                 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
12160                 {
12161                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
12162                 }
12163                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
12164                 
12165                 //clear CAM
12166                 flush_all_cam_entry(padapter);          
12167                 
12168                 _cancel_timer_ex(&pmlmeext->link_timer);
12169                 
12170                 //set MSR to nolink -> infra. mode              
12171                 //Set_MSR(padapter, _HW_STATE_NOLINK_);
12172                 Set_MSR(padapter, _HW_STATE_STATION_);  
12173                 
12174
12175                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
12176         }
12177
12178 #ifdef CONFIG_ANTENNA_DIVERSITY
12179         rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, _FALSE);
12180 #endif
12181
12182 #ifdef CONFIG_WAPI_SUPPORT
12183         rtw_wapi_clear_all_cam_entry(padapter);
12184 #endif
12185
12186         rtw_joinbss_reset(padapter);
12187         
12188         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
12189         pmlmeext->cur_ch_offset= HAL_PRIME_CHNL_OFFSET_DONT_CARE;       
12190         pmlmeinfo->ERP_enable = 0;
12191         pmlmeinfo->WMM_enable = 0;
12192         pmlmeinfo->HT_enable = 0;
12193         pmlmeinfo->HT_caps_enable = 0;
12194         pmlmeinfo->HT_info_enable = 0;
12195         pmlmeinfo->agg_enable_bitmap = 0;
12196         pmlmeinfo->candidate_tid_bitmap = 0;
12197         pmlmeinfo->bwmode_updated = _FALSE;
12198         //pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX;
12199         pmlmeinfo->VHT_enable = 0;
12200
12201         _rtw_memcpy(pnetwork, pbuf, FIELD_OFFSET(WLAN_BSSID_EX, IELength)); 
12202         pnetwork->IELength = ((WLAN_BSSID_EX *)pbuf)->IELength;
12203         
12204         if(pnetwork->IELength>MAX_IE_SZ)//Check pbuf->IELength
12205                 return H2C_PARAMETERS_ERROR;    
12206                 
12207         _rtw_memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength); 
12208
12209         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
12210         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
12211
12212         //Check AP vendor to move rtw_joinbss_cmd()
12213         //pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength);
12214
12215         //sizeof(NDIS_802_11_FIXED_IEs) 
12216         for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;)
12217         {
12218                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
12219
12220                 switch (pIE->ElementID)
12221                 {
12222                         case _VENDOR_SPECIFIC_IE_://Get WMM IE.
12223                                 if ( _rtw_memcmp(pIE->data, WMM_OUI, 4) )
12224                                 {
12225                                         WMM_param_handler(padapter, pIE);
12226                                 }
12227                                 break;
12228
12229                         case _HT_CAPABILITY_IE_:        //Get HT Cap IE.
12230                                 pmlmeinfo->HT_caps_enable = 1;
12231                                 break;
12232
12233                         case _HT_EXTRA_INFO_IE_:        //Get HT Info IE.
12234 #ifdef CONFIG_80211N_HT
12235                                 pmlmeinfo->HT_info_enable = 1;
12236
12237                                 //spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz      
12238 //#if !defined(CONFIG_CONCURRENT_MODE) && !defined(CONFIG_DUALMAC_CONCURRENT)
12239 //                              if(pmlmeinfo->assoc_AP_vendor == ciscoAP)
12240 //#endif
12241                                 {                               
12242                                         struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
12243
12244                                         if (pnetwork->Configuration.DSConfig > 14) {
12245                                                 if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20)
12246                                                         cbw40_enable = 1;
12247                                         } else {
12248                                                 if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20)
12249                                                         cbw40_enable = 1;
12250                                         }
12251
12252                                         if ((cbw40_enable) && (pht_info->infos[0] & BIT(2)))
12253                                         {
12254                                                 //switch to the 40M Hz mode according to the AP
12255                                                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
12256                                                 switch (pht_info->infos[0] & 0x3)
12257                                                 {
12258                                                         case 1:
12259                                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
12260                                                                 break;
12261                         
12262                                                         case 3:
12263                                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
12264                                                                 break;
12265                                 
12266                                                         default:
12267                                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
12268                                                                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
12269                                                                 break;
12270                                                 }
12271
12272                                                 DBG_871X("set HT ch/bw before connected\n");
12273                                         }
12274                                 }
12275 #endif //CONFIG_80211N_HT
12276                                 break;
12277 #ifdef CONFIG_80211AC_VHT
12278                         case EID_VHTCapability://Get VHT Cap IE.
12279                                 pmlmeinfo->VHT_enable = 1;
12280                                 break;
12281
12282                         case EID_VHTOperation://Get VHT Operation IE.
12283                                 if((GET_VHT_OPERATION_ELE_CHL_WIDTH(pIE->data) >= 1) 
12284                                         && ((pregpriv->bw_mode >> 4) >= CHANNEL_WIDTH_80)) {
12285                                         pmlmeext->cur_bwmode = CHANNEL_WIDTH_80;
12286                                         DBG_871X("VHT center ch = %d\n", GET_VHT_OPERATION_ELE_CENTER_FREQ1(pIE->data));
12287                                         DBG_871X("set VHT ch/bw before connected\n");
12288                                 }
12289                                 break;
12290 #endif
12291                         default:
12292                                 break;
12293                 }
12294
12295                 i += (pIE->Length + 2);
12296         }
12297 #if 0
12298         if (padapter->registrypriv.wifi_spec) {
12299                 // for WiFi test, follow WMM test plan spec
12300                 acparm = 0x002F431C; // VO
12301                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
12302                 acparm = 0x005E541C; // VI
12303                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
12304                 acparm = 0x0000A525; // BE
12305                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
12306                 acparm = 0x0000A549; // BK
12307                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
12308         
12309                 // for WiFi test, mixed mode with intel STA under bg mode throughput issue
12310                 if (padapter->mlmepriv.htpriv.ht_option == _FALSE){
12311                         acparm = 0x00004320;
12312                         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
12313                 }
12314         }
12315         else {
12316                 acparm = 0x002F3217; // VO
12317                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
12318                 acparm = 0x005E4317; // VI
12319                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
12320                 acparm = 0x00105320; // BE
12321                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
12322                 acparm = 0x0000A444; // BK
12323                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
12324         }
12325 #endif
12326
12327         /* check channel, bandwidth, offset and switch */
12328 #ifdef CONFIG_DUALMAC_CONCURRENT
12329         if(dc_handle_join_request(padapter, &ch, &bw, &offset) == _FAIL) {
12330                 DBG_871X("dc_handle_join_request fail !!!\n");
12331                 return H2C_SUCCESS;
12332         }
12333 #else //NON CONFIG_DUALMAC_CONCURRENT
12334         if(rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) {
12335                 report_join_res(padapter, (-4));
12336                 return H2C_SUCCESS;
12337         }
12338 #endif
12339
12340         //disable dynamic functions, such as high power, DIG
12341         //Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
12342
12343         //config the initial gain under linking, need to write the BB registers
12344         //initialgain = 0x1E;
12345         //rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
12346
12347         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
12348         join_type = 0;
12349         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
12350         rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
12351
12352         set_channel_bwmode(padapter, ch, offset, bw);
12353
12354         //cancel link timer 
12355         _cancel_timer_ex(&pmlmeext->link_timer);
12356         
12357         start_clnt_join(padapter);
12358         
12359         return H2C_SUCCESS;
12360         
12361 }
12362
12363 u8 disconnect_hdl(_adapter *padapter, unsigned char *pbuf)
12364 {
12365         struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
12366         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12367         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12368         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
12369         u8 val8;
12370
12371
12372 #if 1
12373         /*
12374          * For safety, prevent from keeping macid sleep.
12375          * If we can sure all power mode enter/leave are paired,
12376          * this check can be removed.
12377          * Lucas@20131113
12378          */
12379         {
12380         struct sta_info *psta;
12381         psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
12382         if (psta)
12383                 rtw_hal_macid_wakeup(padapter, psta->mac_id);
12384         }
12385 #endif
12386
12387         if (is_client_associated_to_ap(padapter))
12388         {
12389 #ifdef CONFIG_DFS
12390                 if(padapter->mlmepriv.handle_dfs == _FALSE)
12391 #endif //CONFIG_DFS
12392 #ifdef CONFIG_PLATFORM_ROCKCHIPS
12393                         //To avoid connecting to AP fail during resume process, change retry count from 5 to 1
12394                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
12395 #else
12396                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
12397 #endif //CONFIG_PLATFORM_ROCKCHIPS
12398         }
12399
12400 #ifdef CONFIG_DFS
12401         if( padapter->mlmepriv.handle_dfs == _TRUE )
12402                 padapter->mlmepriv.handle_dfs = _FALSE;
12403 #endif //CONFIG_DFS
12404
12405         if(((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
12406         {
12407                 //Stop BCN
12408                 val8 = 0;
12409                 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
12410         }
12411
12412         rtw_mlmeext_disconnect(padapter);
12413
12414         rtw_free_uc_swdec_pending_queue(padapter);
12415         
12416         return  H2C_SUCCESS;
12417 }
12418
12419 u8 rtw_scan_sparse(_adapter *adapter, struct rtw_ieee80211_channel *ch, u8 ch_num)
12420 {
12421 /* interval larger than this is treated as backgroud scan */
12422 #ifndef RTW_SCAN_SPARSE_BG_INTERVAL_MS
12423 #define RTW_SCAN_SPARSE_BG_INTERVAL_MS 12000
12424 #endif
12425
12426 #ifndef RTW_SCAN_SPARSE_CH_NUM_MIRACAST
12427 #define RTW_SCAN_SPARSE_CH_NUM_MIRACAST 1
12428 #endif
12429 #ifndef RTW_SCAN_SPARSE_CH_NUM_BG
12430 #define RTW_SCAN_SPARSE_CH_NUM_BG 4
12431 #endif
12432
12433 #define SCAN_SPARSE_CH_NUM_INVALID 255
12434
12435         static u8 token = 255;
12436         u32 interval;
12437         bool busy_traffic = _FALSE;
12438         bool miracast_enabled = _FALSE;
12439         bool bg_scan = _FALSE;
12440         u8 max_allow_ch = SCAN_SPARSE_CH_NUM_INVALID;
12441         u8 scan_division_num;
12442         u8 ret_num = ch_num;
12443         struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter));
12444         struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
12445
12446         if (regsty->wifi_spec)
12447                 goto exit;
12448
12449         /* assume ch_num > 6 is normal scan */
12450         if (ch_num <= 6)
12451                 goto exit;
12452
12453         if (mlmeext->last_scan_time == 0)
12454                 mlmeext->last_scan_time = rtw_get_current_time();
12455
12456         interval = rtw_get_passing_time_ms(mlmeext->last_scan_time);
12457
12458         if (adapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE
12459                 #ifdef CONFIG_CONCURRENT_MODE
12460                 || (adapter->pbuddy_adapter && adapter->pbuddy_adapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE)
12461                 #endif
12462         )
12463                         busy_traffic = _TRUE;
12464
12465         #ifdef CONFIG_WFD
12466         if (is_miracast_enabled(adapter->wfd_info.stack_wfd_mode)
12467                 #ifdef CONFIG_CONCURRENT_MODE
12468                 || (adapter->pbuddy_adapter && is_miracast_enabled(adapter->pbuddy_adapter->wfd_info.stack_wfd_mode))
12469                 #endif
12470         )
12471                 miracast_enabled = _TRUE;
12472         #endif
12473
12474         if (interval > RTW_SCAN_SPARSE_BG_INTERVAL_MS)
12475                 bg_scan = _TRUE;
12476
12477         /* max_allow_ch by conditions*/
12478
12479         #if RTW_SCAN_SPARSE_MIRACAST
12480         if (miracast_enabled == _TRUE && busy_traffic == _TRUE)
12481                 max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_MIRACAST);
12482         #endif
12483
12484         #if RTW_SCAN_SPARSE_BG
12485         if (bg_scan == _TRUE)
12486                 max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_BG);
12487         #endif
12488
12489
12490         if (max_allow_ch != SCAN_SPARSE_CH_NUM_INVALID) {
12491                 int i;
12492                 int k = 0;
12493
12494                 scan_division_num = (ch_num / max_allow_ch) + ((ch_num % max_allow_ch)?1:0);
12495                 token = (token + 1) % scan_division_num;
12496                 
12497                 if (0)
12498                         DBG_871X("scan_division_num:%u, token:%u\n", scan_division_num, token);
12499                 
12500                 for (i = 0; i < ch_num; i++) {
12501                         if (ch[i].hw_value && (i % scan_division_num) == token
12502                         ) {
12503                                 if (i != k)
12504                                         _rtw_memcpy(&ch[k], &ch[i], sizeof(struct rtw_ieee80211_channel));
12505                                 k++;
12506                         }
12507                 }
12508
12509                 _rtw_memset(&ch[k], 0, sizeof(struct rtw_ieee80211_channel));
12510
12511                 ret_num = k;
12512                 mlmeext->last_scan_time = rtw_get_current_time();
12513         }
12514
12515 exit:
12516         return ret_num;
12517 }
12518
12519 static int rtw_scan_ch_decision(_adapter *padapter, struct rtw_ieee80211_channel *out,
12520         u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
12521 {
12522         int i, j;
12523         int scan_ch_num = 0;
12524         int set_idx;
12525         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12526
12527         /* clear first */
12528         _rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
12529
12530         /* acquire channels from in */
12531         j = 0;
12532         for (i=0;i<in_num;i++) {
12533
12534                 if (0)
12535                 DBG_871X(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
12536
12537                 if(in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED)
12538                         && (set_idx=rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value)) >=0
12539                         && rtw_mlme_band_check(padapter, in[i].hw_value) == _TRUE
12540                 )
12541                 {
12542                         if (j >= out_num) {
12543                                 DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
12544                                         FUNC_ADPT_ARG(padapter), out_num);
12545                                 break;
12546                         }
12547
12548                         _rtw_memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
12549                         
12550                         if(pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
12551                                 out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
12552                                 
12553                         j++;
12554                 }
12555                 if(j>=out_num)
12556                         break;
12557         }
12558         
12559         /* if out is empty, use channel_set as default */
12560         if(j == 0) {
12561                 for (i=0;i<pmlmeext->max_chan_nums;i++) {
12562
12563                         if (0)
12564                         DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), pmlmeext->channel_set[i].ChannelNum);
12565
12566                         if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum) == _TRUE) {
12567
12568                                 if (j >= out_num) {
12569                                         DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
12570                                                 FUNC_ADPT_ARG(padapter), out_num);
12571                                         break;
12572                                 }
12573
12574                                 out[j].hw_value = pmlmeext->channel_set[i].ChannelNum;
12575                         
12576                                 if(pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
12577                                         out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
12578
12579                                 j++;
12580                         }
12581                 }
12582         }
12583
12584         /* scan_sparse */
12585         j = rtw_scan_sparse(padapter, out, j);
12586
12587         return j;
12588 }
12589
12590 u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf)
12591 {
12592         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12593         struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
12594         u8      bdelayscan = _FALSE;
12595         u8      val8;
12596         u32     initialgain;
12597         u32     i;
12598         struct dvobj_priv *psdpriv = padapter->dvobj;
12599         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
12600
12601 #ifdef CONFIG_P2P
12602         struct wifidirect_info* pwdinfo = &padapter->wdinfo;
12603 #endif
12604 #ifdef DBG_CHECK_FW_PS_STATE
12605         if(rtw_fw_ps_state(padapter) == _FAIL)
12606         {
12607                 DBG_871X("scan without leave 32k\n");
12608                 pdbgpriv->dbg_scan_pwr_state_cnt++;
12609         }
12610 #endif //DBG_CHECK_FW_PS_STATE
12611
12612         if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE)
12613         {
12614 #ifdef CONFIG_CONCURRENT_MODE   
12615                 //for first time sitesurvey_cmd
12616                 rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);     
12617 #endif //CONFIG_CONCURRENT_MODE
12618                 
12619                 pmlmeext->sitesurvey_res.state = SCAN_START;
12620                 pmlmeext->sitesurvey_res.bss_cnt = 0;
12621                 pmlmeext->sitesurvey_res.channel_idx = 0;
12622
12623                 for(i=0;i<RTW_SSID_SCAN_AMOUNT;i++){
12624                         if(pparm->ssid[i].SsidLength) {
12625                                 _rtw_memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
12626                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength= pparm->ssid[i].SsidLength;
12627                         } else {
12628                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength= 0;
12629                         }
12630                 }
12631
12632                 pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
12633                         , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
12634                         , pparm->ch, pparm->ch_num
12635                 );
12636
12637                 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
12638
12639 #ifdef CONFIG_DUALMAC_CONCURRENT
12640                 bdelayscan = dc_handle_site_survey(padapter);
12641 #endif
12642
12643                 //issue null data if associating to the AP
12644                 if (is_client_associated_to_ap(padapter) == _TRUE)
12645                 {
12646                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
12647
12648                         issue_nulldata(padapter, NULL, 1, 3, 500);
12649
12650 #ifdef CONFIG_CONCURRENT_MODE
12651                         if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
12652                         {
12653                                 DBG_871X("adapter is scanning(buddy_adapter is linked), issue nulldata(pwrbit=1)\n");
12654                                 
12655                                 issue_nulldata(padapter->pbuddy_adapter, NULL, 1, 3, 500);
12656                         }
12657 #endif
12658                         bdelayscan = _TRUE;
12659                 }
12660 #ifdef CONFIG_CONCURRENT_MODE
12661                 else if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
12662                 {
12663                         #ifdef CONFIG_TDLS
12664                         if(padapter->pbuddy_adapter->wdinfo.wfd_tdls_enable == 1)
12665                         {
12666                                 issue_tunneled_probe_req(padapter->pbuddy_adapter);
12667                         }
12668                         #endif //CONFIG_TDLS
12669
12670                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
12671
12672                         issue_nulldata(padapter->pbuddy_adapter, NULL, 1, 3, 500);
12673
12674                         bdelayscan = _TRUE;                     
12675                 }
12676 #endif          
12677                 if(bdelayscan)
12678                 {
12679                         //delay 50ms to protect nulldata(1).
12680                         set_survey_timer(pmlmeext, 50);
12681                         return H2C_SUCCESS;
12682                 }
12683         }
12684
12685         if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL))
12686         {
12687 #ifdef CONFIG_FIND_BEST_CHANNEL
12688 #if 0
12689                 for (i=0; pmlmeext->channel_set[i].ChannelNum !=0; i++) {
12690                         pmlmeext->channel_set[i].rx_count = 0;                          
12691                 }
12692 #endif
12693 #endif /* CONFIG_FIND_BEST_CHANNEL */
12694
12695                 //disable dynamic functions, such as high power, DIG
12696                 Save_DM_Func_Flag(padapter);
12697                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
12698
12699                 //config the initial gain under scaning, need to write the BB registers
12700 #ifdef CONFIG_P2P
12701 #ifdef CONFIG_IOCTL_CFG80211
12702                 if(adapter_wdev_data(padapter)->p2p_enabled == _TRUE && pwdinfo->driver_interface == DRIVER_CFG80211 )
12703                         initialgain = 0x30;
12704                 else
12705 #endif //CONFIG_IOCTL_CFG80211
12706                 if ( !rtw_p2p_chk_state( pwdinfo, P2P_STATE_NONE ) )
12707                         initialgain = 0x28;
12708                 else
12709 #endif //CONFIG_P2P
12710                         initialgain = 0x1e;
12711
12712                 rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
12713                 
12714                 //set MSR to no link state
12715                 Set_MSR(padapter, _HW_STATE_NOLINK_);
12716
12717                 val8 = 1; //under site survey
12718                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
12719
12720                 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
12721         }
12722
12723         site_survey(padapter);
12724
12725         return H2C_SUCCESS;
12726         
12727 }
12728
12729 u8 setauth_hdl(_adapter *padapter, unsigned char *pbuf)
12730 {
12731         struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
12732         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12733         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12734         
12735         if (pparm->mode < 4)
12736         {
12737                 pmlmeinfo->auth_algo = pparm->mode;
12738         }
12739
12740         return  H2C_SUCCESS;
12741 }
12742
12743 u8 setkey_hdl(_adapter *padapter, u8 *pbuf)
12744 {
12745         u16     ctrl = 0;
12746         s16 cam_id = 0;
12747         struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
12748         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12749         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12750         unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
12751         u8 *addr;
12752
12753         //main tx key for wep.
12754         if(pparm->set_tx)
12755                 pmlmeinfo->key_index = pparm->keyid;
12756
12757         cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid);
12758
12759         if (cam_id < 0){
12760         } else {
12761                 if (cam_id > 3) /* not default key, searched by A2 */
12762                         addr = get_bssid(&padapter->mlmepriv);
12763                 else
12764                         addr = null_addr;
12765                 
12766                 ctrl = BIT(15) | BIT6 |((pparm->algorithm) << 2) | pparm->keyid;
12767                 write_cam(padapter, cam_id, ctrl, addr, pparm->key);
12768                 DBG_871X_LEVEL(_drv_always_, "set group key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n"
12769                         ,cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm));
12770         }
12771
12772         #ifdef DYNAMIC_CAMID_ALLOC
12773         if (cam_id >=0 && cam_id <=3)
12774                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8*)_TRUE);
12775         #endif
12776
12777         //allow multicast packets to driver
12778         padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
12779
12780         return H2C_SUCCESS;
12781 }
12782
12783 u8 set_stakey_hdl(_adapter *padapter, u8 *pbuf)
12784 {
12785         u16 ctrl = 0;
12786         s16 cam_id = 0;
12787         u8 ret = H2C_SUCCESS;
12788         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12789         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12790         struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
12791         struct sta_priv *pstapriv = &padapter->stapriv;
12792         struct sta_info *psta;
12793 #ifdef CONFIG_TDLS
12794         struct tdls_info        *ptdlsinfo = &padapter->tdlsinfo;
12795 #endif //CONFIG_TDLS
12796
12797         if(pparm->algorithm == _NO_PRIVACY_)
12798                 goto write_to_cam;
12799
12800         psta = rtw_get_stainfo(pstapriv, pparm->addr);
12801         if (!psta) {
12802                 DBG_871X_LEVEL(_drv_always_, "%s sta:"MAC_FMT" not found\n", __func__, MAC_ARG(pparm->addr));
12803                 ret = H2C_REJECTED;
12804                 goto exit;
12805         }
12806
12807         pmlmeinfo->enc_algo = pparm->algorithm;
12808         cam_id = rtw_camid_alloc(padapter, psta, 0);
12809         if (cam_id < 0)
12810                 goto exit;
12811
12812 write_to_cam:
12813         if(pparm->algorithm == _NO_PRIVACY_) {
12814                 while((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) {
12815                         DBG_871X_LEVEL(_drv_always_, "clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), cam_id);
12816                         clear_cam_entry(padapter, cam_id);
12817                         rtw_camid_free(padapter,cam_id);
12818                 }
12819         } else {
12820                 DBG_871X_LEVEL(_drv_always_, "set pairwise key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n",
12821                         cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm));
12822                 ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
12823                 write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
12824         }
12825         ret = H2C_SUCCESS_RSP;
12826
12827 exit:
12828         return ret;
12829 }
12830
12831 u8 add_ba_hdl(_adapter *padapter, unsigned char *pbuf)
12832 {
12833         struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
12834         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12835         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12836
12837         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
12838         
12839         if(!psta)
12840                 return  H2C_SUCCESS;
12841                 
12842 #ifdef CONFIG_80211N_HT
12843         if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
12844                 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
12845         {
12846                 //pmlmeinfo->ADDBA_retry_count = 0;
12847                 //pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid);               
12848                 //psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid);
12849                 issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);             
12850                 //_set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO);
12851                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
12852         }
12853 #ifdef CONFIG_TDLS
12854         else if((psta->tdls_sta_state & TDLS_LINKED_STATE)&& 
12855                 (psta->htpriv.ht_option==_TRUE) && 
12856                 (psta->htpriv.ampdu_enable==_TRUE) )
12857         {
12858                 issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);             
12859                 //_set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO);
12860                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
12861         }
12862 #endif //CONFIG
12863         else
12864         {               
12865                 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);          
12866         }
12867 #endif //CONFIG_80211N_HT
12868         return  H2C_SUCCESS;
12869 }
12870
12871
12872 u8 chk_bmc_sleepq_cmd(_adapter* padapter)
12873 {
12874         struct cmd_obj *ph2c;
12875         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
12876         u8 res = _SUCCESS;
12877
12878 _func_enter_;
12879
12880         if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
12881         {
12882                 res= _FAIL;
12883                 goto exit;
12884         }
12885
12886         init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));
12887
12888         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
12889
12890 exit:
12891
12892 _func_exit_;
12893
12894         return res;
12895 }
12896
12897 u8 set_tx_beacon_cmd(_adapter* padapter)
12898 {
12899         struct cmd_obj  *ph2c;
12900         struct Tx_Beacon_param  *ptxBeacon_parm;        
12901         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
12902         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12903         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12904         u8      res = _SUCCESS;
12905         int len_diff = 0;
12906         
12907 _func_enter_;   
12908
12909         if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
12910         {
12911                 res= _FAIL;
12912                 goto exit;
12913         }
12914
12915         if ((ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param))) == NULL)
12916         {
12917                 rtw_mfree((unsigned char *)ph2c, sizeof(struct  cmd_obj));
12918                 res= _FAIL;
12919                 goto exit;
12920         }
12921
12922         _rtw_memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));
12923
12924         len_diff = update_hidden_ssid(
12925                 ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_
12926                 , ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_
12927                 , pmlmeinfo->hidden_ssid_mode
12928         );
12929         ptxBeacon_parm->network.IELength += len_diff;
12930
12931         init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
12932
12933         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
12934
12935         
12936 exit:
12937         
12938 _func_exit_;
12939
12940         return res;
12941 }
12942
12943
12944 u8 mlme_evt_hdl(_adapter *padapter, unsigned char *pbuf)
12945 {
12946         u8 evt_code, evt_seq;
12947         u16 evt_sz;
12948         uint    *peventbuf;
12949         void (*event_callback)(_adapter *dev, u8 *pbuf);
12950         struct evt_priv *pevt_priv = &(padapter->evtpriv);
12951
12952         if (pbuf == NULL)
12953                 goto _abort_event_;
12954
12955         peventbuf = (uint*)pbuf;
12956         evt_sz = (u16)(*peventbuf&0xffff);
12957         evt_seq = (u8)((*peventbuf>>24)&0x7f);
12958         evt_code = (u8)((*peventbuf>>16)&0xff);
12959         
12960                 
12961         #ifdef CHECK_EVENT_SEQ
12962         // checking event sequence...           
12963         if (evt_seq != (ATOMIC_READ(&pevt_priv->event_seq) & 0x7f) )
12964         {
12965                 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)));
12966         
12967                 pevt_priv->event_seq = (evt_seq+1)&0x7f;
12968
12969                 goto _abort_event_;
12970         }
12971         #endif
12972
12973         // checking if event code is valid
12974         if (evt_code >= MAX_C2HEVT)
12975         {
12976                 RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\nEvent Code(%d) mismatch!\n", evt_code));
12977                 goto _abort_event_;
12978         }
12979
12980         // checking if event size match the event parm size     
12981         if ((wlanevents[evt_code].parmsize != 0) && 
12982                         (wlanevents[evt_code].parmsize != evt_sz))
12983         {
12984                         
12985                 RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n", 
12986                         evt_code, wlanevents[evt_code].parmsize, evt_sz));
12987                 goto _abort_event_;     
12988                         
12989         }
12990
12991         ATOMIC_INC(&pevt_priv->event_seq);
12992
12993         peventbuf += 2;
12994                                 
12995         if(peventbuf)
12996         {
12997                 event_callback = wlanevents[evt_code].event_callback;
12998                 event_callback(padapter, (u8*)peventbuf);
12999
13000                 pevt_priv->evt_done_cnt++;
13001         }
13002
13003
13004 _abort_event_:
13005
13006
13007         return H2C_SUCCESS;
13008                 
13009 }
13010
13011 u8 h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)
13012 {
13013         if(!pbuf)
13014                 return H2C_PARAMETERS_ERROR;
13015
13016         return H2C_SUCCESS;
13017 }
13018
13019 u8 chk_bmc_sleepq_hdl(_adapter *padapter, unsigned char *pbuf)
13020 {
13021 #ifdef CONFIG_AP_MODE
13022         _irqL irqL;
13023         struct sta_info *psta_bmc;
13024         _list   *xmitframe_plist, *xmitframe_phead;
13025         struct xmit_frame *pxmitframe=NULL;
13026         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
13027         struct sta_priv  *pstapriv = &padapter->stapriv;
13028
13029         //for BC/MC Frames
13030         psta_bmc = rtw_get_bcmc_stainfo(padapter);
13031         if(!psta_bmc)
13032                 return H2C_SUCCESS;
13033
13034         if((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len>0))
13035         {
13036 #ifndef CONFIG_PCI_HCI
13037                 rtw_msleep_os(10);// 10ms, ATIM(HIQ) Windows
13038 #endif
13039                 //_enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
13040                 _enter_critical_bh(&pxmitpriv->lock, &irqL);
13041
13042                 xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
13043                 xmitframe_plist = get_next(xmitframe_phead);
13044
13045                 while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
13046                 {
13047                         pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
13048
13049                         xmitframe_plist = get_next(xmitframe_plist);
13050
13051                         rtw_list_delete(&pxmitframe->list);
13052
13053                         psta_bmc->sleepq_len--;
13054                         if(psta_bmc->sleepq_len>0)
13055                                 pxmitframe->attrib.mdata = 1;
13056                         else
13057                                 pxmitframe->attrib.mdata = 0;
13058
13059                         pxmitframe->attrib.triggered=1;
13060
13061                         if (xmitframe_hiq_filter(pxmitframe) == _TRUE)
13062                                 pxmitframe->attrib.qsel = 0x11;//HIQ
13063
13064                         #if 0
13065                         _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
13066                         if(rtw_hal_xmit(padapter, pxmitframe) == _TRUE)
13067                         {
13068                                 rtw_os_xmit_complete(padapter, pxmitframe);
13069                         }
13070                         _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
13071                         #endif
13072                         rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
13073                 }
13074
13075                 //_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
13076                 _exit_critical_bh(&pxmitpriv->lock, &irqL);
13077
13078                 if (padapter->interface_type != RTW_PCIE) {
13079                         /* check hi queue and bmc_sleepq */
13080                         rtw_chk_hi_queue_cmd(padapter);
13081                 }
13082         }
13083 #endif
13084
13085         return H2C_SUCCESS;
13086 }
13087
13088 u8 tx_beacon_hdl(_adapter *padapter, unsigned char *pbuf)
13089 {
13090         if(send_beacon(padapter)==_FAIL)
13091         {
13092                 DBG_871X("issue_beacon, fail!\n");
13093                 return H2C_PARAMETERS_ERROR;
13094         }
13095
13096         /* tx bc/mc frames after update TIM */
13097         chk_bmc_sleepq_hdl(padapter, NULL);
13098
13099         return H2C_SUCCESS;
13100 }
13101
13102 void change_band_update_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
13103 {
13104         u8      network_type,rate_len, total_rate_len,remainder_rate_len;
13105         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
13106         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
13107         u8      erpinfo=0x4;
13108
13109         //DBG_871X("%s\n", __FUNCTION__);
13110
13111         if(pmlmeext->cur_channel >= 36)
13112         {
13113                 network_type = WIRELESS_11A;
13114                 total_rate_len = IEEE80211_NUM_OFDM_RATESLEN;
13115                 DBG_871X("%s(): change to 5G Band\n",__FUNCTION__);
13116                 rtw_remove_bcn_ie(padapter, pnetwork, _ERPINFO_IE_);
13117         }
13118         else
13119         {
13120                 network_type = WIRELESS_11BG;
13121                 total_rate_len = IEEE80211_CCK_RATE_LEN+IEEE80211_NUM_OFDM_RATESLEN;
13122                 DBG_871X("%s(): change to 2.4G Band\n",__FUNCTION__);
13123                 rtw_add_bcn_ie(padapter, pnetwork, _ERPINFO_IE_, &erpinfo, 1);
13124         }
13125
13126         rtw_set_supported_rate(pnetwork->SupportedRates, network_type);
13127
13128         UpdateBrateTbl(padapter, pnetwork->SupportedRates);
13129         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
13130
13131         if(total_rate_len > 8)
13132         {
13133                 rate_len = 8;
13134                 remainder_rate_len = total_rate_len - 8;
13135         }
13136         else
13137         {
13138                 rate_len = total_rate_len;
13139                 remainder_rate_len = 0;
13140         }
13141
13142         rtw_add_bcn_ie(padapter, pnetwork, _SUPPORTEDRATES_IE_, pnetwork->SupportedRates, rate_len);
13143
13144         if(remainder_rate_len)
13145         {
13146                 rtw_add_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_, (pnetwork->SupportedRates+8), remainder_rate_len);
13147         }
13148         else
13149         {
13150                 rtw_remove_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_);
13151         }
13152 }
13153
13154 #ifdef CONFIG_DUALMAC_CONCURRENT
13155 void dc_SelectChannel(_adapter *padapter, unsigned char channel)
13156 {
13157         PADAPTER ptarget_adapter;
13158
13159         if( (padapter->pbuddy_adapter != NULL) && 
13160                 (padapter->DualMacConcurrent == _TRUE) &&
13161                 (padapter->adapter_type == SECONDARY_ADAPTER))
13162         {
13163                 // only mac0 could control BB&RF
13164                 ptarget_adapter = padapter->pbuddy_adapter;
13165         }
13166         else
13167         {
13168                 ptarget_adapter = padapter;
13169         }
13170
13171         _enter_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setch_mutex), NULL);
13172
13173         rtw_hal_set_chan(ptarget_adapter, channel);
13174
13175         _exit_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setch_mutex), NULL);
13176 }
13177
13178 void dc_SetBWMode(_adapter *padapter, unsigned short bwmode, unsigned char channel_offset)
13179 {
13180         PADAPTER ptarget_adapter;
13181
13182         if( (padapter->pbuddy_adapter != NULL) && 
13183                 (padapter->DualMacConcurrent == _TRUE) &&
13184                 (padapter->adapter_type == SECONDARY_ADAPTER))
13185         {
13186                 // only mac0 could control BB&RF
13187                 ptarget_adapter = padapter->pbuddy_adapter;
13188         }
13189         else
13190         {
13191                 ptarget_adapter = padapter;
13192         }
13193
13194         _enter_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setbw_mutex), NULL);
13195
13196         rtw_hal_set_bwmode(ptarget_adapter, (CHANNEL_WIDTH)bwmode, channel_offset);
13197
13198         _exit_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setbw_mutex), NULL);
13199 }
13200
13201 void dc_set_channel_bwmode_disconnect(_adapter *padapter)
13202 {
13203         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13204         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13205         struct mlme_priv *pbuddy_mlmepriv = NULL;
13206
13207         if(pbuddy_adapter != NULL && 
13208                 padapter->DualMacConcurrent == _TRUE)
13209         {
13210                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13211                 if((check_fwstate(pbuddy_mlmepriv, _FW_LINKED)) != _TRUE)
13212                 {
13213                         //switch to the 20M Hz mode after disconnect
13214                         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
13215                         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13216
13217                         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13218                 }
13219         }
13220         else
13221         {
13222                 //switch to the 20M Hz mode after disconnect
13223                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
13224                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13225
13226                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13227         }
13228 }
13229
13230 u8 dc_handle_join_request(_adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
13231 {
13232         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13233         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
13234         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
13235         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;             
13236         struct mlme_ext_priv *pbuddy_mlmeext = NULL;
13237         struct mlme_priv        *pbuddy_mlmepriv = NULL;
13238         u8      ret = _SUCCESS;
13239
13240         if(pbuddy_adapter != NULL && 
13241                 padapter->DualMacConcurrent == _TRUE)
13242         {
13243                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13244                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13245
13246                 if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel ||
13247                         pmlmeext->cur_bwmode != pbuddy_mlmeext->cur_bwmode ||
13248                         pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)
13249                 {
13250                         if((check_fwstate(pbuddy_mlmepriv, WIFI_AP_STATE)) == _TRUE)
13251                         {
13252                                 //issue deauth to all stas if if2 is at ap mode
13253                                 rtw_sta_flush(pbuddy_adapter);
13254
13255                                 //rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
13256                                 rtw_hal_set_hwreg(pbuddy_adapter, HW_VAR_CHECK_TXBUF, 0);
13257                         }
13258                         else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED) == _TRUE)
13259                         {
13260                                 if(pmlmeext->cur_channel == pbuddy_mlmeext->cur_channel)
13261                                 {
13262                                         // CHANNEL_WIDTH_40 or CHANNEL_WIDTH_20 but channel offset is different
13263                                         if((pmlmeext->cur_bwmode == pbuddy_mlmeext->cur_bwmode) &&
13264                                                 (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset) )
13265                                         {
13266                                                 report_join_res(padapter, -4);
13267                                                 ret = _FAIL;
13268                                         }
13269                                 }
13270                                 else
13271                                 {
13272                                         report_join_res(padapter, -4);
13273                                         ret = _FAIL;
13274                                 }
13275                         }
13276                 }
13277                 else     if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
13278                 {
13279                         issue_nulldata(pbuddy_adapter, NULL, 1, 0, 0);
13280                 }
13281         }
13282
13283         if (!ch || !bw || !offset) {
13284                 rtw_warn_on(1);
13285                 ret = _FAIL;
13286         }
13287
13288         if (ret == _SUCCESS) {
13289                 *ch = pmlmeext->cur_channel;
13290                 *bw = pmlmeext->cur_bwmode;
13291                 *offset = pmlmeext->cur_ch_offset;
13292         }
13293
13294 exit:
13295         return ret;
13296 }
13297
13298 void dc_handle_join_done(_adapter *padapter, u8 join_res)
13299 {
13300         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13301         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
13302         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13303         struct mlme_priv *pbuddy_mlmepriv = NULL;
13304         struct mlme_ext_priv *pbuddy_mlmeext = NULL;
13305         struct mlme_ext_info *pbuddy_mlmeinfo = NULL;
13306         WLAN_BSSID_EX *pbuddy_network_mlmeext = NULL;
13307         u8      change_band = _FALSE;
13308
13309
13310         if(pbuddy_adapter != NULL && 
13311                 padapter->DualMacConcurrent == _TRUE)
13312         {
13313                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13314                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13315                 pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
13316                 pbuddy_network_mlmeext = &(pbuddy_mlmeinfo->network);
13317         
13318                 if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
13319                                 check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
13320                 {
13321                         //restart and update beacon
13322                         DBG_871X("after join, current adapter, CH=%d, BW=%d, offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
13323
13324                         if(join_res >= 0)
13325                         {
13326                                 u8 *p;
13327                                 int     ie_len;
13328                                 struct HT_info_element *pht_info=NULL;
13329
13330                                 if((pbuddy_mlmeext->cur_channel <= 14 && pmlmeext->cur_channel >= 36) ||
13331                                         (pbuddy_mlmeext->cur_channel >= 36 && pmlmeext->cur_channel <= 14))
13332                                 {
13333                                         change_band = _TRUE;
13334                                 }
13335
13336                                 //sync channel/bwmode/ch_offset with another adapter
13337                                 pbuddy_mlmeext->cur_channel = pmlmeext->cur_channel;
13338                                 
13339                                 if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40)
13340                                 {
13341                                         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)));
13342                                         if( p && ie_len)
13343                                         {
13344                                                 pht_info = (struct HT_info_element *)(p+2);
13345                                                 pht_info->infos[0] &= ~(BIT(0)|BIT(1)); //no secondary channel is present
13346                                         }       
13347                                 
13348                                         if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_40)
13349                                         {
13350                                                 pbuddy_mlmeext->cur_ch_offset = pmlmeext->cur_ch_offset;
13351
13352                                                 //to update cur_ch_offset value in beacon
13353                                                 if( pht_info )
13354                                                 {
13355                                                         switch(pmlmeext->cur_ch_offset)
13356                                                         {
13357                                                                 case HAL_PRIME_CHNL_OFFSET_LOWER:
13358                                                                         pht_info->infos[0] |= 0x1;
13359                                                                         break;
13360                                                                 case HAL_PRIME_CHNL_OFFSET_UPPER:
13361                                                                         pht_info->infos[0] |= 0x3;
13362                                                                         break;
13363                                                                 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   
13364                                                                 default:                                                        
13365                                                                         break;                                  
13366                                                         }
13367                                                 }
13368                                         }
13369                                         else if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_20)
13370                                         {
13371                                                 pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_20;
13372                                                 pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13373
13374                                                 if(pmlmeext->cur_channel>0 && pmlmeext->cur_channel<5)
13375                                                 {
13376                                                         if(pht_info)
13377                                                                 pht_info->infos[0] |= 0x1;
13378
13379                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_40;
13380                                                         pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
13381                                                 }
13382
13383                                                 if(pmlmeext->cur_channel>7 && pmlmeext->cur_channel<(14+1))
13384                                                 {
13385                                                         if(pht_info)
13386                                                                 pht_info->infos[0] |= 0x3;
13387
13388                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_40;
13389                                                         pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
13390                                                 }
13391
13392                                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13393                                         }
13394                                 }
13395
13396                                 // to update channel value in beacon
13397                                 pbuddy_network_mlmeext->Configuration.DSConfig = pmlmeext->cur_channel;
13398                                 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)));
13399                                 if(p && ie_len>0)
13400                                         *(p + 2) = pmlmeext->cur_channel;
13401
13402                                 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)));
13403                                 if( p && ie_len)
13404                                 {
13405                                         pht_info = (struct HT_info_element *)(p+2);
13406                                         pht_info->primary_channel = pmlmeext->cur_channel;
13407                                 }
13408
13409                                 // update mlmepriv's cur_network
13410                                 _rtw_memcpy(&pbuddy_mlmepriv->cur_network.network, pbuddy_network_mlmeext, pbuddy_network_mlmeext->Length);
13411                         }
13412                         else
13413                         {
13414                                 // switch back to original channel/bwmode/ch_offset;
13415                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13416                         }
13417
13418                         DBG_871X("after join, another adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
13419
13420                         if(change_band == _TRUE)
13421                                 change_band_update_ie(pbuddy_adapter, pbuddy_network_mlmeext);
13422
13423                         DBG_871X("update pbuddy_adapter's beacon\n");
13424
13425                         update_beacon(pbuddy_adapter, 0, NULL, _TRUE);
13426                 }
13427                 else     if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
13428                 {
13429                         if((pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
13430                                 (pmlmeext->cur_bwmode == CHANNEL_WIDTH_20))
13431                         {
13432                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13433                         }
13434                 
13435                         issue_nulldata(pbuddy_adapter, NULL, 0, 0, 0);
13436                 }
13437         }
13438 }
13439
13440 sint    dc_check_fwstate(_adapter *padapter, sint fw_state)
13441 {
13442         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13443         struct mlme_priv *pbuddy_mlmepriv = NULL;
13444
13445         if(padapter->pbuddy_adapter != NULL && 
13446                 padapter->DualMacConcurrent == _TRUE)
13447
13448         {
13449                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13450
13451                 return check_fwstate(pbuddy_mlmepriv, fw_state);
13452         }
13453
13454         return _FALSE;
13455 }
13456
13457 u8 dc_handle_site_survey(_adapter *padapter)
13458 {
13459         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13460         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
13461         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;             
13462
13463         // only mac0 can do scan request, help issue nulldata(1) for mac1
13464         if(pbuddy_adapter != NULL && 
13465                 padapter->DualMacConcurrent == _TRUE)
13466         {
13467                 if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
13468                 {
13469                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
13470                 
13471                         issue_nulldata(pbuddy_adapter, NULL, 1, 2, 0);                  
13472
13473                         return _TRUE;
13474                 }
13475         }
13476
13477         return _FALSE;
13478 }
13479
13480 void    dc_report_survey_event(_adapter *padapter, union recv_frame *precv_frame)
13481 {
13482         if(padapter->pbuddy_adapter != NULL && 
13483                 padapter->DualMacConcurrent == _TRUE)
13484         {
13485                 report_survey_event(padapter->pbuddy_adapter, precv_frame);     
13486         }
13487 }
13488
13489 void dc_set_channel_bwmode_survey_done(_adapter *padapter)
13490 {
13491         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
13492         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13493         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13494         struct mlme_priv *pbuddy_mlmepriv = NULL;
13495         struct mlme_ext_priv *pbuddy_mlmeext = NULL;
13496         struct mlme_ext_info *pbuddy_mlmeinfo = NULL;
13497         u8 cur_channel;
13498         u8 cur_bwmode;
13499         u8 cur_ch_offset;
13500
13501         if(pbuddy_adapter != NULL && 
13502                 padapter->DualMacConcurrent == _TRUE)
13503         {
13504                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13505                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13506                 pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
13507
13508                 if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
13509                 {
13510                         if(check_fwstate(pmlmepriv, _FW_LINKED) &&
13511                                 (pmlmeext->cur_bwmode == CHANNEL_WIDTH_40))
13512                         {
13513                                 cur_channel = pmlmeext->cur_channel;
13514                                 cur_bwmode = pmlmeext->cur_bwmode;
13515                                 cur_ch_offset = pmlmeext->cur_ch_offset;
13516                         }
13517                         else
13518                         {
13519                                 cur_channel = pbuddy_mlmeext->cur_channel;
13520                                 cur_bwmode = pbuddy_mlmeext->cur_bwmode;
13521                                 cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
13522                         }
13523                 }
13524                 else
13525                 {
13526                         cur_channel = pmlmeext->cur_channel;
13527                         cur_bwmode = pmlmeext->cur_bwmode;
13528                         cur_ch_offset = pmlmeext->cur_ch_offset;
13529                 }
13530
13531                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
13532
13533                 if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
13534                 {
13535                         //issue null data 
13536                         issue_nulldata(pbuddy_adapter, NULL, 0, 0, 0);
13537                 }
13538
13539                 if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
13540                         check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
13541                 {
13542
13543                         DBG_871X("survey done, current CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
13544
13545                         DBG_871X("restart pbuddy_adapter's beacon\n");
13546                 
13547                         update_beacon(pbuddy_adapter, 0, NULL, _TRUE);
13548                 }
13549         }
13550         else
13551         {
13552                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13553         }
13554 }
13555
13556 void dc_set_ap_channel_bandwidth(_adapter *padapter, u8 channel, u8 channel_offset, u8 bwmode)
13557 {
13558         u8      *p;
13559         u8      val8, cur_channel, cur_bwmode, cur_ch_offset, change_band;
13560         int     ie_len; 
13561         struct registry_priv    *pregpriv = &padapter->registrypriv;
13562         struct mlme_priv                *pmlmepriv = &(padapter->mlmepriv);
13563         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
13564         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
13565         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
13566         struct HT_info_element  *pht_info=NULL;
13567         _adapter        *pbuddy_adapter = padapter->pbuddy_adapter;
13568         struct mlme_priv        *pbuddy_mlmepriv = NULL;
13569         struct mlme_ext_priv    *pbuddy_mlmeext = NULL;
13570
13571         DBG_871X("dualmac_concurrent_ap_set_channel_bwmode ==>\n");
13572
13573         cur_channel = channel;
13574         cur_bwmode = bwmode;
13575         cur_ch_offset = channel_offset;
13576         change_band = _FALSE;
13577
13578         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)));
13579         if( p && ie_len)
13580         {
13581                 pht_info = (struct HT_info_element *)(p+2);
13582         }
13583
13584         if(pbuddy_adapter != NULL && 
13585                 padapter->DualMacConcurrent == _TRUE)
13586         {
13587                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13588                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13589                 
13590                 if(!check_fwstate(pbuddy_mlmepriv, _FW_LINKED|_FW_UNDER_LINKING|_FW_UNDER_SURVEY))
13591                 {
13592                         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
13593                 }
13594                 else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED)==_TRUE)
13595                 {
13596                         //To sync cur_channel/cur_bwmode/cur_ch_offset with another adapter
13597                         DBG_871X("Another iface is at linked state, sync cur_channel/cur_bwmode/cur_ch_offset\n");
13598                         DBG_871X("Another adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
13599                         DBG_871X("Current adapter, CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
13600                         
13601                         cur_channel = pbuddy_mlmeext->cur_channel;
13602                         if(cur_bwmode == CHANNEL_WIDTH_40)
13603                         {
13604                                 if(pht_info)
13605                                         pht_info->infos[0] &= ~(BIT(0)|BIT(1));
13606
13607                                 if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40)
13608                                 {
13609                                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
13610
13611                                         //to update cur_ch_offset value in beacon
13612                                         if(pht_info)
13613                                         {                               
13614                                                 switch(cur_ch_offset)
13615                                                 {
13616                                                         case HAL_PRIME_CHNL_OFFSET_LOWER:
13617                                                                 pht_info->infos[0] |= 0x1;
13618                                                                 break;
13619                                                         case HAL_PRIME_CHNL_OFFSET_UPPER:
13620                                                                 pht_info->infos[0] |= 0x3;
13621                                                                 break;
13622                                                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
13623                                                         default:                                                        
13624                                                                 break;                                  
13625                                                 }
13626                                         }
13627                                 }
13628                                 else if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_20)
13629                                 {
13630                                         cur_bwmode = CHANNEL_WIDTH_20;
13631                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13632
13633                                         if(cur_channel>0 && cur_channel<5)
13634                                         {
13635                                                 if(pht_info)
13636                                                         pht_info->infos[0] |= 0x1;              
13637
13638                                                 cur_bwmode = CHANNEL_WIDTH_40;
13639                                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
13640                                         }
13641
13642                                         if(cur_channel>7 && cur_channel<(14+1))
13643                                         {
13644                                                 if(pht_info)
13645                                                         pht_info->infos[0] |= 0x3;
13646
13647                                                 cur_bwmode = CHANNEL_WIDTH_40;
13648                                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
13649                                         }
13650
13651                                         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
13652                                 }
13653                         }
13654
13655                         // to update channel value in beacon
13656                         pnetwork->Configuration.DSConfig = cur_channel;         
13657                         p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
13658                         if(p && ie_len>0)
13659                                 *(p + 2) = cur_channel;
13660
13661                         if(pht_info)
13662                                 pht_info->primary_channel = cur_channel;
13663                 }
13664         }
13665         else
13666         {
13667                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
13668         }
13669
13670         DBG_871X("CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
13671
13672         if((channel <= 14 && cur_channel >= 36) ||
13673                 (channel >= 36 && cur_channel <= 14))
13674         {
13675                 change_band = _TRUE;
13676         }
13677
13678         pmlmeext->cur_channel = cur_channel;
13679         pmlmeext->cur_bwmode = cur_bwmode;
13680         pmlmeext->cur_ch_offset = cur_ch_offset;
13681
13682         if(change_band == _TRUE)
13683                 change_band_update_ie(padapter, pnetwork);
13684
13685         DBG_871X("dualmac_concurrent_ap_set_channel_bwmode <==\n");
13686 }
13687
13688 void dc_resume_xmit(_adapter *padapter)
13689 {
13690         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13691         
13692         if(pbuddy_adapter != NULL && 
13693                 padapter->DualMacConcurrent == _TRUE)
13694         {
13695                 DBG_871X("dc_resume_xmit,  resume pbuddy_adapter Tx\n");
13696                 rtw_os_xmit_schedule(pbuddy_adapter);
13697         }
13698 }
13699
13700 u8      dc_check_xmit(_adapter *padapter)
13701 {
13702         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13703         struct mlme_priv *pbuddy_mlmepriv = NULL;
13704
13705         if(pbuddy_adapter != NULL && 
13706                 padapter->DualMacConcurrent == _TRUE)
13707         {
13708                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13709                 if (check_fwstate(pbuddy_mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
13710                 {
13711                         DBG_871X("dc_check_xmit  pbuddy_adapter is under survey or under linking\n");
13712                         return _FALSE;
13713                 }
13714         }
13715
13716         return _TRUE;
13717 }
13718 #endif
13719
13720 #ifdef CONFIG_CONCURRENT_MODE
13721 sint check_buddy_mlmeinfo_state(_adapter *padapter, u32 state)
13722 {
13723         PADAPTER pbuddy_adapter;
13724         struct mlme_ext_priv *pbuddy_mlmeext;
13725         struct mlme_ext_info *pbuddy_mlmeinfo;
13726
13727         if(padapter == NULL)
13728                 return _FALSE;  
13729         
13730         pbuddy_adapter = padapter->pbuddy_adapter;
13731
13732         if(pbuddy_adapter == NULL)
13733                 return _FALSE;  
13734
13735
13736         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13737         pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
13738                 
13739         if((pbuddy_mlmeinfo->state&0x03) == state)
13740                 return _TRUE;           
13741
13742         return _FALSE;
13743         
13744 }
13745
13746 void concurrent_chk_joinbss_done(_adapter *padapter, int join_res)
13747 {
13748         struct mlme_ext_priv    *pmlmeext;
13749         struct mlme_ext_info    *pmlmeinfo;     
13750         PADAPTER pbuddy_adapter;
13751         struct mlme_priv *pbuddy_mlmepriv;
13752         struct mlme_ext_priv *pbuddy_mlmeext;
13753         struct mlme_ext_info *pbuddy_mlmeinfo;
13754         WLAN_BSSID_EX *pbuddy_network_mlmeext;
13755         WLAN_BSSID_EX *pnetwork;
13756
13757         pmlmeext = &padapter->mlmeextpriv;
13758         pmlmeinfo = &(pmlmeext->mlmext_info);
13759
13760
13761         if(!rtw_buddy_adapter_up(padapter))
13762         {
13763                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13764                 return;
13765         }
13766
13767         pbuddy_adapter = padapter->pbuddy_adapter;
13768         pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13769         pnetwork = (WLAN_BSSID_EX *)&pbuddy_mlmepriv->cur_network.network;
13770         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13771         pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
13772         pbuddy_network_mlmeext = &(pbuddy_mlmeinfo->network);
13773
13774         if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
13775                         check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
13776         {
13777                 //restart and update beacon
13778
13779                 DBG_871X("after join,primary adapter, CH=%d, BW=%d, offset=%d\n"
13780                         , pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
13781                 
13782
13783                 if(join_res >= 0)
13784                 {
13785                         u8 *p;
13786                         int     ie_len;
13787                         u8      change_band = _FALSE;
13788                         struct HT_info_element *pht_info=NULL;
13789
13790                         if((pmlmeext->cur_channel <= 14 && pbuddy_mlmeext->cur_channel >= 36) ||
13791                                 (pmlmeext->cur_channel >= 36 && pbuddy_mlmeext->cur_channel <= 14))
13792                                 change_band = _TRUE;
13793
13794                         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)));
13795                         if( p && ie_len)
13796                         {
13797                                 pht_info = (struct HT_info_element *)(p+2);
13798                                 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; //no secondary channel is present
13799                         }
13800
13801                         pbuddy_mlmeext->cur_channel = pmlmeext->cur_channel;
13802 #ifdef CONFIG_80211AC_VHT
13803                         if(pbuddy_mlmeext->cur_bwmode  == CHANNEL_WIDTH_80)
13804                         {
13805                                 u8 *pvht_cap_ie, *pvht_op_ie;
13806                                 int vht_cap_ielen, vht_op_ielen;
13807                         
13808                                 pvht_cap_ie = rtw_get_ie((pbuddy_network_mlmeext->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTCapability, &vht_cap_ielen, (pbuddy_network_mlmeext->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
13809                                 pvht_op_ie = rtw_get_ie((pbuddy_network_mlmeext->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTOperation, &vht_op_ielen, (pbuddy_network_mlmeext->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
13810                                                 
13811                                 if(pmlmeext->cur_channel <= 14) // downgrade to 20/40Mhz
13812                                 {
13813                                         //modify vht cap ie
13814                                         if( pvht_cap_ie && vht_cap_ielen)
13815                                         {
13816                                                 SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvht_cap_ie+2, 0);
13817                                         }
13818                                 
13819                                         //modify vht op ie
13820                                         if( pvht_op_ie && vht_op_ielen)
13821                                         {
13822                                                 SET_VHT_OPERATION_ELE_CHL_WIDTH(pvht_op_ie+2, 0); //change to 20/40Mhz
13823                                                 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pvht_op_ie+2, 0);
13824                                                 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(pvht_op_ie+2, 0);
13825                                                 //SET_VHT_OPERATION_ELE_BASIC_MCS_SET(p+2, 0xFFFF);                                     
13826                                                 pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_40;
13827                                         }               
13828                                 }
13829                                 else
13830                                 {
13831                                         u8      center_freq;
13832                                 
13833                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_80;
13834                                 
13835                                         if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||
13836                                                 pmlmeext->cur_bwmode == CHANNEL_WIDTH_80)
13837                                         {
13838                                                 pbuddy_mlmeext->cur_ch_offset = pmlmeext->cur_ch_offset;
13839                                         }
13840                                         else if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_20)
13841                                         {
13842                                                 pbuddy_mlmeext->cur_ch_offset =  rtw_get_offset_by_ch(pmlmeext->cur_channel);
13843                                         }       
13844
13845                                         //modify ht info ie
13846                                         if(pht_info)
13847                                                 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
13848                                 
13849                                         switch(pbuddy_mlmeext->cur_ch_offset)
13850                                         {
13851                                                 case HAL_PRIME_CHNL_OFFSET_LOWER:
13852                                                         if(pht_info)
13853                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;            
13854                                                         //cur_bwmode = CHANNEL_WIDTH_40;
13855                                                         break;
13856                                                 case HAL_PRIME_CHNL_OFFSET_UPPER:
13857                                                         if(pht_info)
13858                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;                                            
13859                                                         //cur_bwmode = CHANNEL_WIDTH_40;
13860                                                         break;
13861                                                 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   
13862                                                 default:
13863                                                         if(pht_info)
13864                                                                 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
13865                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_20;
13866                                                         pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13867                                                         break;                                  
13868                                         }
13869
13870                                         //modify vht op ie
13871                                         center_freq = rtw_get_center_ch(pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, HAL_PRIME_CHNL_OFFSET_LOWER);
13872                                         if( pvht_op_ie && vht_op_ielen)
13873                                                 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pvht_op_ie+2, center_freq);
13874
13875                                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13876                                 
13877                                 }
13878                         
13879                         }
13880 #endif //CONFIG_80211AC_VHT
13881                         
13882                         if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40)              
13883                         {
13884                                 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)));
13885                                 if( p && ie_len)
13886                                 {
13887                                         pht_info = (struct HT_info_element *)(p+2);
13888                                         pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; //no secondary channel is present
13889                                 }
13890                         
13891                                 if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||
13892                                         pmlmeext->cur_bwmode == CHANNEL_WIDTH_80)
13893                                 {
13894                                         pbuddy_mlmeext->cur_ch_offset = pmlmeext->cur_ch_offset;
13895
13896                                         //to update cur_ch_offset value in beacon
13897                                         if( pht_info )
13898                                         {
13899                                                 switch(pmlmeext->cur_ch_offset)
13900                                                 {
13901                                                         case HAL_PRIME_CHNL_OFFSET_LOWER:
13902                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
13903                                                                 break;
13904                                                         case HAL_PRIME_CHNL_OFFSET_UPPER:
13905                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
13906                                                                 break;
13907                                                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   
13908                                                         default:                                                        
13909                                                                 break;                                  
13910                                                 }
13911                                                 
13912                                         }                                       
13913                                 
13914                                 }
13915                                 else if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_20)
13916                                 {
13917                                         pbuddy_mlmeext->cur_ch_offset =  rtw_get_offset_by_ch(pmlmeext->cur_channel);
13918                                         
13919                                         switch(pbuddy_mlmeext->cur_ch_offset)
13920                                         {
13921                                                 case HAL_PRIME_CHNL_OFFSET_LOWER:
13922                                                         if(pht_info)
13923                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;            
13924                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_40;
13925                                                         break;
13926                                                 case HAL_PRIME_CHNL_OFFSET_UPPER:
13927                                                         if(pht_info)
13928                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;                                            
13929                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_40;
13930                                                         break;
13931                                                 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   
13932                                                 default:
13933                                                         if(pht_info)
13934                                                                 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
13935                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_20;
13936                                                         pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13937                                                         break;                                  
13938                                         }
13939                                         
13940                                 }
13941
13942                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13943
13944                         }
13945                         else
13946                         {
13947                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13948                         }
13949
13950                 
13951                         // to update channel value in beacon
13952                         pbuddy_network_mlmeext->Configuration.DSConfig = pmlmeext->cur_channel;         
13953                         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)));
13954                         if(p && ie_len>0)
13955                                 *(p + 2) = pmlmeext->cur_channel;
13956
13957                         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)));
13958                         if( p && ie_len)
13959                         {
13960                                 pht_info = (struct HT_info_element *)(p+2);
13961                                 pht_info->primary_channel = pmlmeext->cur_channel;
13962                         }
13963
13964                         //buddy interface band is different from current interface, update ERP, support rate, ext support rate IE
13965                         if(change_band == _TRUE)
13966                                 change_band_update_ie(pbuddy_adapter, pbuddy_network_mlmeext);
13967                 }
13968                 else
13969                 {
13970                         // switch back to original channel/bwmode/ch_offset;
13971                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13972                 }
13973
13974                 DBG_871X("after join, second adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
13975
13976                 DBG_871X("update pbuddy_adapter's beacon\n");
13977                 
13978                 _rtw_memcpy(pnetwork, pbuddy_network_mlmeext, sizeof(WLAN_BSSID_EX));
13979                 //update bmc rate to avoid bb cck hang
13980                 update_bmc_sta(pbuddy_adapter);
13981                 update_beacon(pbuddy_adapter, 0, NULL, _TRUE);
13982
13983         }
13984         else if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) &&
13985                         check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
13986         {               
13987                 if(join_res >= 0)
13988                 {       
13989                         pbuddy_mlmeext->cur_channel = pmlmeext->cur_channel;
13990                         if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||
13991                                 pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80)
13992                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);           
13993                         else if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||
13994                                 pmlmeext->cur_bwmode == CHANNEL_WIDTH_80)
13995                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);             
13996                         else
13997                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
13998                 }
13999                 else
14000                 {
14001                         // switch back to original channel/bwmode/ch_offset;
14002                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
14003                 }                       
14004         }
14005         else
14006         {
14007                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
14008         }
14009         
14010 }
14011 #endif //CONFIG_CONCURRENT_MODE
14012
14013 int rtw_chk_start_clnt_join(_adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
14014 {
14015         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
14016         unsigned char   cur_ch = pmlmeext->cur_channel;
14017         unsigned char   cur_bw = pmlmeext->cur_bwmode;
14018         unsigned char   cur_ch_offset = pmlmeext->cur_ch_offset;
14019         bool chbw_allow = _TRUE;
14020         bool connect_allow = _TRUE;
14021
14022 #ifdef CONFIG_CONCURRENT_MODE
14023         PADAPTER pbuddy_adapter;
14024         struct mlme_ext_priv *pbuddy_mlmeext;
14025         struct mlme_ext_info    *pbuddy_pmlmeinfo;
14026         struct mlme_priv *pbuddy_mlmepriv;
14027 #endif
14028
14029         if (!ch || !bw || !offset) {
14030                 connect_allow = _FALSE;
14031                 rtw_warn_on(1);
14032                 goto exit;
14033         }
14034
14035         if (cur_ch == 0) {
14036                 connect_allow = _FALSE;
14037                 DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" cur_ch:%u\n"
14038                         , FUNC_ADPT_ARG(padapter), cur_ch);
14039                 rtw_warn_on(1);
14040                 goto exit;
14041         }
14042
14043 #ifdef CONFIG_CONCURRENT_MODE
14044         if (!rtw_buddy_adapter_up(padapter)) {
14045                 goto exit;
14046         }
14047
14048         pbuddy_adapter = padapter->pbuddy_adapter;              
14049         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
14050         pbuddy_pmlmeinfo = &(pbuddy_mlmeext->mlmext_info);
14051         pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
14052
14053         if((pbuddy_pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)//for AP MODE
14054         {
14055                 DBG_871X("start_clnt_join: "ADPT_FMT"(ch=%d, bw=%d, ch_offset=%d)"
14056                         ", "ADPT_FMT" AP mode(ch=%d, bw=%d, ch_offset=%d)\n",
14057                         ADPT_ARG(padapter), pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset,
14058                         ADPT_ARG(pbuddy_adapter), pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
14059
14060                 if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel)
14061                 {
14062                         chbw_allow = _FALSE;
14063                 }
14064                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
14065                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
14066                         (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset))
14067                 {
14068                         chbw_allow = _FALSE;
14069                 }
14070                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_20) && 
14071                         ((pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40)||
14072                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80)) )
14073                 {
14074                         cur_ch = pmlmeext->cur_channel;
14075                         cur_bw = pbuddy_mlmeext->cur_bwmode;
14076                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
14077                 }
14078
14079                 DBG_871X("start_clnt_join: connect_allow:%d, chbw_allow:%d\n", connect_allow, chbw_allow);
14080                 if (chbw_allow == _FALSE) {
14081                         #ifdef CONFIG_SPCT_CH_SWITCH
14082                         if (1) {
14083                                 rtw_ap_inform_ch_switch(pbuddy_adapter, pmlmeext->cur_channel , pmlmeext->cur_ch_offset);
14084                         } else
14085                         #endif
14086                         {
14087                                 //issue deauth to all stas if if2 is at ap mode
14088                                 rtw_sta_flush(pbuddy_adapter);
14089                         }
14090                         rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
14091                 }
14092         }
14093         else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED) == _TRUE &&
14094                 check_fwstate(pbuddy_mlmepriv, WIFI_STATION_STATE) == _TRUE) //for Client Mode/p2p client
14095         {
14096                 DBG_871X("start_clnt_join: "ADPT_FMT"(ch=%d, bw=%d, ch_offset=%d)"
14097                         ", "ADPT_FMT" STA mode(ch=%d, bw=%d, ch_offset=%d)\n",
14098                         ADPT_ARG(padapter), pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset,
14099                         ADPT_ARG(pbuddy_adapter), pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
14100
14101                 if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel)
14102                 {
14103                         chbw_allow = _FALSE;
14104                 }
14105                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_20) &&
14106                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40))
14107                 {
14108                         cur_bw = CHANNEL_WIDTH_40;
14109                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
14110                 }
14111                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_20) &&
14112                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80))
14113                 {
14114                         cur_bw = CHANNEL_WIDTH_80;
14115                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
14116                 }
14117                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
14118                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
14119                         (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset))
14120                 {
14121                         chbw_allow = _FALSE;
14122                 }
14123                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
14124                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80))
14125                 {
14126                         if(pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)
14127                         {
14128                                 chbw_allow = _FALSE;
14129                         }
14130                         else
14131                         {
14132                                 cur_bw = CHANNEL_WIDTH_80;
14133                         }
14134                 }
14135                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_80) &&
14136                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40))
14137                 {
14138                         if(pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)
14139                         {
14140                                 chbw_allow = _FALSE;
14141                         }
14142                 }
14143                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_80) &&
14144                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80))
14145                 {
14146                         if(pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)
14147                         {
14148                                 chbw_allow = _FALSE;
14149                         }
14150                 }
14151
14152
14153                 connect_allow = chbw_allow;
14154
14155 #ifdef CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT
14156                 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
14157                 /* wlan0-sta mode has higher priority than p2p0-p2p client */
14158                 if (!rtw_p2p_chk_state(&(pbuddy_adapter->wdinfo), P2P_STATE_NONE)
14159                         && pbuddy_adapter->wdinfo.driver_interface == DRIVER_CFG80211)
14160                 {
14161                         connect_allow = _TRUE;
14162                 }
14163                 #endif /* CONFIG_P2P && CONFIG_IOCTL_CFG80211 */
14164 #else
14165                 connect_allow = _TRUE;
14166 #endif /* CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT */
14167
14168                 DBG_871X("start_clnt_join: connect_allow:%d, chbw_allow:%d\n", connect_allow, chbw_allow);
14169                 if (connect_allow == _TRUE && chbw_allow == _FALSE) {
14170                         /* disconnect buddy's connection */
14171                         rtw_disassoc_cmd(pbuddy_adapter, 500, _FALSE);
14172                         rtw_indicate_disconnect(pbuddy_adapter);
14173                         rtw_free_assoc_resources(pbuddy_adapter, 1);
14174                 }
14175         }       
14176
14177 #endif /* CONFIG_CONCURRENT_MODE */
14178
14179 exit:
14180
14181         if (connect_allow == _TRUE) {
14182                 DBG_871X("start_join_set_ch_bw: ch=%d, bwmode=%d, ch_offset=%d\n", cur_ch, cur_bw, cur_ch_offset);
14183                 *ch = cur_ch;
14184                 *bw = cur_bw;
14185                 *offset = cur_ch_offset;
14186         }
14187
14188         return connect_allow == _TRUE ? _SUCCESS : _FAIL;
14189 }
14190
14191 /* Find union about ch, bw, ch_offset of all linked/linking interfaces */
14192 int rtw_get_ch_setting_union(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
14193 {
14194         struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
14195         _adapter *iface;
14196         struct mlme_ext_priv *mlmeext;
14197         int i;
14198         u8 ch_ret = 0;
14199         u8 bw_ret = CHANNEL_WIDTH_20;
14200         u8 offset_ret = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
14201         int num = 0;
14202
14203         if (ch) *ch = 0;
14204         if (bw) *bw = CHANNEL_WIDTH_20;
14205         if (offset) *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
14206
14207         for (i = 0; i<dvobj->iface_nums; i++) {
14208                 iface = dvobj->padapters[i];
14209                 mlmeext = &iface->mlmeextpriv;
14210
14211                 if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING))
14212                         continue;
14213
14214                 if (num == 0) {
14215                         ch_ret = mlmeext->cur_channel;
14216                         bw_ret = mlmeext->cur_bwmode;
14217                         offset_ret = mlmeext->cur_ch_offset;
14218                         num++;
14219                         continue;
14220                 }
14221
14222                 if (ch_ret != mlmeext->cur_channel) {
14223                         num = 0;
14224                         break;
14225                 }
14226
14227                 if (bw_ret < mlmeext->cur_bwmode) {
14228                         bw_ret = mlmeext->cur_bwmode;
14229                         offset_ret = mlmeext->cur_ch_offset;
14230                 } else if (bw_ret == mlmeext->cur_bwmode && offset_ret != mlmeext->cur_ch_offset) {
14231                         num = 0;
14232                         break;
14233                 }
14234
14235                 num++;
14236         }
14237
14238         if (num) {
14239                 if (ch) *ch = ch_ret;
14240                 if (bw) *bw = bw_ret;
14241                 if (offset) *offset = offset_ret;
14242         }
14243
14244         return num;
14245 }
14246
14247 u8 set_ch_hdl(_adapter *padapter, u8 *pbuf)
14248 {
14249         struct set_ch_parm *set_ch_parm;
14250         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
14251         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
14252
14253         if(!pbuf)
14254                 return H2C_PARAMETERS_ERROR;
14255
14256         set_ch_parm = (struct set_ch_parm *)pbuf;
14257
14258         DBG_871X(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
14259                 FUNC_NDEV_ARG(padapter->pnetdev),
14260                 set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
14261
14262         pmlmeext->cur_channel = set_ch_parm->ch;
14263         pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
14264         pmlmeext->cur_bwmode = set_ch_parm->bw;
14265
14266         set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
14267
14268         return  H2C_SUCCESS;
14269 }
14270
14271 u8 set_chplan_hdl(_adapter *padapter, unsigned char *pbuf)
14272 {
14273         struct SetChannelPlan_param *setChannelPlan_param;
14274         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
14275         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
14276
14277         if(!pbuf)
14278                 return H2C_PARAMETERS_ERROR;
14279
14280         setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
14281
14282         pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
14283         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);   
14284
14285 #ifdef CONFIG_IOCTL_CFG80211
14286         rtw_reg_notify_by_driver(padapter);
14287 #endif //CONFIG_IOCTL_CFG80211
14288
14289         return  H2C_SUCCESS;
14290 }
14291
14292 u8 led_blink_hdl(_adapter *padapter, unsigned char *pbuf)
14293 {
14294         struct LedBlink_param *ledBlink_param;
14295
14296         if(!pbuf)
14297                 return H2C_PARAMETERS_ERROR;
14298
14299         ledBlink_param = (struct LedBlink_param *)pbuf;
14300
14301         #ifdef CONFIG_LED_HANDLED_BY_CMD_THREAD
14302         BlinkHandler((PLED_DATA)ledBlink_param->pLed);
14303         #endif
14304
14305         return  H2C_SUCCESS;
14306 }
14307
14308 u8 set_csa_hdl(_adapter *padapter, unsigned char *pbuf)
14309 {
14310 #ifdef CONFIG_DFS
14311         struct SetChannelSwitch_param *setChannelSwitch_param;
14312         u8 new_ch_no;
14313         u8 gval8 = 0x00, sval8 = 0xff;
14314
14315         if(!pbuf)
14316                 return H2C_PARAMETERS_ERROR;
14317
14318         setChannelSwitch_param = (struct SetChannelSwitch_param *)pbuf;
14319         new_ch_no = setChannelSwitch_param->new_ch_no;
14320
14321         rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, &gval8);
14322
14323         rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &sval8);
14324
14325         DBG_871X("DFS detected! Swiching channel to %d!\n", new_ch_no);
14326         SelectChannel(padapter, new_ch_no);
14327
14328         rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &gval8);
14329
14330         rtw_disassoc_cmd(padapter, 0, _FALSE);
14331         rtw_indicate_disconnect(padapter);
14332         rtw_free_assoc_resources(padapter, 1);
14333         rtw_free_network_queue(padapter, _TRUE);
14334
14335         if ( ((new_ch_no >= 52) && (new_ch_no <= 64)) ||((new_ch_no >= 100) && (new_ch_no <= 140)) ) {
14336                 DBG_871X("Switched to DFS band (ch %02x) again!!\n", new_ch_no);
14337         }
14338
14339         return  H2C_SUCCESS;
14340 #else
14341         return  H2C_REJECTED;
14342 #endif //CONFIG_DFS
14343
14344 }
14345
14346 // TDLS_ESTABLISHED     : write RCR DATA BIT
14347 // TDLS_CS_OFF          : go back to the channel linked with AP, terminating channel switch procedure
14348 // TDLS_INIT_CH_SEN     : init channel sensing, receive all data and mgnt frame
14349 // TDLS_DONE_CH_SEN: channel sensing and report candidate channel
14350 // TDLS_OFF_CH          : first time set channel to off channel
14351 // TDLS_BASE_CH         : go back tp the channel linked with AP when set base channel as target channel
14352 // TDLS_P_OFF_CH        : periodically go to off channel
14353 // TDLS_P_BASE_CH       : periodically go back to base channel
14354 // TDLS_RS_RCR          : restore RCR
14355 // TDLS_TEAR_STA        : free tdls sta
14356 u8 tdls_hdl(_adapter *padapter, unsigned char *pbuf)
14357 {
14358 #ifdef CONFIG_TDLS
14359         _irqL irqL;
14360         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
14361         struct TDLSoption_param *TDLSoption;
14362         struct sta_info *ptdls_sta;
14363         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
14364         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
14365         u8 survey_channel, i, min, option;
14366
14367         if(!pbuf)
14368                 return H2C_PARAMETERS_ERROR;
14369
14370         TDLSoption = (struct TDLSoption_param *)pbuf;
14371
14372         ptdls_sta = rtw_get_stainfo( &(padapter->stapriv), TDLSoption->addr );
14373         option = TDLSoption->option;
14374
14375         if( ptdls_sta == NULL )
14376         {
14377                 if( option != TDLS_RS_RCR )
14378                         return H2C_REJECTED;
14379         }
14380
14381         //_enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL);
14382         DBG_871X("[%s] option:%d\n", __FUNCTION__, option);
14383                 
14384         switch(option){
14385                 case TDLS_ESTABLISHED:
14386                 {
14387                         u8 sta_band = 0;
14388                         
14389                         //leave ALL PS when TDLS is established
14390                         rtw_pwr_wakeup(padapter);
14391                         
14392                         //As long as TDLS handshake success, we should set RCR_CBSSID_DATA bit to 0
14393                         //so we can receive all kinds of data frames.                   
14394                         rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_WRCR, 0);
14395                         DBG_871X("Created Direct Link with "MAC_FMT"\n", MAC_ARG(ptdls_sta->hwaddr));
14396
14397                         pmlmeinfo->FW_sta_info[ptdls_sta->mac_id].psta = ptdls_sta;
14398                         //set TDLS sta rate.
14399                         //update station supportRate
14400                         rtw_hal_update_sta_rate_mask(padapter, ptdls_sta);
14401                         if(padapter->mlmeextpriv.cur_channel > 14) {
14402                                 if (ptdls_sta->ra_mask & 0xffff000)
14403                                         sta_band |= WIRELESS_11_5N ;
14404
14405                                 if (ptdls_sta->ra_mask & 0xff0)
14406                                         sta_band |= WIRELESS_11A;
14407
14408                                 // 5G band
14409                                 #ifdef CONFIG_80211AC_VHT
14410                                 if (ptdls_sta->vhtpriv.vht_option)  {
14411                                         sta_band = WIRELESS_11_5AC;
14412                                 }               
14413                                 #endif
14414                                 
14415                         } else {
14416                                 if (ptdls_sta->ra_mask & 0xffff000)
14417                                         sta_band |= WIRELESS_11_24N;
14418
14419                                 if (ptdls_sta->ra_mask & 0xff0)
14420                                         sta_band |= WIRELESS_11G;
14421
14422                                 if (ptdls_sta->ra_mask & 0x0f)
14423                                         sta_band |= WIRELESS_11B;
14424                         }
14425                         ptdls_sta->wireless_mode = sta_band;
14426                         ptdls_sta->raid = rtw_hal_networktype_to_raid(padapter,ptdls_sta);
14427                         set_sta_rate(padapter, ptdls_sta);
14428                         //sta mode
14429                         rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,ptdls_sta,_TRUE);
14430                         break;
14431                 }
14432                 case TDLS_SD_PTI:
14433                         ptdls_sta->tdls_sta_state |= TDLS_WAIT_PTR_STATE;
14434                         issue_tdls_peer_traffic_indication(padapter, ptdls_sta);
14435                         _set_timer(&ptdls_sta->pti_timer, TDLS_PTI_TIME);
14436                         break;
14437                 case TDLS_CS_OFF:
14438                         _cancel_timer_ex(&ptdls_sta->base_ch_timer);
14439                         _cancel_timer_ex(&ptdls_sta->off_ch_timer);
14440                         SelectChannel(padapter, pmlmeext->cur_channel);
14441                         ptdls_sta->tdls_sta_state &= ~(TDLS_CH_SWITCH_ON_STATE | 
14442                                                                 TDLS_PEER_AT_OFF_STATE | 
14443                                                                 TDLS_AT_OFF_CH_STATE);
14444                         DBG_871X("go back to base channel\n ");
14445                         issue_nulldata(padapter, NULL, 0, 0, 0);
14446                         break;
14447                 case TDLS_INIT_CH_SEN:
14448                         rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_INIT_CH_SEN, 0);
14449                         pmlmeext->sitesurvey_res.channel_idx = 0;
14450                         ptdls_sta->option = TDLS_DONE_CH_SEN;
14451                         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_DONE_CH_SEN);
14452                         break;
14453                 case TDLS_DONE_CH_SEN:
14454                         survey_channel = pmlmeext->channel_set[pmlmeext->sitesurvey_res.channel_idx].ChannelNum;
14455                         if(survey_channel){
14456                                 SelectChannel(padapter, survey_channel);
14457                                 ptdlsinfo->cur_channel = survey_channel;
14458                                 pmlmeext->sitesurvey_res.channel_idx++;
14459                                 _set_timer(&ptdls_sta->option_timer, SURVEY_TO);
14460                         }else{
14461                                 SelectChannel(padapter, pmlmeext->cur_channel);
14462
14463                                 rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_DONE_CH_SEN, 0);
14464
14465                                 if(ptdlsinfo->ch_sensing==1){
14466                                         ptdlsinfo->ch_sensing=0;
14467                                         ptdlsinfo->cur_channel=1;
14468                                         min=ptdlsinfo->collect_pkt_num[0];
14469                                         for(i=1; i<MAX_CHANNEL_NUM-1; i++){
14470                                                 if(min > ptdlsinfo->collect_pkt_num[i]){
14471                                                         ptdlsinfo->cur_channel=i+1;
14472                                                         min=ptdlsinfo->collect_pkt_num[i];
14473                                                 }
14474                                                 ptdlsinfo->collect_pkt_num[i]=0;
14475                                         }
14476                                         ptdlsinfo->collect_pkt_num[0]=0;
14477                                         ptdlsinfo->candidate_ch=ptdlsinfo->cur_channel;
14478                                         DBG_871X("TDLS channel sensing done, candidate channel: %02x\n", ptdlsinfo->candidate_ch);
14479                                         ptdlsinfo->cur_channel=0;
14480
14481                                 }
14482
14483                                 if(ptdls_sta->tdls_sta_state & TDLS_PEER_SLEEP_STATE){
14484                                         ptdls_sta->tdls_sta_state |= TDLS_APSD_CHSW_STATE;
14485                                 }else{
14486                                         //send null data with pwrbit==1 before send ch_switching_req to peer STA.
14487                                         issue_nulldata(padapter, NULL, 1, 0, 0);
14488
14489                                         ptdls_sta->tdls_sta_state |= TDLS_CH_SW_INITIATOR_STATE;
14490
14491                                         issue_tdls_ch_switch_req(padapter, ptdls_sta->hwaddr);
14492                                         DBG_871X("issue tdls ch switch req\n");
14493                                 }
14494                         }
14495                         break;
14496                 case TDLS_OFF_CH:
14497                         issue_nulldata(padapter, NULL, 1, 0, 0);
14498                         SelectChannel(padapter, ptdls_sta->off_ch);
14499
14500                         DBG_871X("change channel to tar ch:%02x\n", ptdls_sta->off_ch);
14501                         ptdls_sta->tdls_sta_state |= TDLS_AT_OFF_CH_STATE;
14502                         ptdls_sta->tdls_sta_state &= ~(TDLS_PEER_AT_OFF_STATE);
14503                         _set_timer(&ptdls_sta->option_timer, (u32)ptdls_sta->ch_switch_time);
14504                         break;
14505                 case TDLS_BASE_CH:
14506                         _cancel_timer_ex(&ptdls_sta->base_ch_timer);
14507                         _cancel_timer_ex(&ptdls_sta->off_ch_timer);
14508                         SelectChannel(padapter, pmlmeext->cur_channel);
14509                         ptdls_sta->tdls_sta_state &= ~(TDLS_CH_SWITCH_ON_STATE | 
14510                                                                 TDLS_PEER_AT_OFF_STATE | 
14511                                                                 TDLS_AT_OFF_CH_STATE);
14512                         DBG_871X("go back to base channel\n ");
14513                         issue_nulldata(padapter, NULL, 0, 0, 0);
14514                         _set_timer(&ptdls_sta->option_timer, (u32)ptdls_sta->ch_switch_time);
14515                         break;
14516                 case TDLS_P_OFF_CH:
14517                         SelectChannel(padapter, pmlmeext->cur_channel);
14518                         issue_nulldata(padapter, NULL, 0, 0, 0);
14519                         DBG_871X("change channel to base ch:%02x\n", pmlmeext->cur_channel);
14520                         ptdls_sta->tdls_sta_state &= ~(TDLS_PEER_AT_OFF_STATE| TDLS_AT_OFF_CH_STATE);
14521                         _set_timer(&ptdls_sta->off_ch_timer, TDLS_STAY_TIME);
14522                         break;
14523                 case TDLS_P_BASE_CH:
14524                         issue_nulldata(ptdls_sta->padapter, NULL, 1, 0, 0);
14525                         SelectChannel(padapter, ptdls_sta->off_ch);
14526                         DBG_871X("change channel to off ch:%02x\n", ptdls_sta->off_ch);
14527                         ptdls_sta->tdls_sta_state |= TDLS_AT_OFF_CH_STATE;
14528                         if((ptdls_sta->tdls_sta_state & TDLS_PEER_AT_OFF_STATE) != TDLS_PEER_AT_OFF_STATE){
14529                                 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 3, 300);
14530                         }
14531                         _set_timer(&ptdls_sta->base_ch_timer, TDLS_STAY_TIME);  
14532                         break;
14533                 case TDLS_RS_RCR:
14534                         rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_RS_RCR, 0);
14535                         DBG_871X("wirte REG_RCR, set bit6 on\n");
14536                         break;
14537                 case TDLS_TEAR_STA:
14538                         free_tdls_sta(padapter, ptdls_sta);
14539                         break;
14540                         
14541         }
14542
14543         //_exit_critical_bh(&(ptdlsinfo->hdl_lock), &irqL);
14544
14545         return H2C_SUCCESS;
14546 #else
14547         return H2C_REJECTED;
14548 #endif //CONFIG_TDLS
14549
14550 }
14551