WiFi: add rtl8189es/etv support, Optimization wifi configuration.
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8189es / 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 #ifdef CONFIG_SOFTAP_NO_CHECK_SUPPORT_RATE
1957                 supportRateNum = rtw_get_rateset_len(cur->SupportedRates);
1958                 _rtw_memcpy(supportRate, cur->SupportedRates, supportRateNum);
1959 #else
1960                 // use our own rate set as statoin used
1961                 //_rtw_memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN);
1962                 //supportRateNum = AP_BSSRATE_LEN;
1963                 
1964                 status = _STATS_FAILURE_;
1965                 goto OnAssocReqFail;
1966 #endif
1967         }
1968         else {
1969                 _rtw_memcpy(supportRate, p+2, ie_len);
1970                 supportRateNum = ie_len;
1971
1972                 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &ie_len,
1973                                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1974                 if (p !=  NULL) {
1975                         
1976                         if(supportRateNum<=sizeof(supportRate))
1977                         {
1978                                 _rtw_memcpy(supportRate+supportRateNum, p+2, ie_len);
1979                                 supportRateNum += ie_len;
1980                         }                       
1981                 }
1982         }
1983
1984         //todo: mask supportRate between AP & STA -> move to update raid
1985         //get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0);
1986
1987         //update station supportRate    
1988         pstat->bssratelen = supportRateNum;
1989         _rtw_memcpy(pstat->bssrateset, supportRate, supportRateNum);
1990         UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1991
1992         //check RSN/WPA/WPS
1993         pstat->dot8021xalg = 0;
1994         pstat->wpa_psk = 0;
1995         pstat->wpa_group_cipher = 0;
1996         pstat->wpa2_group_cipher = 0;
1997         pstat->wpa_pairwise_cipher = 0;
1998         pstat->wpa2_pairwise_cipher = 0;
1999         _rtw_memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
2000         if((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
2001
2002                 int group_cipher=0, pairwise_cipher=0;  
2003                 
2004                 wpa_ie = elems.rsn_ie;
2005                 wpa_ie_len = elems.rsn_ie_len;
2006
2007                 if(rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
2008                 {
2009                         pstat->dot8021xalg = 1;//psk,  todo:802.1x                                              
2010                         pstat->wpa_psk |= BIT(1);
2011
2012                         pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;                               
2013                         pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
2014                         
2015                         if(!pstat->wpa2_group_cipher)
2016                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
2017
2018                         if(!pstat->wpa2_pairwise_cipher)
2019                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
2020                 }
2021                 else
2022                 {
2023                         status = WLAN_STATUS_INVALID_IE;
2024                 }       
2025                         
2026         } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
2027
2028                 int group_cipher=0, pairwise_cipher=0;  
2029                 
2030                 wpa_ie = elems.wpa_ie;
2031                 wpa_ie_len = elems.wpa_ie_len;
2032
2033                 if(rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
2034                 {
2035                         pstat->dot8021xalg = 1;//psk,  todo:802.1x                                              
2036                         pstat->wpa_psk |= BIT(0);
2037
2038                         pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;                         
2039                         pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
2040                         
2041                         if(!pstat->wpa_group_cipher)
2042                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
2043
2044                         if(!pstat->wpa_pairwise_cipher)
2045                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
2046                 
2047                 }
2048                 else
2049                 {
2050                         status = WLAN_STATUS_INVALID_IE;
2051                 }
2052                 
2053         } else {
2054                 wpa_ie = NULL;
2055                 wpa_ie_len = 0;
2056         }
2057
2058         if(_STATS_SUCCESSFUL_ != status)
2059                 goto OnAssocReqFail;
2060
2061         pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
2062         //if (hapd->conf->wps_state && wpa_ie == NULL) { //todo: to check ap if supporting WPS
2063         if(wpa_ie == NULL) {
2064                 if (elems.wps_ie) {
2065                         DBG_871X("STA included WPS IE in "
2066                                    "(Re)Association Request - assume WPS is "
2067                                    "used\n");
2068                         pstat->flags |= WLAN_STA_WPS;
2069                         //wpabuf_free(sta->wps_ie);
2070                         //sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4,
2071                         //                              elems.wps_ie_len - 4);
2072                 } else {
2073                         DBG_871X("STA did not include WPA/RSN IE "
2074                                    "in (Re)Association Request - possible WPS "
2075                                    "use\n");
2076                         pstat->flags |= WLAN_STA_MAYBE_WPS;
2077                 }
2078
2079
2080                 // AP support WPA/RSN, and sta is going to do WPS, but AP is not ready
2081                 // that the selected registrar of AP is _FLASE
2082                 if((psecuritypriv->wpa_psk >0)  
2083                         && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS)))
2084                 {
2085                         if(pmlmepriv->wps_beacon_ie)
2086                         {       
2087                                 u8 selected_registrar = 0;
2088                                 
2089                                 rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR , &selected_registrar, NULL);
2090
2091                                 if(!selected_registrar)
2092                                 {                                               
2093                                         DBG_871X("selected_registrar is _FALSE , or AP is not ready to do WPS\n");
2094                                                 
2095                                         status = _STATS_UNABLE_HANDLE_STA_;
2096                         
2097                                         goto OnAssocReqFail;
2098                                 }                                               
2099                         }                       
2100                 }
2101                         
2102         }
2103         else
2104         {
2105                 int copy_len;
2106
2107                 if(psecuritypriv->wpa_psk == 0)
2108                 {
2109                         DBG_871X("STA " MAC_FMT ": WPA/RSN IE in association "
2110                         "request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr));
2111                         
2112                         status = WLAN_STATUS_INVALID_IE;
2113                         
2114                         goto OnAssocReqFail;
2115
2116                 }
2117
2118                 if (elems.wps_ie) {
2119                         DBG_871X("STA included WPS IE in "
2120                                    "(Re)Association Request - WPS is "
2121                                    "used\n");
2122                         pstat->flags |= WLAN_STA_WPS;
2123                         copy_len=0;
2124                 }
2125                 else
2126                 {
2127                         copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
2128                 }
2129
2130                 
2131                 if(copy_len>0)
2132                         _rtw_memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
2133                 
2134         }
2135
2136
2137         // check if there is WMM IE & support WWM-PS
2138         pstat->flags &= ~WLAN_STA_WME;
2139         pstat->qos_option = 0;
2140         pstat->qos_info = 0;
2141         pstat->has_legacy_ac = _TRUE;
2142         pstat->uapsd_vo = 0;
2143         pstat->uapsd_vi = 0;
2144         pstat->uapsd_be = 0;
2145         pstat->uapsd_bk = 0;
2146         if (pmlmepriv->qospriv.qos_option) 
2147         {
2148                 p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
2149                 for (;;) 
2150                 {
2151                         p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
2152                         if (p != NULL) {
2153                                 if (_rtw_memcmp(p+2, WMM_IE, 6)) {
2154
2155                                         pstat->flags |= WLAN_STA_WME;
2156                                         
2157                                         pstat->qos_option = 1;                          
2158                                         pstat->qos_info = *(p+8);
2159                                         
2160                                         pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
2161
2162                                         if((pstat->qos_info&0xf) !=0xf)
2163                                                 pstat->has_legacy_ac = _TRUE;
2164                                         else
2165                                                 pstat->has_legacy_ac = _FALSE;
2166                                         
2167                                         if(pstat->qos_info&0xf)
2168                                         {
2169                                                 if(pstat->qos_info&BIT(0))
2170                                                         pstat->uapsd_vo = BIT(0)|BIT(1);
2171                                                 else
2172                                                         pstat->uapsd_vo = 0;
2173                 
2174                                                 if(pstat->qos_info&BIT(1))
2175                                                         pstat->uapsd_vi = BIT(0)|BIT(1);
2176                                                 else
2177                                                         pstat->uapsd_vi = 0;
2178                         
2179                                                 if(pstat->qos_info&BIT(2))
2180                                                         pstat->uapsd_bk = BIT(0)|BIT(1);
2181                                                 else
2182                                                         pstat->uapsd_bk = 0;
2183                         
2184                                                 if(pstat->qos_info&BIT(3))                      
2185                                                         pstat->uapsd_be = BIT(0)|BIT(1);
2186                                                 else
2187                                                         pstat->uapsd_be = 0;
2188                 
2189                                         }
2190         
2191                                         break;
2192                                 }
2193                         }
2194                         else {
2195                                 break;
2196                         }
2197                         p = p + ie_len + 2;
2198                 }
2199         }
2200
2201
2202 #ifdef CONFIG_80211N_HT
2203         /* save HT capabilities in the sta object */
2204         _rtw_memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
2205         if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) 
2206         {
2207                 pstat->flags |= WLAN_STA_HT;
2208                 
2209                 pstat->flags |= WLAN_STA_WME;
2210                 
2211                 _rtw_memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));                 
2212                 
2213         } else
2214                 pstat->flags &= ~WLAN_STA_HT;
2215
2216         
2217         if((pmlmepriv->htpriv.ht_option == _FALSE) && (pstat->flags&WLAN_STA_HT))
2218         {
2219                 status = _STATS_FAILURE_;
2220                 goto OnAssocReqFail;
2221         }
2222                 
2223
2224         if ((pstat->flags & WLAN_STA_HT) &&
2225                     ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
2226                       (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP)))
2227         {                   
2228                 DBG_871X("HT: " MAC_FMT " tried to "
2229                                    "use TKIP with HT association\n", MAC_ARG(pstat->hwaddr));
2230                 
2231                 //status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
2232                 //goto OnAssocReqFail;
2233         }
2234 #endif /* CONFIG_80211N_HT */
2235
2236 #ifdef CONFIG_80211AC_VHT
2237         _rtw_memset(&pstat->vhtpriv, 0, sizeof(struct vht_priv));
2238         if (elems.vht_capabilities && elems.vht_capabilities_len == 12) {
2239                 pstat->flags |= WLAN_STA_VHT;
2240
2241                 _rtw_memcpy(pstat->vhtpriv.vht_cap, elems.vht_capabilities, 12);
2242
2243                 if (elems.vht_op_mode_notify && elems.vht_op_mode_notify_len == 1) {
2244                         _rtw_memcpy(&pstat->vhtpriv.vht_op_mode_notify, elems.vht_op_mode_notify, 1);
2245                 }
2246         }
2247         else {
2248                 pstat->flags &= ~WLAN_STA_VHT;
2249         }
2250
2251         if((pmlmepriv->vhtpriv.vht_option == _FALSE) && (pstat->flags&WLAN_STA_VHT))
2252         {
2253                 status = _STATS_FAILURE_;
2254                 goto OnAssocReqFail;
2255         }
2256 #endif /* CONFIG_80211AC_VHT */
2257
2258        //
2259        //if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)//?
2260         pstat->flags |= WLAN_STA_NONERP;        
2261         for (i = 0; i < pstat->bssratelen; i++) {
2262                 if ((pstat->bssrateset[i] & 0x7f) > 22) {
2263                         pstat->flags &= ~WLAN_STA_NONERP;
2264                         break;
2265                 }
2266         }
2267
2268         if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
2269                 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
2270         else
2271                 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
2272
2273         
2274         
2275         if (status != _STATS_SUCCESSFUL_)
2276                 goto OnAssocReqFail;
2277
2278 #ifdef CONFIG_P2P
2279         pstat->is_p2p_device = _FALSE;
2280         if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2281         {               
2282                 if( (p2pie=rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , NULL, &p2pielen)))
2283                 {
2284                         pstat->is_p2p_device = _TRUE;
2285                         if((p2p_status_code=(u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat))>0)
2286                         {
2287                                 pstat->p2p_status_code = p2p_status_code;
2288                                 status = _STATS_CAP_FAIL_;
2289                                 goto OnAssocReqFail;
2290                         }
2291                 }
2292 #ifdef CONFIG_WFD
2293                 if(rtw_get_wfd_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , wfd_ie, &wfd_ielen ))
2294                 {
2295                         u8      attr_content[ 10 ] = { 0x00 };
2296                         u32     attr_contentlen = 0;
2297
2298                         DBG_8192C( "[%s] WFD IE Found!!\n", __FUNCTION__ );
2299                         rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
2300                         if ( attr_contentlen )
2301                         {
2302                                 pwdinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );
2303                                 DBG_8192C( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_rtsp_ctrlport );
2304                         }
2305                 }
2306 #endif
2307         }
2308         pstat->p2p_status_code = p2p_status_code;
2309 #endif //CONFIG_P2P
2310
2311         //TODO: identify_proprietary_vendor_ie();
2312         // Realtek proprietary IE
2313         // identify if this is Broadcom sta
2314         // identify if this is ralink sta
2315         // Customer proprietary IE
2316
2317         
2318
2319         /* get a unique AID */
2320         if (pstat->aid > 0) {
2321                 DBG_871X("  old AID %d\n", pstat->aid);
2322         } else {
2323                 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
2324                         if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
2325                                 break;
2326                                 
2327                 //if (pstat->aid > NUM_STA) {
2328                 if (pstat->aid > pstapriv->max_num_sta) {
2329                                 
2330                         pstat->aid = 0;
2331                                 
2332                         DBG_871X("  no room for more AIDs\n");
2333
2334                         status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2335                                 
2336                         goto OnAssocReqFail;
2337                                 
2338                         
2339                 } else {
2340                         pstapriv->sta_aid[pstat->aid - 1] = pstat;
2341                         DBG_871X("allocate new AID = (%d)\n", pstat->aid);
2342                 }       
2343         }
2344
2345
2346         pstat->state &= (~WIFI_FW_ASSOC_STATE); 
2347         pstat->state |= WIFI_FW_ASSOC_SUCCESS;
2348         
2349         _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
2350         if (!rtw_is_list_empty(&pstat->auth_list))
2351         {
2352                 rtw_list_delete(&pstat->auth_list);
2353                 pstapriv->auth_list_cnt--;
2354         }
2355         _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
2356
2357         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);   
2358         if (rtw_is_list_empty(&pstat->asoc_list))
2359         {
2360                 pstat->expire_to = pstapriv->expire_to;
2361                 rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list);
2362                 pstapriv->asoc_list_cnt++;
2363         }
2364         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2365
2366         // now the station is qualified to join our BSS...      
2367         if(pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_==status))
2368         {
2369 #ifdef CONFIG_NATIVEAP_MLME
2370                 //.1 bss_cap_update & sta_info_update
2371                 bss_cap_update_on_sta_join(padapter, pstat);
2372                 sta_info_update(padapter, pstat);
2373
2374                 //.2 issue assoc rsp before notify station join event.
2375                 if (frame_type == WIFI_ASSOCREQ)
2376                         issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
2377                 else
2378                         issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
2379
2380 #ifdef CONFIG_IOCTL_CFG80211
2381                 _enter_critical_bh(&pstat->lock, &irqL);
2382                 if(pstat->passoc_req)
2383                 {
2384                         rtw_mfree(pstat->passoc_req, pstat->assoc_req_len);
2385                         pstat->passoc_req = NULL;
2386                         pstat->assoc_req_len = 0;
2387                 }
2388
2389                 pstat->passoc_req =  rtw_zmalloc(pkt_len);
2390                 if(pstat->passoc_req)
2391                 {
2392                         _rtw_memcpy(pstat->passoc_req, pframe, pkt_len);
2393                         pstat->assoc_req_len = pkt_len;
2394                 }
2395                 _exit_critical_bh(&pstat->lock, &irqL);
2396 #endif //CONFIG_IOCTL_CFG80211
2397
2398                 //.3-(1) report sta add event
2399                 report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
2400         
2401 #endif //CONFIG_NATIVEAP_MLME
2402         }
2403
2404         return _SUCCESS;
2405
2406 asoc_class2_error:
2407
2408 #ifdef CONFIG_NATIVEAP_MLME
2409         issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
2410 #endif
2411
2412         return _FAIL;           
2413
2414 OnAssocReqFail:
2415
2416
2417 #ifdef CONFIG_NATIVEAP_MLME
2418         pstat->aid = 0;
2419         if (frame_type == WIFI_ASSOCREQ)
2420                 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
2421         else
2422                 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
2423 #endif
2424
2425
2426 #endif /* CONFIG_AP_MODE */
2427
2428         return _FAIL;           
2429
2430 }
2431
2432 unsigned int OnAssocRsp(_adapter *padapter, union recv_frame *precv_frame)
2433 {
2434         uint i;
2435         int res;
2436         unsigned short  status;
2437         PNDIS_802_11_VARIABLE_IEs       pIE;
2438         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2439         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2440         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2441         //WLAN_BSSID_EX                 *cur_network = &(pmlmeinfo->network);
2442         u8 *pframe = precv_frame->u.hdr.rx_data;
2443         uint pkt_len = precv_frame->u.hdr.len;
2444         PNDIS_802_11_VARIABLE_IEs       pWapiIE = NULL;
2445
2446         DBG_871X("%s\n", __FUNCTION__);
2447         
2448         //check A1 matches or not
2449         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
2450                 return _SUCCESS;
2451
2452         if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
2453                 return _SUCCESS;
2454
2455         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
2456                 return _SUCCESS;
2457
2458         _cancel_timer_ex(&pmlmeext->link_timer);
2459
2460         //status
2461         if ((status = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 2))) > 0)
2462         {
2463                 DBG_871X("assoc reject, status code: %d\n", status);
2464                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
2465                 res = -4;
2466                 goto report_assoc_result;
2467         }
2468
2469         //get capabilities
2470         pmlmeinfo->capability = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
2471
2472         //set slot time
2473         pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
2474
2475         //AID
2476         res = pmlmeinfo->aid = (int)(le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
2477
2478         //following are moved to join event callback function
2479         //to handle HT, WMM, rate adaptive, update MAC reg
2480         //for not to handle the synchronous IO in the tasklet
2481         for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;)
2482         {
2483                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pframe + i);
2484
2485                 switch (pIE->ElementID)
2486                 {
2487                         case _VENDOR_SPECIFIC_IE_:
2488                                 if (_rtw_memcmp(pIE->data, WMM_PARA_OUI, 6))    //WMM
2489                                 {
2490                                         WMM_param_handler(padapter, pIE);
2491                                 }
2492 #if defined(CONFIG_P2P) && defined(CONFIG_WFD)
2493                                 else if ( _rtw_memcmp(pIE->data, WFD_OUI, 4))           //WFD
2494                                 {
2495                                         DBG_871X( "[%s] Found WFD IE\n", __FUNCTION__ );
2496                                         WFD_info_handler( padapter, pIE );
2497                                 }
2498 #endif                          
2499                                 break;
2500
2501 #ifdef CONFIG_WAPI_SUPPORT
2502                         case _WAPI_IE_:
2503                                 pWapiIE = pIE;
2504                                 break;
2505 #endif
2506
2507                         case _HT_CAPABILITY_IE_:        //HT caps
2508                                 HT_caps_handler(padapter, pIE);
2509                                 break;
2510
2511                         case _HT_EXTRA_INFO_IE_:        //HT info
2512                                 HT_info_handler(padapter, pIE);
2513                                 break;
2514
2515 #ifdef CONFIG_80211AC_VHT
2516                         case EID_VHTCapability:
2517                                 VHT_caps_handler(padapter, pIE);
2518                                 break;
2519
2520                         case EID_VHTOperation:
2521                                 VHT_operation_handler(padapter, pIE);
2522                                 break;
2523 #endif
2524
2525                         case _ERPINFO_IE_:
2526                                 ERP_IE_handler(padapter, pIE);
2527
2528                         default:
2529                                 break;
2530                 }
2531
2532                 i += (pIE->Length + 2);
2533         }
2534
2535 #ifdef CONFIG_WAPI_SUPPORT
2536         rtw_wapi_on_assoc_ok(padapter, pIE);
2537 #endif
2538
2539         pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
2540         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
2541
2542         //Update Basic Rate Table for spec, 2010-12-28 , by thomas
2543         UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
2544
2545 report_assoc_result:
2546         if (res > 0) {
2547                 rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
2548         } else {
2549                 rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
2550         }
2551
2552         report_join_res(padapter, res);
2553
2554         return _SUCCESS;
2555 }
2556
2557 unsigned int OnDeAuth(_adapter *padapter, union recv_frame *precv_frame)
2558 {
2559         unsigned short  reason;
2560         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2561         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2562         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2563         u8 *pframe = precv_frame->u.hdr.rx_data;
2564 #ifdef CONFIG_P2P
2565         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
2566 #endif //CONFIG_P2P
2567
2568         //check A3
2569         if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
2570                 return _SUCCESS;
2571
2572 #ifdef CONFIG_P2P
2573         if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
2574         {
2575                 _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
2576                 _set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
2577         }
2578 #endif //CONFIG_P2P
2579
2580         reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
2581
2582         DBG_871X("%s Reason code(%d)\n", __FUNCTION__,reason);
2583
2584         rtw_lock_rx_suspend_timeout(8000);
2585
2586 #ifdef CONFIG_AP_MODE
2587         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
2588         {               
2589                 _irqL irqL;
2590                 struct sta_info *psta;
2591                 struct sta_priv *pstapriv = &padapter->stapriv;
2592                 
2593                 //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);                
2594                 //rtw_free_stainfo(padapter, psta);
2595                 //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);         
2596
2597                 DBG_871X_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
2598                                 reason, GetAddr2Ptr(pframe));
2599
2600                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));  
2601                 if(psta)
2602                 {
2603                         u8 updated = _FALSE;
2604                 
2605                         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2606                         if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
2607                         {                       
2608                                 rtw_list_delete(&psta->asoc_list);
2609                                 pstapriv->asoc_list_cnt--;
2610                                 updated = ap_free_sta(padapter, psta, _FALSE, reason);
2611
2612                         }
2613                         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2614
2615                         associated_clients_update(padapter, updated);
2616                 }
2617                 
2618
2619                 return _SUCCESS;
2620         }
2621         else
2622 #endif
2623         {
2624                 int     ignore_received_deauth = 0;
2625
2626                 //      Commented by Albert 20130604
2627                 //      Before sending the auth frame to start the STA/GC mode connection with AP/GO, 
2628                 //      we will send the deauth first.
2629                 //      However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth.
2630                 //      Added the following code to avoid this case.
2631                 if ( ( pmlmeinfo->state & WIFI_FW_AUTH_STATE ) ||
2632                         ( pmlmeinfo->state & WIFI_FW_ASSOC_STATE ) )
2633                 {
2634                         if ( reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA )
2635                         {
2636                                 ignore_received_deauth = 1;
2637                         } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) {
2638                                 // TODO: 802.11r
2639                                 ignore_received_deauth = 1;
2640                         }
2641                 }
2642
2643                 DBG_871X_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n",
2644                                 reason, GetAddr3Ptr(pframe), ignore_received_deauth);
2645                 
2646                 if ( 0 == ignore_received_deauth )
2647                 {
2648                         receive_disconnect(padapter, GetAddr3Ptr(pframe) ,reason);
2649                 }
2650         }       
2651         pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
2652         return _SUCCESS;
2653
2654 }
2655
2656 unsigned int OnDisassoc(_adapter *padapter, union recv_frame *precv_frame)
2657 {
2658         unsigned short  reason;
2659         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2660         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2661         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2662         u8 *pframe = precv_frame->u.hdr.rx_data;
2663 #ifdef CONFIG_P2P
2664         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
2665 #endif //CONFIG_P2P
2666
2667         //check A3
2668         if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
2669                 return _SUCCESS;
2670
2671 #ifdef CONFIG_P2P
2672         if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
2673         {
2674                 _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
2675                 _set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
2676         }
2677 #endif //CONFIG_P2P
2678
2679         reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
2680
2681         DBG_871X("%s Reason code(%d)\n", __FUNCTION__,reason);
2682
2683         rtw_lock_rx_suspend_timeout(8000);
2684         
2685 #ifdef CONFIG_AP_MODE
2686         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
2687         {       
2688                 _irqL irqL;
2689                 struct sta_info *psta;
2690                 struct sta_priv *pstapriv = &padapter->stapriv;
2691                 
2692                 //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);        
2693                 //rtw_free_stainfo(padapter, psta);
2694                 //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);         
2695
2696                 DBG_871X_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
2697                                 reason, GetAddr2Ptr(pframe));
2698
2699                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));  
2700                 if(psta)
2701                 {
2702                         u8 updated = _FALSE;
2703                         
2704                         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2705                         if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
2706                         {
2707                                 rtw_list_delete(&psta->asoc_list);
2708                                 pstapriv->asoc_list_cnt--;
2709                                 updated = ap_free_sta(padapter, psta, _FALSE, reason);
2710                         
2711                         }
2712                         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2713
2714                         associated_clients_update(padapter, updated);
2715                 }
2716
2717                 return _SUCCESS;
2718         }
2719         else
2720 #endif
2721         {
2722                 DBG_871X_LEVEL(_drv_always_, "sta recv disassoc reason code(%d) sta:%pM\n",
2723                                 reason, GetAddr3Ptr(pframe));
2724                 
2725                 receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
2726         }       
2727         pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
2728         return _SUCCESS;
2729
2730 }
2731
2732 unsigned int OnAtim(_adapter *padapter, union recv_frame *precv_frame)
2733 {
2734         DBG_871X("%s\n", __FUNCTION__);
2735         return _SUCCESS;
2736 }
2737
2738 unsigned int on_action_spct_ch_switch(_adapter *padapter, struct sta_info *psta, u8 *ies, uint ies_len)
2739 {
2740         unsigned int ret = _FAIL;
2741         struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv;
2742         struct mlme_ext_info    *pmlmeinfo = &(mlmeext->mlmext_info);
2743
2744         if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
2745                 ret = _SUCCESS; 
2746                 goto exit;
2747         }
2748
2749         if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
2750                 
2751                 int ch_switch_mode = -1, ch = -1, ch_switch_cnt = -1;
2752                 int ch_offset = -1;
2753                 u8 bwmode;
2754                 struct ieee80211_info_element *ie;
2755
2756                 DBG_871X(FUNC_NDEV_FMT" from "MAC_FMT"\n",
2757                         FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(psta->hwaddr));
2758
2759                 for_each_ie(ie, ies, ies_len) {
2760                         if (ie->id == WLAN_EID_CHANNEL_SWITCH) {
2761                                 ch_switch_mode = ie->data[0];
2762                                 ch = ie->data[1];
2763                                 ch_switch_cnt = ie->data[2];
2764                                 DBG_871X("ch_switch_mode:%d, ch:%d, ch_switch_cnt:%d\n",
2765                                         ch_switch_mode, ch, ch_switch_cnt);
2766                         }
2767                         else if (ie->id == WLAN_EID_SECONDARY_CHANNEL_OFFSET) {
2768                                 ch_offset = secondary_ch_offset_to_hal_ch_offset(ie->data[0]);
2769                                 DBG_871X("ch_offset:%d\n", ch_offset);
2770                         }
2771                 }
2772
2773                 if (ch == -1)
2774                         return _SUCCESS;
2775
2776                 if (ch_offset == -1)
2777                         bwmode = mlmeext->cur_bwmode;
2778                 else
2779                         bwmode = (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) ?
2780                                 CHANNEL_WIDTH_20 : CHANNEL_WIDTH_40;
2781
2782                 ch_offset = (ch_offset == -1) ? mlmeext->cur_ch_offset : ch_offset;
2783
2784                 /* todo:
2785                  * 1. the decision of channel switching
2786                  * 2. things after channel switching
2787                  */
2788
2789                 ret = rtw_set_ch_cmd(padapter, ch, bwmode, ch_offset, _TRUE);
2790         }
2791
2792 exit:
2793         return ret;
2794 }
2795
2796 unsigned int on_action_spct(_adapter *padapter, union recv_frame *precv_frame)
2797 {
2798         unsigned int ret = _FAIL;
2799         struct sta_info *psta = NULL;
2800         struct sta_priv *pstapriv = &padapter->stapriv;
2801         u8 *pframe = precv_frame->u.hdr.rx_data;
2802         uint frame_len = precv_frame->u.hdr.len;
2803         u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2804         u8 category;
2805         u8 action;
2806
2807         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
2808
2809         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
2810
2811         if (!psta)
2812                 goto exit;
2813
2814         category = frame_body[0];
2815         if(category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
2816                 goto exit;
2817
2818         action = frame_body[1];
2819         switch (action) {
2820         case RTW_WLAN_ACTION_SPCT_MSR_REQ:
2821         case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
2822         case RTW_WLAN_ACTION_SPCT_TPC_REQ:
2823         case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
2824                 break;
2825         case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
2826                 #ifdef CONFIG_SPCT_CH_SWITCH
2827                 ret = on_action_spct_ch_switch(padapter, psta, &frame_body[2],
2828                         frame_len-(frame_body-pframe)-2);
2829                 #endif
2830                 break;
2831         default:
2832                 break;
2833         }
2834
2835 exit:
2836         return ret;
2837 }
2838
2839 unsigned int OnAction_qos(_adapter *padapter, union recv_frame *precv_frame)
2840 {
2841         return _SUCCESS;
2842 }
2843
2844 unsigned int OnAction_dls(_adapter *padapter, union recv_frame *precv_frame)
2845 {
2846         return _SUCCESS;
2847 }
2848
2849 unsigned int OnAction_back(_adapter *padapter, union recv_frame *precv_frame)
2850 {
2851         u8 *addr;
2852         struct sta_info *psta=NULL;
2853         struct recv_reorder_ctrl *preorder_ctrl;
2854         unsigned char           *frame_body;
2855         unsigned char           category, action;
2856         unsigned short  tid, status, reason_code = 0;
2857         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2858         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2859         u8 *pframe = precv_frame->u.hdr.rx_data;
2860         struct sta_priv *pstapriv = &padapter->stapriv;
2861 #ifdef CONFIG_80211N_HT
2862
2863         DBG_871X("%s\n", __FUNCTION__);
2864
2865         //check RA matches or not       
2866         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))//for if1, sta/ap mode
2867                 return _SUCCESS;
2868
2869 /*
2870         //check A1 matches or not
2871         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
2872                 return _SUCCESS;
2873 */
2874
2875         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 
2876                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2877                         return _SUCCESS;
2878
2879         addr = GetAddr2Ptr(pframe);
2880         psta = rtw_get_stainfo(pstapriv, addr);
2881
2882         if(psta==NULL)
2883                 return _SUCCESS;
2884
2885         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2886
2887         category = frame_body[0];
2888         if (category == RTW_WLAN_CATEGORY_BACK)// representing Block Ack
2889         {
2890 #ifdef CONFIG_TDLS
2891                 if((psta->tdls_sta_state & TDLS_LINKED_STATE) && 
2892                         (psta->htpriv.ht_option==_TRUE) &&
2893                         (psta->htpriv.ampdu_enable==_TRUE))
2894                 {
2895                         DBG_871X("Recv [%s] from direc link\n", __FUNCTION__);
2896                 }
2897                 else
2898 #endif //CONFIG_TDLS
2899                 if (!pmlmeinfo->HT_enable)
2900                 {
2901                         return _SUCCESS;
2902                 }
2903
2904                 action = frame_body[1];
2905                 DBG_871X("%s, action=%d\n", __FUNCTION__, action);
2906                 switch (action)
2907                 {
2908                         case RTW_WLAN_ACTION_ADDBA_REQ: //ADDBA request
2909
2910                                 _rtw_memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
2911                                 //process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe));
2912                                 process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), addr);
2913                                 
2914                                 if(pmlmeinfo->bAcceptAddbaReq == _TRUE)
2915                                 {
2916                                         issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
2917                                 }
2918                                 else
2919                                 {
2920                                         issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);//reject ADDBA Req
2921                                 }
2922                                                                 
2923                                 break;
2924
2925                         case RTW_WLAN_ACTION_ADDBA_RESP: //ADDBA response
2926
2927                                 //status = frame_body[3] | (frame_body[4] << 8); //endian issue
2928                                 status = RTW_GET_LE16(&frame_body[3]);
2929                                 tid = ((frame_body[5] >> 2) & 0x7);
2930
2931                                 if (status == 0)
2932                                 {       //successful                                    
2933                                         DBG_871X("agg_enable for TID=%d\n", tid);
2934                                         psta->htpriv.agg_enable_bitmap |= 1 << tid;                                     
2935                                         psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);                         
2936                                 }
2937                                 else
2938                                 {                                       
2939                                         psta->htpriv.agg_enable_bitmap &= ~BIT(tid);                                    
2940                                 }
2941
2942                                 if(psta->state & WIFI_STA_ALIVE_CHK_STATE)
2943                                 {
2944                                         DBG_871X("%s alive check - rx ADDBA response\n", __func__);
2945                                         psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2946                                         psta->expire_to = pstapriv->expire_to;
2947                                         psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
2948                                 }
2949
2950                                 //DBG_871X("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap);
2951                                 break;
2952
2953                         case RTW_WLAN_ACTION_DELBA: //DELBA
2954                                 if ((frame_body[3] & BIT(3)) == 0)
2955                                 {
2956                                         psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
2957                                         psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
2958                                         
2959                                         //reason_code = frame_body[4] | (frame_body[5] << 8);
2960                                         reason_code = RTW_GET_LE16(&frame_body[4]);
2961                                 }
2962                                 else if((frame_body[3] & BIT(3)) == BIT(3))
2963                                 {                                               
2964                                         tid = (frame_body[3] >> 4) & 0x0F;
2965                                 
2966                                         preorder_ctrl =  &psta->recvreorder_ctrl[tid];
2967                                         preorder_ctrl->enable = _FALSE;
2968                                         preorder_ctrl->indicate_seq = 0xffff;
2969                                         #ifdef DBG_RX_SEQ
2970                                         DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u \n", __FUNCTION__, __LINE__,
2971                                                 preorder_ctrl->indicate_seq);
2972                                         #endif
2973                                 }
2974                                 
2975                                 DBG_871X("%s(): DELBA: %x(%x)\n", __FUNCTION__,pmlmeinfo->agg_enable_bitmap, reason_code);
2976                                 //todo: how to notify the host while receiving DELETE BA
2977                                 break;
2978
2979                         default:
2980                                 break;
2981                 }
2982         }
2983 #endif //CONFIG_80211N_HT
2984         return _SUCCESS;
2985 }
2986
2987 #ifdef CONFIG_P2P
2988
2989 static int get_reg_classes_full_count(struct p2p_channels channel_list) {
2990         int cnt = 0;
2991         int i;
2992
2993         for (i = 0; i < channel_list.reg_classes; i++) {
2994                 cnt += channel_list.reg_class[i].channels;
2995         }
2996
2997         return cnt;
2998 }
2999
3000 static void get_channel_cnt_24g_5gl_5gh(  struct mlme_ext_priv *pmlmeext, u8* p24g_cnt, u8* p5gl_cnt, u8* p5gh_cnt )
3001 {
3002         int     i = 0;
3003
3004         *p24g_cnt = 0;
3005         *p5gl_cnt = 0;
3006         *p5gh_cnt = 0;  
3007         
3008         for( i = 0; i < pmlmeext->max_chan_nums; i++ )
3009         {
3010                 if ( pmlmeext->channel_set[ i ].ChannelNum <= 14 )
3011                 {
3012                         (*p24g_cnt)++;
3013                 }
3014                 else if ( ( pmlmeext->channel_set[ i ].ChannelNum > 14 ) && ( pmlmeext->channel_set[ i ].ChannelNum <= 48 ) )
3015                 {
3016                         //      Just include the channel 36, 40, 44, 48 channels for 5G low
3017                         (*p5gl_cnt)++;
3018                 }
3019                 else if ( ( pmlmeext->channel_set[ i ].ChannelNum >= 149 ) && ( pmlmeext->channel_set[ i ].ChannelNum <= 161 ) )
3020                 {
3021                         //      Just include the channel 149, 153, 157, 161 channels for 5G high
3022                         (*p5gh_cnt)++;
3023                 }
3024         }
3025 }
3026
3027 void issue_p2p_GO_request(_adapter *padapter, u8* raddr)
3028 {
3029
3030         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3031         u8                      action = P2P_PUB_ACTION_ACTION;
3032         u32                     p2poui = cpu_to_be32(P2POUI);
3033         u8                      oui_subtype = P2P_GO_NEGO_REQ;
3034         u8                      wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
3035         u8                      wpsielen = 0, p2pielen = 0, i;
3036         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
3037         u16                     len_channellist_attr = 0;
3038 #ifdef CONFIG_WFD
3039         u32                                     wfdielen = 0;
3040 #endif //CONFIG_WFD             
3041         
3042         struct xmit_frame                       *pmgntframe;
3043         struct pkt_attrib                       *pattrib;
3044         unsigned char                                   *pframe;
3045         struct rtw_ieee80211_hdr        *pwlanhdr;
3046         unsigned short                          *fctrl;
3047         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3048         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3049         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3050         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
3051
3052
3053         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
3054         {
3055                 return;
3056         }
3057
3058         DBG_871X( "[%s] In\n", __FUNCTION__ );
3059         //update attribute
3060         pattrib = &pmgntframe->attrib;
3061         update_mgntframe_attrib(padapter, pattrib);
3062
3063         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3064
3065         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3066         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3067
3068         fctrl = &(pwlanhdr->frame_ctl);
3069         *(fctrl) = 0;
3070
3071         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3072         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3073         _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
3074
3075         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3076         pmlmeext->mgnt_seq++;
3077         SetFrameSubType(pframe, WIFI_ACTION);
3078
3079         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3080         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3081
3082         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3083         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3084         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
3085         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
3086         pwdinfo->negotiation_dialog_token = 1;  //      Initialize the dialog value
3087         pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &(pattrib->pktlen));
3088
3089         
3090
3091         //      WPS Section
3092         wpsielen = 0;
3093         //      WPS OUI
3094         *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
3095         wpsielen += 4;
3096
3097         //      WPS version
3098         //      Type:
3099         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
3100         wpsielen += 2;
3101
3102         //      Length:
3103         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
3104         wpsielen += 2;
3105
3106         //      Value:
3107         wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0
3108
3109         //      Device Password ID
3110         //      Type:
3111         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
3112         wpsielen += 2;
3113
3114         //      Length:
3115         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
3116         wpsielen += 2;
3117
3118         //      Value:
3119
3120         if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN )
3121         {
3122                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_USER_SPEC );
3123         }
3124         else if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN )
3125         {
3126                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );
3127         }
3128         else if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC )
3129         {
3130                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_PBC );
3131         }
3132
3133         wpsielen += 2;
3134
3135         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
3136
3137
3138         //      P2P IE Section.
3139
3140         //      P2P OUI
3141         p2pielen = 0;
3142         p2pie[ p2pielen++ ] = 0x50;
3143         p2pie[ p2pielen++ ] = 0x6F;
3144         p2pie[ p2pielen++ ] = 0x9A;
3145         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
3146
3147         //      Commented by Albert 20110306
3148         //      According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes
3149         //      1. P2P Capability
3150         //      2. Group Owner Intent
3151         //      3. Configuration Timeout
3152         //      4. Listen Channel
3153         //      5. Extended Listen Timing
3154         //      6. Intended P2P Interface Address
3155         //      7. Channel List
3156         //      8. P2P Device Info
3157         //      9. Operating Channel
3158
3159
3160         //      P2P Capability
3161         //      Type:
3162         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
3163
3164         //      Length:
3165         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3166         p2pielen += 2;
3167
3168         //      Value:
3169         //      Device Capability Bitmap, 1 byte
3170         p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
3171
3172         //      Group Capability Bitmap, 1 byte
3173         if ( pwdinfo->persistent_supported )
3174         {
3175                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
3176         }
3177         else
3178         {
3179                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
3180         }
3181
3182
3183         //      Group Owner Intent
3184         //      Type:
3185         p2pie[ p2pielen++ ] = P2P_ATTR_GO_INTENT;
3186
3187         //      Length:
3188         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
3189         p2pielen += 2;
3190
3191         //      Value:
3192         //      Todo the tie breaker bit.
3193         p2pie[ p2pielen++ ] = ( ( pwdinfo->intent << 1 ) | BIT(0) );
3194
3195         //      Configuration Timeout
3196         //      Type:
3197         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
3198
3199         //      Length:
3200         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3201         p2pielen += 2;
3202
3203         //      Value:
3204         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P GO
3205         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P Client
3206
3207
3208         //      Listen Channel
3209         //      Type:
3210         p2pie[ p2pielen++ ] = P2P_ATTR_LISTEN_CH;
3211
3212         //      Length:
3213         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
3214         p2pielen += 2;
3215
3216         //      Value:
3217         //      Country String
3218         p2pie[ p2pielen++ ] = 'X';
3219         p2pie[ p2pielen++ ] = 'X';
3220         
3221         //      The third byte should be set to 0x04.
3222         //      Described in the "Operating Channel Attribute" section.
3223         p2pie[ p2pielen++ ] = 0x04;
3224
3225         //      Operating Class
3226         p2pie[ p2pielen++ ] = 0x51;     //      Copy from SD7
3227         
3228         //      Channel Number
3229         p2pie[ p2pielen++ ] = pwdinfo->listen_channel;  //      listening channel number
3230         
3231
3232         //      Extended Listen Timing ATTR
3233         //      Type:
3234         p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
3235
3236         //      Length:
3237         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
3238         p2pielen += 2;
3239
3240         //      Value:
3241         //      Availability Period
3242         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
3243         p2pielen += 2;
3244
3245         //      Availability Interval
3246         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
3247         p2pielen += 2;
3248
3249
3250         //      Intended P2P Interface Address
3251         //      Type:
3252         p2pie[ p2pielen++ ] = P2P_ATTR_INTENTED_IF_ADDR;
3253
3254         //      Length:
3255         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
3256         p2pielen += 2;
3257
3258         //      Value:
3259         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3260         p2pielen += ETH_ALEN;
3261
3262
3263         //      Channel List
3264         //      Type:
3265         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
3266
3267         // Length:
3268         // Country String(3)
3269         // + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
3270         // + number of channels in all classes
3271         len_channellist_attr = 3
3272            + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
3273            + get_reg_classes_full_count(pmlmeext->channel_list);
3274
3275 #ifdef CONFIG_CONCURRENT_MODE
3276         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3277         {
3278                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
3279         }
3280         else
3281         {
3282                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3283         }
3284 #else
3285
3286         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3287
3288 #endif
3289         p2pielen += 2;
3290
3291         //      Value:
3292         //      Country String
3293         p2pie[ p2pielen++ ] = 'X';
3294         p2pie[ p2pielen++ ] = 'X';
3295         
3296         //      The third byte should be set to 0x04.
3297         //      Described in the "Operating Channel Attribute" section.
3298         p2pie[ p2pielen++ ] = 0x04;
3299
3300         //      Channel Entry List
3301
3302 #ifdef CONFIG_CONCURRENT_MODE
3303         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3304         {
3305                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;    
3306                 struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3307
3308                 //      Operating Class
3309                 if ( pbuddy_mlmeext->cur_channel > 14 )
3310                 {
3311                         if ( pbuddy_mlmeext->cur_channel >= 149 )
3312                         {
3313                                 p2pie[ p2pielen++ ] = 0x7c;
3314                         }
3315                         else
3316                         {
3317                                 p2pie[ p2pielen++ ] = 0x73;
3318                         }
3319                 }
3320                 else
3321                 {
3322                         p2pie[ p2pielen++ ] = 0x51;
3323                 }
3324
3325                 //      Number of Channels
3326                 //      Just support 1 channel and this channel is AP's channel
3327                 p2pie[ p2pielen++ ] = 1;
3328
3329                 //      Channel List
3330                 p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
3331         }
3332         else
3333         {
3334                 int i,j;
3335                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3336                         //      Operating Class
3337                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3338
3339                         //      Number of Channels
3340                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3341
3342                         //      Channel List
3343                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3344                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3345                         }
3346                 }
3347         }
3348 #else // CONFIG_CONCURRENT_MODE
3349         {
3350                 int i,j;
3351                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3352                         //      Operating Class
3353                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3354
3355                         //      Number of Channels
3356                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3357
3358                         //      Channel List
3359                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3360                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3361                         }
3362                 }
3363         }
3364 #endif // CONFIG_CONCURRENT_MODE
3365
3366         //      Device Info
3367         //      Type:
3368         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
3369
3370         //      Length:
3371         //      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
3372         //      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
3373         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
3374         p2pielen += 2;
3375
3376         //      Value:
3377         //      P2P Device Address
3378         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3379         p2pielen += ETH_ALEN;
3380
3381         //      Config Method
3382         //      This field should be big endian. Noted by P2P specification.
3383
3384         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
3385
3386         p2pielen += 2;
3387
3388         //      Primary Device Type
3389         //      Category ID
3390         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
3391         p2pielen += 2;
3392
3393         //      OUI
3394         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
3395         p2pielen += 4;
3396
3397         //      Sub Category ID
3398         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
3399         p2pielen += 2;
3400
3401         //      Number of Secondary Device Types
3402         p2pie[ p2pielen++ ] = 0x00;     //      No Secondary Device Type List
3403
3404         //      Device Name
3405         //      Type:
3406         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
3407         p2pielen += 2;
3408
3409         //      Length:
3410         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
3411         p2pielen += 2;
3412
3413         //      Value:
3414         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len );
3415         p2pielen += pwdinfo->device_name_len;   
3416         
3417
3418         //      Operating Channel
3419         //      Type:
3420         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
3421
3422         //      Length:
3423         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
3424         p2pielen += 2;
3425
3426         //      Value:
3427         //      Country String
3428         p2pie[ p2pielen++ ] = 'X';
3429         p2pie[ p2pielen++ ] = 'X';
3430         
3431         //      The third byte should be set to 0x04.
3432         //      Described in the "Operating Channel Attribute" section.
3433         p2pie[ p2pielen++ ] = 0x04;
3434
3435         //      Operating Class
3436         if ( pwdinfo->operating_channel <= 14 )
3437         {
3438                 //      Operating Class
3439                 p2pie[ p2pielen++ ] = 0x51;
3440         }
3441         else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
3442         {
3443                 //      Operating Class
3444                 p2pie[ p2pielen++ ] = 0x73;
3445         }
3446         else
3447         {
3448                 //      Operating Class
3449                 p2pie[ p2pielen++ ] = 0x7c;
3450         }
3451
3452         //      Channel Number
3453         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       //      operating channel number
3454
3455         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );                
3456
3457 #ifdef CONFIG_WFD
3458         wfdielen = build_nego_req_wfd_ie(pwdinfo, pframe);
3459         pframe += wfdielen;
3460         pattrib->pktlen += wfdielen;
3461 #endif //CONFIG_WFD
3462
3463         pattrib->last_txcmdsz = pattrib->pktlen;
3464
3465         dump_mgntframe(padapter, pmgntframe);
3466
3467         return;
3468
3469 }
3470
3471
3472 void issue_p2p_GO_response(_adapter *padapter, u8* raddr, u8* frame_body,uint len, u8 result)
3473 {
3474
3475         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3476         u8                      action = P2P_PUB_ACTION_ACTION;
3477         u32                     p2poui = cpu_to_be32(P2POUI);
3478         u8                      oui_subtype = P2P_GO_NEGO_RESP;
3479         u8                      wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
3480         u8                      p2pielen = 0, i;
3481         uint                    wpsielen = 0;
3482         u16                     wps_devicepassword_id = 0x0000;
3483         uint                    wps_devicepassword_id_len = 0;
3484         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh;
3485         u16                     len_channellist_attr = 0;
3486         
3487         struct xmit_frame                       *pmgntframe;
3488         struct pkt_attrib                       *pattrib;
3489         unsigned char                                   *pframe;
3490         struct rtw_ieee80211_hdr        *pwlanhdr;
3491         unsigned short                          *fctrl;
3492         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3493         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3494         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3495         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
3496
3497 #ifdef CONFIG_WFD
3498         u32                                     wfdielen = 0;
3499 #endif //CONFIG_WFD
3500
3501         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
3502         {
3503                 return;
3504         }
3505
3506         DBG_871X( "[%s] In, result = %d\n", __FUNCTION__,  result );
3507         //update attribute
3508         pattrib = &pmgntframe->attrib;
3509         update_mgntframe_attrib(padapter, pattrib);
3510
3511         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3512
3513         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3514         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3515
3516         fctrl = &(pwlanhdr->frame_ctl);
3517         *(fctrl) = 0;
3518
3519         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3520         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3521         _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
3522
3523         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3524         pmlmeext->mgnt_seq++;
3525         SetFrameSubType(pframe, WIFI_ACTION);
3526
3527         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3528         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3529
3530         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3531         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3532         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
3533         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
3534         pwdinfo->negotiation_dialog_token = frame_body[7];      //      The Dialog Token of provisioning discovery request frame.
3535         pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
3536
3537         //      Commented by Albert 20110328
3538         //      Try to get the device password ID from the WPS IE of group negotiation request frame
3539         //      WiFi Direct test plan 5.1.15
3540         rtw_get_wps_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
3541         rtw_get_wps_attr_content( wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
3542         wps_devicepassword_id = be16_to_cpu( wps_devicepassword_id );
3543
3544         _rtw_memset( wpsie, 0x00, 255 );
3545         wpsielen = 0;
3546
3547         //      WPS Section
3548         wpsielen = 0;
3549         //      WPS OUI
3550         *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
3551         wpsielen += 4;
3552
3553         //      WPS version
3554         //      Type:
3555         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
3556         wpsielen += 2;
3557
3558         //      Length:
3559         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
3560         wpsielen += 2;
3561
3562         //      Value:
3563         wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0
3564
3565         //      Device Password ID
3566         //      Type:
3567         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
3568         wpsielen += 2;
3569
3570         //      Length:
3571         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
3572         wpsielen += 2;
3573
3574         //      Value:
3575         if ( wps_devicepassword_id == WPS_DPID_USER_SPEC )
3576         {
3577                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );
3578         }
3579         else if ( wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC )
3580         {
3581                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_USER_SPEC );
3582         }
3583         else
3584         {
3585                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_PBC );
3586         }
3587         wpsielen += 2;
3588
3589         //      Commented by Kurt 20120113
3590         //      If some device wants to do p2p handshake without sending prov_disc_req
3591         //      We have to get peer_req_cm from here.
3592         if(_rtw_memcmp( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3) )
3593         {
3594                 if ( wps_devicepassword_id == WPS_DPID_USER_SPEC )
3595                 {
3596                         _rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3 );
3597                 }
3598                 else if ( wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC )
3599                 {
3600                         _rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3 );     
3601                 }
3602                 else
3603                 {
3604                         _rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3 );     
3605                 }
3606         }
3607
3608         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
3609
3610
3611         //      P2P IE Section.
3612
3613         //      P2P OUI
3614         p2pielen = 0;
3615         p2pie[ p2pielen++ ] = 0x50;
3616         p2pie[ p2pielen++ ] = 0x6F;
3617         p2pie[ p2pielen++ ] = 0x9A;
3618         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
3619
3620         //      Commented by Albert 20100908
3621         //      According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes
3622         //      1. Status
3623         //      2. P2P Capability
3624         //      3. Group Owner Intent
3625         //      4. Configuration Timeout
3626         //      5. Operating Channel
3627         //      6. Intended P2P Interface Address
3628         //      7. Channel List
3629         //      8. Device Info
3630         //      9. Group ID     ( Only GO )
3631
3632
3633         //      ToDo:
3634
3635         //      P2P Status
3636         //      Type:
3637         p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
3638
3639         //      Length:
3640         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
3641         p2pielen += 2;
3642
3643         //      Value:
3644         p2pie[ p2pielen++ ] = result;
3645         
3646         //      P2P Capability
3647         //      Type:
3648         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
3649
3650         //      Length:
3651         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3652         p2pielen += 2;
3653
3654         //      Value:
3655         //      Device Capability Bitmap, 1 byte
3656
3657         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
3658         {
3659                 //      Commented by Albert 2011/03/08
3660                 //      According to the P2P specification
3661                 //      if the sending device will be client, the P2P Capability should be reserved of group negotation response frame
3662                 p2pie[ p2pielen++ ] = 0;
3663         }
3664         else
3665         {
3666                 //      Be group owner or meet the error case
3667                 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
3668         }
3669         
3670         //      Group Capability Bitmap, 1 byte
3671         if ( pwdinfo->persistent_supported )
3672         {
3673                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
3674         }
3675         else
3676         {
3677                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
3678         }
3679
3680         //      Group Owner Intent
3681         //      Type:
3682         p2pie[ p2pielen++ ] = P2P_ATTR_GO_INTENT;
3683
3684         //      Length:
3685         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
3686         p2pielen += 2;
3687
3688         //      Value:
3689         if ( pwdinfo->peer_intent & 0x01 )
3690         {
3691                 //      Peer's tie breaker bit is 1, our tie breaker bit should be 0
3692                 p2pie[ p2pielen++ ] = ( pwdinfo->intent << 1 );
3693         }
3694         else
3695         {
3696                 //      Peer's tie breaker bit is 0, our tie breaker bit should be 1
3697                 p2pie[ p2pielen++ ] = ( ( pwdinfo->intent << 1 ) | BIT(0) );
3698         }
3699
3700
3701         //      Configuration Timeout
3702         //      Type:
3703         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
3704
3705         //      Length:
3706         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
3707         p2pielen += 2;
3708
3709         //      Value:
3710         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P GO
3711         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P Client
3712
3713         //      Operating Channel
3714         //      Type:
3715         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
3716
3717         //      Length:
3718         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
3719         p2pielen += 2;
3720
3721         //      Value:
3722         //      Country String
3723         p2pie[ p2pielen++ ] = 'X';
3724         p2pie[ p2pielen++ ] = 'X';
3725         
3726         //      The third byte should be set to 0x04.
3727         //      Described in the "Operating Channel Attribute" section.
3728         p2pie[ p2pielen++ ] = 0x04;
3729
3730         //      Operating Class
3731         if ( pwdinfo->operating_channel <= 14 )
3732         {
3733                 //      Operating Class
3734                 p2pie[ p2pielen++ ] = 0x51;
3735         }
3736         else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
3737         {
3738                 //      Operating Class
3739                 p2pie[ p2pielen++ ] = 0x73;
3740         }
3741         else
3742         {
3743                 //      Operating Class
3744                 p2pie[ p2pielen++ ] = 0x7c;
3745         }
3746         
3747         //      Channel Number
3748         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       //      operating channel number
3749
3750         //      Intended P2P Interface Address  
3751         //      Type:
3752         p2pie[ p2pielen++ ] = P2P_ATTR_INTENTED_IF_ADDR;
3753
3754         //      Length:
3755         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
3756         p2pielen += 2;
3757
3758         //      Value:
3759         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3760         p2pielen += ETH_ALEN;
3761
3762         //      Channel List
3763         //      Type:
3764         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
3765
3766         // Country String(3)
3767         // + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
3768         // + number of channels in all classes
3769         len_channellist_attr = 3
3770            + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
3771            + get_reg_classes_full_count(pmlmeext->channel_list);
3772
3773 #ifdef CONFIG_CONCURRENT_MODE
3774         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3775         {
3776                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
3777         }
3778         else
3779         {
3780                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3781         }
3782 #else
3783
3784         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
3785
3786  #endif
3787         p2pielen += 2;
3788
3789         //      Value:
3790         //      Country String
3791         p2pie[ p2pielen++ ] = 'X';
3792         p2pie[ p2pielen++ ] = 'X';
3793         
3794         //      The third byte should be set to 0x04.
3795         //      Described in the "Operating Channel Attribute" section.
3796         p2pie[ p2pielen++ ] = 0x04;
3797
3798         //      Channel Entry List
3799
3800 #ifdef CONFIG_CONCURRENT_MODE
3801         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3802         {
3803                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;    
3804                 struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3805
3806                 //      Operating Class
3807                 if ( pbuddy_mlmeext->cur_channel > 14 )
3808                 {
3809                         if ( pbuddy_mlmeext->cur_channel >= 149 )
3810                         {
3811                                 p2pie[ p2pielen++ ] = 0x7c;
3812                         }
3813                         else
3814                         {
3815                                 p2pie[ p2pielen++ ] = 0x73;
3816                         }
3817                 }
3818                 else
3819                 {
3820                         p2pie[ p2pielen++ ] = 0x51;
3821                 }
3822
3823                 //      Number of Channels
3824                 //      Just support 1 channel and this channel is AP's channel
3825                 p2pie[ p2pielen++ ] = 1;
3826
3827                 //      Channel List
3828                 p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
3829         }
3830         else
3831         {
3832                 int i, j;
3833                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3834                         //      Operating Class
3835                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3836
3837                         //      Number of Channels
3838                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3839
3840                         //      Channel List
3841                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3842                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3843                         }
3844                 }
3845         }
3846 #else // CONFIG_CONCURRENT_MODE
3847         {
3848                 int i, j;
3849                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3850                         //      Operating Class
3851                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3852
3853                         //      Number of Channels
3854                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3855
3856                         //      Channel List
3857                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3858                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3859                         }
3860                 }
3861         }
3862 #endif // CONFIG_CONCURRENT_MODE
3863
3864         
3865         //      Device Info
3866         //      Type:
3867         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
3868
3869         //      Length:
3870         //      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
3871         //      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
3872         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
3873         p2pielen += 2;
3874
3875         //      Value:
3876         //      P2P Device Address
3877         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
3878         p2pielen += ETH_ALEN;
3879
3880         //      Config Method
3881         //      This field should be big endian. Noted by P2P specification.
3882
3883         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
3884
3885         p2pielen += 2;
3886
3887         //      Primary Device Type
3888         //      Category ID
3889         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
3890         p2pielen += 2;
3891
3892         //      OUI
3893         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
3894         p2pielen += 4;
3895
3896         //      Sub Category ID
3897         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
3898         p2pielen += 2;
3899
3900         //      Number of Secondary Device Types
3901         p2pie[ p2pielen++ ] = 0x00;     //      No Secondary Device Type List
3902
3903         //      Device Name
3904         //      Type:
3905         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
3906         p2pielen += 2;
3907
3908         //      Length:
3909         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
3910         p2pielen += 2;
3911
3912         //      Value:
3913         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len );
3914         p2pielen += pwdinfo->device_name_len;   
3915         
3916         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
3917         {
3918                 //      Group ID Attribute
3919                 //      Type:
3920                 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
3921
3922                 //      Length:
3923                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + pwdinfo->nego_ssidlen );
3924                 p2pielen += 2;
3925
3926                 //      Value:
3927                 //      p2P Device Address
3928                 _rtw_memcpy( p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN );
3929                 p2pielen += ETH_ALEN;
3930
3931                 //      SSID
3932                 _rtw_memcpy( p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
3933                 p2pielen += pwdinfo->nego_ssidlen;
3934                 
3935         }
3936         
3937         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );        
3938         
3939 #ifdef CONFIG_WFD
3940         wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe);
3941         pframe += wfdielen;
3942         pattrib->pktlen += wfdielen;
3943 #endif //CONFIG_WFD
3944
3945         pattrib->last_txcmdsz = pattrib->pktlen;
3946
3947         dump_mgntframe(padapter, pmgntframe);
3948
3949         return;
3950
3951 }
3952
3953 void issue_p2p_GO_confirm(_adapter *padapter, u8* raddr, u8 result)
3954 {
3955
3956         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3957         u8                      action = P2P_PUB_ACTION_ACTION;
3958         u32                     p2poui = cpu_to_be32(P2POUI);
3959         u8                      oui_subtype = P2P_GO_NEGO_CONF;
3960         u8                      wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
3961         u8                      wpsielen = 0, p2pielen = 0;
3962         
3963         struct xmit_frame                       *pmgntframe;
3964         struct pkt_attrib                       *pattrib;
3965         unsigned char                                   *pframe;
3966         struct rtw_ieee80211_hdr        *pwlanhdr;
3967         unsigned short                          *fctrl;
3968         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3969         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3970         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3971         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
3972 #ifdef CONFIG_WFD
3973         u32                                     wfdielen = 0;
3974 #endif //CONFIG_WFD
3975
3976         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
3977         {
3978                 return;
3979         }
3980
3981         DBG_871X( "[%s] In\n", __FUNCTION__ );
3982         //update attribute
3983         pattrib = &pmgntframe->attrib;
3984         update_mgntframe_attrib(padapter, pattrib);
3985
3986         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3987
3988         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3989         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3990
3991         fctrl = &(pwlanhdr->frame_ctl);
3992         *(fctrl) = 0;
3993
3994         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3995         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3996         _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
3997
3998         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3999         pmlmeext->mgnt_seq++;
4000         SetFrameSubType(pframe, WIFI_ACTION);
4001
4002         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4003         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4004
4005         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4006         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4007         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
4008         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
4009         pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
4010
4011         
4012
4013         //      P2P IE Section.
4014
4015         //      P2P OUI
4016         p2pielen = 0;
4017         p2pie[ p2pielen++ ] = 0x50;
4018         p2pie[ p2pielen++ ] = 0x6F;
4019         p2pie[ p2pielen++ ] = 0x9A;
4020         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
4021
4022         //      Commented by Albert 20110306
4023         //      According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes
4024         //      1. Status
4025         //      2. P2P Capability
4026         //      3. Operating Channel
4027         //      4. Channel List
4028         //      5. Group ID     ( if this WiFi is GO )
4029
4030         //      P2P Status
4031         //      Type:
4032         p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
4033
4034         //      Length:
4035         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
4036         p2pielen += 2;
4037
4038         //      Value:
4039         p2pie[ p2pielen++ ] = result;
4040
4041         //      P2P Capability
4042         //      Type:
4043         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
4044
4045         //      Length:
4046         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
4047         p2pielen += 2;
4048
4049         //      Value:
4050         //      Device Capability Bitmap, 1 byte
4051         p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
4052         
4053         //      Group Capability Bitmap, 1 byte
4054         if ( pwdinfo->persistent_supported )
4055         {
4056                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
4057         }
4058         else
4059         {
4060                 p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
4061         }
4062
4063
4064         //      Operating Channel
4065         //      Type:
4066         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
4067
4068         //      Length:
4069         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
4070         p2pielen += 2;
4071
4072         //      Value:
4073         //      Country String
4074         p2pie[ p2pielen++ ] = 'X';
4075         p2pie[ p2pielen++ ] = 'X';
4076         
4077         //      The third byte should be set to 0x04.
4078         //      Described in the "Operating Channel Attribute" section.
4079         p2pie[ p2pielen++ ] = 0x04;
4080
4081
4082         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
4083         {
4084                 if ( pwdinfo->peer_operating_ch <= 14 )
4085                 {
4086                         //      Operating Class
4087                         p2pie[ p2pielen++ ] = 0x51;
4088                 }
4089                 else if ( ( pwdinfo->peer_operating_ch >= 36 ) && ( pwdinfo->peer_operating_ch <= 48 ) )
4090                 {
4091                         //      Operating Class
4092                         p2pie[ p2pielen++ ] = 0x73;
4093                 }
4094                 else
4095                 {
4096                         //      Operating Class
4097                         p2pie[ p2pielen++ ] = 0x7c;
4098                 }
4099                 
4100                 p2pie[ p2pielen++ ] = pwdinfo->peer_operating_ch;
4101         }
4102         else
4103         {
4104                 if ( pwdinfo->operating_channel <= 14 )
4105                 {
4106                         //      Operating Class
4107                         p2pie[ p2pielen++ ] = 0x51;
4108                 }
4109                 else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
4110                 {
4111                         //      Operating Class
4112                         p2pie[ p2pielen++ ] = 0x73;
4113                 }
4114                 else
4115                 {
4116                         //      Operating Class
4117                         p2pie[ p2pielen++ ] = 0x7c;
4118                 }
4119                 
4120                 //      Channel Number
4121                 p2pie[ p2pielen++ ] = pwdinfo->operating_channel;               //      Use the listen channel as the operating channel
4122         }
4123
4124
4125         //      Channel List
4126         //      Type:
4127         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
4128
4129         *(u16*) ( p2pie + p2pielen ) = 6;
4130         p2pielen += 2;
4131
4132         //      Country String
4133         p2pie[ p2pielen++ ] = 'X';
4134         p2pie[ p2pielen++ ] = 'X';
4135         
4136         //      The third byte should be set to 0x04.
4137         //      Described in the "Operating Channel Attribute" section.
4138         p2pie[ p2pielen++ ] = 0x04;
4139
4140         //      Value:
4141         if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
4142         {
4143                 if ( pwdinfo->peer_operating_ch <= 14 )
4144                 {
4145                         //      Operating Class
4146                         p2pie[ p2pielen++ ] = 0x51;
4147                 }
4148                 else if ( ( pwdinfo->peer_operating_ch >= 36 ) && ( pwdinfo->peer_operating_ch <= 48 ) )
4149                 {
4150                         //      Operating Class
4151                         p2pie[ p2pielen++ ] = 0x73;
4152                 }
4153                 else
4154                 {
4155                         //      Operating Class
4156                         p2pie[ p2pielen++ ] = 0x7c;
4157                 }
4158                 p2pie[ p2pielen++ ] = 1;
4159                 p2pie[ p2pielen++ ] = pwdinfo->peer_operating_ch;
4160         }
4161         else
4162         {
4163                 if ( pwdinfo->operating_channel <= 14 )
4164                 {
4165                         //      Operating Class
4166                         p2pie[ p2pielen++ ] = 0x51;
4167                 }
4168                 else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
4169                 {
4170                         //      Operating Class
4171                         p2pie[ p2pielen++ ] = 0x73;
4172                 }
4173                 else
4174                 {
4175                         //      Operating Class
4176                         p2pie[ p2pielen++ ] = 0x7c;
4177                 }
4178                 
4179                 //      Channel Number
4180                 p2pie[ p2pielen++ ] = 1;
4181                 p2pie[ p2pielen++ ] = pwdinfo->operating_channel;               //      Use the listen channel as the operating channel
4182         }
4183
4184         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
4185         {
4186                 //      Group ID Attribute
4187                 //      Type:
4188                 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
4189
4190                 //      Length:
4191                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + pwdinfo->nego_ssidlen );
4192                 p2pielen += 2;
4193
4194                 //      Value:
4195                 //      p2P Device Address
4196                 _rtw_memcpy( p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN );
4197                 p2pielen += ETH_ALEN;
4198
4199                 //      SSID
4200                 _rtw_memcpy( p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
4201                 p2pielen += pwdinfo->nego_ssidlen;
4202         }
4203         
4204         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
4205         
4206 #ifdef CONFIG_WFD
4207         wfdielen = build_nego_confirm_wfd_ie(pwdinfo, pframe);
4208         pframe += wfdielen;
4209         pattrib->pktlen += wfdielen;
4210 #endif //CONFIG_WFD
4211
4212         pattrib->last_txcmdsz = pattrib->pktlen;
4213
4214         dump_mgntframe(padapter, pmgntframe);
4215
4216         return;
4217
4218 }
4219
4220 void issue_p2p_invitation_request(_adapter *padapter, u8* raddr )
4221 {
4222
4223         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
4224         u8                      action = P2P_PUB_ACTION_ACTION;
4225         u32                     p2poui = cpu_to_be32(P2POUI);
4226         u8                      oui_subtype = P2P_INVIT_REQ;
4227         u8                      p2pie[ 255 ] = { 0x00 };
4228         u8                      p2pielen = 0, i;
4229         u8                      dialogToken = 3;
4230         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
4231         u16                     len_channellist_attr = 0;       
4232 #ifdef CONFIG_WFD
4233         u32                                     wfdielen = 0;
4234 #endif //CONFIG_WFD
4235 #ifdef CONFIG_CONCURRENT_MODE
4236         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
4237         struct wifidirect_info  *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
4238         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
4239         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4240 #endif
4241
4242         struct xmit_frame                       *pmgntframe;
4243         struct pkt_attrib                       *pattrib;
4244         unsigned char                                   *pframe;
4245         struct rtw_ieee80211_hdr        *pwlanhdr;
4246         unsigned short                          *fctrl;
4247         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
4248         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4249         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4250         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
4251
4252
4253         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
4254         {
4255                 return;
4256         }
4257
4258         //update attribute
4259         pattrib = &pmgntframe->attrib;
4260         update_mgntframe_attrib(padapter, pattrib);
4261
4262         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4263
4264         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4265         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4266
4267         fctrl = &(pwlanhdr->frame_ctl);
4268         *(fctrl) = 0;
4269
4270         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
4271         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4272         _rtw_memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
4273
4274         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4275         pmlmeext->mgnt_seq++;
4276         SetFrameSubType(pframe, WIFI_ACTION);
4277
4278         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4279         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4280
4281         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4282         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4283         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
4284         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
4285         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
4286
4287         //      P2P IE Section.
4288
4289         //      P2P OUI
4290         p2pielen = 0;
4291         p2pie[ p2pielen++ ] = 0x50;
4292         p2pie[ p2pielen++ ] = 0x6F;
4293         p2pie[ p2pielen++ ] = 0x9A;
4294         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
4295
4296         //      Commented by Albert 20101011
4297         //      According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes
4298         //      1. Configuration Timeout
4299         //      2. Invitation Flags
4300         //      3. Operating Channel    ( Only GO )
4301         //      4. P2P Group BSSID      ( Should be included if I am the GO )
4302         //      5. Channel List
4303         //      6. P2P Group ID
4304         //      7. P2P Device Info
4305
4306         //      Configuration Timeout
4307         //      Type:
4308         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
4309
4310         //      Length:
4311         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
4312         p2pielen += 2;
4313
4314         //      Value:
4315         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P GO
4316         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P Client
4317
4318         //      Invitation Flags
4319         //      Type:
4320         p2pie[ p2pielen++ ] = P2P_ATTR_INVITATION_FLAGS;
4321
4322         //      Length:
4323         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
4324         p2pielen += 2;
4325
4326         //      Value:
4327         p2pie[ p2pielen++ ] = P2P_INVITATION_FLAGS_PERSISTENT;
4328
4329
4330         //      Operating Channel
4331         //      Type:
4332         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
4333
4334         //      Length:
4335         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
4336         p2pielen += 2;
4337
4338         //      Value:
4339         //      Country String
4340         p2pie[ p2pielen++ ] = 'X';
4341         p2pie[ p2pielen++ ] = 'X';
4342         
4343         //      The third byte should be set to 0x04.
4344         //      Described in the "Operating Channel Attribute" section.
4345         p2pie[ p2pielen++ ] = 0x04;
4346
4347         //      Operating Class
4348         if ( pwdinfo->invitereq_info.operating_ch <= 14 )
4349                 p2pie[ p2pielen++ ] = 0x51;
4350         else if ( ( pwdinfo->invitereq_info.operating_ch >= 36 ) && ( pwdinfo->invitereq_info.operating_ch <= 48 ) )
4351                 p2pie[ p2pielen++ ] = 0x73;
4352         else
4353                 p2pie[ p2pielen++ ] = 0x7c;
4354         
4355         //      Channel Number
4356         p2pie[ p2pielen++ ] = pwdinfo->invitereq_info.operating_ch;     //      operating channel number
4357
4358         if ( _rtw_memcmp( myid( &padapter->eeprompriv ), pwdinfo->invitereq_info.go_bssid, ETH_ALEN ) )
4359         {
4360                 //      P2P Group BSSID
4361                 //      Type:
4362                 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_BSSID;
4363
4364                 //      Length:
4365                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
4366                 p2pielen += 2;
4367
4368                 //      Value:
4369                 //      P2P Device Address for GO
4370                 _rtw_memcpy( p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN );
4371                 p2pielen += ETH_ALEN;
4372         }
4373
4374         //      Channel List
4375         //      Type:
4376         p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
4377
4378         
4379         //      Length:
4380         // Country String(3)
4381         // + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
4382         // + number of channels in all classes
4383         len_channellist_attr = 3
4384            + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
4385            + get_reg_classes_full_count(pmlmeext->channel_list);
4386
4387 #ifdef CONFIG_CONCURRENT_MODE
4388         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4389         {
4390                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
4391         }
4392         else
4393         {
4394                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
4395         }
4396 #else
4397
4398         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
4399
4400  #endif
4401         p2pielen += 2;
4402
4403         //      Value:
4404         //      Country String
4405         p2pie[ p2pielen++ ] = 'X';
4406         p2pie[ p2pielen++ ] = 'X';
4407         
4408         //      The third byte should be set to 0x04.
4409         //      Described in the "Operating Channel Attribute" section.
4410         p2pie[ p2pielen++ ] = 0x04;
4411
4412         //      Channel Entry List
4413 #ifdef CONFIG_CONCURRENT_MODE
4414         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4415         {
4416                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;    
4417                 struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4418
4419                 //      Operating Class
4420                 if ( pbuddy_mlmeext->cur_channel > 14 )
4421                 {
4422                         if ( pbuddy_mlmeext->cur_channel >= 149 )
4423                         {
4424                                 p2pie[ p2pielen++ ] = 0x7c;
4425                         }
4426                         else
4427                         {
4428                                 p2pie[ p2pielen++ ] = 0x73;
4429                         }
4430                 }
4431                 else
4432                 {
4433                         p2pie[ p2pielen++ ] = 0x51;
4434                 }
4435
4436                 //      Number of Channels
4437                 //      Just support 1 channel and this channel is AP's channel
4438                 p2pie[ p2pielen++ ] = 1;
4439
4440                 //      Channel List
4441                 p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
4442         }
4443         else
4444         {
4445                 int i, j;
4446                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
4447                         //      Operating Class
4448                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
4449
4450                         //      Number of Channels
4451                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
4452
4453                         //      Channel List
4454                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
4455                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
4456                         }
4457                 }
4458         }
4459 #else // CONFIG_CONCURRENT_MODE
4460         {
4461                 int i, j;
4462                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
4463                         //      Operating Class
4464                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
4465
4466                         //      Number of Channels
4467                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
4468
4469                         //      Channel List
4470                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
4471                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
4472                         }
4473                 }
4474         }
4475 #endif // CONFIG_CONCURRENT_MODE
4476
4477
4478         //      P2P Group ID
4479         //      Type:
4480         p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
4481
4482         //      Length:
4483         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 6 + pwdinfo->invitereq_info.ssidlen );
4484         p2pielen += 2;
4485
4486         //      Value:
4487         //      P2P Device Address for GO
4488         _rtw_memcpy( p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN );
4489         p2pielen += ETH_ALEN;
4490
4491         //      SSID
4492         _rtw_memcpy( p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen );
4493         p2pielen += pwdinfo->invitereq_info.ssidlen;
4494         
4495
4496         //      Device Info
4497         //      Type:
4498         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
4499
4500         //      Length:
4501         //      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
4502         //      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
4503         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
4504         p2pielen += 2;
4505         
4506         //      Value:
4507         //      P2P Device Address
4508         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
4509         p2pielen += ETH_ALEN;
4510
4511         //      Config Method
4512         //      This field should be big endian. Noted by P2P specification.
4513         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY );
4514         p2pielen += 2;
4515
4516         //      Primary Device Type
4517         //      Category ID
4518         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
4519         p2pielen += 2;
4520
4521         //      OUI
4522         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
4523         p2pielen += 4;
4524
4525         //      Sub Category ID
4526         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
4527         p2pielen += 2;
4528
4529         //      Number of Secondary Device Types
4530         p2pie[ p2pielen++ ] = 0x00;     //      No Secondary Device Type List
4531
4532         //      Device Name
4533         //      Type:
4534         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
4535         p2pielen += 2;
4536
4537         //      Length:
4538         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
4539         p2pielen += 2;
4540
4541         //      Value:
4542         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
4543         p2pielen += pwdinfo->device_name_len;
4544                 
4545         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );        
4546
4547 #ifdef CONFIG_WFD
4548         wfdielen = build_invitation_req_wfd_ie(pwdinfo, pframe);
4549         pframe += wfdielen;
4550         pattrib->pktlen += wfdielen;
4551 #endif //CONFIG_WFD     
4552
4553         pattrib->last_txcmdsz = pattrib->pktlen;
4554
4555         dump_mgntframe(padapter, pmgntframe);
4556
4557         return;
4558
4559 }
4560
4561 void issue_p2p_invitation_response(_adapter *padapter, u8* raddr, u8 dialogToken, u8 status_code)
4562 {
4563
4564         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
4565         u8                      action = P2P_PUB_ACTION_ACTION;
4566         u32                     p2poui = cpu_to_be32(P2POUI);
4567         u8                      oui_subtype = P2P_INVIT_RESP;
4568         u8                      p2pie[ 255 ] = { 0x00 };
4569         u8                      p2pielen = 0, i;
4570         u8                      channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
4571         u16                     len_channellist_attr = 0;
4572 #ifdef CONFIG_CONCURRENT_MODE
4573         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
4574         struct wifidirect_info  *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
4575         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
4576         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4577 #endif  
4578 #ifdef CONFIG_WFD
4579         u32                                     wfdielen = 0;
4580 #endif //CONFIG_WFD
4581         
4582         struct xmit_frame                       *pmgntframe;
4583         struct pkt_attrib                       *pattrib;
4584         unsigned char                                   *pframe;
4585         struct rtw_ieee80211_hdr        *pwlanhdr;
4586         unsigned short                          *fctrl;
4587         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
4588         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4589         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4590         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo);
4591
4592
4593         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
4594         {
4595                 return;
4596         }
4597
4598         //update attribute
4599         pattrib = &pmgntframe->attrib;
4600         update_mgntframe_attrib(padapter, pattrib);
4601
4602         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4603
4604         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4605         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4606
4607         fctrl = &(pwlanhdr->frame_ctl);
4608         *(fctrl) = 0;
4609
4610         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
4611         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4612         _rtw_memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
4613
4614         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4615         pmlmeext->mgnt_seq++;
4616         SetFrameSubType(pframe, WIFI_ACTION);
4617
4618         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4619         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4620
4621         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4622         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4623         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
4624         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
4625         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
4626
4627         //      P2P IE Section.
4628
4629         //      P2P OUI
4630         p2pielen = 0;
4631         p2pie[ p2pielen++ ] = 0x50;
4632         p2pie[ p2pielen++ ] = 0x6F;
4633         p2pie[ p2pielen++ ] = 0x9A;
4634         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
4635
4636         //      Commented by Albert 20101005
4637         //      According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes
4638         //      1. Status
4639         //      2. Configuration Timeout
4640         //      3. Operating Channel    ( Only GO )
4641         //      4. P2P Group BSSID      ( Only GO )
4642         //      5. Channel List
4643
4644         //      P2P Status
4645         //      Type:
4646         p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
4647
4648         //      Length:
4649         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
4650         p2pielen += 2;
4651
4652         //      Value:
4653         //      When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE.
4654         //      Sent the event receiving the P2P Invitation Req frame to DMP UI.
4655         //      DMP had to compare the MAC address to find out the profile.
4656         //      So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB.
4657         //      If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req
4658         //      to NB to rebuild the persistent group.
4659         p2pie[ p2pielen++ ] = status_code;
4660         
4661         //      Configuration Timeout
4662         //      Type:
4663         p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
4664
4665         //      Length:
4666         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
4667         p2pielen += 2;
4668
4669         //      Value:
4670         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P GO
4671         p2pie[ p2pielen++ ] = 200;      //      2 seconds needed to be the P2P Client
4672
4673         if( status_code == P2P_STATUS_SUCCESS )
4674         {
4675                 if( rtw_p2p_chk_role( pwdinfo, P2P_ROLE_GO ) )
4676                 {
4677                         //      The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO
4678                         //      In this case, the P2P Invitation response frame should carry the two more P2P attributes.
4679                         //      First one is operating channel attribute.
4680                         //      Second one is P2P Group BSSID attribute.
4681
4682                         //      Operating Channel
4683                         //      Type:
4684                         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
4685
4686                         //      Length:
4687                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
4688                         p2pielen += 2;
4689
4690                         //      Value:
4691                         //      Country String
4692                         p2pie[ p2pielen++ ] = 'X';
4693                         p2pie[ p2pielen++ ] = 'X';
4694                 
4695                         //      The third byte should be set to 0x04.
4696                         //      Described in the "Operating Channel Attribute" section.
4697                         p2pie[ p2pielen++ ] = 0x04;
4698
4699                         //      Operating Class
4700                         p2pie[ p2pielen++ ] = 0x51;     //      Copy from SD7
4701                 
4702                         //      Channel Number
4703                         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       //      operating channel number
4704                         
4705
4706                         //      P2P Group BSSID
4707                         //      Type:
4708                         p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_BSSID;
4709
4710                         //      Length:
4711                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
4712                         p2pielen += 2;
4713
4714                         //      Value:
4715                         //      P2P Device Address for GO
4716                         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
4717                         p2pielen += ETH_ALEN;
4718
4719                 }
4720
4721                 //      Channel List
4722                 //      Type:
4723                 p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
4724
4725                 //      Length:
4726                 // Country String(3)
4727                 // + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
4728                 // + number of channels in all classes
4729                 len_channellist_attr = 3
4730                         + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
4731                         + get_reg_classes_full_count(pmlmeext->channel_list);
4732
4733 #ifdef CONFIG_CONCURRENT_MODE
4734                 if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4735                 {
4736                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
4737                 }
4738                 else
4739                 {
4740                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
4741                 }
4742 #else
4743
4744                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
4745
4746 #endif
4747                 p2pielen += 2;
4748
4749                 //      Value:
4750                 //      Country String
4751                 p2pie[ p2pielen++ ] = 'X';
4752                 p2pie[ p2pielen++ ] = 'X';
4753
4754                 //      The third byte should be set to 0x04.
4755                 //      Described in the "Operating Channel Attribute" section.
4756                 p2pie[ p2pielen++ ] = 0x04;
4757
4758                 //      Channel Entry List
4759 #ifdef CONFIG_CONCURRENT_MODE
4760                 if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4761                 {
4762                         _adapter *pbuddy_adapter = padapter->pbuddy_adapter;    
4763                         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4764
4765                         //      Operating Class
4766                         if ( pbuddy_mlmeext->cur_channel > 14 )
4767                         {
4768                                 if ( pbuddy_mlmeext->cur_channel >= 149 )
4769                                 {
4770                                         p2pie[ p2pielen++ ] = 0x7c;
4771                                 }
4772                                 else
4773                                 {
4774                                         p2pie[ p2pielen++ ] = 0x73;
4775                                 }
4776                         }
4777                         else
4778                         {
4779                                 p2pie[ p2pielen++ ] = 0x51;
4780                         }
4781
4782                         //      Number of Channels
4783                         //      Just support 1 channel and this channel is AP's channel
4784                         p2pie[ p2pielen++ ] = 1;
4785
4786                         //      Channel List
4787                         p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
4788                 }
4789                 else
4790                 {
4791                         int i, j;
4792                         for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
4793                                 //      Operating Class
4794                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
4795
4796                                 //      Number of Channels
4797                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
4798
4799                                 //      Channel List
4800                                 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
4801                                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
4802                                 }
4803                         }
4804                 }
4805 #else // CONFIG_CONCURRENT_MODE
4806                 {
4807                         int i, j;
4808                         for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
4809                                 //      Operating Class
4810                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
4811
4812                                 //      Number of Channels
4813                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
4814
4815                                 //      Channel List
4816                                 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
4817                                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
4818                                 }
4819                         }
4820                 }
4821 #endif // CONFIG_CONCURRENT_MODE
4822         }
4823                 
4824         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );        
4825         
4826 #ifdef CONFIG_WFD
4827         wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe);
4828         pframe += wfdielen;
4829         pattrib->pktlen += wfdielen;
4830 #endif //CONFIG_WFD
4831
4832         pattrib->last_txcmdsz = pattrib->pktlen;
4833
4834         dump_mgntframe(padapter, pmgntframe);
4835
4836         return;
4837
4838 }
4839
4840 void issue_p2p_provision_request(_adapter *padapter, u8* pssid, u8 ussidlen, u8* pdev_raddr )
4841 {
4842         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
4843         u8                      action = P2P_PUB_ACTION_ACTION;
4844         u8                      dialogToken = 1;
4845         u32                     p2poui = cpu_to_be32(P2POUI);
4846         u8                      oui_subtype = P2P_PROVISION_DISC_REQ;
4847         u8                      wpsie[ 100 ] = { 0x00 };
4848         u8                      wpsielen = 0;
4849         u32                     p2pielen = 0;
4850 #ifdef CONFIG_WFD
4851         u32                                     wfdielen = 0;
4852 #endif //CONFIG_WFD             
4853         
4854         struct xmit_frame                       *pmgntframe;
4855         struct pkt_attrib                       *pattrib;
4856         unsigned char                                   *pframe;
4857         struct rtw_ieee80211_hdr        *pwlanhdr;
4858         unsigned short                          *fctrl;
4859         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
4860         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4861         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4862         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4863
4864
4865         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
4866         {
4867                 return;
4868         }
4869
4870         DBG_871X( "[%s] In\n", __FUNCTION__ );
4871         //update attribute
4872         pattrib = &pmgntframe->attrib;
4873         update_mgntframe_attrib(padapter, pattrib);
4874
4875         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4876
4877         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4878         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4879
4880         fctrl = &(pwlanhdr->frame_ctl);
4881         *(fctrl) = 0;
4882
4883         _rtw_memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
4884         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4885         _rtw_memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
4886
4887         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4888         pmlmeext->mgnt_seq++;
4889         SetFrameSubType(pframe, WIFI_ACTION);
4890
4891         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4892         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4893
4894         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4895         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4896         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
4897         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));       
4898         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));               
4899
4900         p2pielen = build_prov_disc_request_p2p_ie( pwdinfo, pframe, pssid, ussidlen, pdev_raddr );
4901
4902         pframe += p2pielen;
4903         pattrib->pktlen += p2pielen;
4904
4905         wpsielen = 0;
4906         //      WPS OUI
4907         *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
4908         wpsielen += 4;
4909
4910         //      WPS version
4911         //      Type:
4912         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
4913         wpsielen += 2;
4914
4915         //      Length:
4916         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
4917         wpsielen += 2;
4918
4919         //      Value:
4920         wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0
4921
4922         //      Config Method
4923         //      Type:
4924         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
4925         wpsielen += 2;
4926
4927         //      Length:
4928         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
4929         wpsielen += 2;
4930
4931         //      Value:
4932         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->tx_prov_disc_info.wps_config_method_request );
4933         wpsielen += 2;
4934
4935         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
4936
4937
4938 #ifdef CONFIG_WFD
4939         wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
4940         pframe += wfdielen;
4941         pattrib->pktlen += wfdielen;
4942 #endif //CONFIG_WFD
4943
4944         pattrib->last_txcmdsz = pattrib->pktlen;
4945
4946         dump_mgntframe(padapter, pmgntframe);
4947
4948         return;
4949
4950 }
4951
4952
4953 u8 is_matched_in_profilelist( u8* peermacaddr, struct profile_info* profileinfo )
4954 {
4955         u8 i, match_result = 0;
4956
4957         DBG_871X( "[%s] peermac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
4958                     peermacaddr[0], peermacaddr[1],peermacaddr[2],peermacaddr[3],peermacaddr[4],peermacaddr[5]);
4959         
4960         for( i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++ )
4961         {
4962                DBG_871X( "[%s] profileinfo_mac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
4963                             profileinfo->peermac[0], profileinfo->peermac[1],profileinfo->peermac[2],profileinfo->peermac[3],profileinfo->peermac[4],profileinfo->peermac[5]);             
4964                 if ( _rtw_memcmp( peermacaddr, profileinfo->peermac, ETH_ALEN ) )
4965                 {
4966                         match_result = 1;
4967                         DBG_871X( "[%s] Match!\n", __FUNCTION__ );
4968                         break;
4969                 }
4970         }
4971         
4972         return (match_result );
4973 }
4974
4975 void issue_probersp_p2p(_adapter *padapter, unsigned char *da)
4976 {
4977         struct xmit_frame                       *pmgntframe;
4978         struct pkt_attrib                       *pattrib;
4979         unsigned char                                   *pframe;
4980         struct rtw_ieee80211_hdr        *pwlanhdr;
4981         unsigned short                          *fctrl; 
4982         unsigned char                                   *mac;
4983         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
4984         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4985         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4986         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4987         //WLAN_BSSID_EX                 *cur_network = &(pmlmeinfo->network);
4988         u16                                     beacon_interval = 100;
4989         u16                                     capInfo = 0;
4990         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4991         u8                                      wpsie[255] = { 0x00 };
4992         u32                                     wpsielen = 0, p2pielen = 0;
4993 #ifdef CONFIG_WFD
4994         u32                                     wfdielen = 0;
4995 #endif //CONFIG_WFD
4996 #ifdef CONFIG_INTEL_WIDI
4997         u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 };
4998 #endif //CONFIG_INTEL_WIDI
4999
5000         //DBG_871X("%s\n", __FUNCTION__);
5001         
5002         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
5003         {
5004                 return;
5005         }
5006         
5007         //update attribute
5008         pattrib = &pmgntframe->attrib;
5009         update_mgntframe_attrib(padapter, pattrib);     
5010         
5011         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5012                 
5013         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5014         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;  
5015         
5016         mac = myid(&(padapter->eeprompriv));
5017         
5018         fctrl = &(pwlanhdr->frame_ctl);
5019         *(fctrl) = 0;
5020         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5021         _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
5022         
5023         //      Use the device address for BSSID field. 
5024         _rtw_memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
5025
5026         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5027         pmlmeext->mgnt_seq++;
5028         SetFrameSubType(fctrl, WIFI_PROBERSP);
5029         
5030         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5031         pattrib->pktlen = pattrib->hdrlen;
5032         pframe += pattrib->hdrlen;
5033
5034         //timestamp will be inserted by hardware
5035         pframe += 8;
5036         pattrib->pktlen += 8;
5037
5038         // beacon interval: 2 bytes
5039         _rtw_memcpy(pframe, (unsigned char *) &beacon_interval, 2); 
5040         pframe += 2;
5041         pattrib->pktlen += 2;
5042
5043         //      capability info: 2 bytes
5044         //      ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec)
5045         capInfo |= cap_ShortPremble;
5046         capInfo |= cap_ShortSlot;
5047         
5048         _rtw_memcpy(pframe, (unsigned char *) &capInfo, 2);
5049         pframe += 2;
5050         pattrib->pktlen += 2;
5051
5052
5053         // SSID
5054         pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
5055
5056         // supported rates...
5057         //      Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 )
5058         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
5059
5060         // DS parameter set
5061         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
5062
5063 #ifdef CONFIG_IOCTL_CFG80211
5064         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
5065         {
5066                 if( pmlmepriv->wps_probe_resp_ie != NULL && pmlmepriv->p2p_probe_resp_ie != NULL )
5067                 {
5068                         //WPS IE
5069                         _rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
5070                         pattrib->pktlen += pmlmepriv->wps_probe_resp_ie_len;
5071                         pframe += pmlmepriv->wps_probe_resp_ie_len;
5072
5073                         //P2P IE
5074                         _rtw_memcpy(pframe, pmlmepriv->p2p_probe_resp_ie, pmlmepriv->p2p_probe_resp_ie_len);
5075                         pattrib->pktlen += pmlmepriv->p2p_probe_resp_ie_len;
5076                         pframe += pmlmepriv->p2p_probe_resp_ie_len;
5077                 }
5078         }
5079         else
5080 #endif //CONFIG_IOCTL_CFG80211          
5081         {
5082
5083                 //      Todo: WPS IE
5084                 //      Noted by Albert 20100907
5085                 //      According to the WPS specification, all the WPS attribute is presented by Big Endian.
5086
5087                 wpsielen = 0;
5088                 //      WPS OUI
5089                 *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
5090                 wpsielen += 4;
5091
5092                 //      WPS version
5093                 //      Type:
5094                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
5095                 wpsielen += 2;
5096
5097                 //      Length:
5098                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
5099                 wpsielen += 2;
5100
5101                 //      Value:
5102                 wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0
5103
5104 #ifdef CONFIG_INTEL_WIDI
5105                 //      Commented by Kurt
5106                 //      Appended WiDi info. only if we did issued_probereq_widi(), and then we saved ven. ext. in pmlmepriv->sa_ext.
5107                 if(  _rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE 
5108                         || pmlmepriv->num_p2p_sdt != 0 )
5109                 {
5110                         //Sec dev type
5111                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SEC_DEV_TYPE_LIST );
5112                         wpsielen += 2;
5113
5114                         //      Length:
5115                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
5116                         wpsielen += 2;
5117
5118                         //      Value:
5119                         //      Category ID
5120                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_DISPLAYS );
5121                         wpsielen += 2;
5122
5123                         //      OUI
5124                         *(u32*) ( wpsie + wpsielen ) = cpu_to_be32( INTEL_DEV_TYPE_OUI );
5125                         wpsielen += 4;
5126
5127                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_WIDI_CONSUMER_SINK );
5128                         wpsielen += 2;
5129
5130                         if(  _rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE )
5131                         {
5132                                 //      Vendor Extension
5133                                 _rtw_memcpy( wpsie + wpsielen, pmlmepriv->sa_ext, L2SDTA_SERVICE_VE_LEN );
5134                                 wpsielen += L2SDTA_SERVICE_VE_LEN;
5135                         }
5136                 }
5137 #endif //CONFIG_INTEL_WIDI
5138
5139                 //      WiFi Simple Config State
5140                 //      Type:
5141                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SIMPLE_CONF_STATE );
5142                 wpsielen += 2;
5143
5144                 //      Length:
5145                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
5146                 wpsielen += 2;
5147
5148                 //      Value:
5149                 wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;   //      Not Configured.
5150
5151                 //      Response Type
5152                 //      Type:
5153                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_RESP_TYPE );
5154                 wpsielen += 2;
5155
5156                 //      Length:
5157                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
5158                 wpsielen += 2;
5159
5160                 //      Value:
5161                 wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
5162
5163                 //      UUID-E
5164                 //      Type:
5165                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_UUID_E );
5166                 wpsielen += 2;
5167
5168                 //      Length:
5169                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0010 );
5170                 wpsielen += 2;
5171
5172                 //      Value:
5173                 if (pwdinfo->external_uuid == 0) {
5174                         _rtw_memset( wpsie + wpsielen, 0x0, 16 );
5175                         _rtw_memcpy( wpsie + wpsielen, myid( &padapter->eeprompriv ), ETH_ALEN );
5176                 } else {
5177                         _rtw_memcpy( wpsie + wpsielen, pwdinfo->uuid, 0x10 );
5178                 }
5179                 wpsielen += 0x10;
5180
5181                 //      Manufacturer
5182                 //      Type:
5183                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MANUFACTURER );
5184                 wpsielen += 2;
5185
5186                 //      Length:
5187                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0007 );
5188                 wpsielen += 2;
5189
5190                 //      Value:
5191                 _rtw_memcpy( wpsie + wpsielen, "Realtek", 7 );
5192                 wpsielen += 7;
5193
5194                 //      Model Name
5195                 //      Type:
5196                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MODEL_NAME );
5197                 wpsielen += 2;
5198
5199                 //      Length:
5200                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0006 );
5201                 wpsielen += 2;  
5202
5203                 //      Value:
5204                 _rtw_memcpy( wpsie + wpsielen, "8192CU", 6 );
5205                 wpsielen += 6;
5206
5207                 //      Model Number
5208                 //      Type:
5209                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MODEL_NUMBER );
5210                 wpsielen += 2;
5211
5212                 //      Length:
5213                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
5214                 wpsielen += 2;
5215
5216                 //      Value:
5217                 wpsie[ wpsielen++ ] = 0x31;             //      character 1
5218
5219                 //      Serial Number
5220                 //      Type:
5221                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SERIAL_NUMBER );
5222                 wpsielen += 2;
5223
5224                 //      Length:
5225                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( ETH_ALEN );
5226                 wpsielen += 2;
5227
5228                 //      Value:
5229                 _rtw_memcpy( wpsie + wpsielen, "123456" , ETH_ALEN );
5230                 wpsielen += ETH_ALEN;
5231
5232                 //      Primary Device Type
5233                 //      Type:
5234                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
5235                 wpsielen += 2;
5236
5237                 //      Length:
5238                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
5239                 wpsielen += 2;
5240
5241                 //      Value:
5242                 //      Category ID
5243                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
5244                 wpsielen += 2;
5245
5246                 //      OUI
5247                 *(u32*) ( wpsie + wpsielen ) = cpu_to_be32( WPSOUI );
5248                 wpsielen += 4;
5249
5250                 //      Sub Category ID
5251                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
5252                 wpsielen += 2;
5253
5254                 //      Device Name
5255                 //      Type:
5256                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
5257                 wpsielen += 2;
5258
5259                 //      Length:
5260                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->device_name_len );
5261                 wpsielen += 2;
5262
5263                 //      Value:
5264                 _rtw_memcpy( wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len );
5265                 wpsielen += pwdinfo->device_name_len;
5266
5267                 //      Config Method
5268                 //      Type:
5269                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
5270                 wpsielen += 2;
5271
5272                 //      Length:
5273                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
5274                 wpsielen += 2;
5275
5276                 //      Value:
5277                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
5278                 wpsielen += 2;
5279                 
5280
5281                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
5282                 
5283
5284                 p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
5285                 pframe += p2pielen;
5286                 pattrib->pktlen += p2pielen;
5287         }
5288
5289 #ifdef CONFIG_WFD
5290 #ifdef CONFIG_IOCTL_CFG80211
5291         if ( _TRUE == pwdinfo->wfd_info->wfd_enable )
5292 #endif //CONFIG_IOCTL_CFG80211
5293         {
5294                 wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
5295                 pframe += wfdielen;
5296                 pattrib->pktlen += wfdielen;
5297         }
5298 #ifdef CONFIG_IOCTL_CFG80211
5299         else if (pmlmepriv->wfd_probe_resp_ie != NULL && pmlmepriv->wfd_probe_resp_ie_len>0)
5300         {
5301                 //WFD IE
5302                 _rtw_memcpy(pframe, pmlmepriv->wfd_probe_resp_ie, pmlmepriv->wfd_probe_resp_ie_len);
5303                 pattrib->pktlen += pmlmepriv->wfd_probe_resp_ie_len;
5304                 pframe += pmlmepriv->wfd_probe_resp_ie_len;             
5305         }
5306 #endif //CONFIG_IOCTL_CFG80211
5307 #endif //CONFIG_WFD     
5308
5309         pattrib->last_txcmdsz = pattrib->pktlen;
5310         
5311
5312         dump_mgntframe(padapter, pmgntframe);
5313         
5314         return;
5315
5316 }
5317
5318 int _issue_probereq_p2p(_adapter *padapter, u8 *da, int wait_ack)
5319 {
5320         int ret = _FAIL;
5321         struct xmit_frame               *pmgntframe;
5322         struct pkt_attrib               *pattrib;
5323         unsigned char                   *pframe;
5324         struct rtw_ieee80211_hdr        *pwlanhdr;
5325         unsigned short          *fctrl;
5326         unsigned char                   *mac;
5327         unsigned char                   bssrate[NumRates];
5328         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
5329         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5330         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5331         int     bssrate_len = 0;
5332         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
5333         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo); 
5334         u8                                      wpsie[255] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
5335         u16                                     wpsielen = 0, p2pielen = 0;
5336 #ifdef CONFIG_WFD
5337         u32                                     wfdielen = 0;
5338 #endif //CONFIG_WFD
5339
5340         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5341
5342
5343         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
5344         {
5345                 goto exit;
5346         }
5347
5348         //update attribute
5349         pattrib = &pmgntframe->attrib;
5350         update_mgntframe_attrib(padapter, pattrib);
5351
5352
5353         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5354
5355         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5356         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5357
5358         mac = myid(&(padapter->eeprompriv));
5359
5360         fctrl = &(pwlanhdr->frame_ctl);
5361         *(fctrl) = 0;
5362
5363         if (da) {
5364                 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5365                 _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);
5366         } else {
5367                 if ( ( pwdinfo->p2p_info.scan_op_ch_only ) || ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) )
5368                 {
5369                         //      This two flags will be set when this is only the P2P client mode.
5370                         _rtw_memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
5371                         _rtw_memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
5372                 }
5373                 else
5374                 {
5375                         //      broadcast probe request frame
5376                         _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
5377                         _rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
5378                 }
5379         }
5380         _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
5381
5382         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5383         pmlmeext->mgnt_seq++;
5384         SetFrameSubType(pframe, WIFI_PROBEREQ);
5385
5386         pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
5387         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
5388
5389         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
5390         {
5391                 pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &(pattrib->pktlen));
5392         }
5393         else
5394         {
5395                 pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &(pattrib->pktlen));
5396         }
5397         //      Use the OFDM rate in the P2P probe request frame. ( 6(B), 9(B), 12(B), 24(B), 36, 48, 54 )
5398         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
5399
5400 #ifdef CONFIG_IOCTL_CFG80211
5401         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
5402         {
5403                 if( pmlmepriv->wps_probe_req_ie != NULL && pmlmepriv->p2p_probe_req_ie != NULL )
5404                 {
5405                         //WPS IE
5406                         _rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
5407                         pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
5408                         pframe += pmlmepriv->wps_probe_req_ie_len;
5409
5410                         //P2P IE
5411                         _rtw_memcpy(pframe, pmlmepriv->p2p_probe_req_ie, pmlmepriv->p2p_probe_req_ie_len);
5412                         pattrib->pktlen += pmlmepriv->p2p_probe_req_ie_len;
5413                         pframe += pmlmepriv->p2p_probe_req_ie_len;
5414                 }
5415         }
5416         else
5417 #endif //CONFIG_IOCTL_CFG80211
5418         {
5419
5420                 //      WPS IE
5421                 //      Noted by Albert 20110221
5422                 //      According to the WPS specification, all the WPS attribute is presented by Big Endian.
5423
5424                 wpsielen = 0;
5425                 //      WPS OUI
5426                 *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
5427                 wpsielen += 4;
5428
5429                 //      WPS version
5430                 //      Type:
5431                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
5432                 wpsielen += 2;
5433
5434                 //      Length:
5435                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
5436                 wpsielen += 2;
5437
5438                 //      Value:
5439                 wpsie[wpsielen++] = WPS_VERSION_1;      //      Version 1.0
5440
5441                 if( pmlmepriv->wps_probe_req_ie == NULL )
5442                 {
5443                         //      UUID-E
5444                         //      Type:
5445                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_UUID_E );
5446                         wpsielen += 2;
5447
5448                         //      Length:
5449                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0010 );
5450                         wpsielen += 2;
5451
5452                         //      Value:
5453                         if (pwdinfo->external_uuid == 0) {
5454                                 _rtw_memset( wpsie + wpsielen, 0x0, 16 );
5455                                 _rtw_memcpy( wpsie + wpsielen, myid( &padapter->eeprompriv ), ETH_ALEN );
5456                         } else {
5457                                 _rtw_memcpy( wpsie + wpsielen, pwdinfo->uuid, 0x10 );
5458                         }
5459                         wpsielen += 0x10;
5460
5461                         //      Config Method
5462                         //      Type:
5463                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
5464                         wpsielen += 2;
5465
5466                         //      Length:
5467                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
5468                         wpsielen += 2;
5469
5470                         //      Value:
5471                         *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
5472                         wpsielen += 2;
5473                 }
5474
5475                 //      Device Name
5476                 //      Type:
5477                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
5478                 wpsielen += 2;
5479
5480                 //      Length:
5481                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->device_name_len );
5482                 wpsielen += 2;
5483
5484                 //      Value:
5485                 _rtw_memcpy( wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len );
5486                 wpsielen += pwdinfo->device_name_len;
5487
5488                 //      Primary Device Type
5489                 //      Type:
5490                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
5491                 wpsielen += 2;
5492
5493                 //      Length:
5494                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
5495                 wpsielen += 2;
5496
5497                 //      Value:
5498                 //      Category ID
5499                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_RTK_WIDI );
5500                 wpsielen += 2;
5501
5502                 //      OUI
5503                 *(u32*) ( wpsie + wpsielen ) = cpu_to_be32( WPSOUI );
5504                 wpsielen += 4;
5505
5506                 //      Sub Category ID
5507                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_RTK_DMP );
5508                 wpsielen += 2;
5509
5510                 //      Device Password ID
5511                 //      Type:
5512                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
5513                 wpsielen += 2;
5514
5515                 //      Length:
5516                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
5517                 wpsielen += 2;
5518
5519                 //      Value:
5520                 *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );  //      Registrar-specified
5521                 wpsielen += 2;  
5522
5523                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
5524                 
5525                 //      P2P OUI
5526                 p2pielen = 0;
5527                 p2pie[ p2pielen++ ] = 0x50;
5528                 p2pie[ p2pielen++ ] = 0x6F;
5529                 p2pie[ p2pielen++ ] = 0x9A;
5530                 p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
5531
5532                 //      Commented by Albert 20110221
5533                 //      According to the P2P Specification, the probe request frame should contain 5 P2P attributes
5534                 //      1. P2P Capability
5535                 //      2. P2P Device ID if this probe request wants to find the specific P2P device
5536                 //      3. Listen Channel
5537                 //      4. Extended Listen Timing
5538                 //      5. Operating Channel if this WiFi is working as the group owner now
5539
5540                 //      P2P Capability
5541                 //      Type:
5542                 p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
5543
5544                 //      Length:
5545                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
5546                 p2pielen += 2;
5547
5548                 //      Value:
5549                 //      Device Capability Bitmap, 1 byte
5550                 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
5551                 
5552                 //      Group Capability Bitmap, 1 byte
5553                 if ( pwdinfo->persistent_supported )
5554                         p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
5555                 else
5556                         p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
5557
5558                 //      Listen Channel
5559                 //      Type:
5560                 p2pie[ p2pielen++ ] = P2P_ATTR_LISTEN_CH;
5561
5562                 //      Length:
5563                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
5564                 p2pielen += 2;
5565
5566                 //      Value:
5567                 //      Country String
5568                 p2pie[ p2pielen++ ] = 'X';
5569                 p2pie[ p2pielen++ ] = 'X';
5570                 
5571                 //      The third byte should be set to 0x04.
5572                 //      Described in the "Operating Channel Attribute" section.
5573                 p2pie[ p2pielen++ ] = 0x04;
5574
5575                 //      Operating Class
5576                 p2pie[ p2pielen++ ] = 0x51;     //      Copy from SD7
5577                 
5578                 //      Channel Number
5579                 p2pie[ p2pielen++ ] = pwdinfo->listen_channel;  //      listen channel
5580                 
5581
5582                 //      Extended Listen Timing
5583                 //      Type:
5584                 p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
5585
5586                 //      Length:
5587                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
5588                 p2pielen += 2;
5589
5590                 //      Value:
5591                 //      Availability Period
5592                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
5593                 p2pielen += 2;
5594
5595                 //      Availability Interval
5596                 *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
5597                 p2pielen += 2;
5598
5599                 if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
5600                 {
5601                         //      Operating Channel (if this WiFi is working as the group owner now)
5602                         //      Type:
5603                         p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
5604
5605                         //      Length:
5606                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
5607                         p2pielen += 2;
5608
5609                         //      Value:
5610                         //      Country String
5611                         p2pie[ p2pielen++ ] = 'X';
5612                         p2pie[ p2pielen++ ] = 'X';
5613                 
5614                         //      The third byte should be set to 0x04.
5615                         //      Described in the "Operating Channel Attribute" section.
5616                         p2pie[ p2pielen++ ] = 0x04;
5617
5618                         //      Operating Class
5619                         p2pie[ p2pielen++ ] = 0x51;     //      Copy from SD7
5620                 
5621                         //      Channel Number
5622                         p2pie[ p2pielen++ ] = pwdinfo->operating_channel;       //      operating channel number
5623                         
5624                 }
5625                 
5626                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );        
5627
5628         }
5629
5630 #ifdef CONFIG_WFD
5631 #ifdef CONFIG_IOCTL_CFG80211
5632         if ( _TRUE == pwdinfo->wfd_info->wfd_enable )
5633 #endif
5634         {
5635                 wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
5636                 pframe += wfdielen;
5637                 pattrib->pktlen += wfdielen;
5638         }
5639 #ifdef CONFIG_IOCTL_CFG80211
5640         else if (pmlmepriv->wfd_probe_req_ie != NULL && pmlmepriv->wfd_probe_req_ie_len>0)              
5641         {
5642                 //WFD IE
5643                 _rtw_memcpy(pframe, pmlmepriv->wfd_probe_req_ie, pmlmepriv->wfd_probe_req_ie_len);
5644                 pattrib->pktlen += pmlmepriv->wfd_probe_req_ie_len;
5645                 pframe += pmlmepriv->wfd_probe_req_ie_len;              
5646         }
5647 #endif //CONFIG_IOCTL_CFG80211
5648 #endif //CONFIG_WFD     
5649
5650         pattrib->last_txcmdsz = pattrib->pktlen;
5651
5652         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
5653
5654         if (wait_ack) {
5655                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5656         } else {
5657                 dump_mgntframe(padapter, pmgntframe);
5658                 ret = _SUCCESS;
5659         }
5660
5661 exit:
5662         return ret;
5663 }
5664
5665 inline void issue_probereq_p2p(_adapter *adapter, u8 *da)
5666 {
5667         _issue_probereq_p2p(adapter, da, _FALSE);
5668 }
5669
5670 int issue_probereq_p2p_ex(_adapter *adapter, u8 *da, int try_cnt, int wait_ms)
5671 {
5672         int ret;
5673         int i = 0;
5674         u32 start = rtw_get_current_time();
5675
5676         do
5677         {
5678                 ret = _issue_probereq_p2p(adapter, da, wait_ms>0?_TRUE:_FALSE);
5679
5680                 i++;
5681
5682                 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
5683                         break;
5684
5685                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
5686                         rtw_msleep_os(wait_ms);
5687
5688         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
5689
5690         if (ret != _FAIL) {
5691                 ret = _SUCCESS;
5692                 #ifndef DBG_XMIT_ACK
5693                 goto exit;
5694                 #endif
5695         }
5696
5697         if (try_cnt && wait_ms) {
5698                 if (da)
5699                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
5700                                 FUNC_ADPT_ARG(adapter), MAC_ARG(da), rtw_get_oper_ch(adapter),
5701                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
5702                 else
5703                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5704                                 FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter),
5705                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
5706         }
5707 exit:
5708         return ret;
5709 }
5710
5711 #endif //CONFIG_P2P
5712
5713 s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
5714 {
5715         _adapter *adapter = recv_frame->u.hdr.adapter;
5716         struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
5717         u8 *frame = recv_frame->u.hdr.rx_data;
5718         u16 seq_ctrl = ( (recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
5719                 (recv_frame->u.hdr.attrib.frag_num & 0xf);
5720         
5721         if (GetRetry(frame)) {
5722                 if (token >= 0) {
5723                         if ((seq_ctrl == mlmeext->action_public_rxseq)
5724                                 && (token == mlmeext->action_public_dialog_token))
5725                         {
5726                                 DBG_871X(FUNC_ADPT_FMT" seq_ctrl=0x%x, rxseq=0x%x, token:%d\n",
5727                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
5728                                 return _FAIL;
5729                         }
5730                 } else {
5731                         if (seq_ctrl == mlmeext->action_public_rxseq) {
5732                                 DBG_871X(FUNC_ADPT_FMT" seq_ctrl=0x%x, rxseq=0x%x\n",
5733                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
5734                                 return _FAIL;
5735                         }
5736                 }
5737         }
5738         
5739         mlmeext->action_public_rxseq = seq_ctrl;
5740         
5741         if (token >= 0)
5742                 mlmeext->action_public_dialog_token = token;
5743
5744         return _SUCCESS;
5745 }
5746
5747 unsigned int on_action_public_p2p(union recv_frame *precv_frame)
5748 {
5749         _adapter *padapter = precv_frame->u.hdr.adapter;
5750         u8 *pframe = precv_frame->u.hdr.rx_data;
5751         uint len = precv_frame->u.hdr.len;
5752         u8 *frame_body;
5753         u8 dialogToken=0;
5754 #ifdef CONFIG_P2P
5755         u8 *p2p_ie;
5756         u32     p2p_ielen, wps_ielen;
5757         struct  wifidirect_info *pwdinfo = &( padapter->wdinfo );
5758         u8      result = P2P_STATUS_SUCCESS;
5759         u8      empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
5760         u8 *merged_p2pie = NULL;
5761         u32 merged_p2p_ielen= 0;
5762 #endif //CONFIG_P2P
5763
5764         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
5765
5766         dialogToken = frame_body[7];
5767
5768         if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
5769                 return _FAIL;
5770         
5771 #ifdef CONFIG_P2P
5772         _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
5773 #ifdef CONFIG_IOCTL_CFG80211
5774         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211)
5775         {
5776                 rtw_cfg80211_rx_p2p_action_public(padapter, pframe, len);
5777         }
5778         else
5779 #endif //CONFIG_IOCTL_CFG80211
5780         {
5781                 //      Do nothing if the driver doesn't enable the P2P function.
5782                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
5783                         return _SUCCESS;
5784
5785                 len -= sizeof(struct rtw_ieee80211_hdr_3addr);
5786
5787                 switch( frame_body[ 6 ] )//OUI Subtype
5788                 {
5789                         case P2P_GO_NEGO_REQ:
5790                         {
5791                                 DBG_871X( "[%s] Got GO Nego Req Frame\n", __FUNCTION__);
5792                                 _rtw_memset( &pwdinfo->groupid_info, 0x00, sizeof( struct group_id_info ) );
5793
5794                                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
5795                                 {
5796                                         rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
5797                                 }
5798
5799                                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
5800                                 {
5801                                         //      Commented by Albert 20110526
5802                                         //      In this case, this means the previous nego fail doesn't be reset yet.
5803                                         _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5804                                         //      Restore the previous p2p state
5805                                         rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
5806                                         DBG_871X( "[%s] Restore the previous p2p state to %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo) );                                                
5807                                 }                                       
5808 #ifdef CONFIG_CONCURRENT_MODE
5809                                 if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
5810                                 {
5811                                         _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
5812                                 }
5813 #endif // CONFIG_CONCURRENT_MODE
5814
5815                                 //      Commented by Kurt 20110902
5816                                 //Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered.
5817                                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
5818                                         rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
5819
5820                                 //      Commented by Kurt 20120113
5821                                 //      Get peer_dev_addr here if peer doesn't issue prov_disc frame.
5822                                 if( _rtw_memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN) )
5823                                         _rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
5824
5825                                 result = process_p2p_group_negotation_req( pwdinfo, frame_body, len );
5826                                 issue_p2p_GO_response( padapter, GetAddr2Ptr(pframe), frame_body, len, result );
5827 #ifdef CONFIG_INTEL_WIDI
5828                                 if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) )
5829                                 {
5830                                         padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
5831                                         _cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
5832                                         intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
5833                                 }
5834 #endif //CONFIG_INTEL_WIDI
5835
5836                                 //      Commented by Albert 20110718
5837                                 //      No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer.
5838 #ifdef CONFIG_CONCURRENT_MODE
5839                                 //      Commented by Albert 20120107
5840                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
5841 #else // CONFIG_CONCURRENT_MODE
5842                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
5843 #endif // CONFIG_CONCURRENT_MODE
5844                                 break;                                  
5845                         }
5846                         case P2P_GO_NEGO_RESP:
5847                         {
5848                                 DBG_871X( "[%s] Got GO Nego Resp Frame\n", __FUNCTION__);
5849
5850                                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
5851                                 {
5852                                         //      Commented by Albert 20110425
5853                                         //      The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function.
5854                                         _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5855                                         pwdinfo->nego_req_info.benable = _FALSE;
5856                                         result = process_p2p_group_negotation_resp( pwdinfo, frame_body, len);
5857                                         issue_p2p_GO_confirm( pwdinfo->padapter, GetAddr2Ptr(pframe), result);
5858                                         if ( P2P_STATUS_SUCCESS == result )
5859                                         {
5860                                                 if ( rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT )
5861                                                 {
5862                                                         pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
5863                                                         #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5864                                                         pwdinfo->p2p_info.operation_ch[ 1 ] = 1;        //Check whether GO is operating in channel 1;
5865                                                         pwdinfo->p2p_info.operation_ch[ 2 ] = 6;        //Check whether GO is operating in channel 6;
5866                                                         pwdinfo->p2p_info.operation_ch[ 3 ] = 11;       //Check whether GO is operating in channel 11;
5867                                                         #endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
5868                                                         pwdinfo->p2p_info.scan_op_ch_only = 1;
5869                                                         _set_timer( &pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH );
5870                                                 }
5871                                         }
5872
5873                                         //      Reset the dialog token for group negotiation frames.
5874                                         pwdinfo->negotiation_dialog_token = 1;
5875
5876                                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
5877                                         {
5878                                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
5879                                         }
5880                                 }
5881                                 else
5882                                 {
5883                                         DBG_871X( "[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __FUNCTION__);
5884                                 }
5885                                 
5886                                 break;
5887                         }
5888                         case P2P_GO_NEGO_CONF:
5889                         {
5890                                 DBG_871X( "[%s] Got GO Nego Confirm Frame\n", __FUNCTION__);
5891                                 result = process_p2p_group_negotation_confirm( pwdinfo, frame_body, len);
5892                                 if ( P2P_STATUS_SUCCESS == result )
5893                                 {
5894                                         if ( rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT )
5895                                         {
5896                                                 pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
5897                                                 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5898                                                 pwdinfo->p2p_info.operation_ch[ 1 ] = 1;        //Check whether GO is operating in channel 1;
5899                                                 pwdinfo->p2p_info.operation_ch[ 2 ] = 6;        //Check whether GO is operating in channel 6;
5900                                                 pwdinfo->p2p_info.operation_ch[ 3 ] = 11;       //Check whether GO is operating in channel 11;
5901                                                 #endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
5902                                                 pwdinfo->p2p_info.scan_op_ch_only = 1;
5903                                                 _set_timer( &pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH );
5904                                         }
5905                                 }
5906                                 break;
5907                         }
5908                         case P2P_INVIT_REQ:
5909                         {
5910                                 //      Added by Albert 2010/10/05
5911                                 //      Received the P2P Invite Request frame.
5912                                 
5913                                 DBG_871X( "[%s] Got invite request frame!\n", __FUNCTION__ );
5914                                 if ( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)) )
5915                                 {
5916                                         //      Parse the necessary information from the P2P Invitation Request frame.
5917                                         //      For example: The MAC address of sending this P2P Invitation Request frame.
5918                                         u32     attr_contentlen = 0;
5919                                         u8      status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
5920                                         struct group_id_info group_id;
5921                                         u8      invitation_flag = 0;
5922                                         int j=0;
5923
5924                                         merged_p2p_ielen = rtw_get_p2p_merged_ies_len(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_);
5925
5926                                         merged_p2pie = rtw_zmalloc(merged_p2p_ielen + 2);       // 2 is for EID and Length
5927                                         if (merged_p2pie == NULL)
5928                                         {
5929                                                 DBG_871X( "[%s] Malloc p2p ie fail\n", __FUNCTION__);
5930                                                 goto exit;
5931                                         }
5932                                         _rtw_memset(merged_p2pie, 0x00, merged_p2p_ielen);                                      
5933
5934                                         merged_p2p_ielen = rtw_p2p_merge_ies(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, merged_p2pie);
5935
5936                                         rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
5937                                         if ( attr_contentlen )
5938                                         {
5939
5940                                                 rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
5941                                                 //      Commented by Albert 20120510
5942                                                 //      Copy to the pwdinfo->p2p_peer_interface_addr.
5943                                                 //      So that the WFD UI ( or Sigma ) can get the peer interface address by using the following command.
5944                                                 //      #> iwpriv wlan0 p2p_get peer_ifa
5945                                                 //      After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant.
5946
5947                                                 if ( attr_contentlen )
5948                                                 {
5949                                                         DBG_871X( "[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
5950                                                                         pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
5951                                                                         pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
5952                                                                         pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5] );
5953                                                 }                                                               
5954
5955                                                 if ( invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT )
5956                                                 {
5957                                                         //      Re-invoke the persistent group.
5958                                                         
5959                                                         _rtw_memset( &group_id, 0x00, sizeof( struct group_id_info ) );
5960                                                         rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen);
5961                                                         if ( attr_contentlen )
5962                                                         {
5963                                                                 if ( _rtw_memcmp( group_id.go_device_addr, myid( &padapter->eeprompriv ), ETH_ALEN ) )
5964                                                                 {
5965                                                                         //      The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO.
5966                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO );
5967                                                                         rtw_p2p_set_role( pwdinfo, P2P_ROLE_GO );
5968                                                                         status_code = P2P_STATUS_SUCCESS;
5969                                                                 }
5970                                                                 else
5971                                                                 {
5972                                                                         //      The p2p device sending this p2p invitation request wants to be the persistent GO.
5973                                                                         if ( is_matched_in_profilelist( pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[ 0 ] ) )
5974                                                                         {
5975                                                                                 u8 operatingch_info[5] = { 0x00 };
5976                                                                                 if ( rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) )
5977                                                                                 {
5978                                                                                         if( rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4] ) >= 0 )
5979                                                                                         {
5980                                                                                                 //      The operating channel is acceptable for this device.
5981                                                                                                 pwdinfo->rx_invitereq_info.operation_ch[0]= operatingch_info[4];
5982                                                                                                 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5983                                                                                                 pwdinfo->rx_invitereq_info.operation_ch[1]= 1;          //Check whether GO is operating in channel 1;
5984                                                                                                 pwdinfo->rx_invitereq_info.operation_ch[2]= 6;          //Check whether GO is operating in channel 6;
5985                                                                                                 pwdinfo->rx_invitereq_info.operation_ch[3]= 11;         //Check whether GO is operating in channel 11;
5986                                                                                                 #endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
5987                                                                                                 pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
5988                                                                                                 _set_timer( &pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH );
5989                                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH );
5990                                                                                                 rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
5991                                                                                                 status_code = P2P_STATUS_SUCCESS;
5992                                                                                         }
5993                                                                                         else
5994                                                                                         {
5995                                                                                                 //      The operating channel isn't supported by this device.
5996                                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
5997                                                                                                 rtw_p2p_set_role( pwdinfo, P2P_ROLE_DEVICE );
5998                                                                                                 status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
5999                                                                                                 _set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
6000                                                                                         }
6001                                                                                 }
6002                                                                                 else
6003                                                                                 {
6004                                                                                         //      Commented by Albert 20121130
6005                                                                                         //      Intel will use the different P2P IE to store the operating channel information
6006                                                                                         //      Workaround for Intel WiDi 3.5
6007                                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH );
6008                                                                                         rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
6009                                                                                         status_code = P2P_STATUS_SUCCESS;
6010                                                                                 }                                                               
6011                                                                         }
6012                                                                         else
6013                                                                         {
6014                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
6015                                                                                 #ifdef CONFIG_INTEL_WIDI
6016                                                                                 _rtw_memcpy( pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN );
6017                                                                                 rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
6018                                                                                 #endif //CONFIG_INTEL_WIDI
6019
6020                                                                                 status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
6021                                                                         }
6022                                                                 }
6023                                                         }
6024                                                         else
6025                                                         {
6026                                                                 DBG_871X( "[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__ );
6027                                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
6028                                                         }                                                                       
6029                                                 }
6030                                                 else
6031                                                 {
6032                                                         //      Received the invitation to join a P2P group.
6033
6034                                                         _rtw_memset( &group_id, 0x00, sizeof( struct group_id_info ) );
6035                                                         rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen);
6036                                                         if ( attr_contentlen )
6037                                                         {
6038                                                                 if ( _rtw_memcmp( group_id.go_device_addr, myid( &padapter->eeprompriv ), ETH_ALEN ) )
6039                                                                 {
6040                                                                         //      In this case, the GO can't be myself.
6041                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
6042                                                                         status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
6043                                                                 }
6044                                                                 else
6045                                                                 {
6046                                                                         //      The p2p device sending this p2p invitation request wants to join an existing P2P group
6047                                                                         //      Commented by Albert 2012/06/28
6048                                                                         //      In this case, this Wi-Fi device should use the iwpriv command to get the peer device address.
6049                                                                         //      The peer device address should be the destination address for the provisioning discovery request.
6050                                                                         //      Then, this Wi-Fi device should use the iwpriv command to get the peer interface address.
6051                                                                         //      The peer interface address should be the address for WPS mac address
6052                                                                         _rtw_memcpy( pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN );                                                                                       
6053                                                                         rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
6054                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN );
6055                                                                         status_code = P2P_STATUS_SUCCESS;
6056                                                                 }
6057                                                         }
6058                                                         else
6059                                                         {
6060                                                                 DBG_871X( "[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__ );
6061                                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
6062                                                         }
6063                                                 }
6064                                         }
6065                                         else
6066                                         {
6067                                                 DBG_871X( "[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __FUNCTION__ );
6068                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
6069                                         }                                                       
6070
6071                                         DBG_871X( "[%s] status_code = %d\n", __FUNCTION__, status_code );
6072
6073                                         pwdinfo->inviteresp_info.token = frame_body[ 7 ];
6074                                         issue_p2p_invitation_response( padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code );
6075                                         _set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
6076                                 }
6077 #ifdef CONFIG_INTEL_WIDI
6078                                 if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) )
6079                                 {
6080                                         padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
6081                                         _cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
6082                                         intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
6083                                 }
6084 #endif //CONFIG_INTEL_WIDI
6085                                 break;
6086                         }
6087                         case P2P_INVIT_RESP:
6088                         {
6089                                 u8      attr_content = 0x00;
6090                                 u32     attr_contentlen = 0;
6091                                 
6092                                 DBG_871X( "[%s] Got invite response frame!\n", __FUNCTION__ );
6093                                 _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
6094                                 if ( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)) )
6095                                 {
6096                                         rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
6097                                                                         
6098                                         if ( attr_contentlen == 1 )
6099                                         {
6100                                                 DBG_871X( "[%s] Status = %d\n", __FUNCTION__, attr_content );
6101                                                 pwdinfo->invitereq_info.benable = _FALSE;
6102
6103                                                 if ( attr_content == P2P_STATUS_SUCCESS )
6104                                                 {
6105                                                         if ( _rtw_memcmp( pwdinfo->invitereq_info.go_bssid, myid( &padapter->eeprompriv ), ETH_ALEN ))
6106                                                         {
6107                                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO );
6108                                                         }
6109                                                         else
6110                                                         {
6111                                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
6112                                                         }
6113                                                         rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_OK );
6114                                                 }
6115                                                 else
6116                                                 {
6117                                                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
6118                                                         rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
6119                                                 }
6120                                         }
6121                                         else
6122                                         {
6123                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
6124                                                 rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
6125                                         }
6126                                 }
6127                                 else
6128                                 {
6129                                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
6130                                         rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
6131                                 }
6132
6133                                 if ( rtw_p2p_chk_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL ) )
6134                                 {
6135                                         _set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
6136                                 }
6137                                 break;
6138                         }
6139                         case P2P_DEVDISC_REQ:
6140
6141                                 process_p2p_devdisc_req(pwdinfo, pframe, len);
6142
6143                                 break;
6144
6145                         case P2P_DEVDISC_RESP:
6146
6147                                 process_p2p_devdisc_resp(pwdinfo, pframe, len);
6148
6149                                 break;
6150
6151                         case P2P_PROVISION_DISC_REQ:
6152                                 DBG_871X( "[%s] Got Provisioning Discovery Request Frame\n", __FUNCTION__ );
6153                                 process_p2p_provdisc_req(pwdinfo, pframe, len);
6154                                 _rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
6155
6156                                 //20110902 Kurt
6157                                 //Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered.
6158                                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
6159                                         rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
6160                                 
6161                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
6162                                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
6163 #ifdef CONFIG_INTEL_WIDI
6164                                 if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) )
6165                                 {
6166                                         padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
6167                                         _cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
6168                                         intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
6169                                 }
6170 #endif //CONFIG_INTEL_WIDI
6171                                 break;
6172
6173                         case P2P_PROVISION_DISC_RESP:
6174                                 //      Commented by Albert 20110707
6175                                 //      Should we check the pwdinfo->tx_prov_disc_info.bsent flag here??
6176                                 DBG_871X( "[%s] Got Provisioning Discovery Response Frame\n", __FUNCTION__ );
6177                                 //      Commented by Albert 20110426
6178                                 //      The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function.
6179                                 _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
6180                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
6181                                 process_p2p_provdisc_resp(pwdinfo, pframe);
6182                                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
6183                                 break;
6184
6185                 }
6186         }
6187
6188
6189 exit:
6190
6191         if(merged_p2pie)
6192         {
6193                 rtw_mfree(merged_p2pie, merged_p2p_ielen + 2);
6194         }
6195 #endif //CONFIG_P2P
6196         return _SUCCESS;
6197 }
6198
6199 unsigned int on_action_public_vendor(union recv_frame *precv_frame)
6200 {
6201         unsigned int ret = _FAIL;
6202         u8 *pframe = precv_frame->u.hdr.rx_data;
6203         uint frame_len = precv_frame->u.hdr.len;
6204         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
6205
6206         if (_rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE) {
6207                 ret = on_action_public_p2p(precv_frame);
6208         }
6209
6210         return ret;
6211 }
6212
6213 unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
6214 {
6215         unsigned int ret = _FAIL;
6216         u8 *pframe = precv_frame->u.hdr.rx_data;
6217         uint frame_len = precv_frame->u.hdr.len;
6218         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
6219         u8 token;
6220         _adapter *adapter = precv_frame->u.hdr.adapter;
6221         int cnt = 0;
6222         char msg[64];
6223
6224         token = frame_body[2];
6225
6226         if (rtw_action_public_decache(precv_frame, token) == _FAIL)
6227                 goto exit;
6228
6229         #ifdef CONFIG_IOCTL_CFG80211
6230         cnt += sprintf((msg+cnt), "%s(token:%u)", action_public_str(action), token);
6231         rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
6232         #endif
6233
6234         ret = _SUCCESS;
6235         
6236 exit:
6237         return ret;
6238 }
6239
6240 unsigned int on_action_public(_adapter *padapter, union recv_frame *precv_frame)
6241 {
6242         unsigned int ret = _FAIL;
6243         u8 *pframe = precv_frame->u.hdr.rx_data;
6244         uint frame_len = precv_frame->u.hdr.len;
6245         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
6246         u8 category, action;
6247
6248         /* check RA matches or not */
6249         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
6250                 goto exit;
6251
6252         category = frame_body[0];
6253         if(category != RTW_WLAN_CATEGORY_PUBLIC)
6254                 goto exit;
6255
6256         action = frame_body[1];
6257         switch (action) {
6258         case ACT_PUBLIC_VENDOR:
6259                 ret = on_action_public_vendor(precv_frame);
6260                 break;
6261         default:
6262                 ret = on_action_public_default(precv_frame, action);
6263                 break;
6264         }
6265
6266 exit:
6267         return ret;
6268 }
6269
6270 unsigned int OnAction_ht(_adapter *padapter, union recv_frame *precv_frame)
6271 {
6272         u8 *pframe = precv_frame->u.hdr.rx_data;
6273         uint frame_len = precv_frame->u.hdr.len;
6274         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
6275         u8 category, action;
6276
6277         /* check RA matches or not */
6278         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
6279                 goto exit;
6280
6281         category = frame_body[0];
6282         if(category != RTW_WLAN_CATEGORY_HT)
6283                 goto exit;
6284
6285         action = frame_body[1];
6286         switch (action) {
6287         case RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING:
6288 #ifdef CONFIG_BEAMFORMING
6289                 //DBG_871X("RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING\n");
6290                 beamforming_get_report_frame(padapter, precv_frame);
6291 #endif //CONFIG_BEAMFORMING
6292                 break;
6293         default:
6294                 break;
6295         }
6296
6297 exit:
6298
6299         return _SUCCESS;
6300 }
6301
6302 #ifdef CONFIG_IEEE80211W
6303 unsigned int OnAction_sa_query(_adapter *padapter, union recv_frame *precv_frame)
6304 {
6305         u8 *pframe = precv_frame->u.hdr.rx_data;
6306         struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
6307         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6308         unsigned short tid;
6309         //Baron
6310         
6311         DBG_871X("OnAction_sa_query\n");
6312         
6313         switch (pframe[WLAN_HDR_A3_LEN+1])
6314         {
6315                 case 0: //SA Query req
6316                         _rtw_memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short));
6317                         DBG_871X("OnAction_sa_query request,action=%d, tid=%04x\n", pframe[WLAN_HDR_A3_LEN+1], tid);
6318                         issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid);
6319                         break;
6320
6321                 case 1: //SA Query rsp
6322                         _cancel_timer_ex(&pmlmeext->sa_query_timer);
6323                         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]);
6324                         break;
6325                 default:
6326                         break;
6327         }
6328         if(0)
6329         {
6330                 int pp;
6331                 printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
6332                 for(pp=0;pp< pattrib->pkt_len; pp++)
6333                         printk(" %02x ", pframe[pp]);
6334                 printk("\n");
6335         }       
6336         
6337         return _SUCCESS;
6338 }
6339 #endif //CONFIG_IEEE80211W
6340
6341 unsigned int OnAction_wmm(_adapter *padapter, union recv_frame *precv_frame)
6342 {
6343         return _SUCCESS;
6344 }
6345
6346 unsigned int OnAction_vht(_adapter *padapter, union recv_frame *precv_frame)
6347 {
6348 #ifdef CONFIG_80211AC_VHT
6349         struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
6350         u8 *pframe = precv_frame->u.hdr.rx_data;
6351         uint frame_len = precv_frame->u.hdr.len;
6352         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
6353         u8 category, action;
6354         struct sta_info *psta = NULL;
6355
6356         /* check RA matches or not */
6357         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
6358                 goto exit;
6359
6360         category = frame_body[0];
6361         if(category != RTW_WLAN_CATEGORY_VHT)
6362                 goto exit;
6363
6364         action = frame_body[1];
6365         switch (action) {
6366         case RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING:
6367 #ifdef CONFIG_BEAMFORMING
6368                 //DBG_871X("RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING\n");
6369                 beamforming_get_report_frame(padapter, precv_frame);
6370 #endif //CONFIG_BEAMFORMING
6371                 break;
6372         case RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION:
6373                 // CategoryCode(1) + ActionCode(1) + OpModeNotification(1)
6374                 //DBG_871X("RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION\n");
6375                 psta = rtw_get_stainfo(&padapter->stapriv, prxattrib->ta);
6376                 if (psta)
6377                         rtw_process_vht_op_mode_notify(padapter, &frame_body[2], psta);
6378                 break;
6379         default:
6380                 break;
6381         }
6382
6383 exit:
6384 #endif //CONFIG_80211AC_VHT
6385
6386         return _SUCCESS;
6387 }
6388
6389 unsigned int OnAction_p2p(_adapter *padapter, union recv_frame *precv_frame)
6390 {
6391 #ifdef CONFIG_P2P
6392         u8 *frame_body;
6393         u8 category, OUI_Subtype, dialogToken=0;
6394         u8 *pframe = precv_frame->u.hdr.rx_data;
6395         uint len = precv_frame->u.hdr.len;
6396         struct  wifidirect_info *pwdinfo = &( padapter->wdinfo );
6397         
6398         //check RA matches or not
6399         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))//for if1, sta/ap mode
6400                 return _SUCCESS;
6401
6402         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
6403
6404         category = frame_body[0];
6405         if(category != RTW_WLAN_CATEGORY_P2P)
6406                 return _SUCCESS;
6407
6408         if ( cpu_to_be32( *( ( u32* ) ( frame_body + 1 ) ) ) != P2POUI )
6409                 return _SUCCESS;
6410
6411 #ifdef CONFIG_IOCTL_CFG80211
6412         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
6413         {
6414                 rtw_cfg80211_rx_action_p2p(padapter, pframe, len);
6415                 return _SUCCESS;
6416         }
6417         else
6418 #endif //CONFIG_IOCTL_CFG80211
6419         {
6420                 len -= sizeof(struct rtw_ieee80211_hdr_3addr);
6421                 OUI_Subtype = frame_body[5];
6422                 dialogToken = frame_body[6];
6423
6424                 switch(OUI_Subtype)
6425                 {
6426                         case P2P_NOTICE_OF_ABSENCE:
6427                                 
6428                                 break;
6429                                 
6430                         case P2P_PRESENCE_REQUEST:
6431
6432                                 process_p2p_presence_req(pwdinfo, pframe, len);                 
6433                                 
6434                                 break;
6435                                 
6436                         case P2P_PRESENCE_RESPONSE:
6437                                 
6438                                 break;
6439                                 
6440                         case P2P_GO_DISC_REQUEST:
6441                                 
6442                                 break;
6443                                 
6444                         default:
6445                                 break;
6446                                 
6447                 }
6448         }
6449 #endif //CONFIG_P2P
6450
6451         return _SUCCESS;
6452
6453 }
6454
6455 unsigned int OnAction(_adapter *padapter, union recv_frame *precv_frame)
6456 {
6457         int i;
6458         unsigned char   category;
6459         struct action_handler *ptable;
6460         unsigned char   *frame_body;
6461         u8 *pframe = precv_frame->u.hdr.rx_data; 
6462
6463         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
6464         
6465         category = frame_body[0];
6466         
6467         for(i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++) 
6468         {
6469                 ptable = &OnAction_tbl[i];
6470                 
6471                 if(category == ptable->num)
6472                         ptable->func(padapter, precv_frame);
6473         
6474         }
6475
6476         return _SUCCESS;
6477
6478 }
6479
6480 unsigned int DoReserved(_adapter *padapter, union recv_frame *precv_frame)
6481 {
6482
6483         //DBG_871X("rcvd mgt frame(%x, %x)\n", (GetFrameSubType(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe));
6484         return _SUCCESS;
6485 }
6486
6487 struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
6488 {
6489         struct xmit_frame *pmgntframe;
6490         struct xmit_buf *pxmitbuf;
6491
6492         if (once)
6493                 pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
6494         else
6495                 pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
6496
6497         if (pmgntframe == NULL) {
6498                 DBG_871X(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once);
6499                 goto exit;
6500         }
6501
6502         if ((pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv)) == NULL) {
6503                 DBG_871X(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter));
6504                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
6505                 pmgntframe = NULL;
6506                 goto exit;
6507         }
6508
6509         pmgntframe->frame_tag = MGNT_FRAMETAG;
6510         pmgntframe->pxmitbuf = pxmitbuf;
6511         pmgntframe->buf_addr = pxmitbuf->pbuf;
6512         pxmitbuf->priv_data = pmgntframe;
6513
6514 exit:
6515         return pmgntframe;
6516
6517 }
6518
6519 inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
6520 {
6521         return _alloc_mgtxmitframe(pxmitpriv, _FALSE);
6522 }
6523
6524 inline struct xmit_frame *alloc_mgtxmitframe_once(struct xmit_priv *pxmitpriv)
6525 {
6526         return _alloc_mgtxmitframe(pxmitpriv, _TRUE);
6527 }
6528
6529
6530 /****************************************************************************
6531
6532 Following are some TX fuctions for WiFi MLME
6533
6534 *****************************************************************************/
6535
6536 void update_mgnt_tx_rate(_adapter *padapter, u8 rate)
6537 {
6538         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6539
6540         pmlmeext->tx_rate = rate;
6541         //DBG_871X("%s(): rate = %x\n",__FUNCTION__, rate);
6542 }
6543
6544 void update_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
6545 {
6546         u8      wireless_mode;
6547         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6548
6549         //_rtw_memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
6550
6551         pattrib->hdrlen = 24;
6552         pattrib->nr_frags = 1;
6553         pattrib->priority = 7;
6554         pattrib->mac_id = 0;
6555         pattrib->qsel = 0x12;
6556
6557         pattrib->pktlen = 0;
6558
6559         if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
6560                 wireless_mode = WIRELESS_11B;
6561         else
6562                 wireless_mode = WIRELESS_11G;
6563         pattrib->raid =  rtw_get_mgntframe_raid(padapter, wireless_mode);
6564         pattrib->rate = pmlmeext->tx_rate;
6565
6566         pattrib->encrypt = _NO_PRIVACY_;
6567         pattrib->bswenc = _FALSE;       
6568
6569         pattrib->qos_en = _FALSE;
6570         pattrib->ht_en = _FALSE;
6571         pattrib->bwmode = CHANNEL_WIDTH_20;
6572         pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6573         pattrib->sgi = _FALSE;
6574
6575         pattrib->seqnum = pmlmeext->mgnt_seq;
6576
6577         pattrib->retry_ctrl = _TRUE;
6578
6579         pattrib->mbssid = 0;
6580
6581 }
6582
6583 void update_mgntframe_attrib_addr(_adapter *padapter, struct xmit_frame *pmgntframe)
6584 {
6585         u8      *pframe;
6586         struct pkt_attrib       *pattrib = &pmgntframe->attrib;
6587
6588         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6589
6590         _rtw_memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);
6591         _rtw_memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN);
6592 }
6593
6594 void dump_mgntframe(_adapter *padapter, struct xmit_frame *pmgntframe)
6595 {
6596         if(padapter->bSurpriseRemoved == _TRUE ||
6597                 padapter->bDriverStopped == _TRUE)
6598         {
6599                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
6600                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
6601                 return;
6602         }
6603
6604         rtw_hal_mgnt_xmit(padapter, pmgntframe);
6605 }
6606
6607 s32 dump_mgntframe_and_wait(_adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
6608 {
6609         s32 ret = _FAIL;
6610         _irqL irqL;
6611         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;      
6612         struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
6613         struct submit_ctx sctx;
6614
6615         if(padapter->bSurpriseRemoved == _TRUE ||
6616                 padapter->bDriverStopped == _TRUE)
6617         {
6618                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
6619                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
6620                 return ret;
6621         }
6622
6623         rtw_sctx_init(&sctx, timeout_ms);
6624         pxmitbuf->sctx = &sctx;
6625
6626         ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
6627
6628         if (ret == _SUCCESS)
6629                 ret = rtw_sctx_wait(&sctx, __func__);
6630
6631         _enter_critical(&pxmitpriv->lock_sctx, &irqL);
6632         pxmitbuf->sctx = NULL;
6633         _exit_critical(&pxmitpriv->lock_sctx, &irqL);
6634
6635          return ret;
6636 }
6637
6638 s32 dump_mgntframe_and_wait_ack(_adapter *padapter, struct xmit_frame *pmgntframe)
6639 {
6640 #ifdef CONFIG_XMIT_ACK
6641         static u8 seq_no = 0;
6642         s32 ret = _FAIL;
6643         u32 timeout_ms = 500;//  500ms
6644         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
6645         #ifdef CONFIG_CONCURRENT_MODE
6646         if (padapter->pbuddy_adapter && !padapter->isprimary)
6647                 pxmitpriv = &(padapter->pbuddy_adapter->xmitpriv);
6648         #endif
6649
6650         if(padapter->bSurpriseRemoved == _TRUE ||
6651                 padapter->bDriverStopped == _TRUE)
6652         {
6653                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
6654                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
6655                 return -1;
6656         }
6657
6658         _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
6659         pxmitpriv->ack_tx = _TRUE;
6660         pxmitpriv->seq_no = seq_no++;
6661         pmgntframe->ack_report = 1;
6662         if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
6663                 ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
6664         }
6665
6666         pxmitpriv->ack_tx = _FALSE;
6667         _exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
6668
6669          return ret;
6670 #else //!CONFIG_XMIT_ACK
6671         dump_mgntframe(padapter, pmgntframe);
6672         rtw_msleep_os(50);
6673         return _SUCCESS;
6674 #endif //!CONFIG_XMIT_ACK        
6675 }
6676
6677 int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
6678 {
6679         u8 *ssid_ie;
6680         sint ssid_len_ori;
6681         int len_diff = 0;
6682         
6683         ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
6684
6685         //DBG_871X("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __FUNCTION__, hidden_ssid_mode, ssid_ie, ssid_len_ori);
6686         
6687         if(ssid_ie && ssid_len_ori>0)
6688         {
6689                 switch(hidden_ssid_mode)
6690                 {
6691                         case 1:
6692                         {
6693                                 u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
6694                                 u32 remain_len = 0;
6695                                 
6696                                 remain_len = ies_len -(next_ie-ies);
6697                                 
6698                                 ssid_ie[1] = 0;                         
6699                                 _rtw_memcpy(ssid_ie+2, next_ie, remain_len);
6700                                 len_diff -= ssid_len_ori;
6701                                 
6702                                 break;
6703                         }               
6704                         case 2:
6705                                 _rtw_memset(&ssid_ie[2], 0, ssid_len_ori);
6706                                 break;
6707                         default:
6708                                 break;
6709                 }
6710         }
6711
6712         return len_diff;
6713 }
6714
6715 void issue_beacon(_adapter *padapter, int timeout_ms)
6716 {
6717         struct xmit_frame       *pmgntframe;
6718         struct pkt_attrib       *pattrib;
6719         unsigned char   *pframe;
6720         struct rtw_ieee80211_hdr *pwlanhdr;
6721         unsigned short *fctrl;
6722         unsigned int    rate_len;
6723         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
6724 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6725         _irqL irqL;
6726         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6727 #endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6728         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6729         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6730         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
6731         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
6732 #ifdef CONFIG_P2P
6733         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
6734 #endif //CONFIG_P2P
6735
6736
6737         //DBG_871X("%s\n", __FUNCTION__);
6738
6739         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
6740         {
6741                 DBG_871X("%s, alloc mgnt frame fail\n", __FUNCTION__);
6742                 return;
6743         }
6744 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6745         _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
6746 #endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
6747
6748         //update attribute
6749         pattrib = &pmgntframe->attrib;
6750         update_mgntframe_attrib(padapter, pattrib);
6751         pattrib->qsel = 0x10;
6752         #ifdef CONFIG_CONCURRENT_MODE
6753         if(padapter->iface_type == IFACE_PORT1) 
6754                 pattrib->mbssid = 1;
6755         #endif  
6756         
6757         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6758                 
6759         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6760         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;  
6761         
6762         
6763         fctrl = &(pwlanhdr->frame_ctl);
6764         *(fctrl) = 0;
6765         
6766         _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
6767         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
6768         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
6769
6770         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
6771         //pmlmeext->mgnt_seq++;
6772         SetFrameSubType(pframe, WIFI_BEACON);
6773         
6774         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);       
6775         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
6776         
6777         if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
6778         {
6779                 //DBG_871X("ie len=%d\n", cur_network->IELength);
6780 #ifdef CONFIG_P2P
6781                 // for P2P : Primary Device Type & Device Name
6782                 u32 wpsielen=0, insert_len=0;
6783                 u8 *wpsie=NULL;         
6784                 wpsie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wpsielen);
6785                 
6786                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen>0)
6787                 {
6788                         uint wps_offset, remainder_ielen;
6789                         u8 *premainder_ie, *pframe_wscie;
6790         
6791                         wps_offset = (uint)(wpsie - cur_network->IEs);
6792
6793                         premainder_ie = wpsie + wpsielen;
6794
6795                         remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
6796
6797 #ifdef CONFIG_IOCTL_CFG80211
6798                         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
6799                         {
6800                                 if(pmlmepriv->wps_beacon_ie && pmlmepriv->wps_beacon_ie_len>0)
6801                                 {
6802                                         _rtw_memcpy(pframe, cur_network->IEs, wps_offset);
6803                                         pframe += wps_offset;
6804                                         pattrib->pktlen += wps_offset;
6805
6806                                         _rtw_memcpy(pframe, pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
6807                                         pframe += pmlmepriv->wps_beacon_ie_len;
6808                                         pattrib->pktlen += pmlmepriv->wps_beacon_ie_len;
6809
6810                                         //copy remainder_ie to pframe
6811                                         _rtw_memcpy(pframe, premainder_ie, remainder_ielen);
6812                                         pframe += remainder_ielen;              
6813                                         pattrib->pktlen += remainder_ielen;
6814                                 }
6815                                 else
6816                                 {
6817                                         _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
6818                                         pframe += cur_network->IELength;
6819                                         pattrib->pktlen += cur_network->IELength;
6820                                 }
6821                         }
6822                         else
6823 #endif //CONFIG_IOCTL_CFG80211
6824                         {
6825                                 pframe_wscie = pframe + wps_offset;
6826                                 _rtw_memcpy(pframe, cur_network->IEs, wps_offset+wpsielen);                     
6827                                 pframe += (wps_offset + wpsielen);              
6828                                 pattrib->pktlen += (wps_offset + wpsielen);
6829
6830                                 //now pframe is end of wsc ie, insert Primary Device Type & Device Name
6831                                 //      Primary Device Type
6832                                 //      Type:
6833                                 *(u16*) ( pframe + insert_len) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
6834                                 insert_len += 2;
6835                                 
6836                                 //      Length:
6837                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( 0x0008 );
6838                                 insert_len += 2;
6839                                 
6840                                 //      Value:
6841                                 //      Category ID
6842                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
6843                                 insert_len += 2;
6844
6845                                 //      OUI
6846                                 *(u32*) ( pframe + insert_len ) = cpu_to_be32( WPSOUI );
6847                                 insert_len += 4;
6848
6849                                 //      Sub Category ID
6850                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
6851                                 insert_len += 2;
6852
6853
6854                                 //      Device Name
6855                                 //      Type:
6856                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
6857                                 insert_len += 2;
6858
6859                                 //      Length:
6860                                 *(u16*) ( pframe + insert_len ) = cpu_to_be16( pwdinfo->device_name_len );
6861                                 insert_len += 2;
6862
6863                                 //      Value:
6864                                 _rtw_memcpy( pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len );
6865                                 insert_len += pwdinfo->device_name_len;
6866
6867
6868                                 //update wsc ie length
6869                                 *(pframe_wscie+1) = (wpsielen -2) + insert_len;
6870
6871                                 //pframe move to end
6872                                 pframe+=insert_len;
6873                                 pattrib->pktlen += insert_len;
6874
6875                                 //copy remainder_ie to pframe
6876                                 _rtw_memcpy(pframe, premainder_ie, remainder_ielen);
6877                                 pframe += remainder_ielen;              
6878                                 pattrib->pktlen += remainder_ielen;
6879                         }
6880                 }
6881                 else
6882 #endif //CONFIG_P2P
6883                 {
6884                         int len_diff;
6885                         _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
6886                         len_diff = update_hidden_ssid(
6887                                 pframe+_BEACON_IE_OFFSET_
6888                                 , cur_network->IELength-_BEACON_IE_OFFSET_
6889                                 , pmlmeinfo->hidden_ssid_mode
6890                         );
6891                         pframe += (cur_network->IELength+len_diff);
6892                         pattrib->pktlen += (cur_network->IELength+len_diff);
6893                 }
6894
6895                 {
6896                         u8 *wps_ie;
6897                         uint wps_ielen;
6898                         u8 sr = 0;
6899                         wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof (struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
6900                                 pattrib->pktlen-sizeof (struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
6901                         if (wps_ie && wps_ielen>0) {
6902                                 rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8*)(&sr), NULL);
6903                         }
6904                         if (sr != 0)
6905                                 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
6906                         else
6907                                 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
6908                 }
6909
6910 #ifdef CONFIG_P2P
6911                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
6912                 {
6913                         u32 len;
6914 #ifdef CONFIG_IOCTL_CFG80211
6915                         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
6916                         {
6917                                 len = pmlmepriv->p2p_beacon_ie_len;
6918                                 if(pmlmepriv->p2p_beacon_ie && len>0)                           
6919                                         _rtw_memcpy(pframe, pmlmepriv->p2p_beacon_ie, len);
6920                         }
6921                         else
6922 #endif //CONFIG_IOCTL_CFG80211
6923                         {
6924                                 len = build_beacon_p2p_ie(pwdinfo, pframe);
6925                         }
6926
6927                         pframe += len;
6928                         pattrib->pktlen += len;
6929 #ifdef CONFIG_WFD
6930 #ifdef CONFIG_IOCTL_CFG80211
6931                         if(_TRUE == pwdinfo->wfd_info->wfd_enable)
6932 #endif //CONFIG_IOCTL_CFG80211
6933                         {
6934                         len = build_beacon_wfd_ie( pwdinfo, pframe );
6935                         }
6936 #ifdef CONFIG_IOCTL_CFG80211
6937                         else
6938                         {       
6939                                 len = 0;
6940                                 if(pmlmepriv->wfd_beacon_ie && pmlmepriv->wfd_beacon_ie_len>0)
6941                                 {
6942                                         len = pmlmepriv->wfd_beacon_ie_len;
6943                                         _rtw_memcpy(pframe, pmlmepriv->wfd_beacon_ie, len);     
6944                                 }
6945                         }               
6946 #endif //CONFIG_IOCTL_CFG80211
6947                         pframe += len;
6948                         pattrib->pktlen += len;
6949 #endif //CONFIG_WFD
6950                 }
6951 #endif //CONFIG_P2P
6952
6953                 goto _issue_bcn;
6954
6955         }
6956
6957         //below for ad-hoc mode
6958
6959         //timestamp will be inserted by hardware
6960         pframe += 8;
6961         pattrib->pktlen += 8;
6962
6963         // beacon interval: 2 bytes
6964
6965         _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 
6966
6967         pframe += 2;
6968         pattrib->pktlen += 2;
6969
6970         // capability info: 2 bytes
6971
6972         _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
6973
6974         pframe += 2;
6975         pattrib->pktlen += 2;
6976
6977         // SSID
6978         pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
6979
6980         // supported rates...
6981         rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
6982         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pattrib->pktlen);
6983
6984         // DS parameter set
6985         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
6986
6987         //if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
6988         {
6989                 u8 erpinfo=0;
6990                 u32 ATIMWindow;
6991                 // IBSS Parameter Set...
6992                 //ATIMWindow = cur->Configuration.ATIMWindow;
6993                 ATIMWindow = 0;
6994                 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
6995
6996                 //ERP IE
6997                 pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
6998         }       
6999
7000
7001         // EXTERNDED SUPPORTED RATE
7002         if (rate_len > 8)
7003         {
7004                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
7005         }
7006
7007
7008         //todo:HT for adhoc
7009
7010 _issue_bcn:
7011
7012 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
7013         pmlmepriv->update_bcn = _FALSE;
7014         
7015         _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);  
7016 #endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
7017
7018         if ((pattrib->pktlen + TXDESC_SIZE) > 512)
7019         {
7020                 DBG_871X("beacon frame too large\n");
7021                 return;
7022         }
7023         
7024         pattrib->last_txcmdsz = pattrib->pktlen;
7025
7026         //DBG_871X("issue bcn_sz=%d\n", pattrib->last_txcmdsz);
7027         if(timeout_ms > 0)
7028                 dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
7029         else
7030                 dump_mgntframe(padapter, pmgntframe);
7031
7032 }
7033
7034 void issue_probersp(_adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
7035 {
7036         struct xmit_frame                       *pmgntframe;
7037         struct pkt_attrib                       *pattrib;
7038         unsigned char                                   *pframe;
7039         struct rtw_ieee80211_hdr        *pwlanhdr;
7040         unsigned short                          *fctrl; 
7041         unsigned char                                   *mac, *bssid;
7042         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
7043 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
7044         u8 *pwps_ie;
7045         uint wps_ielen;
7046         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
7047 #endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
7048         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7049         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7050         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
7051         unsigned int    rate_len;
7052 #ifdef CONFIG_P2P
7053         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
7054 #ifdef CONFIG_WFD
7055         u32                                     wfdielen = 0;
7056 #endif //CONFIG_WFD
7057 #endif //CONFIG_P2P
7058
7059         //DBG_871X("%s\n", __FUNCTION__);
7060
7061         if(da == NULL)
7062                 return;
7063
7064         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7065         {
7066                 DBG_871X("%s, alloc mgnt frame fail\n", __FUNCTION__);
7067                 return;
7068         }
7069
7070
7071         //update attribute
7072         pattrib = &pmgntframe->attrib;
7073         update_mgntframe_attrib(padapter, pattrib);     
7074         
7075         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7076                 
7077         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7078         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;  
7079         
7080         mac = myid(&(padapter->eeprompriv));
7081         bssid = cur_network->MacAddress;
7082         
7083         fctrl = &(pwlanhdr->frame_ctl);
7084         *(fctrl) = 0;
7085         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
7086         _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
7087         _rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
7088
7089         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7090         pmlmeext->mgnt_seq++;
7091         SetFrameSubType(fctrl, WIFI_PROBERSP);
7092         
7093         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7094         pattrib->pktlen = pattrib->hdrlen;
7095         pframe += pattrib->hdrlen;
7096
7097
7098         if(cur_network->IELength>MAX_IE_SZ)
7099                 return;
7100         
7101 #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
7102         if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
7103         {
7104                 pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
7105         
7106                 //inerset & update wps_probe_resp_ie
7107                 if((pmlmepriv->wps_probe_resp_ie!=NULL) && pwps_ie && (wps_ielen>0))
7108                 {
7109                         uint wps_offset, remainder_ielen;
7110                         u8 *premainder_ie;              
7111         
7112                         wps_offset = (uint)(pwps_ie - cur_network->IEs);
7113
7114                         premainder_ie = pwps_ie + wps_ielen;
7115
7116                         remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
7117
7118                         _rtw_memcpy(pframe, cur_network->IEs, wps_offset);              
7119                         pframe += wps_offset;           
7120                         pattrib->pktlen += wps_offset;          
7121
7122                         wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];//to get ie data len
7123                         if((wps_offset+wps_ielen+2)<=MAX_IE_SZ)
7124                         {
7125                                 _rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
7126                                 pframe += wps_ielen+2;          
7127                                 pattrib->pktlen += wps_ielen+2; 
7128                         }
7129
7130                         if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)
7131                         {
7132                                 _rtw_memcpy(pframe, premainder_ie, remainder_ielen);
7133                                 pframe += remainder_ielen;              
7134                                 pattrib->pktlen += remainder_ielen;     
7135                         }
7136                 }
7137                 else
7138                 {
7139                         _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
7140                         pframe += cur_network->IELength;
7141                         pattrib->pktlen += cur_network->IELength;
7142                 }
7143
7144                 /* retrieve SSID IE from cur_network->Ssid */
7145                 {
7146                         u8 *ssid_ie;
7147                         sint ssid_ielen;
7148                         sint ssid_ielen_diff;
7149                         u8 buf[MAX_IE_SZ];
7150                         u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct rtw_ieee80211_hdr_3addr);
7151
7152                         ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
7153                                 (pframe-ies)-_FIXED_IE_LENGTH_);
7154
7155                         ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
7156
7157                         if (ssid_ie &&  cur_network->Ssid.SsidLength) {
7158                                 uint remainder_ielen;
7159                                 u8 *remainder_ie;
7160                                 remainder_ie = ssid_ie+2;
7161                                 remainder_ielen = (pframe-remainder_ie);
7162
7163                                 if (remainder_ielen > MAX_IE_SZ) {
7164                                         DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));
7165                                         remainder_ielen = MAX_IE_SZ;
7166                                 }
7167
7168                                 _rtw_memcpy(buf, remainder_ie, remainder_ielen);
7169                                 _rtw_memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
7170                                 *(ssid_ie+1) = cur_network->Ssid.SsidLength;
7171                                 _rtw_memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
7172
7173                                 pframe += ssid_ielen_diff;
7174                                 pattrib->pktlen += ssid_ielen_diff;
7175                         }
7176                 }
7177         }       
7178         else            
7179 #endif          
7180         {
7181         
7182                 //timestamp will be inserted by hardware
7183                 pframe += 8;
7184                 pattrib->pktlen += 8;
7185
7186                 // beacon interval: 2 bytes
7187
7188                 _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 
7189
7190                 pframe += 2;
7191                 pattrib->pktlen += 2;
7192
7193                 // capability info: 2 bytes
7194
7195                 _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
7196
7197                 pframe += 2;
7198                 pattrib->pktlen += 2;
7199
7200                 //below for ad-hoc mode
7201
7202                 // SSID
7203                 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
7204
7205                 // supported rates...
7206                 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
7207                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pattrib->pktlen);
7208
7209                 // DS parameter set
7210                 pframe =rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
7211
7212                 if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
7213                 {
7214                         u8 erpinfo=0;
7215                         u32 ATIMWindow;
7216                         // IBSS Parameter Set...
7217                         //ATIMWindow = cur->Configuration.ATIMWindow;
7218                         ATIMWindow = 0;
7219                         pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
7220
7221                         //ERP IE
7222                         pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
7223                 }
7224
7225                 
7226                 // EXTERNDED SUPPORTED RATE
7227                 if (rate_len > 8)
7228                 {
7229                         pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
7230                 }
7231
7232
7233                 //todo:HT for adhoc
7234
7235         }       
7236
7237 #ifdef CONFIG_P2P
7238         if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)
7239                 /* IOT issue, When wifi_spec is not set, send probe_resp with P2P IE even if probe_req has no P2P IE */
7240                 && (is_valid_p2p_probereq || !padapter->registrypriv.wifi_spec))
7241         {
7242                 u32 len;
7243 #ifdef CONFIG_IOCTL_CFG80211
7244                 if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
7245                 {
7246                         //if pwdinfo->role == P2P_ROLE_DEVICE will call issue_probersp_p2p()
7247                         len = pmlmepriv->p2p_go_probe_resp_ie_len;
7248                         if(pmlmepriv->p2p_go_probe_resp_ie && len>0)
7249                                 _rtw_memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie, len);
7250                 }
7251                 else
7252 #endif //CONFIG_IOCTL_CFG80211
7253                 {
7254                         len = build_probe_resp_p2p_ie(pwdinfo, pframe);
7255                 }
7256
7257                 pframe += len;
7258                 pattrib->pktlen += len;
7259                 
7260 #ifdef CONFIG_WFD
7261 #ifdef CONFIG_IOCTL_CFG80211
7262                 if(_TRUE == pwdinfo->wfd_info->wfd_enable)
7263 #endif //CONFIG_IOCTL_CFG80211
7264                 {
7265                         len = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
7266                 }
7267 #ifdef CONFIG_IOCTL_CFG80211
7268                 else
7269                 {       
7270                         len = 0;
7271                         if(pmlmepriv->wfd_probe_resp_ie && pmlmepriv->wfd_probe_resp_ie_len>0)
7272                         {
7273                                 len = pmlmepriv->wfd_probe_resp_ie_len;
7274                                 _rtw_memcpy(pframe, pmlmepriv->wfd_probe_resp_ie, len); 
7275                         }       
7276                 }
7277 #endif //CONFIG_IOCTL_CFG80211          
7278                 pframe += len;
7279                 pattrib->pktlen += len;
7280 #endif //CONFIG_WFD
7281
7282         }
7283 #endif //CONFIG_P2P
7284
7285
7286 #ifdef CONFIG_AUTO_AP_MODE
7287 {
7288         struct sta_info *psta;
7289         struct sta_priv *pstapriv = &padapter->stapriv;
7290
7291         DBG_871X("(%s)\n", __FUNCTION__);
7292
7293         //check rc station
7294         psta = rtw_get_stainfo(pstapriv, da);
7295         if (psta && psta->isrc && psta->pid>0)
7296         {
7297                 u8 RC_OUI[4]={0x00,0xE0,0x4C,0x0A};
7298                 u8 RC_INFO[14] = {0};
7299                 //EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2]
7300                 u16 cu_ch = (u16)cur_network->Configuration.DSConfig;
7301
7302                 DBG_871X("%s, reply rc(pid=0x%x) device "MAC_FMT" in ch=%d\n", __FUNCTION__,
7303                         psta->pid, MAC_ARG(psta->hwaddr), cu_ch);
7304
7305                 //append vendor specific ie
7306                 _rtw_memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI));
7307                 _rtw_memcpy(&RC_INFO[4], mac, ETH_ALEN);
7308                 _rtw_memcpy(&RC_INFO[10], (u8*)&psta->pid, 2);
7309                 _rtw_memcpy(&RC_INFO[12], (u8*)&cu_ch, 2);
7310
7311                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen);
7312         }
7313 }
7314 #endif //CONFIG_AUTO_AP_MODE
7315
7316
7317         pattrib->last_txcmdsz = pattrib->pktlen;
7318         
7319
7320         dump_mgntframe(padapter, pmgntframe);
7321         
7322         return;
7323
7324 }
7325
7326 int _issue_probereq(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da, u8 ch, bool append_wps, int wait_ack)
7327 {
7328         int ret = _FAIL;
7329         struct xmit_frame               *pmgntframe;
7330         struct pkt_attrib               *pattrib;
7331         unsigned char                   *pframe;
7332         struct rtw_ieee80211_hdr        *pwlanhdr;
7333         unsigned short          *fctrl;
7334         unsigned char                   *mac;
7335         unsigned char                   bssrate[NumRates];
7336         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
7337         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7338         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7339         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7340         int     bssrate_len = 0;
7341         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
7342
7343         RT_TRACE(_module_rtl871x_mlme_c_,_drv_notice_,("+issue_probereq\n"));
7344
7345         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7346         {
7347                 goto exit;
7348         }
7349
7350         //update attribute
7351         pattrib = &pmgntframe->attrib;
7352         update_mgntframe_attrib(padapter, pattrib);
7353
7354
7355         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7356
7357         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7358         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7359
7360         mac = myid(&(padapter->eeprompriv));
7361
7362         fctrl = &(pwlanhdr->frame_ctl);
7363         *(fctrl) = 0;
7364
7365         if (da)
7366         {
7367                 //      unicast probe request frame
7368                 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
7369                 _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);
7370         }
7371         else
7372         {
7373                 //      broadcast probe request frame
7374                 _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
7375                 _rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
7376         }
7377
7378         _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
7379
7380         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7381         pmlmeext->mgnt_seq++;
7382         SetFrameSubType(pframe, WIFI_PROBEREQ);
7383
7384         pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
7385         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
7386
7387         if(pssid)
7388                 pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
7389         else
7390                 pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
7391
7392         get_rate_set(padapter, bssrate, &bssrate_len);
7393
7394         if (bssrate_len > 8)
7395         {
7396                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
7397                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
7398         }
7399         else
7400         {
7401                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
7402         }
7403
7404         if (ch)
7405                 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, &ch, &pattrib->pktlen);
7406
7407         if (append_wps) {
7408                 //add wps_ie for wps2.0
7409                 if(pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie)
7410                 {
7411                         _rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
7412                         pframe += pmlmepriv->wps_probe_req_ie_len;
7413                         pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
7414                         //pmlmepriv->wps_probe_req_ie_len = 0 ;//reset to zero
7415                 }
7416         }
7417
7418         pattrib->last_txcmdsz = pattrib->pktlen;
7419
7420         RT_TRACE(_module_rtl871x_mlme_c_,_drv_notice_,("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
7421
7422         if (wait_ack) {
7423                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
7424         } else {
7425                 dump_mgntframe(padapter, pmgntframe);
7426                 ret = _SUCCESS;
7427         }
7428
7429 exit:
7430         return ret;
7431 }
7432
7433 inline void issue_probereq(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da)
7434 {
7435         _issue_probereq(padapter, pssid, da, 0, 1, _FALSE);
7436 }
7437
7438 int issue_probereq_ex(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da, u8 ch, bool append_wps,
7439         int try_cnt, int wait_ms)
7440 {
7441         int ret;
7442         int i = 0;
7443         u32 start = rtw_get_current_time();
7444
7445         do
7446         {
7447                 ret = _issue_probereq(padapter, pssid, da, ch, append_wps, wait_ms>0?_TRUE:_FALSE);
7448
7449                 i++;
7450
7451                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
7452                         break;
7453
7454                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
7455                         rtw_msleep_os(wait_ms);
7456
7457         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
7458
7459         if (ret != _FAIL) {
7460                 ret = _SUCCESS;
7461                 #ifndef DBG_XMIT_ACK
7462                 goto exit;
7463                 #endif
7464         }
7465
7466         if (try_cnt && wait_ms) {
7467                 if (da)
7468                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
7469                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
7470                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
7471                 else
7472                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
7473                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
7474                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
7475         }
7476 exit:
7477         return ret;
7478 }
7479
7480 // if psta == NULL, indiate we are station(client) now...
7481 void issue_auth(_adapter *padapter, struct sta_info *psta, unsigned short status)
7482 {
7483         struct xmit_frame                       *pmgntframe;
7484         struct pkt_attrib                       *pattrib;
7485         unsigned char                                   *pframe;
7486         struct rtw_ieee80211_hdr        *pwlanhdr;
7487         unsigned short                          *fctrl;
7488         unsigned int                                    val32;
7489         unsigned short                          val16;
7490         int use_shared_key = 0;
7491         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
7492         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7493         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7494
7495         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7496         {
7497                 return;
7498         }
7499
7500         //update attribute
7501         pattrib = &pmgntframe->attrib;
7502         update_mgntframe_attrib(padapter, pattrib);
7503
7504         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7505
7506         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7507         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7508
7509         fctrl = &(pwlanhdr->frame_ctl);
7510         *(fctrl) = 0;
7511
7512         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7513         pmlmeext->mgnt_seq++;
7514         SetFrameSubType(pframe, WIFI_AUTH);
7515
7516         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
7517         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7518
7519
7520         if(psta)// for AP mode
7521         {
7522 #ifdef CONFIG_NATIVEAP_MLME
7523
7524                 _rtw_memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);           
7525                 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
7526                 _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
7527
7528         
7529                 // setting auth algo number
7530                 val16 = (u16)psta->authalg;
7531
7532                 if(status != _STATS_SUCCESSFUL_)
7533                         val16 = 0;
7534
7535                 if (val16)      {
7536                         val16 = cpu_to_le16(val16);     
7537                         use_shared_key = 1;
7538                 }
7539
7540                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
7541
7542                 // setting auth seq number
7543                 val16 =(u16)psta->auth_seq;
7544                 val16 = cpu_to_le16(val16);     
7545                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
7546
7547                 // setting status code...
7548                 val16 = status;
7549                 val16 = cpu_to_le16(val16);     
7550                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));
7551
7552                 // added challenging text...
7553                 if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
7554                 {
7555                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
7556                 }
7557 #endif
7558         }
7559         else
7560         {               
7561                 _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
7562                 _rtw_memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
7563                 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
7564         
7565                 // setting auth algo number             
7566                 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)? 1: 0;// 0:OPEN System, 1:Shared key
7567                 if (val16)      {
7568                         val16 = cpu_to_le16(val16);     
7569                         use_shared_key = 1;
7570                 }       
7571                 //DBG_871X("%s auth_algo= %s auth_seq=%d\n",__FUNCTION__,(pmlmeinfo->auth_algo==0)?"OPEN":"SHARED",pmlmeinfo->auth_seq);
7572                 
7573                 //setting IV for auth seq #3
7574                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
7575                 {
7576                         //DBG_871X("==> iv(%d),key_index(%d)\n",pmlmeinfo->iv,pmlmeinfo->key_index);
7577                         val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
7578                         val32 = cpu_to_le32(val32);
7579                         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&val32, &(pattrib->pktlen));
7580
7581                         pattrib->iv_len = 4;
7582                 }
7583
7584                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
7585                 
7586                 // setting auth seq number
7587                 val16 = pmlmeinfo->auth_seq;
7588                 val16 = cpu_to_le16(val16);     
7589                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
7590
7591                 
7592                 // setting status code...
7593                 val16 = status;
7594                 val16 = cpu_to_le16(val16);     
7595                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));
7596
7597                 // then checking to see if sending challenging text...
7598                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
7599                 {
7600                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
7601
7602                         SetPrivacy(fctrl);
7603                         
7604                         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);                       
7605                         
7606                         pattrib->encrypt = _WEP40_;
7607
7608                         pattrib->icv_len = 4;
7609                         
7610                         pattrib->pktlen += pattrib->icv_len;                    
7611                         
7612                 }
7613                 
7614         }
7615
7616         pattrib->last_txcmdsz = pattrib->pktlen;
7617
7618         rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
7619         DBG_871X("%s\n", __FUNCTION__);
7620         dump_mgntframe(padapter, pmgntframe);
7621
7622         return;
7623 }
7624
7625
7626 void issue_asocrsp(_adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
7627 {
7628 #ifdef CONFIG_AP_MODE
7629         struct xmit_frame       *pmgntframe;
7630         struct rtw_ieee80211_hdr        *pwlanhdr;
7631         struct pkt_attrib *pattrib;
7632         unsigned char   *pbuf, *pframe;
7633         unsigned short val;             
7634         unsigned short *fctrl;
7635         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
7636         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7637         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7638         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);  
7639         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
7640         u8 *ie = pnetwork->IEs; 
7641 #ifdef CONFIG_P2P
7642         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
7643 #ifdef CONFIG_WFD
7644         u32                                     wfdielen = 0;
7645 #endif //CONFIG_WFD
7646
7647 #endif //CONFIG_P2P
7648
7649         DBG_871X("%s\n", __FUNCTION__);
7650
7651         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7652         {
7653                 return;
7654         }
7655
7656         //update attribute
7657         pattrib = &pmgntframe->attrib;
7658         update_mgntframe_attrib(padapter, pattrib);
7659
7660
7661         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7662
7663         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7664         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7665
7666         fctrl = &(pwlanhdr->frame_ctl);
7667         *(fctrl) = 0;
7668
7669         _rtw_memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
7670         _rtw_memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
7671         _rtw_memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7672
7673
7674         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7675         pmlmeext->mgnt_seq++;
7676         if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
7677                 SetFrameSubType(pwlanhdr, pkt_type);            
7678         else
7679                 return;
7680
7681         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7682         pattrib->pktlen += pattrib->hdrlen;
7683         pframe += pattrib->hdrlen;
7684
7685         //capability
7686         val = *(unsigned short *)rtw_get_capability_from_ie(ie);
7687
7688         pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_ , (unsigned char *)&val, &(pattrib->pktlen));
7689
7690         status = cpu_to_le16(status);
7691         pframe = rtw_set_fixed_ie(pframe , _STATUS_CODE_ , (unsigned char *)&status, &(pattrib->pktlen));
7692         
7693         val = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
7694         pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_ , (unsigned char *)&val, &(pattrib->pktlen));
7695
7696         if (pstat->bssratelen <= 8)
7697         {
7698                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
7699         }       
7700         else 
7701         {
7702                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
7703                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
7704         }
7705
7706 #ifdef CONFIG_80211N_HT
7707         if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option))
7708         {
7709                 uint ie_len=0;
7710                 
7711                 //FILL HT CAP INFO IE
7712                 //p = hostapd_eid_ht_capabilities_info(hapd, p);
7713                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
7714                 if(pbuf && ie_len>0)
7715                 {
7716                         _rtw_memcpy(pframe, pbuf, ie_len+2);
7717                         pframe += (ie_len+2);
7718                         pattrib->pktlen +=(ie_len+2);
7719                 }
7720
7721                 //FILL HT ADD INFO IE
7722                 //p = hostapd_eid_ht_operation(hapd, p);
7723                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
7724                 if(pbuf && ie_len>0)
7725                 {
7726                         _rtw_memcpy(pframe, pbuf, ie_len+2);
7727                         pframe += (ie_len+2);
7728                         pattrib->pktlen +=(ie_len+2);
7729                 }
7730                 
7731         }       
7732 #endif
7733
7734 #ifdef CONFIG_80211AC_VHT
7735         if ((pstat->flags & WLAN_STA_VHT) && (pmlmepriv->vhtpriv.vht_option))
7736         {
7737                 u32 ie_len=0;
7738
7739                 //FILL VHT CAP IE
7740                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &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                 //FILL VHT OPERATION IE
7749                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTOperation, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
7750                 if(pbuf && ie_len>0)
7751                 {
7752                         _rtw_memcpy(pframe, pbuf, ie_len+2);
7753                         pframe += (ie_len+2);
7754                         pattrib->pktlen +=(ie_len+2);
7755                 }
7756         }
7757 #endif //CONFIG_80211AC_VHT
7758
7759         //FILL WMM IE
7760         if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option))
7761         {
7762                 uint ie_len=0;
7763                 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};     
7764                 
7765                 for (pbuf = ie + _BEACON_IE_OFFSET_; ;pbuf+= (ie_len + 2))
7766                 {                       
7767                         pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));       
7768                         if(pbuf && _rtw_memcmp(pbuf+2, WMM_PARA_IE, 6)) 
7769                         {                               
7770                                 _rtw_memcpy(pframe, pbuf, ie_len+2);
7771                                 pframe += (ie_len+2);
7772                                 pattrib->pktlen +=(ie_len+2);
7773                                 
7774                                 break;                          
7775                         }
7776                         
7777                         if ((pbuf == NULL) || (ie_len == 0))
7778                         {
7779                                 break;
7780                         }                       
7781                 }
7782                 
7783         }
7784
7785
7786         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
7787         {
7788                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
7789         }
7790
7791         //add WPS IE ie for wps 2.0
7792         if(pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len>0)
7793         {
7794                 _rtw_memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
7795                 
7796                 pframe += pmlmepriv->wps_assoc_resp_ie_len;
7797                 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
7798         }
7799
7800 #ifdef CONFIG_P2P
7801         if( padapter->wdinfo.driver_interface == DRIVER_WEXT )
7802         {
7803                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device == _TRUE))
7804                 {
7805                         u32 len;
7806
7807                         len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
7808
7809                         pframe += len;
7810                         pattrib->pktlen += len;
7811                 }
7812         }
7813 #ifdef CONFIG_WFD
7814         if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)
7815 #ifdef CONFIG_IOCTL_CFG80211            
7816                 && (_TRUE == pwdinfo->wfd_info->wfd_enable)
7817 #endif //CONFIG_IOCTL_CFG80211  
7818         )
7819         {
7820                 wfdielen = build_assoc_resp_wfd_ie(pwdinfo, pframe);
7821                 pframe += wfdielen;
7822                 pattrib->pktlen += wfdielen;
7823         }
7824 #endif //CONFIG_WFD
7825 #endif //CONFIG_P2P
7826
7827         pattrib->last_txcmdsz = pattrib->pktlen;
7828         
7829         dump_mgntframe(padapter, pmgntframe);
7830         
7831 #endif
7832 }
7833
7834 void issue_assocreq(_adapter *padapter)
7835 {
7836         int ret = _FAIL;
7837         struct xmit_frame                               *pmgntframe;
7838         struct pkt_attrib                               *pattrib;
7839         unsigned char                                   *pframe, *p;
7840         struct rtw_ieee80211_hdr                        *pwlanhdr;
7841         unsigned short                          *fctrl;
7842         unsigned short                          val16;
7843         unsigned int                                    i, j, ie_len, index=0;
7844         unsigned char                                   rf_type, bssrate[NumRates], sta_bssrate[NumRates];
7845         PNDIS_802_11_VARIABLE_IEs       pIE;
7846         struct registry_priv    *pregpriv = &padapter->registrypriv;
7847         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
7848         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7849         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7850         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7851         int     bssrate_len = 0, sta_bssrate_len = 0;
7852         u8      vs_ie_length = 0;
7853 #ifdef CONFIG_P2P
7854         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
7855         u8                                      p2pie[ 255 ] = { 0x00 };
7856         u16                                     p2pielen = 0;   
7857 #ifdef CONFIG_WFD
7858         u32                                     wfdielen = 0;
7859 #endif //CONFIG_WFD
7860 #endif //CONFIG_P2P
7861
7862 #ifdef CONFIG_DFS
7863         u16     cap;
7864
7865         /* Dot H */
7866         u8 pow_cap_ele[2] = { 0x00 };
7867         u8 sup_ch[ 30 * 2 ] = {0x00 }, sup_ch_idx = 0, idx_5g = 2;      //For supported channel
7868 #endif //CONFIG_DFS
7869
7870         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
7871                 goto exit;
7872
7873         //update attribute
7874         pattrib = &pmgntframe->attrib;
7875         update_mgntframe_attrib(padapter, pattrib);
7876
7877
7878         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7879
7880         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7881         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7882
7883         fctrl = &(pwlanhdr->frame_ctl);
7884         *(fctrl) = 0;
7885         _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7886         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
7887         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
7888
7889         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7890         pmlmeext->mgnt_seq++;
7891         SetFrameSubType(pframe, WIFI_ASSOCREQ);
7892
7893         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
7894         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7895
7896         //caps
7897
7898 #ifdef CONFIG_DFS
7899         _rtw_memcpy(&cap, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
7900         cap |= cap_SpecMgmt;
7901         _rtw_memcpy(pframe, &cap, 2);
7902 #else
7903         _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
7904 #endif //CONFIG_DFS
7905
7906         pframe += 2;
7907         pattrib->pktlen += 2;
7908
7909         //listen interval
7910         //todo: listen interval for power saving
7911         val16 = cpu_to_le16(3);
7912         _rtw_memcpy(pframe ,(unsigned char *)&val16, 2);
7913         pframe += 2;
7914         pattrib->pktlen += 2;
7915
7916         //SSID
7917         pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
7918
7919 #ifdef CONFIG_DFS
7920         /* Dot H */
7921         if(pmlmeext->cur_channel > 14)
7922         {
7923                 pow_cap_ele[0] = 13;    // Minimum transmit power capability
7924                 pow_cap_ele[1] = 21;    // Maximum transmit power capability
7925                 pframe = rtw_set_ie(pframe, EID_PowerCap, 2, pow_cap_ele, &(pattrib->pktlen));
7926
7927                 //supported channels
7928                 do{
7929                         if( pmlmeext->channel_set[sup_ch_idx].ChannelNum <= 14 )
7930                         {
7931                                 sup_ch[0] = 1;  //First channel number
7932                                 sup_ch[1] = pmlmeext->channel_set[sup_ch_idx].ChannelNum;       //Number of channel
7933                         }
7934                         else
7935                         {
7936                                 sup_ch[idx_5g++] = pmlmeext->channel_set[sup_ch_idx].ChannelNum;
7937                                 sup_ch[idx_5g++] = 1;
7938                         }
7939                         sup_ch_idx++;
7940                 }
7941                 while( pmlmeext->channel_set[sup_ch_idx].ChannelNum != 0 );
7942                 pframe = rtw_set_ie(pframe, EID_SupportedChannels, idx_5g, sup_ch, &(pattrib->pktlen));
7943         }
7944 #endif //CONFIG_DFS
7945
7946         //supported rate & extended supported rate
7947
7948 #if 1   // Check if the AP's supported rates are also supported by STA.
7949         get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
7950         //DBG_871X("sta_bssrate_len=%d\n", sta_bssrate_len);
7951         
7952         if(pmlmeext->cur_channel == 14)// for JAPAN, channel 14 can only uses B Mode(CCK) 
7953         {
7954                 sta_bssrate_len = 4;
7955         }
7956
7957         
7958         //for (i = 0; i < sta_bssrate_len; i++) {
7959         //      DBG_871X("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]);
7960         //}
7961
7962         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
7963                 if (pmlmeinfo->network.SupportedRates[i] == 0) break;
7964                 DBG_871X("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
7965         }
7966         
7967
7968         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
7969                 if (pmlmeinfo->network.SupportedRates[i] == 0) break;
7970
7971                 
7972                 // Check if the AP's supported rates are also supported by STA.
7973                 for (j=0; j < sta_bssrate_len; j++) {
7974                          // Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP
7975                         if ( (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK) 
7976                                         == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) {
7977                                 //DBG_871X("match i = %d, j=%d\n", i, j);
7978                                 break;
7979                         } else {
7980                                 //DBG_871X("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK));
7981                         }
7982                 }
7983                 
7984                 if (j == sta_bssrate_len) {
7985                         // the rate is not supported by STA
7986                         DBG_871X("%s(): the rate[%d]=%02X is not supported by STA!\n",__FUNCTION__, i, pmlmeinfo->network.SupportedRates[i]);
7987                 } else {
7988                         // the rate is supported by STA
7989                         bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
7990                 }
7991         }
7992         
7993         bssrate_len = index;
7994         DBG_871X("bssrate_len = %d\n", bssrate_len);
7995
7996 #else   // Check if the AP's supported rates are also supported by STA.
7997 #if 0
7998         get_rate_set(padapter, bssrate, &bssrate_len);
7999 #else
8000         for (bssrate_len = 0; bssrate_len < NumRates; bssrate_len++) {
8001                 if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0) break;
8002
8003                 if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0x2C) // Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP
8004                         break;
8005
8006                 bssrate[bssrate_len] = pmlmeinfo->network.SupportedRates[bssrate_len];
8007         }
8008 #endif
8009 #endif  // Check if the AP's supported rates are also supported by STA.
8010
8011         if (bssrate_len == 0) {
8012                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
8013                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
8014                 goto exit; //don't connect to AP if no joint supported rate
8015         }
8016
8017
8018         if (bssrate_len > 8)
8019         {
8020                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
8021                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
8022         }
8023         else
8024         {
8025                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
8026         }
8027
8028         //vendor specific IE, such as WPA, WMM, WPS
8029         for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pmlmeinfo->network.IELength;)
8030         {
8031                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pmlmeinfo->network.IEs + i);
8032
8033                 switch (pIE->ElementID)
8034                 {
8035                         case _VENDOR_SPECIFIC_IE_:
8036                                 if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
8037                                                 (_rtw_memcmp(pIE->data, WMM_OUI, 4)) ||
8038                                                 (_rtw_memcmp(pIE->data, WPS_OUI, 4)))
8039                                 {       
8040                                         vs_ie_length = pIE->Length;
8041                                         if((!padapter->registrypriv.wifi_spec) && (_rtw_memcmp(pIE->data, WPS_OUI, 4)))
8042                                         {
8043                                                 //Commented by Kurt 20110629
8044                                                 //In some older APs, WPS handshake
8045                                                 //would be fail if we append vender extensions informations to AP
8046
8047                                                 vs_ie_length = 14;
8048                                         }
8049                                         
8050                                         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, vs_ie_length, pIE->data, &(pattrib->pktlen));
8051                                 }
8052                                 break;
8053
8054                         case EID_WPA2:
8055                                 pframe = rtw_set_ie(pframe, EID_WPA2, pIE->Length, pIE->data, &(pattrib->pktlen));
8056                                 break;
8057 #ifdef CONFIG_80211N_HT
8058                         case EID_HTCapability:
8059                                 if(padapter->mlmepriv.htpriv.ht_option==_TRUE) {
8060                                         if (!(is_ap_in_tkip(padapter)))
8061                                         {
8062                                                 _rtw_memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
8063
8064                                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
8065
8066                                                 pframe = rtw_set_ie(pframe, EID_HTCapability, pIE->Length , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
8067                                         }
8068                                 }
8069                                 break;
8070
8071                         case EID_EXTCapability:
8072                                 if(padapter->mlmepriv.htpriv.ht_option==_TRUE) {
8073                                         pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
8074                                 }
8075                                 break;
8076 #endif //CONFIG_80211N_HT
8077 #ifdef CONFIG_80211AC_VHT
8078                         case EID_VHTCapability:
8079                                 if (padapter->mlmepriv.vhtpriv.vht_option ==_TRUE) {
8080                                         pframe = rtw_set_ie(pframe, EID_VHTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
8081                                 }
8082                                 break;
8083
8084                         case EID_OpModeNotification:
8085                                 if (padapter->mlmepriv.vhtpriv.vht_option ==_TRUE) {
8086                                         pframe = rtw_set_ie(pframe, EID_OpModeNotification, pIE->Length, pIE->data, &(pattrib->pktlen));
8087                                 }
8088                                 break;
8089 #endif // CONFIG_80211AC_VHT
8090                         default:
8091                                 break;
8092                 }
8093
8094                 i += (pIE->Length + 2);
8095         }
8096
8097         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
8098         {
8099                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
8100         }
8101
8102
8103 #ifdef CONFIG_WAPI_SUPPORT
8104         rtw_build_assoc_req_wapi_ie(padapter, pframe, pattrib);
8105 #endif
8106
8107
8108 #ifdef CONFIG_P2P
8109
8110 #ifdef CONFIG_IOCTL_CFG80211
8111         if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
8112         {
8113                 if(pmlmepriv->p2p_assoc_req_ie && pmlmepriv->p2p_assoc_req_ie_len>0)
8114                 {
8115                         _rtw_memcpy(pframe, pmlmepriv->p2p_assoc_req_ie, pmlmepriv->p2p_assoc_req_ie_len);
8116                         pframe += pmlmepriv->p2p_assoc_req_ie_len;
8117                         pattrib->pktlen += pmlmepriv->p2p_assoc_req_ie_len;
8118                 }
8119         }
8120         else
8121 #endif //CONFIG_IOCTL_CFG80211
8122         {
8123                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
8124                 {
8125                         //      Should add the P2P IE in the association request frame. 
8126                         //      P2P OUI
8127                         
8128                         p2pielen = 0;
8129                         p2pie[ p2pielen++ ] = 0x50;
8130                         p2pie[ p2pielen++ ] = 0x6F;
8131                         p2pie[ p2pielen++ ] = 0x9A;
8132                         p2pie[ p2pielen++ ] = 0x09;     //      WFA P2P v1.0
8133
8134                         //      Commented by Albert 20101109
8135                         //      According to the P2P Specification, the association request frame should contain 3 P2P attributes
8136                         //      1. P2P Capability
8137                         //      2. Extended Listen Timing
8138                         //      3. Device Info
8139                         //      Commented by Albert 20110516
8140                         //      4. P2P Interface
8141
8142                         //      P2P Capability
8143                         //      Type:
8144                         p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
8145
8146                         //      Length:
8147                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
8148                         p2pielen += 2;
8149
8150                         //      Value:
8151                         //      Device Capability Bitmap, 1 byte
8152                         p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
8153
8154                         //      Group Capability Bitmap, 1 byte
8155                         if ( pwdinfo->persistent_supported )
8156                                 p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
8157                         else
8158                                 p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
8159
8160                         //      Extended Listen Timing
8161                         //      Type:
8162                         p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
8163
8164                         //      Length:
8165                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
8166                         p2pielen += 2;
8167
8168                         //      Value:
8169                         //      Availability Period
8170                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
8171                         p2pielen += 2;
8172
8173                         //      Availability Interval
8174                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
8175                         p2pielen += 2;
8176
8177                         //      Device Info
8178                         //      Type:
8179                         p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
8180
8181                         //      Length:
8182                         //      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
8183                         //      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
8184                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
8185                         p2pielen += 2;
8186
8187                         //      Value:
8188                         //      P2P Device Address
8189                         _rtw_memcpy( p2pie + p2pielen, myid( &padapter->eeprompriv ), ETH_ALEN );
8190                         p2pielen += ETH_ALEN;
8191
8192                         //      Config Method
8193                         //      This field should be big endian. Noted by P2P specification.
8194                         if ( ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN ) ||
8195                                 ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN ) )
8196                         {
8197                                 *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY );
8198                         }
8199                         else
8200                         {
8201                                 *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_PBC );
8202                         }
8203
8204                         p2pielen += 2;
8205
8206                         //      Primary Device Type
8207                         //      Category ID
8208                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
8209                         p2pielen += 2;
8210
8211                         //      OUI
8212                         *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
8213                         p2pielen += 4;
8214
8215                         //      Sub Category ID
8216                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
8217                         p2pielen += 2;
8218
8219                         //      Number of Secondary Device Types
8220                         p2pie[ p2pielen++ ] = 0x00;     //      No Secondary Device Type List
8221
8222                         //      Device Name
8223                         //      Type:
8224                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
8225                         p2pielen += 2;
8226
8227                         //      Length:
8228                         *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
8229                         p2pielen += 2;
8230
8231                         //      Value:
8232                         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
8233                         p2pielen += pwdinfo->device_name_len;
8234                 
8235                         //      P2P Interface
8236                         //      Type:
8237                         p2pie[ p2pielen++ ] = P2P_ATTR_INTERFACE;
8238                         
8239                         //      Length:
8240                         *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x000D );
8241                         p2pielen += 2;
8242                         
8243                         //      Value:
8244                         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );        //      P2P Device Address
8245                         p2pielen += ETH_ALEN;
8246
8247                         p2pie[ p2pielen++ ] = 1;        //      P2P Interface Address Count
8248                         
8249                         _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );        //      P2P Interface Address List
8250                         p2pielen += ETH_ALEN;
8251                 
8252                         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
8253
8254 #ifdef CONFIG_WFD
8255                         //wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);
8256                         //pframe += wfdielen;
8257                         //pattrib->pktlen += wfdielen;
8258 #endif //CONFIG_WFD
8259                 }
8260         }
8261
8262 #endif //CONFIG_P2P
8263
8264 #ifdef CONFIG_WFD
8265 #ifdef CONFIG_IOCTL_CFG80211
8266         if ( _TRUE == pwdinfo->wfd_info->wfd_enable )
8267 #endif //CONFIG_IOCTL_CFG80211
8268         {
8269                 wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);
8270                 pframe += wfdielen;
8271                 pattrib->pktlen += wfdielen;
8272         }
8273 #ifdef CONFIG_IOCTL_CFG80211
8274         else if (pmlmepriv->wfd_assoc_req_ie != NULL && pmlmepriv->wfd_assoc_req_ie_len>0)              
8275         {
8276                 //WFD IE
8277                 _rtw_memcpy(pframe, pmlmepriv->wfd_assoc_req_ie, pmlmepriv->wfd_assoc_req_ie_len);
8278                 pattrib->pktlen += pmlmepriv->wfd_assoc_req_ie_len;
8279                 pframe += pmlmepriv->wfd_assoc_req_ie_len;              
8280         }
8281 #endif //CONFIG_IOCTL_CFG80211
8282 #endif //CONFIG_WFD     
8283
8284         pattrib->last_txcmdsz = pattrib->pktlen;
8285         dump_mgntframe(padapter, pmgntframe);
8286
8287         ret = _SUCCESS;
8288
8289 exit:
8290         if (ret == _SUCCESS)
8291                 rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
8292         else
8293                 rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
8294
8295         return;
8296 }
8297
8298 //when wait_ack is ture, this function shoule be called at process context
8299 static int _issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
8300 {
8301         int ret = _FAIL;
8302         struct xmit_frame                       *pmgntframe;
8303         struct pkt_attrib                       *pattrib;
8304         unsigned char                                   *pframe;
8305         struct rtw_ieee80211_hdr        *pwlanhdr;
8306         unsigned short                          *fctrl;
8307         struct xmit_priv        *pxmitpriv;
8308         struct mlme_ext_priv    *pmlmeext;
8309         struct mlme_ext_info    *pmlmeinfo;
8310
8311         //DBG_871X("%s:%d\n", __FUNCTION__, power_mode);
8312
8313         if(!padapter)
8314                 goto exit;
8315
8316         pxmitpriv = &(padapter->xmitpriv);
8317         pmlmeext = &(padapter->mlmeextpriv);
8318         pmlmeinfo = &(pmlmeext->mlmext_info);
8319
8320         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8321         {
8322                 goto exit;
8323         }
8324
8325         //update attribute
8326         pattrib = &pmgntframe->attrib;
8327         update_mgntframe_attrib(padapter, pattrib);
8328         pattrib->retry_ctrl = _FALSE;
8329
8330         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8331
8332         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8333         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8334
8335         fctrl = &(pwlanhdr->frame_ctl);
8336         *(fctrl) = 0;
8337
8338         if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
8339         {
8340                 SetFrDs(fctrl);
8341         }
8342         else if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
8343         {
8344                 SetToDs(fctrl);
8345         }
8346         
8347         if (power_mode)
8348         {
8349                 SetPwrMgt(fctrl);
8350         }
8351
8352         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
8353         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8354         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8355
8356         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8357         pmlmeext->mgnt_seq++;
8358         SetFrameSubType(pframe, WIFI_DATA_NULL);
8359
8360         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8361         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8362
8363         pattrib->last_txcmdsz = pattrib->pktlen;
8364
8365         if(wait_ack)
8366         {
8367                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
8368         }
8369         else
8370         {
8371                 dump_mgntframe(padapter, pmgntframe);
8372                 ret = _SUCCESS;
8373         }
8374
8375 exit:
8376         return ret;
8377 }
8378
8379 /*
8380  * [IMPORTANT] Don't call this function in interrupt context
8381  *
8382  * When wait_ms > 0, this function shoule be called at process context
8383  * da == NULL for station mode
8384  */
8385 int issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
8386 {
8387         int ret;
8388         int i = 0;
8389         u32 start = rtw_get_current_time();
8390         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8391         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8392         struct sta_info *psta;
8393
8394
8395         /* da == NULL, assum it's null data for sta to ap*/
8396         if (da == NULL)
8397                 da = get_my_bssid(&(pmlmeinfo->network));
8398
8399         psta = rtw_get_stainfo(&padapter->stapriv, da);
8400         if (psta) {
8401                 if (power_mode)
8402                         rtw_hal_macid_sleep(padapter, psta->mac_id);
8403                 else
8404                         rtw_hal_macid_wakeup(padapter, psta->mac_id);
8405         } else {
8406                 DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",
8407                         FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup");
8408                 rtw_warn_on(1);
8409         }
8410
8411         do {
8412                 ret = _issue_nulldata(padapter, da, power_mode, wait_ms>0?_TRUE:_FALSE);
8413
8414                 i++;
8415
8416                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
8417                         break;
8418
8419                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
8420                         rtw_msleep_os(wait_ms);
8421
8422         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
8423
8424         if (ret != _FAIL) {
8425                 ret = _SUCCESS;
8426                 #ifndef DBG_XMIT_ACK
8427                 goto exit;
8428                 #endif
8429         }
8430
8431         if (try_cnt && wait_ms) {
8432                 if (da)
8433                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
8434                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
8435                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8436                 else
8437                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
8438                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
8439                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8440         }
8441 exit:
8442         return ret;
8443 }
8444
8445 /*
8446  * [IMPORTANT] This function run in interrupt context
8447  *
8448  * The null data packet would be sent without power bit,
8449  * and not guarantee success.
8450  */
8451 s32 issue_nulldata_in_interrupt(PADAPTER padapter, u8 *da)
8452 {
8453         int ret;
8454         struct mlme_ext_priv *pmlmeext;
8455         struct mlme_ext_info *pmlmeinfo;
8456
8457
8458         pmlmeext = &padapter->mlmeextpriv;
8459         pmlmeinfo = &pmlmeext->mlmext_info;
8460
8461         /* da == NULL, assum it's null data for sta to ap*/
8462         if (da == NULL)
8463                 da = get_my_bssid(&(pmlmeinfo->network));
8464
8465         ret = _issue_nulldata(padapter, da, 0, _FALSE);
8466
8467         return ret;
8468 }
8469
8470 //when wait_ack is ture, this function shoule be called at process context
8471 static int _issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
8472 {
8473         int ret = _FAIL;
8474         struct xmit_frame                       *pmgntframe;
8475         struct pkt_attrib                       *pattrib;
8476         unsigned char                                   *pframe;
8477         struct rtw_ieee80211_hdr        *pwlanhdr;
8478         unsigned short                          *fctrl, *qc;
8479         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
8480         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8481         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8482
8483         DBG_871X("%s\n", __FUNCTION__);
8484
8485         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8486         {
8487                 goto exit;
8488         }
8489
8490         //update attribute
8491         pattrib = &pmgntframe->attrib;
8492         update_mgntframe_attrib(padapter, pattrib);
8493
8494         pattrib->hdrlen +=2;
8495         pattrib->qos_en = _TRUE;
8496         pattrib->eosp = 1;
8497         pattrib->ack_policy = 0;
8498         pattrib->mdata = 0;
8499
8500         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8501
8502         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8503         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8504
8505         fctrl = &(pwlanhdr->frame_ctl);
8506         *(fctrl) = 0;
8507
8508         if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
8509         {
8510                 SetFrDs(fctrl);
8511         }
8512         else if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
8513         {
8514                 SetToDs(fctrl);
8515         }
8516
8517         if(pattrib->mdata)
8518                 SetMData(fctrl);
8519
8520         qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
8521         
8522         SetPriority(qc, tid);
8523
8524         SetEOSP(qc, pattrib->eosp);
8525
8526         SetAckpolicy(qc, pattrib->ack_policy);
8527
8528         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
8529         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8530         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8531
8532         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8533         pmlmeext->mgnt_seq++;
8534         SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
8535
8536         pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
8537         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
8538
8539         pattrib->last_txcmdsz = pattrib->pktlen;
8540         
8541         if(wait_ack)
8542         {
8543                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
8544         }
8545         else
8546         {
8547                 dump_mgntframe(padapter, pmgntframe);
8548                 ret = _SUCCESS;
8549         }
8550
8551 exit:
8552         return ret;
8553 }
8554
8555 //when wait_ms >0 , this function shoule be called at process context
8556 //da == NULL for station mode
8557 int issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
8558 {
8559         int ret;
8560         int i = 0;
8561         u32 start = rtw_get_current_time();
8562         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8563         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8564
8565         /* da == NULL, assum it's null data for sta to ap*/
8566         if (da == NULL)
8567                 da = get_my_bssid(&(pmlmeinfo->network));
8568         
8569         do
8570         {
8571                 ret = _issue_qos_nulldata(padapter, da, tid, wait_ms>0?_TRUE:_FALSE);
8572
8573                 i++;
8574
8575                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
8576                         break;
8577
8578                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
8579                         rtw_msleep_os(wait_ms);
8580
8581         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
8582
8583         if (ret != _FAIL) {
8584                 ret = _SUCCESS;
8585                 #ifndef DBG_XMIT_ACK
8586                 goto exit;
8587                 #endif
8588         }
8589
8590         if (try_cnt && wait_ms) {
8591                 if (da)
8592                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
8593                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
8594                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8595                 else
8596                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
8597                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
8598                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8599         }
8600 exit:
8601         return ret;
8602 }
8603
8604 static int _issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
8605 {
8606         struct xmit_frame                       *pmgntframe;
8607         struct pkt_attrib                       *pattrib;
8608         unsigned char                                   *pframe;
8609         struct rtw_ieee80211_hdr        *pwlanhdr;
8610         unsigned short                          *fctrl;
8611         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
8612         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8613         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8614         int ret = _FAIL;
8615 #ifdef CONFIG_P2P
8616         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
8617 #endif //CONFIG_P2P     
8618
8619         //DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
8620
8621 #ifdef CONFIG_P2P
8622         if ( !( rtw_p2p_chk_state( pwdinfo, P2P_STATE_NONE ) ) && ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) )
8623         {
8624                 _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
8625                 _set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
8626         }
8627 #endif //CONFIG_P2P
8628
8629         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8630         {
8631                 goto exit;
8632         }
8633
8634         //update attribute
8635         pattrib = &pmgntframe->attrib;
8636         update_mgntframe_attrib(padapter, pattrib);
8637         pattrib->retry_ctrl = _FALSE;
8638
8639         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8640
8641         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8642         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8643
8644         fctrl = &(pwlanhdr->frame_ctl);
8645         *(fctrl) = 0;
8646
8647         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
8648         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8649         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8650
8651         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8652         pmlmeext->mgnt_seq++;
8653         SetFrameSubType(pframe, WIFI_DEAUTH);
8654
8655         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8656         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8657
8658         reason = cpu_to_le16(reason);
8659         pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_ , (unsigned char *)&reason, &(pattrib->pktlen));
8660
8661         pattrib->last_txcmdsz = pattrib->pktlen;
8662
8663
8664         if(wait_ack)
8665         {
8666                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
8667         }
8668         else
8669         {
8670                 dump_mgntframe(padapter, pmgntframe);
8671                 ret = _SUCCESS;
8672         }
8673
8674 exit:
8675         return ret;
8676 }
8677
8678 int issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason)
8679 {
8680         DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
8681         return _issue_deauth(padapter, da, reason, _FALSE);
8682 }
8683
8684 int issue_deauth_ex(_adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
8685         int wait_ms)
8686 {
8687         int ret;
8688         int i = 0;
8689         u32 start = rtw_get_current_time();
8690
8691         do
8692         {
8693                 ret = _issue_deauth(padapter, da, reason, wait_ms>0?_TRUE:_FALSE);
8694
8695                 i++;
8696
8697                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
8698                         break;
8699
8700                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
8701                         rtw_msleep_os(wait_ms);
8702
8703         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
8704
8705         if (ret != _FAIL) {
8706                 ret = _SUCCESS;
8707                 #ifndef DBG_XMIT_ACK
8708                 goto exit;
8709                 #endif
8710         }
8711
8712         if (try_cnt && wait_ms) {
8713                 if (da)
8714                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
8715                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
8716                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8717                 else
8718                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
8719                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
8720                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
8721         }
8722 exit:
8723         return ret;
8724 }
8725
8726 void issue_action_spct_ch_switch(_adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)
8727 {       
8728         _irqL   irqL;
8729         _list           *plist, *phead;
8730         struct xmit_frame                       *pmgntframe;
8731         struct pkt_attrib                       *pattrib;
8732         unsigned char                           *pframe;
8733         struct rtw_ieee80211_hdr        *pwlanhdr;
8734         unsigned short                  *fctrl;
8735         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
8736         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8737         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8738         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8739
8740
8741         DBG_871X(FUNC_NDEV_FMT" ra="MAC_FMT", ch:%u, offset:%u\n",
8742                 FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(ra), new_ch, ch_offset);
8743
8744         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8745                 return;
8746
8747         //update attribute
8748         pattrib = &pmgntframe->attrib;
8749         update_mgntframe_attrib(padapter, pattrib);
8750
8751         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8752
8753         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8754         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8755
8756         fctrl = &(pwlanhdr->frame_ctl);
8757         *(fctrl) = 0;
8758
8759         _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */
8760         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); /* TA */
8761         _rtw_memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */
8762
8763         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8764         pmlmeext->mgnt_seq++;
8765         SetFrameSubType(pframe, WIFI_ACTION);
8766
8767         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8768         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8769
8770         /* category, action */
8771         {
8772                 u8 category, action;
8773                 category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;
8774                 action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;
8775
8776                 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
8777                 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
8778         }
8779
8780         pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0);
8781         pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen),
8782                 hal_ch_offset_to_secondary_ch_offset(ch_offset));
8783
8784         pattrib->last_txcmdsz = pattrib->pktlen;
8785
8786         dump_mgntframe(padapter, pmgntframe);
8787
8788 }
8789
8790 #ifdef CONFIG_IEEE80211W
8791 void issue_action_SA_Query(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid)
8792 {
8793         u8      category = RTW_WLAN_CATEGORY_SA_QUERY;
8794         u16     reason_code;
8795         struct xmit_frame               *pmgntframe;
8796         struct pkt_attrib               *pattrib;
8797         u8                                      *pframe;
8798         struct rtw_ieee80211_hdr        *pwlanhdr;
8799         u16                                     *fctrl;
8800         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
8801         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8802         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8803         struct sta_info         *psta;
8804         struct sta_priv         *pstapriv = &padapter->stapriv;
8805         struct registry_priv            *pregpriv = &padapter->registrypriv;
8806
8807
8808         DBG_871X("%s\n", __FUNCTION__);
8809
8810         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8811         {
8812                 DBG_871X("%s: alloc_mgtxmitframe fail\n", __FUNCTION__);
8813                 return;
8814         }
8815
8816         //update attribute
8817         pattrib = &pmgntframe->attrib;
8818         update_mgntframe_attrib(padapter, pattrib);
8819
8820         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8821
8822         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8823         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8824
8825         fctrl = &(pwlanhdr->frame_ctl);
8826         *(fctrl) = 0;
8827
8828         if(raddr)
8829                 _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
8830         else
8831                 _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8832         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8833         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8834
8835         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8836         pmlmeext->mgnt_seq++;
8837         SetFrameSubType(pframe, WIFI_ACTION);
8838
8839         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8840         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8841
8842         pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
8843         pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
8844
8845         switch (action)
8846         {
8847                 case 0: //SA Query req
8848                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);
8849                         pmlmeext->sa_query_seq++;
8850                         //send sa query request to AP, AP should reply sa query response in 1 second
8851                         set_sa_query_timer(pmlmeext, 1000);
8852                         break;
8853
8854                 case 1: //SA Query rsp
8855                         tid = cpu_to_le16(tid);
8856                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&tid, &pattrib->pktlen);
8857                         break;
8858                 default:
8859                         break;
8860         }
8861
8862         pattrib->last_txcmdsz = pattrib->pktlen;
8863
8864         dump_mgntframe(padapter, pmgntframe);
8865 }
8866 #endif //CONFIG_IEEE80211W
8867
8868 void issue_action_BA(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
8869 {
8870         u8      category = RTW_WLAN_CATEGORY_BACK;
8871         u16     start_seq;
8872         u16     BA_para_set;
8873         u16     reason_code;
8874         u16     BA_timeout_value;
8875         u16     BA_starting_seqctrl;
8876         HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;
8877         struct xmit_frame               *pmgntframe;
8878         struct pkt_attrib               *pattrib;
8879         u8                                      *pframe;
8880         struct rtw_ieee80211_hdr        *pwlanhdr;
8881         u16                                     *fctrl;
8882         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
8883         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8884         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8885         struct sta_info         *psta;
8886         struct sta_priv         *pstapriv = &padapter->stapriv;
8887         struct registry_priv            *pregpriv = &padapter->registrypriv;
8888
8889 #ifdef CONFIG_80211N_HT
8890         DBG_871X("%s, category=%d, action=%d, status=%d\n", __FUNCTION__, category, action, status);
8891
8892         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
8893         {
8894                 return;
8895         }
8896
8897         //update attribute
8898         pattrib = &pmgntframe->attrib;
8899         update_mgntframe_attrib(padapter, pattrib);
8900
8901         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8902
8903         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8904         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8905
8906         fctrl = &(pwlanhdr->frame_ctl);
8907         *(fctrl) = 0;
8908
8909         //_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8910         _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
8911         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
8912         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
8913
8914         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
8915         pmlmeext->mgnt_seq++;
8916         SetFrameSubType(pframe, WIFI_ACTION);
8917
8918         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
8919         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
8920
8921         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
8922         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
8923
8924       status = cpu_to_le16(status);
8925         
8926
8927         if (category == 3)
8928         {
8929                 switch (action)
8930                 {
8931                         case 0: //ADDBA req
8932                                 do {
8933                                         pmlmeinfo->dialogToken++;
8934                                 } while (pmlmeinfo->dialogToken == 0);
8935                                 pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
8936
8937 #ifdef CONFIG_BT_COEXIST
8938                                 if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(padapter) == _TRUE)
8939                                 {
8940                                         // A-MSDU NOT Supported
8941                                         BA_para_set = 0;
8942                                         // immediate Block Ack
8943                                         BA_para_set |= (1 << 1) & IEEE80211_ADDBA_PARAM_POLICY_MASK;
8944                                         // TID
8945                                         BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
8946                                         // max buffer size is 8 MSDU
8947                                         BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
8948                                 }
8949                                 else
8950 #endif
8951                                 {
8952                                         #if defined(CONFIG_RTL8188E) && defined(CONFIG_SDIO_HCI)
8953                                         BA_para_set = (0x0802 | ((status & 0xf) << 2)); //immediate ack & 16 buffer size
8954                                         #else
8955                                         BA_para_set = (0x1002 | ((status & 0xf) << 2)); //immediate ack & 64 buffer size
8956                                         #endif
8957                                 }
8958                                 //sys_mib.BA_para_set = 0x0802; //immediate ack & 32 buffer size
8959                                 BA_para_set = cpu_to_le16(BA_para_set);
8960                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
8961
8962                                 //BA_timeout_value = 0xffff;//max: 65535 TUs(~ 65 ms)
8963                                 BA_timeout_value = 5000;//~ 5ms
8964                                 BA_timeout_value = cpu_to_le16(BA_timeout_value);
8965                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_timeout_value)), &(pattrib->pktlen));
8966
8967                                 //if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
8968                                 if ((psta = rtw_get_stainfo(pstapriv, raddr)) != NULL)
8969                                 {
8970                                         start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
8971
8972                                         DBG_871X("BA_starting_seqctrl = %d for TID=%d\n", start_seq, status & 0x07);
8973                                         
8974                                         psta->BA_starting_seqctrl[status & 0x07] = start_seq;
8975                                         
8976                                         BA_starting_seqctrl = start_seq << 4;
8977                                 }
8978                                 
8979                                 BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl);
8980                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_starting_seqctrl)), &(pattrib->pktlen));
8981                                 break;
8982
8983                         case 1: //ADDBA rsp
8984                                 pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
8985                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
8986                                 /*
8987                                 //BA_para_set = cpu_to_le16((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); //64 buffer size
8988                                 #if defined(CONFIG_RTL8188E )&& defined (CONFIG_SDIO_HCI)
8989                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); //32buffer size
8990                                 #else
8991                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); //64 buffer size
8992                                 #endif
8993                                 */
8994                                 rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
8995                                 if(MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)
8996                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); //64 buffer size
8997                                 else if(MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)
8998                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); //32 buffer size
8999                                 else if(MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)
9000                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); //16 buffer size
9001                                 else if(MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)
9002                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); //8 buffer size
9003                                 else
9004                                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); //64 buffer size       
9005
9006 #ifdef CONFIG_BT_COEXIST
9007                                 if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(padapter) == _TRUE)
9008                                 {
9009                                         // max buffer size is 8 MSDU
9010                                         BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
9011                                         BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
9012                                 }
9013 #endif
9014
9015                                 if(pregpriv->ampdu_amsdu==0)//disabled
9016                                         BA_para_set = cpu_to_le16(BA_para_set & ~BIT(0));
9017                                 else if(pregpriv->ampdu_amsdu==1)//enabled
9018                                         BA_para_set = cpu_to_le16(BA_para_set | BIT(0));
9019                                 else //auto
9020                                         BA_para_set = cpu_to_le16(BA_para_set);
9021                                 
9022                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
9023                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
9024                                 break;
9025                         case 2://DELBA
9026                                 BA_para_set = (status & 0x1F) << 3;
9027                                 BA_para_set = cpu_to_le16(BA_para_set);                         
9028                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
9029
9030                                 reason_code = 37;//Requested from peer STA as it does not want to use the mechanism
9031                                 reason_code = cpu_to_le16(reason_code);
9032                                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(reason_code)), &(pattrib->pktlen));
9033                                 break;
9034                         default:
9035                                 break;
9036                 }
9037         }
9038
9039         pattrib->last_txcmdsz = pattrib->pktlen;
9040
9041         dump_mgntframe(padapter, pmgntframe);
9042 #endif //CONFIG_80211N_HT
9043 }
9044
9045 static void issue_action_BSSCoexistPacket(_adapter *padapter)
9046 {       
9047         _irqL   irqL;
9048         _list           *plist, *phead;
9049         unsigned char category, action;
9050         struct xmit_frame                       *pmgntframe;
9051         struct pkt_attrib                       *pattrib;
9052         unsigned char                           *pframe;
9053         struct rtw_ieee80211_hdr        *pwlanhdr;
9054         unsigned short                  *fctrl;
9055         struct  wlan_network    *pnetwork = NULL;
9056         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
9057         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
9058         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
9059         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9060         _queue          *queue  = &(pmlmepriv->scanned_queue);
9061         u8 InfoContent[16] = {0};
9062         u8 ICS[8][15];
9063 #ifdef CONFIG_80211N_HT 
9064         if((pmlmepriv->num_FortyMHzIntolerant==0) || (pmlmepriv->num_sta_no_ht==0))
9065                 return;
9066
9067         if(_TRUE == pmlmeinfo->bwmode_updated)
9068                 return;
9069         
9070
9071         DBG_871X("%s\n", __FUNCTION__);
9072
9073
9074         category = RTW_WLAN_CATEGORY_PUBLIC;
9075         action = ACT_PUBLIC_BSSCOEXIST;
9076
9077         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
9078         {
9079                 return;
9080         }
9081
9082         //update attribute
9083         pattrib = &pmgntframe->attrib;
9084         update_mgntframe_attrib(padapter, pattrib);
9085
9086         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
9087
9088         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
9089         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
9090
9091         fctrl = &(pwlanhdr->frame_ctl);
9092         *(fctrl) = 0;
9093
9094         _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
9095         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
9096         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
9097
9098         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
9099         pmlmeext->mgnt_seq++;
9100         SetFrameSubType(pframe, WIFI_ACTION);
9101
9102         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
9103         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
9104
9105         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
9106         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
9107
9108
9109         //
9110         if(pmlmepriv->num_FortyMHzIntolerant>0)
9111         {
9112                 u8 iedata=0;
9113                 
9114                 iedata |= BIT(2);//20 MHz BSS Width Request
9115
9116                 pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));
9117                 
9118         }
9119         
9120
9121         //
9122         _rtw_memset(ICS, 0, sizeof(ICS));
9123         if(pmlmepriv->num_sta_no_ht>0)
9124         {       
9125                 int i;
9126         
9127                 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
9128
9129                 phead = get_list_head(queue);
9130                 plist = get_next(phead);
9131        
9132                 while(1)
9133                 {
9134                         int len;
9135                         u8 *p;
9136                         WLAN_BSSID_EX *pbss_network;
9137         
9138                         if (rtw_end_of_queue_search(phead,plist)== _TRUE)
9139                                 break;          
9140
9141                         pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);      
9142                 
9143                         plist = get_next(plist);
9144
9145                         pbss_network = (WLAN_BSSID_EX *)&pnetwork->network;
9146
9147                         p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
9148                         if((p==NULL) || (len==0))//non-HT
9149                         {
9150                                 if((pbss_network->Configuration.DSConfig<=0) || (pbss_network->Configuration.DSConfig>14))
9151                                         continue;
9152                                 
9153                                 ICS[0][pbss_network->Configuration.DSConfig]=1;
9154                                 
9155                                 if(ICS[0][0] == 0)
9156                                         ICS[0][0] = 1;          
9157                         }               
9158         
9159                 }        
9160
9161                 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
9162
9163
9164                 for(i= 0;i<8;i++)
9165                 {
9166                         if(ICS[i][0] == 1)
9167                         {
9168                                 int j, k = 0;
9169                                 
9170                                 InfoContent[k] = i;                             
9171                                 //SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent,i);
9172                                 k++;
9173                                 
9174                                 for(j=1;j<=14;j++)
9175                                 {
9176                                         if(ICS[i][j]==1)
9177                                         {
9178                                                 if(k<16)
9179                                                 {
9180                                                         InfoContent[k] = j; //channel number
9181                                                         //SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j);
9182                                                         k++;
9183                                                 }       
9184                                         }       
9185                                 }       
9186
9187                                 pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
9188                                 
9189                         }
9190                         
9191                 }
9192                 
9193
9194         }
9195                 
9196
9197         pattrib->last_txcmdsz = pattrib->pktlen;
9198
9199         dump_mgntframe(padapter, pmgntframe);
9200 #endif //CONFIG_80211N_HT
9201 }
9202
9203 unsigned int send_delba(_adapter *padapter, u8 initiator, u8 *addr)
9204 {
9205         struct sta_priv *pstapriv = &padapter->stapriv;
9206         struct sta_info *psta = NULL;
9207         //struct recv_reorder_ctrl *preorder_ctrl;
9208         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9209         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9210         u16 tid;
9211
9212         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 
9213                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
9214                         return _SUCCESS;
9215         
9216         psta = rtw_get_stainfo(pstapriv, addr);
9217         if(psta==NULL)
9218                 return _SUCCESS;
9219
9220         //DBG_871X("%s:%s\n", __FUNCTION__, (initiator==0)?"RX_DIR":"TX_DIR");
9221         
9222         if(initiator==0) // recipient
9223         {
9224                 for(tid = 0;tid<MAXTID;tid++)
9225                 {
9226                         if(psta->recvreorder_ctrl[tid].enable == _TRUE)
9227                         {
9228                                 DBG_871X("rx agg disable tid(%d)\n",tid);
9229                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
9230                                 psta->recvreorder_ctrl[tid].enable = _FALSE;
9231                                 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
9232                                 #ifdef DBG_RX_SEQ
9233                                 DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u \n", __FUNCTION__, __LINE__,
9234                                         psta->recvreorder_ctrl[tid].indicate_seq);
9235                                 #endif
9236                         }               
9237                 }
9238         }
9239         else if(initiator == 1)// originator
9240         {
9241 #ifdef CONFIG_80211N_HT
9242                 //DBG_871X("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap);
9243                 for(tid = 0;tid<MAXTID;tid++)
9244                 {
9245                         if(psta->htpriv.agg_enable_bitmap & BIT(tid))
9246                         {
9247                                 DBG_871X("tx agg disable tid(%d)\n",tid);
9248                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F) );
9249                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
9250                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
9251                                 
9252                         }                       
9253                 }
9254 #endif //CONFIG_80211N_HT
9255         }
9256         
9257         return _SUCCESS;
9258         
9259 }
9260
9261 unsigned int send_beacon(_adapter *padapter)
9262 {
9263         u8      bxmitok = _FALSE;
9264         int     issue=0;
9265         int poll = 0;
9266 //#ifdef CONFIG_CONCURRENT_MODE
9267         //struct mlme_ext_priv  *pmlmeext = &(padapter->mlmeextpriv);
9268         //struct mlme_ext_info  *pmlmeinfo = &(pmlmeext->mlmext_info);
9269         //_adapter *pbuddy_adapter = padapter->pbuddy_adapter;
9270         //struct mlme_priv *pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
9271 //#endif                
9272
9273 #ifdef CONFIG_PCI_HCI
9274
9275         //DBG_871X("%s\n", __FUNCTION__);
9276
9277         issue_beacon(padapter, 0);
9278
9279         return _SUCCESS;
9280
9281 #endif
9282
9283 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
9284         u32 start = rtw_get_current_time();
9285
9286         rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
9287         rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
9288         do{
9289                 issue_beacon(padapter, 100);
9290                 issue++;
9291                 do {
9292                         rtw_yield_os();
9293                         rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
9294                         poll++;
9295                 }while((poll%10)!=0 && _FALSE == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
9296
9297         }while(_FALSE == bxmitok && issue<100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
9298
9299         if(padapter->bSurpriseRemoved || padapter->bDriverStopped)
9300         {
9301                 return _FAIL;
9302         }
9303
9304         
9305         if(_FALSE == bxmitok)
9306         {
9307                 DBG_871X("%s fail! %u ms\n", __FUNCTION__, rtw_get_passing_time_ms(start));
9308                 return _FAIL;
9309         }
9310         else
9311         {
9312                 u32 passing_time = rtw_get_passing_time_ms(start);
9313
9314                 if(passing_time > 100 || issue > 3)
9315                         DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));
9316                 //else
9317                 //      DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));
9318                 
9319                 return _SUCCESS;
9320         }
9321
9322 #endif
9323
9324 }
9325
9326 /****************************************************************************
9327
9328 Following are some utitity fuctions for WiFi MLME
9329
9330 *****************************************************************************/
9331
9332 BOOLEAN IsLegal5GChannel(
9333         IN PADAPTER                     Adapter,
9334         IN u8                   channel)
9335 {
9336         
9337         int i=0;
9338         u8 Channel_5G[45] = {36,38,40,42,44,46,48,50,52,54,56,58,
9339                 60,62,64,100,102,104,106,108,110,112,114,116,118,120,122,
9340                 124,126,128,130,132,134,136,138,140,149,151,153,155,157,159,
9341                 161,163,165};
9342         for(i=0;i<sizeof(Channel_5G);i++)
9343                 if(channel == Channel_5G[i])
9344                         return _TRUE;
9345         return _FALSE;
9346 }
9347
9348 void site_survey(_adapter *padapter)
9349 {
9350         unsigned char           survey_channel = 0, val8;
9351         RT_SCAN_TYPE    ScanType = SCAN_PASSIVE;
9352         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9353         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9354         u32 initialgain = 0;
9355
9356 #ifdef CONFIG_P2P
9357
9358 #ifdef CONFIG_CONCURRENT_MODE
9359
9360 #if defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE) || defined(CONFIG_ATMEL_RC_PATCH) 
9361         u8 stay_buddy_ch = 0;
9362 #endif
9363         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
9364         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;                     
9365         struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
9366
9367 #endif //CONFIG_CONCURRENT_MODE
9368         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
9369         static unsigned char  prev_survey_channel = 0;
9370         static unsigned int p2p_scan_count = 0; 
9371         
9372         if ( ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) || ( pwdinfo->p2p_info.scan_op_ch_only ) )
9373         {
9374                 if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
9375                 {
9376                         survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
9377                 }
9378                 else
9379                 {
9380                         survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
9381                 }
9382                 ScanType = SCAN_ACTIVE;
9383         }
9384         else if(rtw_p2p_findphase_ex_is_social(pwdinfo))
9385         {
9386                 //      Commented by Albert 2011/06/03
9387                 //      The driver is in the find phase, it should go through the social channel.
9388                 int ch_set_idx;
9389                 survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
9390                 ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, survey_channel);
9391                 if (ch_set_idx >= 0)
9392                         ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
9393                 else
9394                         ScanType = SCAN_ACTIVE;
9395         }
9396         else
9397 #endif //CONFIG_P2P
9398         {
9399                 struct rtw_ieee80211_channel *ch;
9400                 if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
9401                         ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
9402                         survey_channel = ch->hw_value;
9403                         ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
9404                 }
9405         }
9406         
9407         if (0){
9408 #ifdef CONFIG_P2P
9409                 DBG_871X(FUNC_ADPT_FMT" ch:%u (cnt:%u,idx:%d) at %dms, %c%c%c\n"
9410                 , FUNC_ADPT_ARG(padapter)
9411                 , survey_channel
9412                 , pwdinfo->find_phase_state_exchange_cnt, 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 #else
9418                 DBG_871X(FUNC_ADPT_FMT" ch:%u (cnt:%u) at %dms, %c%c%c\n"
9419                 , FUNC_ADPT_ARG(padapter)
9420                 , survey_channel
9421                 , pmlmeext->sitesurvey_res.channel_idx
9422                 , rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
9423                 , ScanType?'A':'P', pmlmeext->sitesurvey_res.scan_mode?'A':'P'
9424                 , pmlmeext->sitesurvey_res.ssid[0].SsidLength?'S':' '
9425                 );
9426 #endif // CONFIG_P2P
9427                 #ifdef DBG_FIXED_CHAN
9428                 DBG_871X(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan);
9429                 #endif
9430         }
9431
9432         if(survey_channel != 0)
9433         {
9434                 //PAUSE 4-AC Queue when site_survey
9435                 //rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8));
9436                 //val8 |= 0x0f;
9437                 //rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8));
9438 #if defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE) || defined(CONFIG_ATMEL_RC_PATCH)
9439                 if((padapter->pbuddy_adapter->mlmeextpriv.mlmext_info.state&0x03) == WIFI_FW_AP_STATE)
9440                 {
9441                         if( pmlmeinfo->scan_cnt == RTW_SCAN_NUM_OF_CH )
9442                         {
9443                                 pmlmeinfo->scan_cnt = 0;
9444                                 survey_channel = pbuddy_mlmeext->cur_channel;
9445                                 stay_buddy_ch = 1;
9446                         }
9447                         else 
9448                         {
9449                                 if( pmlmeinfo->scan_cnt == 0 )
9450                                         stay_buddy_ch = 2;
9451                                 pmlmeinfo->scan_cnt++;
9452                         }
9453                 }
9454 #endif
9455                 if(pmlmeext->sitesurvey_res.channel_idx == 0)
9456                 {
9457 #ifdef DBG_FIXED_CHAN
9458                         if(pmlmeext->fixed_chan !=0xff)
9459                                 set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
9460                         else    
9461 #endif
9462                                 set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
9463                 }
9464                 else
9465                 {
9466 #ifdef DBG_FIXED_CHAN
9467                         if(pmlmeext->fixed_chan!=0xff)
9468                                 SelectChannel(padapter, pmlmeext->fixed_chan);
9469                         else    
9470 #endif
9471                                 SelectChannel(padapter, survey_channel);
9472                 }
9473
9474 #if defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE) || defined(CONFIG_ATMEL_RC_PATCH) 
9475                 if( stay_buddy_ch == 1 )
9476                 {
9477                         val8 = 0; //survey done
9478                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
9479
9480                         if(check_buddy_mlmeinfo_state(padapter, WIFI_FW_AP_STATE) &&
9481                                 check_buddy_fwstate(padapter, _FW_LINKED))
9482                         {
9483                                 update_beacon(padapter->pbuddy_adapter, 0, NULL, _TRUE);
9484                         }
9485                 }
9486                 else if( stay_buddy_ch == 2 )
9487                 {
9488                         val8 = 1; //under site survey
9489                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
9490                 }
9491 #endif
9492
9493                 if(ScanType == SCAN_ACTIVE) //obey the channel plan setting...
9494                 {
9495                         #ifdef CONFIG_P2P
9496                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || 
9497                                 rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)
9498                         )
9499                         {
9500                                 issue_probereq_p2p(padapter, NULL);
9501                                 issue_probereq_p2p(padapter, NULL);
9502                                 issue_probereq_p2p(padapter, NULL);
9503                         }
9504                         else
9505                         #endif //CONFIG_P2P
9506                         {
9507                                 int i;
9508                                 for(i=0;i<RTW_SSID_SCAN_AMOUNT;i++){
9509                                         if(pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
9510                                                 /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
9511                                                 if (padapter->registrypriv.wifi_spec)
9512                                                         issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
9513                                                 else
9514                                                         issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
9515                                                 issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
9516                                         }
9517                                 }
9518
9519                                 if(pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
9520                                         /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
9521                                         if (padapter->registrypriv.wifi_spec)
9522                                                 issue_probereq(padapter, NULL, NULL);
9523                                         else
9524                                                 issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
9525                                         issue_probereq(padapter, NULL, NULL);
9526                                 }
9527                         }
9528                 }
9529 #if  defined(CONFIG_ATMEL_RC_PATCH)
9530                 // treat wlan0 & p2p0 in same way, may be changed in near feature.
9531                 // assume home channel is 6, channel switch sequence will be 
9532                 //      1,2-6-3,4-6-5,6-6-7,8-6-9,10-6-11,12-6-13,14
9533                 //if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)==_TRUE)
9534
9535                 if( stay_buddy_ch == 1 )
9536                         set_survey_timer(pmlmeext, pmlmeext->chan_scan_time * RTW_STAY_AP_CH_MILLISECOND );
9537                 else {
9538                         if( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
9539                                 set_survey_timer(pmlmeext, 20);
9540                         else
9541                                 set_survey_timer(pmlmeext, 40);
9542                 }
9543 #elif defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE)
9544                 if( stay_buddy_ch == 1 )
9545                         set_survey_timer(pmlmeext, pmlmeext->chan_scan_time * RTW_STAY_AP_CH_MILLISECOND );
9546                 else
9547                         set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
9548 #else
9549                         set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
9550 #endif
9551         }
9552         else
9553         {
9554
9555                 //      channel number is 0 or this channel is not valid.
9556
9557 #ifdef CONFIG_CONCURRENT_MODE
9558                 u8 cur_channel;
9559                 u8 cur_bwmode;
9560                 u8 cur_ch_offset;
9561
9562                 if (rtw_get_ch_setting_union(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset) != 0)
9563                 {
9564                         if (0)
9565                         DBG_871X(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
9566                                 FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
9567                 }
9568                 #ifdef CONFIG_IOCTL_CFG80211
9569                 else if(padapter->pbuddy_adapter
9570                         && pbuddy_adapter->wdinfo.driver_interface == DRIVER_CFG80211
9571                         && adapter_wdev_data(pbuddy_adapter)->p2p_enabled
9572                         && rtw_p2p_chk_state(&pbuddy_adapter->wdinfo, P2P_STATE_LISTEN)
9573                         )
9574                 {
9575                         cur_channel = pbuddy_adapter->wdinfo.listen_channel;
9576                         cur_bwmode = pbuddy_mlmeext->cur_bwmode;
9577                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
9578                 }
9579                 #endif
9580                 else
9581                 {
9582                         cur_channel = pmlmeext->cur_channel;
9583                         cur_bwmode = pmlmeext->cur_bwmode;
9584                         cur_ch_offset = pmlmeext->cur_ch_offset;
9585                 }               
9586 #endif
9587
9588         
9589 #ifdef CONFIG_P2P
9590                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
9591                 {
9592                         if( ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) || ( pwdinfo->p2p_info.scan_op_ch_only ) )
9593                         {
9594                                 //      Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT.
9595                                 //      This will let the following flow to run the scanning end.
9596                                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
9597                         }
9598                         #ifdef CONFIG_DBG_P2P
9599                         DBG_871X( "[%s] find phase exchange cnt = %d\n", __FUNCTION__, pwdinfo->find_phase_state_exchange_cnt );
9600                         #endif
9601                 }
9602
9603                 if(rtw_p2p_findphase_ex_is_needed(pwdinfo))
9604                 {
9605                         //      Set the P2P State to the listen state of find phase and set the current channel to the listen channel
9606                         set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
9607                         rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
9608                         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
9609
9610                         initialgain = 0xff; //restore RX GAIN
9611                         rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 
9612                         //turn on dynamic functions
9613                         Restore_DM_Func_Flag(padapter);
9614                         //Switch_DM_Func(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, _TRUE);
9615                         
9616                         _set_timer( &pwdinfo->find_phase_timer, ( u32 ) ( ( u32 ) ( pwdinfo->listen_dwell ) * 100 ) );
9617                 }
9618                 else
9619 #endif //CONFIG_P2P
9620                 {
9621
9622 #if defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE) || defined(CONFIG_ATMEL_RC_PATCH) 
9623                         pmlmeinfo->scan_cnt = 0;
9624 #endif
9625
9626 #ifdef CONFIG_ANTENNA_DIVERSITY
9627                         // 20100721:Interrupt scan operation here.
9628                         // For SW antenna diversity before link, it needs to switch to another antenna and scan again.
9629                         // It compares the scan result and select beter one to do connection.
9630                         if(rtw_hal_antdiv_before_linked(padapter))
9631                         {                               
9632                                 pmlmeext->sitesurvey_res.bss_cnt = 0;
9633                                 pmlmeext->sitesurvey_res.channel_idx = -1;
9634                                 pmlmeext->chan_scan_time = SURVEY_TO /2;                        
9635                                 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
9636                                 return;
9637                         }
9638 #endif
9639
9640 #ifdef CONFIG_P2P
9641                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
9642                         {
9643                         #ifdef CONFIG_CONCURRENT_MODE
9644                                 if( pwdinfo->driver_interface == DRIVER_WEXT )
9645                                 {
9646                                         if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
9647                                         {
9648                                                 _set_timer( &pwdinfo->ap_p2p_switch_timer, 500 );
9649                                         }
9650                                 }               
9651                                 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
9652                         #else
9653                                 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
9654                         #endif
9655                         }
9656                         rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
9657 #endif //CONFIG_P2P
9658                         
9659                         pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
9660
9661                         //switch back to the original channel
9662                         //SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset);
9663
9664                         {
9665 #ifdef CONFIG_CONCURRENT_MODE
9666                                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
9667 #else
9668 #ifdef CONFIG_DUALMAC_CONCURRENT
9669                                 dc_set_channel_bwmode_survey_done(padapter);
9670 #else
9671
9672 #ifdef CONFIG_P2P
9673                         if( (pwdinfo->driver_interface == DRIVER_WEXT) && (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) )
9674                                 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
9675                         else
9676 #endif //CONFIG_P2P
9677                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
9678
9679 #endif //CONFIG_DUALMAC_CONCURRENT
9680 #endif //CONFIG_CONCURRENT_MODE
9681                         }
9682
9683                         //flush 4-AC Queue after site_survey
9684                         //val8 = 0;
9685                         //rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8));
9686
9687                         //config MSR
9688                         Set_MSR(padapter, (pmlmeinfo->state & 0x3));
9689
9690                         initialgain = 0xff; //restore RX GAIN
9691                         rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 
9692                         //turn on dynamic functions
9693                         Restore_DM_Func_Flag(padapter);
9694                         //Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);
9695
9696                         if (is_client_associated_to_ap(padapter) == _TRUE)
9697                         {
9698                                 issue_nulldata(padapter, NULL, 0, 3, 500);
9699                                 
9700 #ifdef CONFIG_CONCURRENT_MODE
9701                                 if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
9702                                 {
9703                                         DBG_871X("adapter is surveydone(buddy_adapter is linked), issue nulldata(pwrbit=0)\n");
9704                                         
9705                                         issue_nulldata(padapter->pbuddy_adapter, NULL, 0, 3, 500);
9706                                 }
9707 #endif  
9708                         }
9709 #ifdef CONFIG_CONCURRENT_MODE
9710                         else if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
9711                         {
9712                                 issue_nulldata(padapter->pbuddy_adapter, NULL, 0, 3, 500);
9713                         }
9714 #endif  
9715
9716                         val8 = 0; //survey done
9717                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
9718
9719                         report_surveydone_event(padapter);
9720
9721                         pmlmeext->chan_scan_time = SURVEY_TO;
9722                         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
9723
9724                         issue_action_BSSCoexistPacket(padapter);
9725                         issue_action_BSSCoexistPacket(padapter);
9726                         issue_action_BSSCoexistPacket(padapter);
9727
9728                 }
9729
9730 #ifdef CONFIG_CONCURRENT_MODE
9731                 if(check_buddy_mlmeinfo_state(padapter, WIFI_FW_AP_STATE) &&
9732                         check_buddy_fwstate(padapter, _FW_LINKED))
9733                 {
9734
9735                         DBG_871X("survey done, current CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
9736
9737                         DBG_871X("restart pbuddy_adapter's beacon\n");
9738                 
9739                         update_beacon(padapter->pbuddy_adapter, 0, NULL, _TRUE);
9740                 }
9741 #endif
9742
9743         }
9744
9745         return;
9746
9747 }
9748
9749 //collect bss info from Beacon and Probe request/response frames.
9750 u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSID_EX *bssid)
9751 {
9752         int     i;
9753         u32     len;
9754         u8      *p;
9755         u16     val16, subtype;
9756         u8      *pframe = precv_frame->u.hdr.rx_data;
9757         u32     packet_len = precv_frame->u.hdr.len;
9758         u8 ie_offset;
9759         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
9760         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
9761         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
9762
9763         len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
9764
9765         if (len > MAX_IE_SZ)
9766         {
9767                 //DBG_871X("IE too long for survey event\n");
9768                 return _FAIL;
9769         }
9770
9771         _rtw_memset(bssid, 0, sizeof(WLAN_BSSID_EX));
9772
9773         subtype = GetFrameSubType(pframe);
9774
9775         if(subtype==WIFI_BEACON) {
9776                 bssid->Reserved[0] = 1;
9777                 ie_offset = _BEACON_IE_OFFSET_;
9778         } else {
9779                 // FIXME : more type
9780                 if (subtype == WIFI_PROBERSP) {
9781                         ie_offset = _PROBERSP_IE_OFFSET_;
9782                         bssid->Reserved[0] = 3;
9783                 }
9784                 else if (subtype == WIFI_PROBEREQ) {
9785                         ie_offset = _PROBEREQ_IE_OFFSET_;
9786                         bssid->Reserved[0] = 2;
9787                 }
9788                 else {
9789                         bssid->Reserved[0] = 0;
9790                         ie_offset = _FIXED_IE_LENGTH_;
9791                 }
9792         }
9793                 
9794         bssid->Length = sizeof(WLAN_BSSID_EX) - MAX_IE_SZ + len;
9795
9796         //below is to copy the information element
9797         bssid->IELength = len;
9798         _rtw_memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
9799
9800         //get the signal strength
9801         //bssid->Rssi = precv_frame->u.hdr.attrib.SignalStrength; // 0-100 index.
9802         bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; // in dBM.raw data    
9803         bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;//in percentage 
9804         bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;//in percentage
9805 #ifdef CONFIG_ANTENNA_DIVERSITY
9806         //rtw_hal_get_hwreg(padapter, HW_VAR_CURRENT_ANTENNA, (u8 *)(&bssid->PhyInfo.Optimum_antenna));
9807         rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA,  &bssid->PhyInfo.Optimum_antenna);
9808 #endif
9809
9810         // checking SSID
9811         if ((p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset)) == NULL)
9812         {
9813                 DBG_871X("marc: cannot find SSID for survey event\n");
9814                 return _FAIL;
9815         }
9816
9817         if (*(p + 1))
9818         {
9819                 if (len > NDIS_802_11_LENGTH_SSID)
9820                 {
9821                         DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
9822                         return _FAIL;
9823                 }
9824                 _rtw_memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
9825                 bssid->Ssid.SsidLength = *(p + 1);
9826         }
9827         else
9828         {
9829                 bssid->Ssid.SsidLength = 0;
9830         }
9831
9832         _rtw_memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
9833
9834         //checking rate info...
9835         i = 0;
9836         p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
9837         if (p != NULL)
9838         {
9839                 if (len > NDIS_802_11_LENGTH_RATES_EX)
9840                 {
9841                         DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
9842                         return _FAIL;
9843                 }
9844                 _rtw_memcpy(bssid->SupportedRates, (p + 2), len);
9845                 i = len;
9846         }
9847
9848         p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
9849         if (p != NULL)
9850         {
9851                 if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
9852                 {
9853                         DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
9854                         return _FAIL;
9855                 }
9856                 _rtw_memcpy(bssid->SupportedRates + i, (p + 2), len);
9857         }
9858
9859         //todo:
9860 #if 0
9861         if (judge_network_type(bssid->SupportedRates, (len + i)) == WIRELESS_11B)
9862         {
9863                 bssid->NetworkTypeInUse = Ndis802_11DS;
9864         }
9865         else
9866 #endif
9867         {
9868                 bssid->NetworkTypeInUse = Ndis802_11OFDM24;
9869         }
9870
9871 #ifdef CONFIG_P2P
9872         if (subtype == WIFI_PROBEREQ)
9873         {
9874                 u8 *p2p_ie;
9875                 u32     p2p_ielen;
9876                 // Set Listion Channel
9877                 if ((p2p_ie = rtw_get_p2p_ie(bssid->IEs, bssid->IELength, NULL, &p2p_ielen)))
9878                 {
9879                         u32     attr_contentlen = 0;
9880                         u8 listen_ch[5] = { 0x00 };
9881
9882                         if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, listen_ch, &attr_contentlen) != NULL)
9883                                 bssid->Configuration.DSConfig = listen_ch[4];
9884                         else
9885                                 return _FALSE; // Intel device maybe no bring Listen Channel
9886                 } else
9887                 { // use current channel
9888                         bssid->Configuration.DSConfig = padapter->mlmeextpriv.cur_channel;
9889                         DBG_871X("%s()-%d: Cannot get p2p_ie. set DSconfig to op_ch(%d)\n", __FUNCTION__, __LINE__, bssid->Configuration.DSConfig);
9890                 }
9891
9892                 // FIXME
9893                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
9894                 _rtw_memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
9895                 bssid->Privacy = 1;
9896                 return _SUCCESS;
9897         }
9898 #endif //CONFIG_P2P
9899
9900         if (bssid->IELength < 12)
9901                 return _FAIL;
9902
9903         // Checking for DSConfig
9904         p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
9905
9906         bssid->Configuration.DSConfig = 0;
9907         bssid->Configuration.Length = 0;
9908
9909         if (p)
9910         {
9911                 bssid->Configuration.DSConfig = *(p + 2);
9912         }
9913         else
9914         {// In 5G, some ap do not have DSSET IE
9915                 // checking HT info for channel
9916                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
9917                 if(p)
9918                 {
9919                         struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
9920                         bssid->Configuration.DSConfig = HT_info->primary_channel;
9921                 }
9922                 else
9923                 { // use current channel
9924                         bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
9925                 }
9926         }
9927
9928         _rtw_memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
9929         bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod);
9930
9931         val16 = rtw_get_capability((WLAN_BSSID_EX *)bssid);
9932
9933         if (val16 & BIT(0))
9934         {
9935                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
9936                 _rtw_memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
9937         }
9938         else
9939         {
9940                 bssid->InfrastructureMode = Ndis802_11IBSS;
9941                 _rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
9942         }
9943
9944         if (val16 & BIT(4))
9945                 bssid->Privacy = 1;
9946         else
9947                 bssid->Privacy = 0;
9948
9949         bssid->Configuration.ATIMWindow = 0;
9950
9951         //20/40 BSS Coexistence check
9952         if((pregistrypriv->wifi_spec==1) && (_FALSE == pmlmeinfo->bwmode_updated))
9953         {       
9954                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
9955 #ifdef CONFIG_80211N_HT
9956                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
9957                 if(p && len>0)
9958                 {
9959                         struct HT_caps_element  *pHT_caps;
9960                         pHT_caps = (struct HT_caps_element      *)(p + 2);
9961                         
9962                         if(pHT_caps->u.HT_cap_element.HT_caps_info&BIT(14))
9963                         {                               
9964                                 pmlmepriv->num_FortyMHzIntolerant++;
9965                         }
9966                 }
9967                 else
9968                 {
9969                         pmlmepriv->num_sta_no_ht++;
9970                 }
9971 #endif //CONFIG_80211N_HT
9972                 
9973         }
9974
9975 #ifdef CONFIG_INTEL_WIDI
9976         //process_intel_widi_query_or_tigger(padapter, bssid);
9977         if(process_intel_widi_query_or_tigger(padapter, bssid))
9978         {
9979                 return _FAIL;
9980         }
9981 #endif // CONFIG_INTEL_WIDI
9982
9983         #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1
9984         if(strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
9985                 DBG_871X("Receiving %s("MAC_FMT", DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n"
9986                         , bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig
9987                         , rtw_get_oper_ch(padapter)
9988                         , bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi
9989                 );
9990         }
9991         #endif
9992
9993         // mark bss info receving from nearby channel as SignalQuality 101
9994         if(bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
9995         {
9996                 bssid->PhyInfo.SignalQuality= 101;
9997         }
9998
9999         return _SUCCESS;
10000 }
10001
10002 void start_create_ibss(_adapter* padapter)
10003 {
10004         unsigned short  caps;
10005         u8      val8;
10006         u8      join_type;
10007         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10008         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10009         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
10010         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
10011         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
10012
10013         //update wireless mode
10014         update_wireless_mode(padapter);
10015
10016         //udpate capability
10017         caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);
10018         update_capinfo(padapter, caps);
10019         if(caps&cap_IBSS)//adhoc master
10020         {
10021                 //set_opmode_cmd(padapter, adhoc);//removed
10022
10023                 val8 = 0xcf;
10024                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
10025
10026                 rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
10027
10028                 //switch channel
10029                 //SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE);
10030                 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
10031
10032                 beacon_timing_control(padapter);
10033
10034                 //set msr to WIFI_FW_ADHOC_STATE
10035                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
10036                 Set_MSR(padapter, (pmlmeinfo->state & 0x3));
10037
10038                 //issue beacon
10039                 if(send_beacon(padapter)==_FAIL)
10040                 {
10041                         RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("issuing beacon frame fail....\n"));
10042
10043                         report_join_res(padapter, -1);
10044                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
10045                 }
10046                 else
10047                 {
10048                         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
10049                         join_type = 0;
10050                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
10051
10052                         report_join_res(padapter, 1);
10053                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
10054                         rtw_indicate_connect(padapter);
10055                 }
10056         }
10057         else
10058         {
10059                 DBG_871X("start_create_ibss, invalid cap:%x\n", caps);
10060                 return;
10061         }
10062         //update bc/mc sta_info
10063         update_bmc_sta(padapter);
10064
10065 }
10066
10067 void start_clnt_join(_adapter* padapter)
10068 {
10069         unsigned short  caps;
10070         u8      val8;
10071         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10072         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10073         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
10074         int beacon_timeout;
10075
10076         //update wireless mode
10077         update_wireless_mode(padapter);
10078
10079         //udpate capability
10080         caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);
10081         update_capinfo(padapter, caps);
10082         if (caps&cap_ESS)
10083         {
10084                 Set_MSR(padapter, WIFI_FW_STATION_STATE);
10085
10086                 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
10087
10088 #ifdef CONFIG_WAPI_SUPPORT
10089                 if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI)
10090                 {
10091                         //Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey.
10092                         val8 = 0x4c;
10093                 }
10094 #endif
10095                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
10096
10097                 #ifdef CONFIG_DEAUTH_BEFORE_CONNECT
10098                 // Because of AP's not receiving deauth before
10099                 // AP may: 1)not response auth or 2)deauth us after link is complete
10100                 // issue deauth before issuing auth to deal with the situation
10101
10102                 //      Commented by Albert 2012/07/21
10103                 //      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it.
10104                 {
10105                         #ifdef CONFIG_P2P
10106                         _queue *queue = &(padapter->mlmepriv.scanned_queue);
10107                         _list   *head = get_list_head(queue);
10108                         _list *pos = get_next(head);
10109                         struct wlan_network *scanned = NULL;
10110                         u8 ie_offset = 0;
10111                         _irqL irqL;
10112                         bool has_p2p_ie = _FALSE;
10113
10114                         _enter_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL);
10115
10116                         for (pos = get_next(head);!rtw_end_of_queue_search(head, pos); pos = get_next(pos)) {
10117                                 
10118                                 scanned = LIST_CONTAINOR(pos, struct wlan_network, list);
10119                                 if(scanned==NULL)
10120                                         rtw_warn_on(1);
10121
10122                                 if (_rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE
10123                                         && _rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE
10124                                 ) {
10125                                         ie_offset = (scanned->network.Reserved[0] == 2? 0:12);
10126                                         if (rtw_get_p2p_ie(scanned->network.IEs+ie_offset, scanned->network.IELength-ie_offset, NULL, NULL))
10127                                                 has_p2p_ie = _TRUE;
10128                                         break;
10129                                 }
10130                         }
10131         
10132                         _exit_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL);
10133
10134                         if (scanned == NULL || rtw_end_of_queue_search(head, pos) || has_p2p_ie == _FALSE)
10135                         #endif /* CONFIG_P2P */
10136                                 //To avoid connecting to AP fail during resume process, change retry count from 5 to 1
10137                                 issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
10138                 }
10139                 #endif /* CONFIG_DEAUTH_BEFORE_CONNECT */
10140
10141                 //here wait for receiving the beacon to start auth
10142                 //and enable a timer
10143                 beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
10144                 set_link_timer(pmlmeext, beacon_timeout);       
10145                 _set_timer( &padapter->mlmepriv.assoc_timer, 
10146                         (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) +beacon_timeout);
10147                 
10148                 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
10149         }
10150         else if (caps&cap_IBSS) //adhoc client
10151         {
10152                 Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
10153
10154                 val8 = 0xcf;
10155                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
10156
10157                 beacon_timing_control(padapter);
10158
10159                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
10160
10161                 report_join_res(padapter, 1);
10162         }
10163         else
10164         {
10165                 //DBG_871X("marc: invalid cap:%x\n", caps);
10166                 return;
10167         }
10168
10169 }
10170
10171 void start_clnt_auth(_adapter* padapter)
10172 {
10173         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10174         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10175
10176         _cancel_timer_ex(&pmlmeext->link_timer);
10177
10178         pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
10179         pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
10180
10181         pmlmeinfo->auth_seq = 1;
10182         pmlmeinfo->reauth_count = 0;
10183         pmlmeinfo->reassoc_count = 0;
10184         pmlmeinfo->link_count = 0;
10185         pmlmeext->retry = 0;
10186
10187
10188         DBG_871X_LEVEL(_drv_always_, "start auth\n");
10189         issue_auth(padapter, NULL, 0);
10190
10191         set_link_timer(pmlmeext, REAUTH_TO);
10192
10193 }
10194
10195
10196 void start_clnt_assoc(_adapter* padapter)
10197 {
10198         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10199         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10200
10201         _cancel_timer_ex(&pmlmeext->link_timer);
10202
10203         pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
10204         pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
10205
10206         issue_assocreq(padapter);
10207
10208         set_link_timer(pmlmeext, REASSOC_TO);
10209 }
10210
10211 unsigned int receive_disconnect(_adapter *padapter, unsigned char *MacAddr, unsigned short reason)
10212 {
10213         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10214         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10215
10216         //check A3
10217         if (!(_rtw_memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
10218                 return _SUCCESS;
10219
10220         DBG_871X("%s\n", __FUNCTION__);
10221
10222         if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
10223         {
10224                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
10225                 {
10226                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
10227                         report_del_sta_event(padapter, MacAddr, reason);
10228
10229                 }
10230                 else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE)
10231                 {
10232                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
10233                         report_join_res(padapter, -2);
10234                 }
10235         }
10236
10237         return _SUCCESS;
10238 }
10239
10240 #ifdef CONFIG_80211D
10241 static void process_80211d(PADAPTER padapter, WLAN_BSSID_EX *bssid)
10242 {
10243         struct registry_priv *pregistrypriv;
10244         struct mlme_ext_priv *pmlmeext;
10245         RT_CHANNEL_INFO *chplan_new;
10246         u8 channel;
10247         u8 i;
10248
10249
10250         pregistrypriv = &padapter->registrypriv;
10251         pmlmeext = &padapter->mlmeextpriv;
10252
10253         // Adjust channel plan by AP Country IE
10254         if (pregistrypriv->enable80211d &&
10255                 (!pmlmeext->update_channel_plan_by_ap_done))
10256         {
10257                 u8 *ie, *p;
10258                 u32 len;
10259                 RT_CHANNEL_PLAN chplan_ap;
10260                 RT_CHANNEL_INFO chplan_sta[MAX_CHANNEL_NUM];
10261                 u8 country[4];
10262                 u8 fcn; // first channel number
10263                 u8 noc; // number of channel
10264                 u8 j, k;
10265
10266                 ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
10267                 if (!ie) return;
10268                 if (len < 6) return;
10269
10270                 ie += 2;
10271                 p = ie;
10272                 ie += len;
10273
10274                 _rtw_memset(country, 0, 4);
10275                 _rtw_memcpy(country, p, 3);
10276                 p += 3;
10277                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
10278                                 ("%s: 802.11d country=%s\n", __FUNCTION__, country));
10279
10280                 i = 0;
10281                 while ((ie - p) >= 3)
10282                 {
10283                         fcn = *(p++);
10284                         noc = *(p++);
10285                         p++;
10286
10287                         for (j = 0; j < noc; j++)
10288                         {
10289                                 if (fcn <= 14) channel = fcn + j; // 2.4 GHz
10290                                 else channel = fcn + j*4; // 5 GHz
10291
10292                                 chplan_ap.Channel[i++] = channel;
10293                         }
10294                 }
10295                 chplan_ap.Len = i;
10296
10297 #ifdef CONFIG_DEBUG_RTL871X
10298                 i = 0;
10299                 DBG_871X("%s: AP[%s] channel plan {", __FUNCTION__, bssid->Ssid.Ssid);
10300                 while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0))
10301                 {
10302                         DBG_8192C("%02d,", chplan_ap.Channel[i]);
10303                         i++;
10304                 }
10305                 DBG_871X("}\n");
10306 #endif
10307
10308                 _rtw_memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
10309 #ifdef CONFIG_DEBUG_RTL871X
10310                 i = 0;
10311                 DBG_871X("%s: STA channel plan {", __FUNCTION__);
10312                 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0))
10313                 {
10314                         DBG_871X("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType==SCAN_PASSIVE?'p':'a');
10315                         i++;
10316                 }
10317                 DBG_871X("}\n");
10318 #endif
10319
10320                 _rtw_memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
10321                 chplan_new = pmlmeext->channel_set;
10322
10323                 i = j = k = 0;
10324                 if (pregistrypriv->wireless_mode & WIRELESS_11G)
10325                 {
10326                         do {
10327                                 if ((i == MAX_CHANNEL_NUM) ||
10328                                         (chplan_sta[i].ChannelNum == 0) ||
10329                                         (chplan_sta[i].ChannelNum > 14))
10330                                         break;
10331
10332                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
10333                                         break;
10334
10335                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j])
10336                                 {
10337                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10338                                         chplan_new[k].ScanType = SCAN_ACTIVE;
10339                                         i++;
10340                                         j++;
10341                                         k++;
10342                                 }
10343                                 else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j])
10344                                 {
10345                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10346 //                                      chplan_new[k].ScanType = chplan_sta[i].ScanType;
10347                                         chplan_new[k].ScanType = SCAN_PASSIVE;
10348                                         i++;
10349                                         k++;
10350                                 }
10351                                 else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j])
10352                                 {
10353                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10354                                         chplan_new[k].ScanType = SCAN_ACTIVE;
10355                                         j++;
10356                                         k++;
10357                                 }
10358                         } while (1);
10359
10360                         // change AP not support channel to Passive scan
10361                         while ((i < MAX_CHANNEL_NUM) &&
10362                                 (chplan_sta[i].ChannelNum != 0) &&
10363                                 (chplan_sta[i].ChannelNum <= 14))
10364                         {
10365                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10366 //                              chplan_new[k].ScanType = chplan_sta[i].ScanType;
10367                                 chplan_new[k].ScanType = SCAN_PASSIVE;
10368                                 i++;
10369                                 k++;
10370                         }
10371
10372                         // add channel AP supported
10373                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
10374                         {
10375                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10376                                 chplan_new[k].ScanType = SCAN_ACTIVE;
10377                                 j++;
10378                                 k++;
10379                         }
10380                 }
10381                 else
10382                 {
10383                         // keep original STA 2.4G channel plan
10384                         while ((i < MAX_CHANNEL_NUM) &&
10385                                 (chplan_sta[i].ChannelNum != 0) &&
10386                                 (chplan_sta[i].ChannelNum <= 14))
10387                         {
10388                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10389                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
10390                                 i++;
10391                                 k++;
10392                         }
10393
10394                         // skip AP 2.4G channel plan
10395                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
10396                         {
10397                                 j++;
10398                         }
10399                 }
10400
10401                 if (pregistrypriv->wireless_mode & WIRELESS_11A)
10402                 {
10403                         do {
10404                                 if ((i == MAX_CHANNEL_NUM) ||
10405                                         (chplan_sta[i].ChannelNum == 0))
10406                                         break;
10407
10408                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
10409                                         break;
10410
10411                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j])
10412                                 {
10413                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10414                                         chplan_new[k].ScanType = SCAN_ACTIVE;
10415                                         i++;
10416                                         j++;
10417                                         k++;
10418                                 }
10419                                 else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j])
10420                                 {
10421                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10422 //                                      chplan_new[k].ScanType = chplan_sta[i].ScanType;
10423                                         chplan_new[k].ScanType = SCAN_PASSIVE;
10424                                         i++;
10425                                         k++;
10426                                 }
10427                                 else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j])
10428                                 {
10429                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10430                                         chplan_new[k].ScanType = SCAN_ACTIVE;
10431                                         j++;
10432                                         k++;
10433                                 }
10434                         } while (1);
10435
10436                         // change AP not support channel to Passive scan
10437                         while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0))
10438                         {
10439                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10440 //                              chplan_new[k].ScanType = chplan_sta[i].ScanType;
10441                                 chplan_new[k].ScanType = SCAN_PASSIVE;
10442                                 i++;
10443                                 k++;
10444                         }
10445
10446                         // add channel AP supported
10447                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0))
10448                         {
10449                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
10450                                 chplan_new[k].ScanType = SCAN_ACTIVE;
10451                                 j++;
10452                                 k++;
10453                         }
10454                 }
10455                 else
10456                 {
10457                         // keep original STA 5G channel plan
10458                         while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0))
10459                         {
10460                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
10461                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
10462                                 i++;
10463                                 k++;
10464                         }
10465                 }
10466
10467                 pmlmeext->update_channel_plan_by_ap_done = 1;
10468
10469 #ifdef CONFIG_DEBUG_RTL871X
10470                 k = 0;
10471                 DBG_871X("%s: new STA channel plan {", __FUNCTION__);
10472                 while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0))
10473                 {
10474                         DBG_871X("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType==SCAN_PASSIVE?'p':'c');
10475                         k++;
10476                 }
10477                 DBG_871X("}\n");
10478 #endif
10479
10480 #if 0
10481                 // recover the right channel index
10482                 channel = chplan_sta[pmlmeext->sitesurvey_res.channel_idx].ChannelNum;
10483                 k = 0;
10484                 while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0))
10485                 {
10486                         if (chplan_new[k].ChannelNum == channel) {
10487                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
10488                                                  ("%s: change mlme_ext sitesurvey channel index from %d to %d\n",
10489                                                   __FUNCTION__, pmlmeext->sitesurvey_res.channel_idx, k));
10490                                 pmlmeext->sitesurvey_res.channel_idx = k;
10491                                 break;
10492                         }
10493                         k++;
10494                 }
10495 #endif
10496         }
10497
10498         // If channel is used by AP, set channel scan type to active
10499         channel = bssid->Configuration.DSConfig;
10500         chplan_new = pmlmeext->channel_set;
10501         i = 0;
10502         while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0))
10503         {
10504                 if (chplan_new[i].ChannelNum == channel)
10505                 {
10506                         if (chplan_new[i].ScanType == SCAN_PASSIVE)
10507                         {
10508                                 //5G Bnad 2, 3 (DFS) doesn't change to active scan
10509                                 if(channel >= 52 && channel <= 144)
10510                                         break;
10511                                 
10512                                 chplan_new[i].ScanType = SCAN_ACTIVE;
10513                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
10514                                                  ("%s: change channel %d scan type from passive to active\n",
10515                                                   __FUNCTION__, channel));
10516                         }
10517                         break;
10518                 }
10519                 i++;
10520         }
10521 }
10522 #endif
10523
10524 /****************************************************************************
10525
10526 Following are the functions to report events
10527
10528 *****************************************************************************/
10529
10530 void report_survey_event(_adapter *padapter, union recv_frame *precv_frame)
10531 {
10532         struct cmd_obj *pcmd_obj;
10533         u8      *pevtcmd;
10534         u32 cmdsz;
10535         struct survey_event     *psurvey_evt;
10536         struct C2HEvent_Header *pc2h_evt_hdr;
10537         struct mlme_ext_priv *pmlmeext;
10538         struct cmd_priv *pcmdpriv;
10539         //u8 *pframe = precv_frame->u.hdr.rx_data;
10540         //uint len = precv_frame->u.hdr.len;
10541
10542         if(!padapter)
10543                 return;
10544
10545         pmlmeext = &padapter->mlmeextpriv;
10546         pcmdpriv = &padapter->cmdpriv;
10547         
10548
10549         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10550         {
10551                 return;
10552         }
10553
10554         cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
10555         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
10556         {
10557                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10558                 return;
10559         }
10560
10561         _rtw_init_listhead(&pcmd_obj->list);
10562
10563         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
10564         pcmd_obj->cmdsz = cmdsz;
10565         pcmd_obj->parmbuf = pevtcmd;
10566
10567         pcmd_obj->rsp = NULL;
10568         pcmd_obj->rspsz  = 0;
10569
10570         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
10571         pc2h_evt_hdr->len = sizeof(struct survey_event);
10572         pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
10573         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
10574
10575         psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
10576
10577         if (collect_bss_info(padapter, precv_frame, (WLAN_BSSID_EX *)&psurvey_evt->bss) == _FAIL)
10578         {
10579                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10580                 rtw_mfree((u8 *)pevtcmd, cmdsz);
10581                 return;
10582         }
10583
10584 #ifdef CONFIG_80211D
10585         process_80211d(padapter, &psurvey_evt->bss);
10586 #endif
10587
10588         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
10589
10590         pmlmeext->sitesurvey_res.bss_cnt++;
10591
10592         return;
10593
10594 }
10595
10596 void report_surveydone_event(_adapter *padapter)
10597 {
10598         struct cmd_obj *pcmd_obj;
10599         u8      *pevtcmd;
10600         u32 cmdsz;
10601         struct surveydone_event *psurveydone_evt;
10602         struct C2HEvent_Header  *pc2h_evt_hdr;
10603         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
10604         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
10605
10606         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10607         {
10608                 return;
10609         }
10610
10611         cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
10612         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
10613         {
10614                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10615                 return;
10616         }
10617
10618         _rtw_init_listhead(&pcmd_obj->list);
10619
10620         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
10621         pcmd_obj->cmdsz = cmdsz;
10622         pcmd_obj->parmbuf = pevtcmd;
10623
10624         pcmd_obj->rsp = NULL;
10625         pcmd_obj->rspsz  = 0;
10626
10627         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
10628         pc2h_evt_hdr->len = sizeof(struct surveydone_event);
10629         pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
10630         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
10631
10632         psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
10633         psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
10634
10635         DBG_871X("survey done event(%x) band:%d for "ADPT_FMT"\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter));
10636
10637         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
10638
10639         return;
10640
10641 }
10642
10643 void report_join_res(_adapter *padapter, int res)
10644 {
10645         struct cmd_obj *pcmd_obj;
10646         u8      *pevtcmd;
10647         u32 cmdsz;
10648         struct joinbss_event            *pjoinbss_evt;
10649         struct C2HEvent_Header  *pc2h_evt_hdr;
10650         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
10651         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10652         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
10653
10654         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10655         {
10656                 return;
10657         }
10658
10659         cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
10660         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
10661         {
10662                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10663                 return;
10664         }
10665
10666         _rtw_init_listhead(&pcmd_obj->list);
10667
10668         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
10669         pcmd_obj->cmdsz = cmdsz;
10670         pcmd_obj->parmbuf = pevtcmd;
10671
10672         pcmd_obj->rsp = NULL;
10673         pcmd_obj->rspsz  = 0;
10674
10675         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
10676         pc2h_evt_hdr->len = sizeof(struct joinbss_event);
10677         pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
10678         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
10679
10680         pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
10681         _rtw_memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));
10682         pjoinbss_evt->network.join_res  = pjoinbss_evt->network.aid = res;
10683
10684         DBG_871X("report_join_res(%d)\n", res);
10685         
10686         
10687         rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
10688         
10689         
10690         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
10691
10692         return;
10693
10694 }
10695
10696 void report_del_sta_event(_adapter *padapter, unsigned char* MacAddr, unsigned short reason)
10697 {
10698         struct cmd_obj *pcmd_obj;
10699         u8      *pevtcmd;
10700         u32 cmdsz;
10701         struct sta_info *psta;
10702         int     mac_id;
10703         struct stadel_event                     *pdel_sta_evt;
10704         struct C2HEvent_Header  *pc2h_evt_hdr;
10705         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
10706         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
10707
10708         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10709         {
10710                 return;
10711         }
10712
10713         cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
10714         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
10715         {
10716                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10717                 return;
10718         }
10719
10720         _rtw_init_listhead(&pcmd_obj->list);
10721
10722         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
10723         pcmd_obj->cmdsz = cmdsz;
10724         pcmd_obj->parmbuf = pevtcmd;
10725
10726         pcmd_obj->rsp = NULL;
10727         pcmd_obj->rspsz  = 0;
10728
10729         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
10730         pc2h_evt_hdr->len = sizeof(struct stadel_event);
10731         pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
10732         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
10733
10734         pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
10735         _rtw_memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
10736         _rtw_memcpy((unsigned char *)(pdel_sta_evt->rsvd),(unsigned char *)(&reason),2);
10737
10738
10739         psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
10740         if(psta)
10741                 mac_id = (int)psta->mac_id;     
10742         else
10743                 mac_id = (-1);
10744
10745         pdel_sta_evt->mac_id = mac_id;
10746
10747         DBG_871X("report_del_sta_event: delete STA, mac_id=%d\n", mac_id);
10748
10749         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
10750
10751         return;
10752 }
10753
10754 void report_add_sta_event(_adapter *padapter, unsigned char* MacAddr, int cam_idx)
10755 {
10756         struct cmd_obj *pcmd_obj;
10757         u8      *pevtcmd;
10758         u32 cmdsz;
10759         struct stassoc_event            *padd_sta_evt;
10760         struct C2HEvent_Header  *pc2h_evt_hdr;
10761         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
10762         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
10763
10764         if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
10765         {
10766                 return;
10767         }
10768
10769         cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
10770         if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
10771         {
10772                 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
10773                 return;
10774         }
10775
10776         _rtw_init_listhead(&pcmd_obj->list);
10777
10778         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
10779         pcmd_obj->cmdsz = cmdsz;
10780         pcmd_obj->parmbuf = pevtcmd;
10781
10782         pcmd_obj->rsp = NULL;
10783         pcmd_obj->rspsz  = 0;
10784
10785         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
10786         pc2h_evt_hdr->len = sizeof(struct stassoc_event);
10787         pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
10788         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
10789
10790         padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
10791         _rtw_memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
10792         padd_sta_evt->cam_id = cam_idx;
10793
10794         DBG_871X("report_add_sta_event: add STA\n");
10795
10796         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
10797
10798         return;
10799 }
10800
10801
10802 bool rtw_port_switch_chk(_adapter *adapter)
10803 {
10804         bool switch_needed = _FALSE;
10805 #ifdef CONFIG_CONCURRENT_MODE
10806 #ifdef CONFIG_RUNTIME_PORT_SWITCH
10807         struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
10808         struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(dvobj);
10809         _adapter *if_port0 = NULL;
10810         _adapter *if_port1 = NULL;
10811         struct mlme_ext_info *if_port0_mlmeinfo = NULL;
10812         struct mlme_ext_info *if_port1_mlmeinfo = NULL;
10813         int i;
10814
10815         for (i = 0; i < dvobj->iface_nums; i++) {
10816                 if (get_iface_type(dvobj->padapters[i]) == IFACE_PORT0) {
10817                         if_port0 = dvobj->padapters[i];
10818                         if_port0_mlmeinfo = &(if_port0->mlmeextpriv.mlmext_info);
10819                 }
10820                 else if (get_iface_type(dvobj->padapters[i]) == IFACE_PORT1) {
10821                         if_port1 = dvobj->padapters[i];
10822                         if_port1_mlmeinfo = &(if_port1->mlmeextpriv.mlmext_info);
10823                 }
10824         }
10825
10826         if (if_port0 == NULL) {
10827                 rtw_warn_on(1);
10828                 goto exit;
10829         }
10830
10831         if (if_port1 == NULL) {
10832                 rtw_warn_on(1);
10833                 goto exit;
10834         }
10835
10836 #ifdef DBG_RUNTIME_PORT_SWITCH
10837         DBG_871X(FUNC_ADPT_FMT" wowlan_mode:%u\n"
10838                 ADPT_FMT", port0, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n"
10839                 ADPT_FMT", port1, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n",
10840                 FUNC_ADPT_ARG(adapter), pwrctl->wowlan_mode,
10841                 ADPT_ARG(if_port0), if_port0_mlmeinfo->state, rtw_p2p_state(&if_port0->wdinfo), rtw_p2p_chk_state(&if_port0->wdinfo, P2P_STATE_NONE),
10842                 ADPT_ARG(if_port1), if_port1_mlmeinfo->state, rtw_p2p_state(&if_port1->wdinfo), rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE));
10843 #endif /* DBG_RUNTIME_PORT_SWITCH */
10844
10845 #ifdef CONFIG_WOWLAN
10846         /* WOWLAN interface(primary, for now) should be port0 */
10847         if (pwrctl->wowlan_mode == _TRUE) {
10848                 if(!is_primary_adapter(if_port0)) {
10849                         DBG_871X("%s "ADPT_FMT" enable WOWLAN\n", __func__, ADPT_ARG(if_port1));
10850                         switch_needed = _TRUE;
10851                 }
10852                 goto exit;
10853         }
10854 #endif /* CONFIG_WOWLAN */
10855
10856         /* AP should use port0 for ctl frame's ack */
10857         if ((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
10858                 DBG_871X("%s "ADPT_FMT" is AP/GO\n", __func__, ADPT_ARG(if_port1));
10859                 switch_needed = _TRUE;
10860                 goto exit;
10861         }
10862
10863         /* GC should use port0 for p2p ps */    
10864         if (((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
10865                 && (if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
10866                 && !rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE)
10867                 && !check_fwstate(&if_port1->mlmepriv, WIFI_UNDER_WPS)
10868         ) {
10869                 DBG_871X("%s "ADPT_FMT" is GC\n", __func__, ADPT_ARG(if_port1));
10870                 switch_needed = _TRUE;
10871                 goto exit;
10872         }
10873
10874         /* port1 linked, but port0 not linked */
10875         if ((if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
10876                 && !(if_port0_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
10877                 && ((if_port0_mlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
10878         ) {
10879                 DBG_871X("%s "ADPT_FMT" is SINGLE_LINK\n", __func__, ADPT_ARG(if_port1));
10880                 switch_needed = _TRUE;
10881                 goto exit;
10882         }
10883
10884 exit:
10885 #ifdef DBG_RUNTIME_PORT_SWITCH
10886         DBG_871X(FUNC_ADPT_FMT" ret:%d\n", FUNC_ADPT_ARG(adapter), switch_needed);
10887 #endif /* DBG_RUNTIME_PORT_SWITCH */
10888 #endif /* CONFIG_RUNTIME_PORT_SWITCH */
10889 #endif /* CONFIG_CONCURRENT_MODE */
10890         return switch_needed;
10891 }
10892
10893 /****************************************************************************
10894
10895 Following are the event callback functions
10896
10897 *****************************************************************************/
10898
10899 //for sta/adhoc mode
10900 void update_sta_info(_adapter *padapter, struct sta_info *psta)
10901 {
10902         _irqL   irqL;
10903         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
10904         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10905         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10906
10907         //ERP
10908         VCS_update(padapter, psta);
10909
10910 #ifdef CONFIG_80211N_HT
10911         //HT
10912         if(pmlmepriv->htpriv.ht_option)
10913         {
10914                 psta->htpriv.ht_option = _TRUE;
10915
10916                 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
10917
10918                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))
10919                         psta->htpriv.sgi_20m = _TRUE;
10920
10921                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))
10922                         psta->htpriv.sgi_40m = _TRUE;
10923
10924                 psta->qos_option = _TRUE;
10925
10926                 psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;
10927                 psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;
10928                 psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
10929
10930                 _rtw_memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct rtw_ieee80211_ht_cap));
10931         }
10932         else
10933 #endif //CONFIG_80211N_HT
10934         {
10935 #ifdef CONFIG_80211N_HT
10936                 psta->htpriv.ht_option = _FALSE;
10937
10938                 psta->htpriv.ampdu_enable = _FALSE;
10939                 
10940                 psta->htpriv.sgi_20m = _FALSE;
10941                 psta->htpriv.sgi_40m = _FALSE;
10942 #endif //CONFIG_80211N_HT
10943                 psta->qos_option = _FALSE;
10944
10945         }
10946
10947 #ifdef CONFIG_80211N_HT
10948         psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
10949         
10950         psta->htpriv.agg_enable_bitmap = 0x0;//reset
10951         psta->htpriv.candidate_tid_bitmap = 0x0;//reset
10952 #endif //CONFIG_80211N_HT
10953
10954         psta->bw_mode = pmlmeext->cur_bwmode;
10955
10956         //QoS
10957         if(pmlmepriv->qospriv.qos_option)
10958                 psta->qos_option = _TRUE;
10959
10960 #ifdef CONFIG_80211AC_VHT
10961         _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));
10962 #endif //CONFIG_80211AC_VHT
10963
10964         update_ldpc_stbc_cap(psta);
10965
10966         _enter_critical_bh(&psta->lock, &irqL);
10967         psta->state = _FW_LINKED;
10968         _exit_critical_bh(&psta->lock, &irqL);
10969
10970 }
10971
10972 static void rtw_mlmeext_disconnect(_adapter *padapter)
10973 {
10974         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
10975         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
10976         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
10977         u8 state_backup = (pmlmeinfo->state&0x03);
10978
10979         //set_opmode_cmd(padapter, infra_client_with_mlme);
10980
10981         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
10982         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
10983
10984         //set MSR to no link state -> infra. mode
10985         Set_MSR(padapter, _HW_STATE_STATION_);
10986
10987         pmlmeinfo->state = WIFI_FW_NULL_STATE;
10988
10989         if(state_backup == WIFI_FW_STATION_STATE)
10990         {
10991                 if (rtw_port_switch_chk(padapter) == _TRUE) {
10992                         rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
10993                         #ifdef CONFIG_LPS
10994                         {
10995                                 _adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
10996                                 if (port0_iface)
10997                                         rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
10998                         }
10999                         #endif
11000                 }
11001         }
11002
11003 #ifdef CONFIG_DUALMAC_CONCURRENT
11004         dc_set_channel_bwmode_disconnect(padapter);
11005 #else //!CONFIG_DUALMAC_CONCURRENT
11006 #ifdef CONFIG_CONCURRENT_MODE
11007         if((check_buddy_fwstate(padapter, _FW_LINKED)) != _TRUE)
11008         {
11009 #endif //CONFIG_CONCURRENT_MODE
11010                 //switch to the 20M Hz mode after disconnect
11011                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
11012                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
11013
11014                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
11015 #ifdef CONFIG_CONCURRENT_MODE
11016         }
11017 #endif //CONFIG_CONCURRENT_MODE
11018 #ifdef CONFIG_FCS_MODE
11019         else
11020         {
11021                 PADAPTER pbuddy_adapter;        
11022                 struct mlme_ext_priv *pbuddy_mlmeext;
11023
11024                 if(EN_FCS(padapter))
11025                 {                       
11026                         pbuddy_adapter = padapter->pbuddy_adapter;
11027                         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
11028                 
11029                         rtw_hal_set_hwreg(padapter, HW_VAR_STOP_FCS_MODE, NULL);
11030
11031                         //switch to buddy's channel setting if buddy is linked
11032                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
11033                 }       
11034         }
11035 #endif //!CONFIG_FCS_MODE
11036 #endif //!CONFIG_DUALMAC_CONCURRENT
11037
11038
11039         flush_all_cam_entry(padapter);
11040
11041         _cancel_timer_ex(&pmlmeext->link_timer);
11042
11043         //pmlmepriv->LinkDetectInfo.TrafficBusyState = _FALSE;
11044         pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
11045         pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
11046
11047 }
11048
11049 void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res)
11050 {
11051         struct sta_info         *psta, *psta_bmc;
11052         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11053         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11054         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
11055         struct sta_priv         *pstapriv = &padapter->stapriv;
11056         u8      join_type;
11057
11058         if(join_res < 0)
11059         {
11060                 join_type = 1;
11061                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
11062                 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
11063
11064                 goto exit_mlmeext_joinbss_event_callback;
11065         }
11066
11067         if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
11068         {
11069                 //update bc/mc sta_info
11070                 update_bmc_sta(padapter);
11071         }
11072
11073
11074         //turn on dynamic functions
11075         Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);
11076
11077         // update IOT-releated issue
11078         update_IOT_info(padapter);
11079
11080         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
11081
11082         //BCN interval
11083         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
11084
11085         //udpate capability
11086         update_capinfo(padapter, pmlmeinfo->capability);
11087
11088         //WMM, Update EDCA param
11089         WMMOnAssocRsp(padapter);
11090
11091         //HT
11092         HTOnAssocRsp(padapter);
11093
11094 #ifdef CONFIG_80211AC_VHT
11095         //VHT
11096         VHTOnAssocRsp(padapter);
11097 #endif
11098
11099 #ifndef CONFIG_CONCURRENT_MODE
11100         //      Call set_channel_bwmode when the CONFIG_CONCURRENT_MODE doesn't be defined.
11101         //Set cur_channel&cur_bwmode&cur_ch_offset
11102         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
11103 #endif
11104
11105         psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
11106         if (psta) //only for infra. mode
11107         {
11108                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
11109
11110                 //DBG_871X("set_sta_rate\n");
11111
11112                 psta->wireless_mode = pmlmeext->cur_wireless_mode;
11113         
11114                 //set per sta rate after updating HT cap.
11115                 set_sta_rate(padapter, psta);
11116                 
11117                 rtw_sta_media_status_rpt(padapter, psta, 1);
11118         }
11119
11120         if (rtw_port_switch_chk(padapter) == _TRUE)
11121                 rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
11122
11123         join_type = 2;
11124         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
11125
11126         if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
11127         {
11128                 // correcting TSF
11129                 correct_TSF(padapter, pmlmeext);
11130         
11131                 //set_link_timer(pmlmeext, DISCONNECT_TO);
11132         }
11133
11134 #ifdef CONFIG_LPS
11135         if(get_iface_type(padapter) == IFACE_PORT0)
11136                 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
11137 #endif
11138
11139 #ifdef CONFIG_BEAMFORMING
11140         if (psta)
11141                 beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_ENTER, (u8 *)psta, sizeof(struct sta_info), 0);
11142 #endif
11143
11144 exit_mlmeext_joinbss_event_callback:
11145
11146 #ifdef CONFIG_DUALMAC_CONCURRENT
11147         dc_handle_join_done(padapter, join_res);
11148 #endif
11149 #ifdef CONFIG_CONCURRENT_MODE
11150         concurrent_chk_joinbss_done(padapter, join_res);
11151 #endif
11152
11153         DBG_871X("=>%s\n", __FUNCTION__);
11154
11155 }
11156
11157 //currently only adhoc mode will go here
11158 void mlmeext_sta_add_event_callback(_adapter *padapter, struct sta_info *psta)
11159 {
11160         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
11161         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11162         u8      join_type;
11163
11164         DBG_871X("%s\n", __FUNCTION__);
11165
11166         if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
11167         {
11168                 if(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)//adhoc master or sta_count>1
11169                 {
11170                         //nothing to do
11171                 }
11172                 else//adhoc client
11173                 {
11174                         //update TSF Value
11175                         //update_TSF(pmlmeext, pframe, len);                    
11176
11177                         // correcting TSF
11178                         correct_TSF(padapter, pmlmeext);
11179
11180                         //start beacon
11181                         if(send_beacon(padapter)==_FAIL)
11182                         {
11183                                 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
11184
11185                                 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
11186
11187                                 return;
11188                         }
11189
11190                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
11191                                 
11192                 }
11193
11194                 join_type = 2;
11195                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
11196         }
11197
11198         pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
11199
11200         psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates);
11201         _rtw_memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen);
11202
11203         //update adhoc sta_info
11204         update_sta_info(padapter, psta);
11205
11206         rtw_hal_update_sta_rate_mask(padapter, psta);
11207
11208         // ToDo: HT for Ad-hoc 
11209         psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);
11210         psta->raid = rtw_hal_networktype_to_raid(padapter, psta);
11211
11212         //rate radaptive
11213         Update_RA_Entry(padapter, psta);
11214 }
11215
11216 void mlmeext_sta_del_event_callback(_adapter *padapter)
11217 {
11218         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11219         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11220
11221         if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
11222         {
11223                 rtw_mlmeext_disconnect(padapter);
11224         }
11225
11226 }
11227
11228 /****************************************************************************
11229
11230 Following are the functions for the timer handlers
11231
11232 *****************************************************************************/
11233 void _linked_info_dump(_adapter *padapter)
11234 {
11235         int i;
11236         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11237       struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11238         u8 mac_id;
11239         int UndecoratedSmoothedPWDB;
11240         struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
11241         
11242         if(padapter->bLinkInfoDump){
11243
11244                 DBG_871X("\n============["ADPT_FMT"] linked status check ===================\n",ADPT_ARG(padapter));    
11245
11246                 if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
11247                 {
11248                         rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);      
11249                 
11250                         DBG_871X("AP[" MAC_FMT "] - UndecoratedSmoothedPWDB:%d\n",
11251                                 MAC_ARG(padapter->mlmepriv.cur_network.network.MacAddress),UndecoratedSmoothedPWDB);
11252                 }
11253                 else if((pmlmeinfo->state&0x03) == _HW_STATE_AP_)
11254                 {
11255                         _irqL irqL;
11256                         _list   *phead, *plist;
11257         
11258                         struct sta_info *psta=NULL;     
11259                         struct sta_priv *pstapriv = &padapter->stapriv;
11260                         
11261                         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);   
11262                         phead = &pstapriv->asoc_list;
11263                         plist = get_next(phead);
11264                         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
11265                         {
11266                                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
11267                                 plist = get_next(plist);                        
11268                                 
11269                                 DBG_871X("STA[" MAC_FMT "]:UndecoratedSmoothedPWDB:%d\n", 
11270                                         MAC_ARG(psta->hwaddr),psta->rssi_stat.UndecoratedSmoothedPWDB);
11271                         }
11272                         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);            
11273                         
11274                 }
11275                 for(i=0; i<NUM_STA; i++)
11276                 {
11277                         if(pdvobj->macid[i] == _TRUE)
11278                         {
11279                                 if(i !=1) //skip bc/mc sta
11280                                         //============  tx info ============    
11281                                         rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i);                 
11282                         }
11283                 }
11284                 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL);
11285                         
11286                 
11287         }
11288               
11289
11290 }
11291
11292 u8 chk_ap_is_alive(_adapter *padapter, struct sta_info *psta)
11293 {
11294         u8 ret = _FALSE;
11295         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11296         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11297
11298         #ifdef DBG_EXPIRATION_CHK
11299         DBG_871X(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"
11300                                 /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/
11301                                 ", retry:%u\n"
11302                 , FUNC_ADPT_ARG(padapter)
11303                 , STA_RX_PKTS_DIFF_ARG(psta)
11304                 , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts
11305                 , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts
11306                 /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts
11307                 , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts
11308                 , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts
11309                 , pmlmeinfo->bcn_interval*/
11310                 , pmlmeext->retry
11311         );
11312
11313         DBG_871X(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter)
11314                 , padapter->xmitpriv.tx_pkts
11315                 , pmlmeinfo->link_count
11316         );
11317         #endif
11318
11319         if((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
11320                 && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
11321                 && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
11322         )
11323         {
11324                 ret = _FALSE;
11325         }
11326         else
11327         {
11328                 ret = _TRUE;
11329         }
11330
11331         sta_update_last_rx_pkts(psta);
11332
11333         return ret;
11334 }
11335
11336 #ifdef CONFIG_TDLS
11337 void linked_status_chk_tdls(_adapter *padapter)
11338 {
11339 struct candidate_pool{
11340         struct sta_info *psta;
11341         u8 addr[ETH_ALEN];
11342 };
11343         struct sta_priv *pstapriv = &padapter->stapriv;
11344         _irqL irqL;
11345         u8 ack_chk;
11346         struct sta_info *psta;
11347         int i, num_teardown=0, num_checkalive=0;
11348         _list   *plist, *phead;
11349         struct tdls_txmgmt txmgmt;
11350         struct candidate_pool checkalive[NUM_STA];
11351         struct candidate_pool teardown[NUM_STA];
11352 #define ALIVE_MIN 2
11353 #define ALIVE_MAX 5
11354
11355         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
11356         _rtw_memset(checkalive, 0x00, sizeof(checkalive));
11357         _rtw_memset(teardown, 0x00, sizeof(teardown));
11358
11359         if((padapter->tdlsinfo.link_established == _TRUE)){
11360                 _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
11361                 for(i=0; i< NUM_STA; i++)
11362                 {
11363                         phead = &(pstapriv->sta_hash[i]);
11364                         plist = get_next(phead);
11365                         
11366                         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
11367                         {
11368                                 psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
11369                                 plist = get_next(plist);
11370
11371                                 if(psta->tdls_sta_state & TDLS_LINKED_STATE)
11372                                 {
11373                                         psta->alive_count++;
11374                                         if(psta->alive_count >= ALIVE_MIN)
11375                                         {
11376 #ifdef CONFIG_XMIT_ACK
11377                                                 if(psta->sta_stats.last_rx_data_pkts >= psta->sta_stats.rx_data_pkts)
11378 #else
11379                                                 if((psta->sta_stats.last_rx_data_pkts >= psta->sta_stats.rx_data_pkts) &&
11380                                                         (!(psta->tdls_sta_state & TDLS_ALIVE_STATE)) )
11381 #endif
11382                                                 {
11383                                                         if(psta->alive_count < ALIVE_MAX)
11384                                                         {
11385                                                                 _rtw_memcpy(checkalive[num_checkalive].addr, psta->hwaddr, ETH_ALEN);
11386                                                                 checkalive[num_checkalive].psta = psta;
11387                                                                 num_checkalive++;
11388                                                         }
11389                                                         else
11390                                                         {
11391                                                                 _rtw_memcpy(teardown[num_teardown].addr, psta->hwaddr, ETH_ALEN);
11392                                                                 teardown[num_teardown].psta = psta;
11393                                                                 num_teardown++;
11394                                                         }
11395                                                 }
11396                                                 else
11397                                                 {
11398                                                         psta->tdls_sta_state &= (~TDLS_ALIVE_STATE);
11399                                                         psta->alive_count = 0;
11400                                                 }
11401                                         }
11402                                         psta->sta_stats.last_rx_data_pkts = psta->sta_stats.rx_data_pkts;
11403                                 }
11404                         }
11405                 }
11406                 _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
11407
11408                 if(num_checkalive > 0)
11409                 {
11410                         for(i=0; i< num_checkalive; i++)
11411                         {
11412 #ifdef CONFIG_XMIT_ACK
11413                                 //TDLS: Should we set wait_ms to 300 for keeping alive?
11414                                 ack_chk = issue_nulldata_to_TDLS_peer_STA(padapter,     checkalive[i].addr, 0, 3, 300);
11415
11416                                 if(ack_chk == _SUCCESS)
11417                                 {
11418                                         checkalive[i].psta->alive_count = 0;
11419                                 }
11420 #else
11421                                 checkalive[i].psta->tdls_sta_state &= (~TDLS_ALIVE_STATE);
11422                                 _rtw_memcpy(txmgmt.peer, checkalive[i].addr, ETH_ALEN);
11423                                 issue_tdls_dis_req(padapter, &txmgmt);
11424                                 issue_tdls_dis_req(padapter, &txmgmt);
11425                                 issue_tdls_dis_req(padapter, &txmgmt);
11426 #endif //CONFIG_XMIT_ACK
11427                         }
11428                 }
11429
11430                 if(num_teardown > 0)
11431                 {
11432                         for(i=0; i< num_teardown; i++)
11433                         {
11434                                 DBG_871X("[%s %d] Send teardown to "MAC_FMT" \n", __FUNCTION__, __LINE__, MAC_ARG(teardown[i].addr));
11435                                 txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_;
11436                                 _rtw_memcpy(txmgmt.peer, teardown[i].addr, ETH_ALEN);
11437                                 issue_tdls_teardown(padapter, &txmgmt, _FALSE);
11438                         }
11439                 }
11440         }
11441
11442 }
11443 #endif //CONFIG_TDLS
11444
11445 void linked_status_chk(_adapter *padapter)
11446 {
11447         u32     i;
11448         struct sta_info         *psta;
11449         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
11450         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11451         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11452         struct sta_priv         *pstapriv = &padapter->stapriv;
11453         
11454
11455         if (is_client_associated_to_ap(padapter))
11456         {
11457                 //linked infrastructure client mode
11458
11459                 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
11460                 int rx_chk_limit;
11461                 int link_count_limit;
11462
11463                 #if defined(DBG_ROAMING_TEST)
11464                 rx_chk_limit = 1;
11465                 #elif defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && !defined(CONFIG_LPS_LCLK_WD_TIMER)
11466                 rx_chk_limit = 4;
11467                 #else
11468                 rx_chk_limit = 8;
11469                 #endif
11470 #ifdef CONFIG_P2P
11471                 if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE))
11472                         link_count_limit = 3; // 8 sec
11473                 else
11474 #endif // CONFIG_P2P
11475                         link_count_limit = 7; // 16 sec
11476
11477                 // Marked by Kurt 20130715
11478                 // 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.
11479                 // todo: To check why we under miracast session, rx_chk would be _FALSE
11480                 //#ifdef CONFIG_INTEL_WIDI
11481                 //if (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_NONE)
11482                 //      rx_chk_limit = 1;
11483                 //#endif
11484
11485                 if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
11486                 {
11487                         bool is_p2p_enable = _FALSE;
11488                         #ifdef CONFIG_P2P
11489                         is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
11490                         #endif
11491                         
11492                         if (chk_ap_is_alive(padapter, psta) == _FALSE)
11493                                 rx_chk = _FAIL;
11494
11495                         if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
11496                                 tx_chk = _FAIL;
11497
11498                         #if defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && !defined(CONFIG_LPS_LCLK_WD_TIMER)
11499                         if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
11500                                 u8 backup_oper_channel=0;
11501
11502                                 /* switch to correct channel of current network  before issue keep-alive frames */
11503                                 if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
11504                                         backup_oper_channel = rtw_get_oper_ch(padapter);
11505                                         SelectChannel(padapter, pmlmeext->cur_channel);
11506                                 }
11507
11508                                 if (rx_chk != _SUCCESS)
11509                                         issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 0, 0, 3, 1);
11510
11511                                 if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) || rx_chk != _SUCCESS) {
11512                                         tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
11513                                         /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
11514                                         if (tx_chk == _SUCCESS && !is_p2p_enable)
11515                                                 rx_chk = _SUCCESS;
11516                                 }
11517
11518                                 /* back to the original operation channel */
11519                                 if(backup_oper_channel>0)
11520                                         SelectChannel(padapter, backup_oper_channel);
11521
11522                         }
11523                         else
11524                         #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
11525                         {
11526                                 if (rx_chk != _SUCCESS) {
11527                                         if (pmlmeext->retry == 0) {
11528                                                 #ifdef DBG_EXPIRATION_CHK
11529                                                 DBG_871X("issue_probereq to trigger probersp, retry=%d\n", pmlmeext->retry);
11530                                                 #endif
11531                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
11532                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
11533                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
11534                                         }
11535                                 }
11536
11537                                 if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) {
11538                                         #ifdef DBG_EXPIRATION_CHK
11539                                         DBG_871X("%s issue_nulldata 0\n", __FUNCTION__);
11540                                         #endif
11541                                         tx_chk = issue_nulldata_in_interrupt(padapter, NULL);
11542                                 }
11543                         }
11544
11545                         if (rx_chk == _FAIL) {
11546                                 pmlmeext->retry++;
11547                                 if (pmlmeext->retry > rx_chk_limit) {
11548                                         DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
11549                                                 FUNC_ADPT_ARG(padapter));
11550                                         receive_disconnect(padapter, pmlmeinfo->network.MacAddress
11551                                                 , WLAN_REASON_EXPIRATION_CHK);
11552                                         return;
11553                                 }
11554                         } else {
11555                                 pmlmeext->retry = 0;
11556                         }
11557
11558                         if (tx_chk == _FAIL) {
11559                                 pmlmeinfo->link_count %= (link_count_limit+1);
11560                         } else {
11561                                 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
11562                                 pmlmeinfo->link_count = 0;
11563                         }
11564
11565                 } //end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL)
11566
11567 #if defined (CONFIG_TDLS) && defined (CONFIG_TDLS_AUTOCHECKALIVE)
11568                 linked_status_chk_tdls(padapter);
11569 #endif //CONFIG_TDLS
11570
11571         }
11572         else if (is_client_associated_to_ibss(padapter))
11573         {
11574                 //linked IBSS mode
11575                 //for each assoc list entry to check the rx pkt counter
11576                 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
11577                 {
11578                         if (pmlmeinfo->FW_sta_info[i].status == 1)
11579                         {
11580                                 psta = pmlmeinfo->FW_sta_info[i].psta;
11581
11582                                 if(NULL==psta) continue;
11583
11584                                 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta))
11585                                 {
11586
11587                                         if(pmlmeinfo->FW_sta_info[i].retry<3)
11588                                         {
11589                                                 pmlmeinfo->FW_sta_info[i].retry++;
11590                                         }
11591                                         else
11592                                         {
11593                                                 pmlmeinfo->FW_sta_info[i].retry = 0;
11594                                                 pmlmeinfo->FW_sta_info[i].status = 0;
11595                                                 report_del_sta_event(padapter, psta->hwaddr
11596                                                         , 65535// indicate disconnect caused by no rx
11597                                                 );
11598                                         }       
11599                                 }
11600                                 else
11601                                 {
11602                                         pmlmeinfo->FW_sta_info[i].retry = 0;
11603                                         pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
11604                                 }
11605                         }
11606                 }
11607
11608                 //set_link_timer(pmlmeext, DISCONNECT_TO);
11609
11610         }
11611
11612 }
11613
11614 void survey_timer_hdl(_adapter *padapter)
11615 {
11616         struct cmd_obj  *ph2c;
11617         struct sitesurvey_parm  *psurveyPara;
11618         struct cmd_priv                                 *pcmdpriv=&padapter->cmdpriv;
11619         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
11620 #ifdef CONFIG_P2P
11621         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
11622 #endif
11623
11624         //DBG_871X("marc: survey timer\n");
11625
11626         //issue rtw_sitesurvey_cmd
11627         if (pmlmeext->sitesurvey_res.state > SCAN_START)
11628         {
11629                 if(pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
11630                 {
11631 #if defined(CONFIG_STA_MODE_SCAN_UNDER_AP_MODE) || defined(CONFIG_ATMEL_RC_PATCH) 
11632                         if( padapter->mlmeextpriv.mlmext_info.scan_cnt != RTW_SCAN_NUM_OF_CH )
11633 #endif
11634                                 pmlmeext->sitesurvey_res.channel_idx++;
11635                 }
11636
11637                 if(pmlmeext->scan_abort == _TRUE)
11638                 {
11639                         #ifdef CONFIG_P2P
11640                         if(!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE))
11641                         {
11642                                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
11643                                 pmlmeext->sitesurvey_res.channel_idx = 3;
11644                                 DBG_871X("%s idx:%d, cnt:%u\n", __FUNCTION__
11645                                         , pmlmeext->sitesurvey_res.channel_idx
11646                                         , pwdinfo->find_phase_state_exchange_cnt
11647                                 );
11648                         }
11649                         else
11650                         #endif
11651                         {
11652                                 pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
11653                                 DBG_871X("%s idx:%d\n", __FUNCTION__
11654                                         , pmlmeext->sitesurvey_res.channel_idx
11655                                 );
11656                         }
11657
11658                         pmlmeext->scan_abort = _FALSE;//reset
11659                 }
11660
11661                 if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
11662                 {
11663                         goto exit_survey_timer_hdl;
11664                 }
11665
11666                 if ((psurveyPara = (struct sitesurvey_parm*)rtw_zmalloc(sizeof(struct sitesurvey_parm))) == NULL)
11667                 {
11668                         rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
11669                         goto exit_survey_timer_hdl;
11670                 }
11671
11672                 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
11673                 rtw_enqueue_cmd(pcmdpriv, ph2c);
11674         }
11675
11676
11677 exit_survey_timer_hdl:
11678
11679         return;
11680 }
11681
11682 void link_timer_hdl(_adapter *padapter)
11683 {
11684         //static unsigned int           rx_pkt = 0;
11685         //static u64                            tx_cnt = 0;
11686         //struct xmit_priv              *pxmitpriv = &(padapter->xmitpriv);
11687         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11688         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11689         //struct sta_priv               *pstapriv = &padapter->stapriv;
11690
11691
11692         if (pmlmeinfo->state & WIFI_FW_AUTH_NULL)
11693         {
11694                 DBG_871X("link_timer_hdl:no beacon while connecting\n");
11695                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
11696                 report_join_res(padapter, -3);
11697         }
11698         else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE)
11699         {
11700                 //re-auth timer
11701                 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT)
11702                 {
11703                         //if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto)
11704                         //{
11705                                 pmlmeinfo->state = 0;
11706                                 report_join_res(padapter, -1);
11707                                 return;
11708                         //}
11709                         //else
11710                         //{
11711                         //      pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
11712                         //      pmlmeinfo->reauth_count = 0;
11713                         //}
11714                 }
11715                 
11716                 DBG_871X("link_timer_hdl: auth timeout and try again\n");
11717                 pmlmeinfo->auth_seq = 1;
11718                 issue_auth(padapter, NULL, 0);
11719                 set_link_timer(pmlmeext, REAUTH_TO);
11720         }
11721         else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)
11722         {
11723                 //re-assoc timer
11724                 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT)
11725                 {
11726                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
11727                         report_join_res(padapter, -2);
11728                         return;
11729                 }
11730
11731                 DBG_871X("link_timer_hdl: assoc timeout and try again\n");
11732                 issue_assocreq(padapter);
11733                 set_link_timer(pmlmeext, REASSOC_TO);
11734         }
11735 #if 0
11736         else if (is_client_associated_to_ap(padapter))
11737         {
11738                 //linked infrastructure client mode
11739                 if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
11740                 {
11741                         /*to monitor whether the AP is alive or not*/
11742                         if (rx_pkt == psta->sta_stats.rx_pkts)
11743                         {
11744                                 receive_disconnect(padapter, pmlmeinfo->network.MacAddress);
11745                                 return;
11746                         }
11747                         else
11748                         {
11749                                 rx_pkt = psta->sta_stats.rx_pkts;
11750                                 set_link_timer(pmlmeext, DISCONNECT_TO);
11751                         }
11752
11753                         //update the EDCA paramter according to the Tx/RX mode
11754                         update_EDCA_param(padapter);
11755
11756                         /*to send the AP a nulldata if no frame is xmitted in order to keep alive*/
11757                         if (pmlmeinfo->link_count++ == 0)
11758                         {
11759                                 tx_cnt = pxmitpriv->tx_pkts;
11760                         }
11761                         else if ((pmlmeinfo->link_count & 0xf) == 0)
11762                         {
11763                                 if (tx_cnt == pxmitpriv->tx_pkts)
11764                                 {
11765                                         issue_nulldata_in_interrupt(padapter, NULL);
11766                                 }
11767
11768                                 tx_cnt = pxmitpriv->tx_pkts;
11769                         }
11770                 } //end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL)
11771         }
11772         else if (is_client_associated_to_ibss(padapter))
11773         {
11774                 //linked IBSS mode
11775                 //for each assoc list entry to check the rx pkt counter
11776                 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
11777                 {
11778                         if (pmlmeinfo->FW_sta_info[i].status == 1)
11779                         {
11780                                 psta = pmlmeinfo->FW_sta_info[i].psta;
11781
11782                                 if (pmlmeinfo->FW_sta_info[i].rx_pkt == psta->sta_stats.rx_pkts)
11783                                 {
11784                                         pmlmeinfo->FW_sta_info[i].status = 0;
11785                                         report_del_sta_event(padapter, psta->hwaddr);
11786                                 }
11787                                 else
11788                                 {
11789                                         pmlmeinfo->FW_sta_info[i].rx_pkt = psta->sta_stats.rx_pkts;
11790                                 }
11791                         }
11792                 }
11793
11794                 set_link_timer(pmlmeext, DISCONNECT_TO);
11795         }
11796 #endif
11797
11798         return;
11799 }
11800
11801 void addba_timer_hdl(struct sta_info *psta)
11802 {
11803 #ifdef CONFIG_80211N_HT
11804         struct ht_priv  *phtpriv;
11805
11806         if(!psta)
11807                 return;
11808         
11809         phtpriv = &psta->htpriv;
11810
11811         if((phtpriv->ht_option==_TRUE) && (phtpriv->ampdu_enable==_TRUE)) 
11812         {
11813                 if(phtpriv->candidate_tid_bitmap)
11814                         phtpriv->candidate_tid_bitmap=0x0;
11815                 
11816         }
11817 #endif //CONFIG_80211N_HT
11818 }
11819
11820 #ifdef CONFIG_IEEE80211W
11821 void sa_query_timer_hdl(_adapter *padapter)
11822 {
11823         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11824         struct mlme_priv * pmlmepriv = &padapter->mlmepriv;
11825         _irqL irqL;
11826         //disconnect
11827         _enter_critical_bh(&pmlmepriv->lock, &irqL);
11828
11829         if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
11830         {
11831                 rtw_disassoc_cmd(padapter, 0, _TRUE);
11832                 rtw_indicate_disconnect(padapter);
11833                 rtw_free_assoc_resources(padapter, 1);  
11834         }
11835
11836         _exit_critical_bh(&pmlmepriv->lock, &irqL);
11837         DBG_871X("SA query timeout disconnect\n");
11838 }
11839 #endif //CONFIG_IEEE80211W
11840
11841 u8 NULL_hdl(_adapter *padapter, u8 *pbuf)
11842 {
11843         return H2C_SUCCESS;
11844 }
11845
11846 #ifdef CONFIG_AUTO_AP_MODE
11847 void rtw_start_auto_ap(_adapter *adapter)
11848 {
11849         DBG_871X("%s\n", __FUNCTION__);
11850
11851         rtw_set_802_11_infrastructure_mode(adapter, Ndis802_11APMode);
11852
11853         rtw_setopmode_cmd(adapter, Ndis802_11APMode,_TRUE);
11854 }
11855
11856 static int rtw_auto_ap_start_beacon(_adapter *adapter)
11857 {
11858         int ret=0;
11859         u8 *pbuf = NULL;
11860         uint len;
11861         u8      supportRate[16];
11862         int     sz = 0, rateLen;
11863         u8 *    ie;
11864         u8      wireless_mode, oper_channel;
11865         u8 ssid[3] = {0}; //hidden ssid
11866         u32 ssid_len = sizeof(ssid);
11867         struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
11868
11869
11870         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
11871                 return -EINVAL;
11872
11873
11874         len = 128;
11875         pbuf = rtw_zmalloc(len);
11876         if(!pbuf)
11877                 return -ENOMEM;
11878
11879
11880         //generate beacon
11881         ie = pbuf;
11882
11883         //timestamp will be inserted by hardware
11884         sz += 8;
11885         ie += sz;
11886
11887         //beacon interval : 2bytes
11888         *(u16*)ie = cpu_to_le16((u16)100);//BCN_INTERVAL=100;
11889         sz += 2;
11890         ie += 2;
11891
11892         //capability info
11893         *(u16*)ie = 0;
11894         *(u16*)ie |= cpu_to_le16(cap_ESS);
11895         *(u16*)ie |= cpu_to_le16(cap_ShortPremble);
11896         //*(u16*)ie |= cpu_to_le16(cap_Privacy);
11897         sz += 2;
11898         ie += 2;
11899
11900         //SSID
11901         ie = rtw_set_ie(ie, _SSID_IE_, ssid_len, ssid, &sz);
11902
11903         //supported rates
11904         wireless_mode = WIRELESS_11BG_24N;
11905         rtw_set_supported_rate(supportRate, wireless_mode) ;
11906         rateLen = rtw_get_rateset_len(supportRate);
11907         if (rateLen > 8)
11908         {
11909                 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, supportRate, &sz);
11910         }
11911         else
11912         {
11913                 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, supportRate, &sz);
11914         }
11915
11916
11917         //DS parameter set
11918         if(check_buddy_fwstate(adapter, _FW_LINKED) &&
11919                 check_buddy_fwstate(adapter, WIFI_STATION_STATE))
11920         {
11921                 PADAPTER pbuddy_adapter = adapter->pbuddy_adapter;
11922                 struct mlme_ext_priv *pbuddy_mlmeext  = &pbuddy_adapter->mlmeextpriv;
11923
11924                 oper_channel = pbuddy_mlmeext->cur_channel;
11925         }
11926         else
11927         {
11928                 oper_channel = adapter_to_dvobj(adapter)->oper_channel;
11929         }
11930         ie = rtw_set_ie(ie, _DSSET_IE_, 1, &oper_channel, &sz);
11931
11932         //ext supported rates
11933         if (rateLen > 8)
11934         {
11935                 ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz);
11936         }
11937
11938         DBG_871X("%s, start auto ap beacon sz=%d\n", __FUNCTION__, sz);
11939
11940         //lunch ap mode & start to issue beacon
11941         if(rtw_check_beacon_data(adapter, pbuf,  sz) == _SUCCESS)
11942         {
11943
11944         }
11945         else
11946         {
11947                 ret = -EINVAL;
11948         }
11949
11950
11951         rtw_mfree(pbuf, len);
11952
11953         return ret;
11954
11955 }
11956 #endif//CONFIG_AUTO_AP_MODE
11957
11958 u8 setopmode_hdl(_adapter *padapter, u8 *pbuf)
11959 {
11960         u8      type;
11961         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
11962         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
11963         struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
11964
11965         if(psetop->mode == Ndis802_11APMode)
11966         {
11967                 pmlmeinfo->state = WIFI_FW_AP_STATE;
11968                 type = _HW_STATE_AP_;
11969 #ifdef CONFIG_NATIVEAP_MLME
11970                 //start_ap_mode(padapter);
11971 #endif
11972         }
11973         else if(psetop->mode == Ndis802_11Infrastructure)
11974         {
11975                 pmlmeinfo->state &= ~(BIT(0)|BIT(1));// clear state
11976                 pmlmeinfo->state |= WIFI_FW_STATION_STATE;//set to      STATION_STATE
11977                 type = _HW_STATE_STATION_;
11978         }
11979         else if(psetop->mode == Ndis802_11IBSS)
11980         {
11981                 type = _HW_STATE_ADHOC_;
11982         }
11983         else
11984         {
11985                 type = _HW_STATE_NOLINK_;
11986         }
11987
11988         rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
11989         //Set_NETYPE0_MSR(padapter, type);
11990
11991
11992 #ifdef CONFIG_AUTO_AP_MODE
11993         if(psetop->mode == Ndis802_11APMode)
11994                 rtw_auto_ap_start_beacon(padapter);
11995 #endif
11996
11997         if (rtw_port_switch_chk(padapter) == _TRUE)
11998         {
11999                 rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
12000
12001                 if(psetop->mode == Ndis802_11APMode)
12002                         adapter_to_pwrctl(padapter)->fw_psmode_iface_id = 0xff; //ap mode won't dowload rsvd pages
12003                 else if (psetop->mode == Ndis802_11Infrastructure) {
12004                         #ifdef CONFIG_LPS
12005                         _adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
12006                         if (port0_iface)
12007                                 rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
12008                         #endif  
12009                 }
12010         }       
12011
12012 #ifdef CONFIG_BT_COEXIST
12013         if (psetop->mode == Ndis802_11APMode)
12014         {
12015                 // Do this after port switch to
12016                 // prevent from downloading rsvd page to wrong port
12017                 rtw_btcoex_MediaStatusNotify(padapter, 1); //connect 
12018         }
12019 #endif // CONFIG_BT_COEXIST
12020
12021         return H2C_SUCCESS;
12022         
12023 }
12024
12025 u8 createbss_hdl(_adapter *padapter, u8 *pbuf)
12026 {
12027         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12028         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12029         WLAN_BSSID_EX   *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
12030         struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
12031         //u32   initialgain;
12032         
12033 #ifdef CONFIG_AP_MODE
12034         if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
12035                 WLAN_BSSID_EX *network = &padapter->mlmepriv.cur_network.network;
12036                 start_bss_network(padapter, (u8*)network);
12037                 return H2C_SUCCESS;
12038         }
12039 #endif
12040
12041         //below is for ad-hoc master
12042         if(pparm->network.InfrastructureMode == Ndis802_11IBSS)
12043         {
12044                 rtw_joinbss_reset(padapter);
12045         
12046                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
12047                 pmlmeext->cur_ch_offset= HAL_PRIME_CHNL_OFFSET_DONT_CARE;       
12048                 pmlmeinfo->ERP_enable = 0;
12049                 pmlmeinfo->WMM_enable = 0;
12050                 pmlmeinfo->HT_enable = 0;
12051                 pmlmeinfo->HT_caps_enable = 0;
12052                 pmlmeinfo->HT_info_enable = 0;
12053                 pmlmeinfo->agg_enable_bitmap = 0;
12054                 pmlmeinfo->candidate_tid_bitmap = 0;
12055
12056                 //disable dynamic functions, such as high power, DIG
12057                 Save_DM_Func_Flag(padapter);
12058                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
12059
12060                 //config the initial gain under linking, need to write the BB registers
12061                 //initialgain = 0x1E;
12062                 //rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
12063
12064                 //cancel link timer 
12065                 _cancel_timer_ex(&pmlmeext->link_timer);
12066
12067                 //clear CAM
12068                 flush_all_cam_entry(padapter);  
12069
12070                 _rtw_memcpy(pnetwork, pbuf, FIELD_OFFSET(WLAN_BSSID_EX, IELength)); 
12071                 pnetwork->IELength = ((WLAN_BSSID_EX *)pbuf)->IELength;
12072
12073                 if(pnetwork->IELength>MAX_IE_SZ)//Check pbuf->IELength
12074                         return H2C_PARAMETERS_ERROR;
12075
12076                 _rtw_memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength);
12077         
12078                 start_create_ibss(padapter);
12079
12080         }       
12081
12082         return H2C_SUCCESS;
12083
12084 }
12085
12086 u8 join_cmd_hdl(_adapter *padapter, u8 *pbuf)
12087 {
12088         u8      join_type;
12089         PNDIS_802_11_VARIABLE_IEs       pIE;
12090         struct registry_priv    *pregpriv = &padapter->registrypriv;
12091         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12092         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12093         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
12094 #ifdef CONFIG_ANTENNA_DIVERSITY
12095         struct joinbss_parm     *pparm = (struct joinbss_parm *)pbuf;
12096 #endif //CONFIG_ANTENNA_DIVERSITY
12097         u32 i;
12098         u8      cbw40_enable=0;
12099         //u32   initialgain;
12100         //u32   acparm;
12101         u8 ch, bw, offset;
12102
12103 #if 1
12104         /*
12105          * For safety, prevent from keeping macid sleep.
12106          * If we can sure all power mode enter/leave are paired,
12107          * this check can be removed.
12108          * Lucas@20131113
12109          */
12110         {
12111         struct sta_info *psta;
12112         psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
12113         if (psta)
12114                 rtw_hal_macid_wakeup(padapter, psta->mac_id);
12115         }
12116 #endif
12117
12118 #ifdef CONFIG_BT_COEXIST
12119 {
12120         static u8 bw_mode = 0;
12121
12122         if (0 == bw_mode)
12123         {
12124                 bw_mode = pregpriv->bw_mode; // keep original bw_mode
12125                 DBG_871X(FUNC_ADPT_FMT ": [BTCOEX] Save bw_mode(0x%02x)\n",
12126                         FUNC_ADPT_ARG(padapter), pregpriv->bw_mode);
12127         }
12128
12129         if ((rtw_btcoex_1Ant(padapter) == _TRUE)
12130                 && (rtw_btcoex_IsBtLinkExist(padapter) == _TRUE))
12131         {
12132                 pregpriv->bw_mode = 0x00;
12133                 DBG_871X(FUNC_ADPT_FMT ": [BTCOEX] Change bw_mode to 20MHz(0x%02x)\n",
12134                         FUNC_ADPT_ARG(padapter), pregpriv->bw_mode);
12135         }
12136         else
12137         {
12138                 pregpriv->bw_mode = bw_mode;
12139                 DBG_871X(FUNC_ADPT_FMT ": [BTCOEX] Restore bw_mode(0x%02x)\n",
12140                         FUNC_ADPT_ARG(padapter), pregpriv->bw_mode);
12141         }
12142 }
12143 #endif // CONFIG_BT_COEXIST
12144
12145         //check already connecting to AP or not
12146         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
12147         {
12148                 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
12149                 {
12150                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
12151                 }
12152                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
12153                 
12154                 //clear CAM
12155                 flush_all_cam_entry(padapter);          
12156                 
12157                 _cancel_timer_ex(&pmlmeext->link_timer);
12158                 
12159                 //set MSR to nolink -> infra. mode              
12160                 //Set_MSR(padapter, _HW_STATE_NOLINK_);
12161                 Set_MSR(padapter, _HW_STATE_STATION_);  
12162                 
12163
12164                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
12165         }
12166
12167 #ifdef CONFIG_ANTENNA_DIVERSITY
12168         rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, _FALSE);
12169 #endif
12170
12171 #ifdef CONFIG_WAPI_SUPPORT
12172         rtw_wapi_clear_all_cam_entry(padapter);
12173 #endif
12174
12175         rtw_joinbss_reset(padapter);
12176         
12177         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
12178         pmlmeext->cur_ch_offset= HAL_PRIME_CHNL_OFFSET_DONT_CARE;       
12179         pmlmeinfo->ERP_enable = 0;
12180         pmlmeinfo->WMM_enable = 0;
12181         pmlmeinfo->HT_enable = 0;
12182         pmlmeinfo->HT_caps_enable = 0;
12183         pmlmeinfo->HT_info_enable = 0;
12184         pmlmeinfo->agg_enable_bitmap = 0;
12185         pmlmeinfo->candidate_tid_bitmap = 0;
12186         pmlmeinfo->bwmode_updated = _FALSE;
12187         //pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX;
12188         pmlmeinfo->VHT_enable = 0;
12189
12190         _rtw_memcpy(pnetwork, pbuf, FIELD_OFFSET(WLAN_BSSID_EX, IELength)); 
12191         pnetwork->IELength = ((WLAN_BSSID_EX *)pbuf)->IELength;
12192         
12193         if(pnetwork->IELength>MAX_IE_SZ)//Check pbuf->IELength
12194                 return H2C_PARAMETERS_ERROR;    
12195                 
12196         _rtw_memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength); 
12197
12198         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
12199         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
12200
12201         //Check AP vendor to move rtw_joinbss_cmd()
12202         //pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength);
12203
12204         //sizeof(NDIS_802_11_FIXED_IEs) 
12205         for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;)
12206         {
12207                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
12208
12209                 switch (pIE->ElementID)
12210                 {
12211                         case _VENDOR_SPECIFIC_IE_://Get WMM IE.
12212                                 if ( _rtw_memcmp(pIE->data, WMM_OUI, 4) )
12213                                 {
12214                                         WMM_param_handler(padapter, pIE);
12215                                 }
12216                                 break;
12217
12218                         case _HT_CAPABILITY_IE_:        //Get HT Cap IE.
12219                                 pmlmeinfo->HT_caps_enable = 1;
12220                                 break;
12221
12222                         case _HT_EXTRA_INFO_IE_:        //Get HT Info IE.
12223 #ifdef CONFIG_80211N_HT
12224                                 pmlmeinfo->HT_info_enable = 1;
12225
12226                                 //spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz      
12227 //#if !defined(CONFIG_CONCURRENT_MODE) && !defined(CONFIG_DUALMAC_CONCURRENT)
12228 //                              if(pmlmeinfo->assoc_AP_vendor == ciscoAP)
12229 //#endif
12230                                 {                               
12231                                         struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
12232
12233                                         if (pnetwork->Configuration.DSConfig > 14) {
12234                                                 if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20)
12235                                                         cbw40_enable = 1;
12236                                         } else {
12237                                                 if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20)
12238                                                         cbw40_enable = 1;
12239                                         }
12240
12241                                         if ((cbw40_enable) && (pht_info->infos[0] & BIT(2)))
12242                                         {
12243                                                 //switch to the 40M Hz mode according to the AP
12244                                                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
12245                                                 switch (pht_info->infos[0] & 0x3)
12246                                                 {
12247                                                         case 1:
12248                                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
12249                                                                 break;
12250                         
12251                                                         case 3:
12252                                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
12253                                                                 break;
12254                                 
12255                                                         default:
12256                                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
12257                                                                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
12258                                                                 break;
12259                                                 }
12260
12261                                                 DBG_871X("set HT ch/bw before connected\n");
12262                                         }
12263                                 }
12264 #endif //CONFIG_80211N_HT
12265                                 break;
12266 #ifdef CONFIG_80211AC_VHT
12267                         case EID_VHTCapability://Get VHT Cap IE.
12268                                 pmlmeinfo->VHT_enable = 1;
12269                                 break;
12270
12271                         case EID_VHTOperation://Get VHT Operation IE.
12272                                 if((GET_VHT_OPERATION_ELE_CHL_WIDTH(pIE->data) >= 1) 
12273                                         && ((pregpriv->bw_mode >> 4) >= CHANNEL_WIDTH_80)) {
12274                                         pmlmeext->cur_bwmode = CHANNEL_WIDTH_80;
12275                                         DBG_871X("VHT center ch = %d\n", GET_VHT_OPERATION_ELE_CENTER_FREQ1(pIE->data));
12276                                         DBG_871X("set VHT ch/bw before connected\n");
12277                                 }
12278                                 break;
12279 #endif
12280                         default:
12281                                 break;
12282                 }
12283
12284                 i += (pIE->Length + 2);
12285         }
12286 #if 0
12287         if (padapter->registrypriv.wifi_spec) {
12288                 // for WiFi test, follow WMM test plan spec
12289                 acparm = 0x002F431C; // VO
12290                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
12291                 acparm = 0x005E541C; // VI
12292                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
12293                 acparm = 0x0000A525; // BE
12294                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
12295                 acparm = 0x0000A549; // BK
12296                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
12297         
12298                 // for WiFi test, mixed mode with intel STA under bg mode throughput issue
12299                 if (padapter->mlmepriv.htpriv.ht_option == _FALSE){
12300                         acparm = 0x00004320;
12301                         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
12302                 }
12303         }
12304         else {
12305                 acparm = 0x002F3217; // VO
12306                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
12307                 acparm = 0x005E4317; // VI
12308                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
12309                 acparm = 0x00105320; // BE
12310                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
12311                 acparm = 0x0000A444; // BK
12312                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
12313         }
12314 #endif
12315
12316         /* check channel, bandwidth, offset and switch */
12317 #ifdef CONFIG_DUALMAC_CONCURRENT
12318         if(dc_handle_join_request(padapter, &ch, &bw, &offset) == _FAIL) {
12319                 DBG_871X("dc_handle_join_request fail !!!\n");
12320                 return H2C_SUCCESS;
12321         }
12322 #else //NON CONFIG_DUALMAC_CONCURRENT
12323         if(rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) {
12324                 report_join_res(padapter, (-4));
12325                 return H2C_SUCCESS;
12326         }
12327 #endif
12328
12329         //disable dynamic functions, such as high power, DIG
12330         //Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
12331
12332         //config the initial gain under linking, need to write the BB registers
12333         //initialgain = 0x1E;
12334         //rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
12335
12336         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
12337         join_type = 0;
12338         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
12339         rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
12340
12341         set_channel_bwmode(padapter, ch, offset, bw);
12342
12343         //cancel link timer 
12344         _cancel_timer_ex(&pmlmeext->link_timer);
12345         
12346         start_clnt_join(padapter);
12347         
12348         return H2C_SUCCESS;
12349         
12350 }
12351
12352 u8 disconnect_hdl(_adapter *padapter, unsigned char *pbuf)
12353 {
12354         struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
12355         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12356         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12357         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
12358         u8 val8;
12359
12360
12361 #if 1
12362         /*
12363          * For safety, prevent from keeping macid sleep.
12364          * If we can sure all power mode enter/leave are paired,
12365          * this check can be removed.
12366          * Lucas@20131113
12367          */
12368         {
12369         struct sta_info *psta;
12370         psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
12371         if (psta)
12372                 rtw_hal_macid_wakeup(padapter, psta->mac_id);
12373         }
12374 #endif
12375
12376         if (is_client_associated_to_ap(padapter))
12377         {
12378 #ifdef CONFIG_DFS
12379                 if(padapter->mlmepriv.handle_dfs == _FALSE)
12380 #endif //CONFIG_DFS
12381 #ifdef CONFIG_PLATFORM_ROCKCHIPS
12382                         //To avoid connecting to AP fail during resume process, change retry count from 5 to 1
12383                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
12384 #else
12385                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
12386 #endif //CONFIG_PLATFORM_ROCKCHIPS
12387         }
12388
12389 #ifdef CONFIG_DFS
12390         if( padapter->mlmepriv.handle_dfs == _TRUE )
12391                 padapter->mlmepriv.handle_dfs = _FALSE;
12392 #endif //CONFIG_DFS
12393
12394         if(((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
12395         {
12396                 //Stop BCN
12397                 val8 = 0;
12398                 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
12399         }
12400
12401         rtw_mlmeext_disconnect(padapter);
12402
12403         rtw_free_uc_swdec_pending_queue(padapter);
12404         
12405         return  H2C_SUCCESS;
12406 }
12407
12408 int rtw_scan_ch_decision(_adapter *padapter, struct rtw_ieee80211_channel *out,
12409         u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
12410 {
12411         int i, j;
12412         int scan_ch_num = 0;
12413         int set_idx;
12414         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12415
12416         /* clear first */
12417         _rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
12418
12419         /* acquire channels from in */
12420         j = 0;
12421         for (i=0;i<in_num;i++) {
12422
12423                 if (0)
12424                 DBG_871X(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
12425
12426                 if(in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED)
12427                         && (set_idx=rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value)) >=0
12428                         && rtw_mlme_band_check(padapter, in[i].hw_value) == _TRUE
12429                 )
12430                 {
12431                         if (j >= out_num) {
12432                                 DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
12433                                         FUNC_ADPT_ARG(padapter), out_num);
12434                                 break;
12435                         }
12436
12437                         _rtw_memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
12438                         
12439                         if(pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
12440                                 out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
12441                                 
12442                         j++;
12443                 }
12444                 if(j>=out_num)
12445                         break;
12446         }
12447         
12448         /* if out is empty, use channel_set as default */
12449         if(j == 0) {
12450                 for (i=0;i<pmlmeext->max_chan_nums;i++) {
12451
12452                         if (0)
12453                         DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), pmlmeext->channel_set[i].ChannelNum);
12454
12455                         if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum) == _TRUE) {
12456
12457                                 if (j >= out_num) {
12458                                         DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
12459                                                 FUNC_ADPT_ARG(padapter), out_num);
12460                                         break;
12461                                 }
12462
12463                                 out[j].hw_value = pmlmeext->channel_set[i].ChannelNum;
12464                         
12465                                 if(pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
12466                                         out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
12467
12468                                 j++;
12469                         }
12470                 }
12471         }
12472
12473 #ifdef CONFIG_SCAN_SPARSE //partial scan, ASUS RK3188 use the feature
12474         /* assume j>6 is normal scan */
12475         if ((j > 6) && (padapter->registrypriv.wifi_spec != 1))
12476         {
12477                 static u8 token = 0;
12478                 u32 interval;
12479
12480                 if (pmlmeext->last_scan_time == 0)
12481                         pmlmeext->last_scan_time = rtw_get_current_time();
12482
12483                 interval = rtw_get_passing_time_ms(pmlmeext->last_scan_time);
12484                 if ((interval > ALLOW_SCAN_INTERVAL)
12485 #if 0 // Miracast can't do AP scan
12486                         || (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE)
12487 #ifdef CONFIG_CONCURRENT_MODE
12488                         || (padapter->pbuddy_adapter
12489                                 && (padapter->pbuddy_adapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE))
12490 #endif // CONFIG_CONCURRENT_MODE
12491 #endif
12492                         )
12493                 {
12494                         // modify scan plan
12495                         int k = 0;
12496                         _rtw_memset(in, 0, sizeof(struct rtw_ieee80211_channel)*in_num);
12497                         _rtw_memcpy(in, out, sizeof(struct rtw_ieee80211_channel)*j);
12498                         _rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel)*j);
12499
12500                         for (i=0;i<j;i++) {
12501                                 if (in[i].hw_value && (i%SCAN_DIVISION_NUM) == token) {
12502                                         _rtw_memcpy(&out[k], &in[i], sizeof(struct rtw_ieee80211_channel));
12503                                         k++;
12504                                 }
12505                                 if(k>=out_num)
12506                                         break;
12507                         }
12508
12509                         j = k;
12510                         token  = (token+1)%SCAN_DIVISION_NUM;
12511                 }
12512
12513                 pmlmeext->last_scan_time = rtw_get_current_time();
12514         }
12515 #endif //CONFIG_SCAN_SPARSE
12516
12517         return j;
12518 }
12519
12520 u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf)
12521 {
12522         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12523         struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
12524         u8      bdelayscan = _FALSE;
12525         u8      val8;
12526         u32     initialgain;
12527         u32     i;
12528         struct dvobj_priv *psdpriv = padapter->dvobj;
12529         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
12530
12531 #ifdef CONFIG_P2P
12532         struct wifidirect_info* pwdinfo = &padapter->wdinfo;
12533 #endif
12534 #ifdef DBG_CHECK_FW_PS_STATE
12535         if(rtw_fw_ps_state(padapter) == _FAIL)
12536         {
12537                 DBG_871X("scan without leave 32k\n");
12538                 pdbgpriv->dbg_scan_pwr_state_cnt++;
12539         }
12540 #endif //DBG_CHECK_FW_PS_STATE
12541
12542         if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE)
12543         {
12544 #ifdef CONFIG_CONCURRENT_MODE   
12545                 //for first time sitesurvey_cmd
12546                 rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);     
12547 #endif //CONFIG_CONCURRENT_MODE
12548                 
12549                 pmlmeext->sitesurvey_res.state = SCAN_START;
12550                 pmlmeext->sitesurvey_res.bss_cnt = 0;
12551                 pmlmeext->sitesurvey_res.channel_idx = 0;
12552
12553                 for(i=0;i<RTW_SSID_SCAN_AMOUNT;i++){
12554                         if(pparm->ssid[i].SsidLength) {
12555                                 _rtw_memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
12556                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength= pparm->ssid[i].SsidLength;
12557                         } else {
12558                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength= 0;
12559                         }
12560                 }
12561
12562                 pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
12563                         , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
12564                         , pparm->ch, pparm->ch_num
12565                 );
12566
12567                 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
12568
12569 #ifdef CONFIG_DUALMAC_CONCURRENT
12570                 bdelayscan = dc_handle_site_survey(padapter);
12571 #endif
12572
12573                 //issue null data if associating to the AP
12574                 if (is_client_associated_to_ap(padapter) == _TRUE)
12575                 {
12576                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
12577
12578                         issue_nulldata(padapter, NULL, 1, 3, 500);
12579
12580 #ifdef CONFIG_CONCURRENT_MODE
12581                         if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
12582                         {
12583                                 DBG_871X("adapter is scanning(buddy_adapter is linked), issue nulldata(pwrbit=1)\n");
12584                                 
12585                                 issue_nulldata(padapter->pbuddy_adapter, NULL, 1, 3, 500);
12586                         }
12587 #endif
12588                         bdelayscan = _TRUE;
12589                 }
12590 #ifdef CONFIG_CONCURRENT_MODE
12591                 else if(is_client_associated_to_ap(padapter->pbuddy_adapter) == _TRUE)
12592                 {
12593                         #ifdef CONFIG_TDLS
12594                         if(padapter->pbuddy_adapter->wdinfo.wfd_tdls_enable == 1)
12595                         {
12596                                 issue_tunneled_probe_req(padapter->pbuddy_adapter);
12597                         }
12598                         #endif //CONFIG_TDLS
12599
12600                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
12601
12602                         issue_nulldata(padapter->pbuddy_adapter, NULL, 1, 3, 500);
12603
12604                         bdelayscan = _TRUE;                     
12605                 }
12606 #endif          
12607                 if(bdelayscan)
12608                 {
12609                         //delay 50ms to protect nulldata(1).
12610                         set_survey_timer(pmlmeext, 50);
12611                         return H2C_SUCCESS;
12612                 }
12613         }
12614
12615         if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL))
12616         {
12617 #ifdef CONFIG_FIND_BEST_CHANNEL
12618 #if 0
12619                 for (i=0; pmlmeext->channel_set[i].ChannelNum !=0; i++) {
12620                         pmlmeext->channel_set[i].rx_count = 0;                          
12621                 }
12622 #endif
12623 #endif /* CONFIG_FIND_BEST_CHANNEL */
12624
12625                 //disable dynamic functions, such as high power, DIG
12626                 Save_DM_Func_Flag(padapter);
12627                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
12628
12629                 //config the initial gain under scaning, need to write the BB registers
12630 #ifdef CONFIG_P2P
12631 #ifdef CONFIG_IOCTL_CFG80211
12632                 if(adapter_wdev_data(padapter)->p2p_enabled == _TRUE && pwdinfo->driver_interface == DRIVER_CFG80211 )
12633                         initialgain = 0x30;
12634                 else
12635 #endif //CONFIG_IOCTL_CFG80211
12636                 if ( !rtw_p2p_chk_state( pwdinfo, P2P_STATE_NONE ) )
12637                         initialgain = 0x28;
12638                 else
12639 #endif //CONFIG_P2P
12640                         initialgain = 0x1e;
12641
12642                 rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
12643                 
12644                 //set MSR to no link state
12645                 Set_MSR(padapter, _HW_STATE_NOLINK_);
12646
12647                 val8 = 1; //under site survey
12648                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
12649
12650                 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
12651         }
12652
12653         site_survey(padapter);
12654
12655         return H2C_SUCCESS;
12656         
12657 }
12658
12659 u8 setauth_hdl(_adapter *padapter, unsigned char *pbuf)
12660 {
12661         struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
12662         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12663         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12664         
12665         if (pparm->mode < 4)
12666         {
12667                 pmlmeinfo->auth_algo = pparm->mode;
12668         }
12669
12670         return  H2C_SUCCESS;
12671 }
12672
12673 u8 setkey_hdl(_adapter *padapter, u8 *pbuf)
12674 {
12675         u16     ctrl = 0;
12676         s16 cam_id = 0;
12677
12678         struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
12679         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12680         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12681         unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
12682         u8 *addr;
12683
12684         //main tx key for wep.
12685         if(pparm->set_tx)
12686                 pmlmeinfo->key_index = pparm->keyid;
12687         
12688         cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid);
12689
12690         if (cam_id < 0){
12691         } else {
12692                 if (cam_id > 3) /* not default key, searched by A2 */
12693                         addr = get_bssid(&padapter->mlmepriv);
12694                 else
12695                         addr = null_addr;
12696                 
12697                 ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid;
12698                 write_cam(padapter, cam_id, ctrl, addr, pparm->key);
12699                 DBG_871X_LEVEL(_drv_always_, "set group key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n"
12700                         ,cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm));
12701         }
12702
12703 #ifdef DYNAMIC_CAMID_ALLOC
12704         if (cam_id >=0 && cam_id <=3)
12705                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8*)_TRUE);
12706 #endif
12707         
12708         //allow multicast packets to driver
12709         padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
12710
12711         return H2C_SUCCESS;
12712 }
12713
12714 u8 set_stakey_hdl(_adapter *padapter, u8 *pbuf)
12715 {
12716         u16 ctrl=0;
12717         s16 cam_id = 0;//cam_entry
12718         u8 ret = H2C_SUCCESS;
12719         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12720         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12721         struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
12722         struct sta_priv *pstapriv = &padapter->stapriv;
12723         struct sta_info *psta;
12724 #ifdef CONFIG_TDLS
12725         struct tdls_info        *ptdlsinfo = &padapter->tdlsinfo;
12726 #endif //CONFIG_TDLS
12727
12728         if(pparm->algorithm == _NO_PRIVACY_)
12729                 goto write_to_cam;
12730
12731         psta = rtw_get_stainfo(pstapriv, pparm->addr);
12732         if (!psta) {
12733                 DBG_871X_LEVEL(_drv_always_, "%s sta:"MAC_FMT" not found\n", __func__, MAC_ARG(pparm->addr));
12734                 ret = H2C_REJECTED;
12735                 goto exit;
12736         }
12737
12738         pmlmeinfo->enc_algo = pparm->algorithm;
12739         cam_id = rtw_camid_alloc(padapter, psta, 0);
12740         if (cam_id < 0)
12741                 goto exit;
12742
12743 write_to_cam:
12744         if(pparm->algorithm == _NO_PRIVACY_) {
12745                 while((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) {
12746                         DBG_871X_LEVEL(_drv_always_, "clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), cam_id);
12747                         clear_cam_entry(padapter, cam_id);
12748                         rtw_camid_free(padapter,cam_id);
12749                 }
12750         } else {
12751                 DBG_871X_LEVEL(_drv_always_, "set pairwise key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n",
12752                         cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm));
12753                 ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
12754                 write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
12755         }
12756         ret = H2C_SUCCESS_RSP;
12757
12758 exit:   
12759
12760         return ret;
12761 }
12762
12763 u8 add_ba_hdl(_adapter *padapter, unsigned char *pbuf)
12764 {
12765         struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
12766         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12767         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12768
12769         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
12770         
12771         if(!psta)
12772                 return  H2C_SUCCESS;
12773                 
12774 #ifdef CONFIG_80211N_HT
12775         if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
12776                 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
12777         {
12778                 //pmlmeinfo->ADDBA_retry_count = 0;
12779                 //pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid);               
12780                 //psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid);
12781                 issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);             
12782                 //_set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO);
12783                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
12784         }
12785 #ifdef CONFIG_TDLS
12786         else if((psta->tdls_sta_state & TDLS_LINKED_STATE)&& 
12787                 (psta->htpriv.ht_option==_TRUE) && 
12788                 (psta->htpriv.ampdu_enable==_TRUE) )
12789         {
12790                 issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);             
12791                 //_set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO);
12792                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
12793         }
12794 #endif //CONFIG
12795         else
12796         {               
12797                 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);          
12798         }
12799 #endif //CONFIG_80211N_HT
12800         return  H2C_SUCCESS;
12801 }
12802
12803
12804 u8 chk_bmc_sleepq_cmd(_adapter* padapter)
12805 {
12806         struct cmd_obj *ph2c;
12807         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
12808         u8 res = _SUCCESS;
12809
12810 _func_enter_;
12811
12812         if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
12813         {
12814                 res= _FAIL;
12815                 goto exit;
12816         }
12817
12818         init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));
12819
12820         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
12821
12822 exit:
12823
12824 _func_exit_;
12825
12826         return res;
12827 }
12828
12829 u8 set_tx_beacon_cmd(_adapter* padapter)
12830 {
12831         struct cmd_obj  *ph2c;
12832         struct Tx_Beacon_param  *ptxBeacon_parm;        
12833         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
12834         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
12835         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
12836         u8      res = _SUCCESS;
12837         int len_diff = 0;
12838         
12839 _func_enter_;   
12840
12841         if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
12842         {
12843                 res= _FAIL;
12844                 goto exit;
12845         }
12846
12847         if ((ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param))) == NULL)
12848         {
12849                 rtw_mfree((unsigned char *)ph2c, sizeof(struct  cmd_obj));
12850                 res= _FAIL;
12851                 goto exit;
12852         }
12853
12854         _rtw_memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));
12855
12856         len_diff = update_hidden_ssid(
12857                 ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_
12858                 , ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_
12859                 , pmlmeinfo->hidden_ssid_mode
12860         );
12861         ptxBeacon_parm->network.IELength += len_diff;
12862
12863         init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
12864
12865         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
12866
12867         
12868 exit:
12869         
12870 _func_exit_;
12871
12872         return res;
12873 }
12874
12875
12876 u8 mlme_evt_hdl(_adapter *padapter, unsigned char *pbuf)
12877 {
12878         u8 evt_code, evt_seq;
12879         u16 evt_sz;
12880         uint    *peventbuf;
12881         void (*event_callback)(_adapter *dev, u8 *pbuf);
12882         struct evt_priv *pevt_priv = &(padapter->evtpriv);
12883
12884         if (pbuf == NULL)
12885                 goto _abort_event_;
12886
12887         peventbuf = (uint*)pbuf;
12888         evt_sz = (u16)(*peventbuf&0xffff);
12889         evt_seq = (u8)((*peventbuf>>24)&0x7f);
12890         evt_code = (u8)((*peventbuf>>16)&0xff);
12891         
12892                 
12893         #ifdef CHECK_EVENT_SEQ
12894         // checking event sequence...           
12895         if (evt_seq != (ATOMIC_READ(&pevt_priv->event_seq) & 0x7f) )
12896         {
12897                 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)));
12898         
12899                 pevt_priv->event_seq = (evt_seq+1)&0x7f;
12900
12901                 goto _abort_event_;
12902         }
12903         #endif
12904
12905         // checking if event code is valid
12906         if (evt_code >= MAX_C2HEVT)
12907         {
12908                 RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\nEvent Code(%d) mismatch!\n", evt_code));
12909                 goto _abort_event_;
12910         }
12911
12912         // checking if event size match the event parm size     
12913         if ((wlanevents[evt_code].parmsize != 0) && 
12914                         (wlanevents[evt_code].parmsize != evt_sz))
12915         {
12916                         
12917                 RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n", 
12918                         evt_code, wlanevents[evt_code].parmsize, evt_sz));
12919                 goto _abort_event_;     
12920                         
12921         }
12922
12923         ATOMIC_INC(&pevt_priv->event_seq);
12924
12925         peventbuf += 2;
12926                                 
12927         if(peventbuf)
12928         {
12929                 event_callback = wlanevents[evt_code].event_callback;
12930                 event_callback(padapter, (u8*)peventbuf);
12931
12932                 pevt_priv->evt_done_cnt++;
12933         }
12934
12935
12936 _abort_event_:
12937
12938
12939         return H2C_SUCCESS;
12940                 
12941 }
12942
12943 u8 h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)
12944 {
12945         if(!pbuf)
12946                 return H2C_PARAMETERS_ERROR;
12947
12948         return H2C_SUCCESS;
12949 }
12950
12951 u8 chk_bmc_sleepq_hdl(_adapter *padapter, unsigned char *pbuf)
12952 {
12953 #ifdef CONFIG_AP_MODE
12954         _irqL irqL;
12955         struct sta_info *psta_bmc;
12956         _list   *xmitframe_plist, *xmitframe_phead;
12957         struct xmit_frame *pxmitframe=NULL;
12958         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
12959         struct sta_priv  *pstapriv = &padapter->stapriv;
12960
12961         //for BC/MC Frames
12962         psta_bmc = rtw_get_bcmc_stainfo(padapter);
12963         if(!psta_bmc)
12964                 return H2C_SUCCESS;
12965
12966         if((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len>0))
12967         {
12968 #ifndef CONFIG_PCI_HCI
12969                 rtw_msleep_os(10);// 10ms, ATIM(HIQ) Windows
12970 #endif
12971                 //_enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
12972                 _enter_critical_bh(&pxmitpriv->lock, &irqL);
12973
12974                 xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
12975                 xmitframe_plist = get_next(xmitframe_phead);
12976
12977                 while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
12978                 {
12979                         pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
12980
12981                         xmitframe_plist = get_next(xmitframe_plist);
12982
12983                         rtw_list_delete(&pxmitframe->list);
12984
12985                         psta_bmc->sleepq_len--;
12986                         if(psta_bmc->sleepq_len>0)
12987                                 pxmitframe->attrib.mdata = 1;
12988                         else
12989                                 pxmitframe->attrib.mdata = 0;
12990
12991                         pxmitframe->attrib.triggered=1;
12992
12993                         pxmitframe->attrib.qsel = 0x11;//HIQ
12994
12995                         #if 0
12996                         _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
12997                         if(rtw_hal_xmit(padapter, pxmitframe) == _TRUE)
12998                         {
12999                                 rtw_os_xmit_complete(padapter, pxmitframe);
13000                         }
13001                         _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
13002                         #endif
13003                         rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
13004                 }
13005
13006                 //_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
13007                 _exit_critical_bh(&pxmitpriv->lock, &irqL);
13008
13009                 //#if defined(CONFIG_PCI_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
13010                 #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
13011                 rtw_chk_hi_queue_cmd(padapter);
13012                 #endif
13013         }
13014 #endif
13015
13016         return H2C_SUCCESS;
13017 }
13018
13019 u8 tx_beacon_hdl(_adapter *padapter, unsigned char *pbuf)
13020 {
13021         if(send_beacon(padapter)==_FAIL)
13022         {
13023                 DBG_871X("issue_beacon, fail!\n");
13024                 return H2C_PARAMETERS_ERROR;
13025         }
13026
13027         /* tx bc/mc frames after update TIM */
13028         chk_bmc_sleepq_hdl(padapter, NULL);
13029
13030         return H2C_SUCCESS;
13031 }
13032
13033 void change_band_update_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
13034 {
13035         u8      network_type,rate_len, total_rate_len,remainder_rate_len;
13036         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
13037         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
13038         u8      erpinfo=0x4;
13039
13040         //DBG_871X("%s\n", __FUNCTION__);
13041
13042         if(pmlmeext->cur_channel >= 36)
13043         {
13044                 network_type = WIRELESS_11A;
13045                 total_rate_len = IEEE80211_NUM_OFDM_RATESLEN;
13046                 DBG_871X("%s(): change to 5G Band\n",__FUNCTION__);
13047                 rtw_remove_bcn_ie(padapter, pnetwork, _ERPINFO_IE_);
13048         }
13049         else
13050         {
13051                 network_type = WIRELESS_11BG;
13052                 total_rate_len = IEEE80211_CCK_RATE_LEN+IEEE80211_NUM_OFDM_RATESLEN;
13053                 DBG_871X("%s(): change to 2.4G Band\n",__FUNCTION__);
13054                 rtw_add_bcn_ie(padapter, pnetwork, _ERPINFO_IE_, &erpinfo, 1);
13055         }
13056
13057         rtw_set_supported_rate(pnetwork->SupportedRates, network_type);
13058
13059         UpdateBrateTbl(padapter, pnetwork->SupportedRates);
13060         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
13061
13062         if(total_rate_len > 8)
13063         {
13064                 rate_len = 8;
13065                 remainder_rate_len = total_rate_len - 8;
13066         }
13067         else
13068         {
13069                 rate_len = total_rate_len;
13070                 remainder_rate_len = 0;
13071         }
13072
13073         rtw_add_bcn_ie(padapter, pnetwork, _SUPPORTEDRATES_IE_, pnetwork->SupportedRates, rate_len);
13074
13075         if(remainder_rate_len)
13076         {
13077                 rtw_add_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_, (pnetwork->SupportedRates+8), remainder_rate_len);
13078         }
13079         else
13080         {
13081                 rtw_remove_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_);
13082         }
13083 }
13084
13085 #ifdef CONFIG_DUALMAC_CONCURRENT
13086 void dc_SelectChannel(_adapter *padapter, unsigned char channel)
13087 {
13088         PADAPTER ptarget_adapter;
13089
13090         if( (padapter->pbuddy_adapter != NULL) && 
13091                 (padapter->DualMacConcurrent == _TRUE) &&
13092                 (padapter->adapter_type == SECONDARY_ADAPTER))
13093         {
13094                 // only mac0 could control BB&RF
13095                 ptarget_adapter = padapter->pbuddy_adapter;
13096         }
13097         else
13098         {
13099                 ptarget_adapter = padapter;
13100         }
13101
13102         _enter_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setch_mutex), NULL);
13103
13104         rtw_hal_set_chan(ptarget_adapter, channel);
13105
13106         _exit_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setch_mutex), NULL);
13107 }
13108
13109 void dc_SetBWMode(_adapter *padapter, unsigned short bwmode, unsigned char channel_offset)
13110 {
13111         PADAPTER ptarget_adapter;
13112
13113         if( (padapter->pbuddy_adapter != NULL) && 
13114                 (padapter->DualMacConcurrent == _TRUE) &&
13115                 (padapter->adapter_type == SECONDARY_ADAPTER))
13116         {
13117                 // only mac0 could control BB&RF
13118                 ptarget_adapter = padapter->pbuddy_adapter;
13119         }
13120         else
13121         {
13122                 ptarget_adapter = padapter;
13123         }
13124
13125         _enter_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setbw_mutex), NULL);
13126
13127         rtw_hal_set_bwmode(ptarget_adapter, (CHANNEL_WIDTH)bwmode, channel_offset);
13128
13129         _exit_critical_mutex(&(adapter_to_dvobj(ptarget_adapter)->setbw_mutex), NULL);
13130 }
13131
13132 void dc_set_channel_bwmode_disconnect(_adapter *padapter)
13133 {
13134         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13135         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13136         struct mlme_priv *pbuddy_mlmepriv = NULL;
13137
13138         if(pbuddy_adapter != NULL && 
13139                 padapter->DualMacConcurrent == _TRUE)
13140         {
13141                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13142                 if((check_fwstate(pbuddy_mlmepriv, _FW_LINKED)) != _TRUE)
13143                 {
13144                         //switch to the 20M Hz mode after disconnect
13145                         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
13146                         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13147
13148                         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13149                 }
13150         }
13151         else
13152         {
13153                 //switch to the 20M Hz mode after disconnect
13154                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
13155                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13156
13157                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13158         }
13159 }
13160
13161 u8 dc_handle_join_request(_adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
13162 {
13163         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13164         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
13165         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
13166         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;             
13167         struct mlme_ext_priv *pbuddy_mlmeext = NULL;
13168         struct mlme_priv        *pbuddy_mlmepriv = NULL;
13169         u8      ret = _SUCCESS;
13170
13171         if(pbuddy_adapter != NULL && 
13172                 padapter->DualMacConcurrent == _TRUE)
13173         {
13174                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13175                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13176
13177                 if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel ||
13178                         pmlmeext->cur_bwmode != pbuddy_mlmeext->cur_bwmode ||
13179                         pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)
13180                 {
13181                         if((check_fwstate(pbuddy_mlmepriv, WIFI_AP_STATE)) == _TRUE)
13182                         {
13183                                 //issue deauth to all stas if if2 is at ap mode
13184                                 rtw_sta_flush(pbuddy_adapter);
13185
13186                                 //rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
13187                                 rtw_hal_set_hwreg(pbuddy_adapter, HW_VAR_CHECK_TXBUF, 0);
13188                         }
13189                         else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED) == _TRUE)
13190                         {
13191                                 if(pmlmeext->cur_channel == pbuddy_mlmeext->cur_channel)
13192                                 {
13193                                         // CHANNEL_WIDTH_40 or CHANNEL_WIDTH_20 but channel offset is different
13194                                         if((pmlmeext->cur_bwmode == pbuddy_mlmeext->cur_bwmode) &&
13195                                                 (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset) )
13196                                         {
13197                                                 report_join_res(padapter, -4);
13198                                                 ret = _FAIL;
13199                                         }
13200                                 }
13201                                 else
13202                                 {
13203                                         report_join_res(padapter, -4);
13204                                         ret = _FAIL;
13205                                 }
13206                         }
13207                 }
13208                 else     if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
13209                 {
13210                         issue_nulldata(pbuddy_adapter, NULL, 1, 0, 0);
13211                 }
13212         }
13213
13214         if (!ch || !bw || !offset) {
13215                 rtw_warn_on(1);
13216                 ret = _FAIL;
13217         }
13218
13219         if (ret == _SUCCESS) {
13220                 *ch = pmlmeext->cur_channel;
13221                 *bw = pmlmeext->cur_bwmode;
13222                 *offset = pmlmeext->cur_ch_offset;
13223         }
13224
13225 exit:
13226         return ret;
13227 }
13228
13229 void dc_handle_join_done(_adapter *padapter, u8 join_res)
13230 {
13231         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13232         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
13233         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13234         struct mlme_priv *pbuddy_mlmepriv = NULL;
13235         struct mlme_ext_priv *pbuddy_mlmeext = NULL;
13236         struct mlme_ext_info *pbuddy_mlmeinfo = NULL;
13237         WLAN_BSSID_EX *pbuddy_network_mlmeext = NULL;
13238         u8      change_band = _FALSE;
13239
13240
13241         if(pbuddy_adapter != NULL && 
13242                 padapter->DualMacConcurrent == _TRUE)
13243         {
13244                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13245                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13246                 pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
13247                 pbuddy_network_mlmeext = &(pbuddy_mlmeinfo->network);
13248         
13249                 if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
13250                                 check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
13251                 {
13252                         //restart and update beacon
13253                         DBG_871X("after join, current adapter, CH=%d, BW=%d, offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
13254
13255                         if(join_res >= 0)
13256                         {
13257                                 u8 *p;
13258                                 int     ie_len;
13259                                 struct HT_info_element *pht_info=NULL;
13260
13261                                 if((pbuddy_mlmeext->cur_channel <= 14 && pmlmeext->cur_channel >= 36) ||
13262                                         (pbuddy_mlmeext->cur_channel >= 36 && pmlmeext->cur_channel <= 14))
13263                                 {
13264                                         change_band = _TRUE;
13265                                 }
13266
13267                                 //sync channel/bwmode/ch_offset with another adapter
13268                                 pbuddy_mlmeext->cur_channel = pmlmeext->cur_channel;
13269                                 
13270                                 if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40)
13271                                 {
13272                                         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)));
13273                                         if( p && ie_len)
13274                                         {
13275                                                 pht_info = (struct HT_info_element *)(p+2);
13276                                                 pht_info->infos[0] &= ~(BIT(0)|BIT(1)); //no secondary channel is present
13277                                         }       
13278                                 
13279                                         if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_40)
13280                                         {
13281                                                 pbuddy_mlmeext->cur_ch_offset = pmlmeext->cur_ch_offset;
13282
13283                                                 //to update cur_ch_offset value in beacon
13284                                                 if( pht_info )
13285                                                 {
13286                                                         switch(pmlmeext->cur_ch_offset)
13287                                                         {
13288                                                                 case HAL_PRIME_CHNL_OFFSET_LOWER:
13289                                                                         pht_info->infos[0] |= 0x1;
13290                                                                         break;
13291                                                                 case HAL_PRIME_CHNL_OFFSET_UPPER:
13292                                                                         pht_info->infos[0] |= 0x3;
13293                                                                         break;
13294                                                                 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   
13295                                                                 default:                                                        
13296                                                                         break;                                  
13297                                                         }
13298                                                 }
13299                                         }
13300                                         else if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_20)
13301                                         {
13302                                                 pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_20;
13303                                                 pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13304
13305                                                 if(pmlmeext->cur_channel>0 && pmlmeext->cur_channel<5)
13306                                                 {
13307                                                         if(pht_info)
13308                                                                 pht_info->infos[0] |= 0x1;
13309
13310                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_40;
13311                                                         pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
13312                                                 }
13313
13314                                                 if(pmlmeext->cur_channel>7 && pmlmeext->cur_channel<(14+1))
13315                                                 {
13316                                                         if(pht_info)
13317                                                                 pht_info->infos[0] |= 0x3;
13318
13319                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_40;
13320                                                         pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
13321                                                 }
13322
13323                                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13324                                         }
13325                                 }
13326
13327                                 // to update channel value in beacon
13328                                 pbuddy_network_mlmeext->Configuration.DSConfig = pmlmeext->cur_channel;
13329                                 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)));
13330                                 if(p && ie_len>0)
13331                                         *(p + 2) = pmlmeext->cur_channel;
13332
13333                                 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)));
13334                                 if( p && ie_len)
13335                                 {
13336                                         pht_info = (struct HT_info_element *)(p+2);
13337                                         pht_info->primary_channel = pmlmeext->cur_channel;
13338                                 }
13339
13340                                 // update mlmepriv's cur_network
13341                                 _rtw_memcpy(&pbuddy_mlmepriv->cur_network.network, pbuddy_network_mlmeext, pbuddy_network_mlmeext->Length);
13342                         }
13343                         else
13344                         {
13345                                 // switch back to original channel/bwmode/ch_offset;
13346                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13347                         }
13348
13349                         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);
13350
13351                         if(change_band == _TRUE)
13352                                 change_band_update_ie(pbuddy_adapter, pbuddy_network_mlmeext);
13353
13354                         DBG_871X("update pbuddy_adapter's beacon\n");
13355
13356                         update_beacon(pbuddy_adapter, 0, NULL, _TRUE);
13357                 }
13358                 else     if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
13359                 {
13360                         if((pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
13361                                 (pmlmeext->cur_bwmode == CHANNEL_WIDTH_20))
13362                         {
13363                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13364                         }
13365                 
13366                         issue_nulldata(pbuddy_adapter, NULL, 0, 0, 0);
13367                 }
13368         }
13369 }
13370
13371 sint    dc_check_fwstate(_adapter *padapter, sint fw_state)
13372 {
13373         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13374         struct mlme_priv *pbuddy_mlmepriv = NULL;
13375
13376         if(padapter->pbuddy_adapter != NULL && 
13377                 padapter->DualMacConcurrent == _TRUE)
13378
13379         {
13380                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13381
13382                 return check_fwstate(pbuddy_mlmepriv, fw_state);
13383         }
13384
13385         return _FALSE;
13386 }
13387
13388 u8 dc_handle_site_survey(_adapter *padapter)
13389 {
13390         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13391         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
13392         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;             
13393
13394         // only mac0 can do scan request, help issue nulldata(1) for mac1
13395         if(pbuddy_adapter != NULL && 
13396                 padapter->DualMacConcurrent == _TRUE)
13397         {
13398                 if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
13399                 {
13400                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
13401                 
13402                         issue_nulldata(pbuddy_adapter, NULL, 1, 2, 0);                  
13403
13404                         return _TRUE;
13405                 }
13406         }
13407
13408         return _FALSE;
13409 }
13410
13411 void    dc_report_survey_event(_adapter *padapter, union recv_frame *precv_frame)
13412 {
13413         if(padapter->pbuddy_adapter != NULL && 
13414                 padapter->DualMacConcurrent == _TRUE)
13415         {
13416                 report_survey_event(padapter->pbuddy_adapter, precv_frame);     
13417         }
13418 }
13419
13420 void dc_set_channel_bwmode_survey_done(_adapter *padapter)
13421 {
13422         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
13423         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13424         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13425         struct mlme_priv *pbuddy_mlmepriv = NULL;
13426         struct mlme_ext_priv *pbuddy_mlmeext = NULL;
13427         struct mlme_ext_info *pbuddy_mlmeinfo = NULL;
13428         u8 cur_channel;
13429         u8 cur_bwmode;
13430         u8 cur_ch_offset;
13431
13432         if(pbuddy_adapter != NULL && 
13433                 padapter->DualMacConcurrent == _TRUE)
13434         {
13435                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13436                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13437                 pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
13438
13439                 if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
13440                 {
13441                         if(check_fwstate(pmlmepriv, _FW_LINKED) &&
13442                                 (pmlmeext->cur_bwmode == CHANNEL_WIDTH_40))
13443                         {
13444                                 cur_channel = pmlmeext->cur_channel;
13445                                 cur_bwmode = pmlmeext->cur_bwmode;
13446                                 cur_ch_offset = pmlmeext->cur_ch_offset;
13447                         }
13448                         else
13449                         {
13450                                 cur_channel = pbuddy_mlmeext->cur_channel;
13451                                 cur_bwmode = pbuddy_mlmeext->cur_bwmode;
13452                                 cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
13453                         }
13454                 }
13455                 else
13456                 {
13457                         cur_channel = pmlmeext->cur_channel;
13458                         cur_bwmode = pmlmeext->cur_bwmode;
13459                         cur_ch_offset = pmlmeext->cur_ch_offset;
13460                 }
13461
13462                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
13463
13464                 if (is_client_associated_to_ap(pbuddy_adapter) == _TRUE)
13465                 {
13466                         //issue null data 
13467                         issue_nulldata(pbuddy_adapter, NULL, 0, 0, 0);
13468                 }
13469
13470                 if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
13471                         check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
13472                 {
13473
13474                         DBG_871X("survey done, current CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
13475
13476                         DBG_871X("restart pbuddy_adapter's beacon\n");
13477                 
13478                         update_beacon(pbuddy_adapter, 0, NULL, _TRUE);
13479                 }
13480         }
13481         else
13482         {
13483                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13484         }
13485 }
13486
13487 void dc_set_ap_channel_bandwidth(_adapter *padapter, u8 channel, u8 channel_offset, u8 bwmode)
13488 {
13489         u8      *p;
13490         u8      val8, cur_channel, cur_bwmode, cur_ch_offset, change_band;
13491         int     ie_len; 
13492         struct registry_priv    *pregpriv = &padapter->registrypriv;
13493         struct mlme_priv                *pmlmepriv = &(padapter->mlmepriv);
13494         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
13495         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
13496         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
13497         struct HT_info_element  *pht_info=NULL;
13498         _adapter        *pbuddy_adapter = padapter->pbuddy_adapter;
13499         struct mlme_priv        *pbuddy_mlmepriv = NULL;
13500         struct mlme_ext_priv    *pbuddy_mlmeext = NULL;
13501
13502         DBG_871X("dualmac_concurrent_ap_set_channel_bwmode ==>\n");
13503
13504         cur_channel = channel;
13505         cur_bwmode = bwmode;
13506         cur_ch_offset = channel_offset;
13507         change_band = _FALSE;
13508
13509         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)));
13510         if( p && ie_len)
13511         {
13512                 pht_info = (struct HT_info_element *)(p+2);
13513         }
13514
13515         if(pbuddy_adapter != NULL && 
13516                 padapter->DualMacConcurrent == _TRUE)
13517         {
13518                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13519                 pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13520                 
13521                 if(!check_fwstate(pbuddy_mlmepriv, _FW_LINKED|_FW_UNDER_LINKING|_FW_UNDER_SURVEY))
13522                 {
13523                         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
13524                 }
13525                 else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED)==_TRUE)
13526                 {
13527                         //To sync cur_channel/cur_bwmode/cur_ch_offset with another adapter
13528                         DBG_871X("Another iface is at linked state, sync cur_channel/cur_bwmode/cur_ch_offset\n");
13529                         DBG_871X("Another adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
13530                         DBG_871X("Current adapter, CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
13531                         
13532                         cur_channel = pbuddy_mlmeext->cur_channel;
13533                         if(cur_bwmode == CHANNEL_WIDTH_40)
13534                         {
13535                                 if(pht_info)
13536                                         pht_info->infos[0] &= ~(BIT(0)|BIT(1));
13537
13538                                 if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40)
13539                                 {
13540                                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
13541
13542                                         //to update cur_ch_offset value in beacon
13543                                         if(pht_info)
13544                                         {                               
13545                                                 switch(cur_ch_offset)
13546                                                 {
13547                                                         case HAL_PRIME_CHNL_OFFSET_LOWER:
13548                                                                 pht_info->infos[0] |= 0x1;
13549                                                                 break;
13550                                                         case HAL_PRIME_CHNL_OFFSET_UPPER:
13551                                                                 pht_info->infos[0] |= 0x3;
13552                                                                 break;
13553                                                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
13554                                                         default:                                                        
13555                                                                 break;                                  
13556                                                 }
13557                                         }
13558                                 }
13559                                 else if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_20)
13560                                 {
13561                                         cur_bwmode = CHANNEL_WIDTH_20;
13562                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13563
13564                                         if(cur_channel>0 && cur_channel<5)
13565                                         {
13566                                                 if(pht_info)
13567                                                         pht_info->infos[0] |= 0x1;              
13568
13569                                                 cur_bwmode = CHANNEL_WIDTH_40;
13570                                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
13571                                         }
13572
13573                                         if(cur_channel>7 && cur_channel<(14+1))
13574                                         {
13575                                                 if(pht_info)
13576                                                         pht_info->infos[0] |= 0x3;
13577
13578                                                 cur_bwmode = CHANNEL_WIDTH_40;
13579                                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
13580                                         }
13581
13582                                         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
13583                                 }
13584                         }
13585
13586                         // to update channel value in beacon
13587                         pnetwork->Configuration.DSConfig = cur_channel;         
13588                         p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
13589                         if(p && ie_len>0)
13590                                 *(p + 2) = cur_channel;
13591
13592                         if(pht_info)
13593                                 pht_info->primary_channel = cur_channel;
13594                 }
13595         }
13596         else
13597         {
13598                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
13599         }
13600
13601         DBG_871X("CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
13602
13603         if((channel <= 14 && cur_channel >= 36) ||
13604                 (channel >= 36 && cur_channel <= 14))
13605         {
13606                 change_band = _TRUE;
13607         }
13608
13609         pmlmeext->cur_channel = cur_channel;
13610         pmlmeext->cur_bwmode = cur_bwmode;
13611         pmlmeext->cur_ch_offset = cur_ch_offset;
13612
13613         if(change_band == _TRUE)
13614                 change_band_update_ie(padapter, pnetwork);
13615
13616         DBG_871X("dualmac_concurrent_ap_set_channel_bwmode <==\n");
13617 }
13618
13619 void dc_resume_xmit(_adapter *padapter)
13620 {
13621         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13622         
13623         if(pbuddy_adapter != NULL && 
13624                 padapter->DualMacConcurrent == _TRUE)
13625         {
13626                 DBG_871X("dc_resume_xmit,  resume pbuddy_adapter Tx\n");
13627                 rtw_os_xmit_schedule(pbuddy_adapter);
13628         }
13629 }
13630
13631 u8      dc_check_xmit(_adapter *padapter)
13632 {
13633         PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
13634         struct mlme_priv *pbuddy_mlmepriv = NULL;
13635
13636         if(pbuddy_adapter != NULL && 
13637                 padapter->DualMacConcurrent == _TRUE)
13638         {
13639                 pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13640                 if (check_fwstate(pbuddy_mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
13641                 {
13642                         DBG_871X("dc_check_xmit  pbuddy_adapter is under survey or under linking\n");
13643                         return _FALSE;
13644                 }
13645         }
13646
13647         return _TRUE;
13648 }
13649 #endif
13650
13651 #ifdef CONFIG_CONCURRENT_MODE
13652 sint check_buddy_mlmeinfo_state(_adapter *padapter, u32 state)
13653 {
13654         PADAPTER pbuddy_adapter;
13655         struct mlme_ext_priv *pbuddy_mlmeext;
13656         struct mlme_ext_info *pbuddy_mlmeinfo;
13657
13658         if(padapter == NULL)
13659                 return _FALSE;  
13660         
13661         pbuddy_adapter = padapter->pbuddy_adapter;
13662
13663         if(pbuddy_adapter == NULL)
13664                 return _FALSE;  
13665
13666
13667         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13668         pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
13669                 
13670         if((pbuddy_mlmeinfo->state&0x03) == state)
13671                 return _TRUE;           
13672
13673         return _FALSE;
13674         
13675 }
13676
13677 void concurrent_chk_joinbss_done(_adapter *padapter, int join_res)
13678 {
13679         struct mlme_ext_priv    *pmlmeext;
13680         struct mlme_ext_info    *pmlmeinfo;     
13681         PADAPTER pbuddy_adapter;
13682         struct mlme_priv *pbuddy_mlmepriv;
13683         struct mlme_ext_priv *pbuddy_mlmeext;
13684         struct mlme_ext_info *pbuddy_mlmeinfo;
13685         WLAN_BSSID_EX *pbuddy_network_mlmeext;
13686         WLAN_BSSID_EX *pnetwork;
13687
13688         pmlmeext = &padapter->mlmeextpriv;
13689         pmlmeinfo = &(pmlmeext->mlmext_info);
13690
13691
13692         if(!rtw_buddy_adapter_up(padapter))
13693         {
13694                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13695                 return;
13696         }
13697
13698         pbuddy_adapter = padapter->pbuddy_adapter;
13699         pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13700         pnetwork = (WLAN_BSSID_EX *)&pbuddy_mlmepriv->cur_network.network;
13701         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13702         pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
13703         pbuddy_network_mlmeext = &(pbuddy_mlmeinfo->network);
13704
13705         if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
13706                         check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
13707         {
13708                 //restart and update beacon
13709
13710                 DBG_871X("after join,primary adapter, CH=%d, BW=%d, offset=%d\n"
13711                         , pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
13712                 
13713
13714                 if(join_res >= 0)
13715                 {
13716                         u8 *p;
13717                         int     ie_len;
13718                         u8      change_band = _FALSE;
13719                         struct HT_info_element *pht_info=NULL;
13720
13721                         if((pmlmeext->cur_channel <= 14 && pbuddy_mlmeext->cur_channel >= 36) ||
13722                                 (pmlmeext->cur_channel >= 36 && pbuddy_mlmeext->cur_channel <= 14))
13723                                 change_band = _TRUE;
13724
13725                         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)));
13726                         if( p && ie_len)
13727                         {
13728                                 pht_info = (struct HT_info_element *)(p+2);
13729                                 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; //no secondary channel is present
13730                         }
13731
13732                         pbuddy_mlmeext->cur_channel = pmlmeext->cur_channel;
13733 #ifdef CONFIG_80211AC_VHT
13734                         if(pbuddy_mlmeext->cur_bwmode  == CHANNEL_WIDTH_80)
13735                         {
13736                                 u8 *pvht_cap_ie, *pvht_op_ie;
13737                                 int vht_cap_ielen, vht_op_ielen;
13738                         
13739                                 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)));
13740                                 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)));
13741                                                 
13742                                 if(pmlmeext->cur_channel <= 14) // downgrade to 20/40Mhz
13743                                 {
13744                                         //modify vht cap ie
13745                                         if( pvht_cap_ie && vht_cap_ielen)
13746                                         {
13747                                                 SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvht_cap_ie+2, 0);
13748                                         }
13749                                 
13750                                         //modify vht op ie
13751                                         if( pvht_op_ie && vht_op_ielen)
13752                                         {
13753                                                 SET_VHT_OPERATION_ELE_CHL_WIDTH(pvht_op_ie+2, 0); //change to 20/40Mhz
13754                                                 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pvht_op_ie+2, 0);
13755                                                 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(pvht_op_ie+2, 0);
13756                                                 //SET_VHT_OPERATION_ELE_BASIC_MCS_SET(p+2, 0xFFFF);                                     
13757                                                 pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_40;
13758                                         }               
13759                                 }
13760                                 else
13761                                 {
13762                                         u8      center_freq;
13763                                 
13764                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_80;
13765                                 
13766                                         if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||
13767                                                 pmlmeext->cur_bwmode == CHANNEL_WIDTH_80)
13768                                         {
13769                                                 pbuddy_mlmeext->cur_ch_offset = pmlmeext->cur_ch_offset;
13770                                         }
13771                                         else if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_20)
13772                                         {
13773                                                 pbuddy_mlmeext->cur_ch_offset =  rtw_get_offset_by_ch(pmlmeext->cur_channel);
13774                                         }       
13775
13776                                         //modify ht info ie
13777                                         if(pht_info)
13778                                                 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
13779                                 
13780                                         switch(pbuddy_mlmeext->cur_ch_offset)
13781                                         {
13782                                                 case HAL_PRIME_CHNL_OFFSET_LOWER:
13783                                                         if(pht_info)
13784                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;            
13785                                                         //cur_bwmode = CHANNEL_WIDTH_40;
13786                                                         break;
13787                                                 case HAL_PRIME_CHNL_OFFSET_UPPER:
13788                                                         if(pht_info)
13789                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;                                            
13790                                                         //cur_bwmode = CHANNEL_WIDTH_40;
13791                                                         break;
13792                                                 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   
13793                                                 default:
13794                                                         if(pht_info)
13795                                                                 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
13796                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_20;
13797                                                         pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13798                                                         break;                                  
13799                                         }
13800
13801                                         //modify vht op ie
13802                                         center_freq = rtw_get_center_ch(pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, HAL_PRIME_CHNL_OFFSET_LOWER);
13803                                         if( pvht_op_ie && vht_op_ielen)
13804                                                 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pvht_op_ie+2, center_freq);
13805
13806                                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13807                                 
13808                                 }
13809                         
13810                         }
13811 #endif //CONFIG_80211AC_VHT
13812                         
13813                         if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40)              
13814                         {
13815                                 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)));
13816                                 if( p && ie_len)
13817                                 {
13818                                         pht_info = (struct HT_info_element *)(p+2);
13819                                         pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; //no secondary channel is present
13820                                 }
13821                         
13822                                 if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||
13823                                         pmlmeext->cur_bwmode == CHANNEL_WIDTH_80)
13824                                 {
13825                                         pbuddy_mlmeext->cur_ch_offset = pmlmeext->cur_ch_offset;
13826
13827                                         //to update cur_ch_offset value in beacon
13828                                         if( pht_info )
13829                                         {
13830                                                 switch(pmlmeext->cur_ch_offset)
13831                                                 {
13832                                                         case HAL_PRIME_CHNL_OFFSET_LOWER:
13833                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
13834                                                                 break;
13835                                                         case HAL_PRIME_CHNL_OFFSET_UPPER:
13836                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
13837                                                                 break;
13838                                                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   
13839                                                         default:                                                        
13840                                                                 break;                                  
13841                                                 }
13842                                                 
13843                                         }                                       
13844                                 
13845                                 }
13846                                 else if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_20)
13847                                 {
13848                                         pbuddy_mlmeext->cur_ch_offset =  rtw_get_offset_by_ch(pmlmeext->cur_channel);
13849                                         
13850                                         switch(pbuddy_mlmeext->cur_ch_offset)
13851                                         {
13852                                                 case HAL_PRIME_CHNL_OFFSET_LOWER:
13853                                                         if(pht_info)
13854                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;            
13855                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_40;
13856                                                         break;
13857                                                 case HAL_PRIME_CHNL_OFFSET_UPPER:
13858                                                         if(pht_info)
13859                                                                 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;                                            
13860                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_40;
13861                                                         break;
13862                                                 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   
13863                                                 default:
13864                                                         if(pht_info)
13865                                                                 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
13866                                                         pbuddy_mlmeext->cur_bwmode = CHANNEL_WIDTH_20;
13867                                                         pbuddy_mlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
13868                                                         break;                                  
13869                                         }
13870                                         
13871                                 }
13872
13873                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13874
13875                         }
13876                         else
13877                         {
13878                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13879                         }
13880
13881                 
13882                         // to update channel value in beacon
13883                         pbuddy_network_mlmeext->Configuration.DSConfig = pmlmeext->cur_channel;         
13884                         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)));
13885                         if(p && ie_len>0)
13886                                 *(p + 2) = pmlmeext->cur_channel;
13887
13888                         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)));
13889                         if( p && ie_len)
13890                         {
13891                                 pht_info = (struct HT_info_element *)(p+2);
13892                                 pht_info->primary_channel = pmlmeext->cur_channel;
13893                         }
13894
13895                         //buddy interface band is different from current interface, update ERP, support rate, ext support rate IE
13896                         if(change_band == _TRUE)
13897                                 change_band_update_ie(pbuddy_adapter, pbuddy_network_mlmeext);
13898                 }
13899                 else
13900                 {
13901                         // switch back to original channel/bwmode/ch_offset;
13902                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13903                 }
13904
13905                 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);
13906
13907                 DBG_871X("update pbuddy_adapter's beacon\n");
13908                 
13909                 _rtw_memcpy(pnetwork, pbuddy_network_mlmeext, sizeof(WLAN_BSSID_EX));
13910                 //update bmc rate to avoid bb cck hang
13911                 update_bmc_sta(pbuddy_adapter);
13912                 update_beacon(pbuddy_adapter, 0, NULL, _TRUE);
13913
13914         }
13915         else if(((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) &&
13916                         check_fwstate(pbuddy_mlmepriv, _FW_LINKED))
13917         {               
13918                 if(join_res >= 0)
13919                 {       
13920                         pbuddy_mlmeext->cur_channel = pmlmeext->cur_channel;
13921                         if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||
13922                                 pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80)
13923                                 set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);           
13924                         else if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||
13925                                 pmlmeext->cur_bwmode == CHANNEL_WIDTH_80)
13926                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);             
13927                         else
13928                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
13929                 }
13930                 else
13931                 {
13932                         // switch back to original channel/bwmode/ch_offset;
13933                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
13934                 }                       
13935         }
13936         else
13937         {
13938                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
13939         }
13940         
13941 }
13942 #endif //CONFIG_CONCURRENT_MODE
13943
13944 int rtw_chk_start_clnt_join(_adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
13945 {
13946         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
13947         unsigned char   cur_ch = pmlmeext->cur_channel;
13948         unsigned char   cur_bw = pmlmeext->cur_bwmode;
13949         unsigned char   cur_ch_offset = pmlmeext->cur_ch_offset;
13950         bool chbw_allow = _TRUE;
13951         bool connect_allow = _TRUE;
13952
13953 #ifdef CONFIG_CONCURRENT_MODE
13954         PADAPTER pbuddy_adapter;
13955         struct mlme_ext_priv *pbuddy_mlmeext;
13956         struct mlme_ext_info    *pbuddy_pmlmeinfo;
13957         struct mlme_priv *pbuddy_mlmepriv;
13958
13959         if (!rtw_buddy_adapter_up(padapter)) {
13960                 goto exit;
13961         }
13962
13963         pbuddy_adapter = padapter->pbuddy_adapter;              
13964         pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
13965         pbuddy_pmlmeinfo = &(pbuddy_mlmeext->mlmext_info);
13966         pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
13967
13968         if((pbuddy_pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)//for AP MODE
13969         {
13970                 DBG_871X("start_clnt_join: "ADPT_FMT"(ch=%d, bw=%d, ch_offset=%d)"
13971                         ", "ADPT_FMT" AP mode(ch=%d, bw=%d, ch_offset=%d)\n",
13972                         ADPT_ARG(padapter), pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset,
13973                         ADPT_ARG(pbuddy_adapter), pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
13974
13975                 if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel)
13976                 {
13977                         chbw_allow = _FALSE;
13978                 }
13979                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
13980                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
13981                         (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset))
13982                 {
13983                         chbw_allow = _FALSE;
13984                 }
13985                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_20) && 
13986                         ((pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40)||
13987                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80)) )
13988                 {
13989                         cur_ch = pmlmeext->cur_channel;
13990                         cur_bw = pbuddy_mlmeext->cur_bwmode;
13991                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
13992                 }
13993
13994                 DBG_871X("start_clnt_join: connect_allow:%d, chbw_allow:%d\n", connect_allow, chbw_allow);
13995                 if (chbw_allow == _FALSE) {
13996                         #ifdef CONFIG_SPCT_CH_SWITCH
13997                         if (1) {
13998                                 rtw_ap_inform_ch_switch(pbuddy_adapter, pmlmeext->cur_channel , pmlmeext->cur_ch_offset);
13999                         } else
14000                         #endif
14001                         {
14002                                 //issue deauth to all stas if if2 is at ap mode
14003                                 rtw_sta_flush(pbuddy_adapter);
14004                         }
14005                         rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
14006                 }
14007         }
14008         else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED) == _TRUE &&
14009                 check_fwstate(pbuddy_mlmepriv, WIFI_STATION_STATE) == _TRUE) //for Client Mode/p2p client
14010         {
14011                 DBG_871X("start_clnt_join: "ADPT_FMT"(ch=%d, bw=%d, ch_offset=%d)"
14012                         ", "ADPT_FMT" STA mode(ch=%d, bw=%d, ch_offset=%d)\n",
14013                         ADPT_ARG(padapter), pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset,
14014                         ADPT_ARG(pbuddy_adapter), pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
14015
14016                 if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel)
14017                 {
14018                         chbw_allow = _FALSE;
14019                 }
14020                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_20) &&
14021                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40))
14022                 {
14023                         cur_bw = CHANNEL_WIDTH_40;
14024                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
14025                 }
14026                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_20) &&
14027                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80))
14028                 {
14029                         cur_bw = CHANNEL_WIDTH_80;
14030                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
14031                 }
14032                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
14033                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
14034                         (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset))
14035                 {
14036                         chbw_allow = _FALSE;
14037                 }
14038                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_40) &&
14039                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80))
14040                 {
14041                         if(pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)
14042                         {
14043                                 chbw_allow = _FALSE;
14044                         }
14045                         else
14046                         {
14047                                 cur_bw = CHANNEL_WIDTH_80;
14048                         }
14049                 }
14050                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_80) &&
14051                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40))
14052                 {
14053                         if(pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)
14054                         {
14055                                 chbw_allow = _FALSE;
14056                         }
14057                 }
14058                 else if((pmlmeext->cur_bwmode == CHANNEL_WIDTH_80) &&
14059                         (pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80))
14060                 {
14061                         if(pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)
14062                         {
14063                                 chbw_allow = _FALSE;
14064                         }
14065                 }
14066
14067
14068                 connect_allow = chbw_allow;
14069
14070 #ifdef CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT
14071                 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
14072                 /* wlan0-sta mode has higher priority than p2p0-p2p client */
14073                 if (!rtw_p2p_chk_state(&(pbuddy_adapter->wdinfo), P2P_STATE_NONE)
14074                         && pbuddy_adapter->wdinfo.driver_interface == DRIVER_CFG80211)
14075                 {
14076                         connect_allow = _TRUE;
14077                 }
14078                 #endif /* CONFIG_P2P && CONFIG_IOCTL_CFG80211 */
14079 #else
14080                 connect_allow = _TRUE;
14081 #endif /* CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT */
14082
14083                 DBG_871X("start_clnt_join: connect_allow:%d, chbw_allow:%d\n", connect_allow, chbw_allow);
14084                 if (connect_allow == _TRUE && chbw_allow == _FALSE) {
14085                         /* disconnect buddy's connection */
14086                         rtw_disassoc_cmd(pbuddy_adapter, 500, _FALSE);
14087                         rtw_indicate_disconnect(pbuddy_adapter);
14088                         rtw_free_assoc_resources(pbuddy_adapter, 1);
14089                 }
14090         }       
14091
14092 exit:
14093 #endif /* CONFIG_CONCURRENT_MODE */
14094
14095         if (!ch || !bw || !offset) {
14096                 rtw_warn_on(1);
14097                 connect_allow = _FALSE;
14098         }
14099
14100         if (connect_allow == _TRUE) {
14101                 DBG_871X("start_join_set_ch_bw: ch=%d, bwmode=%d, ch_offset=%d\n", cur_ch, cur_bw, cur_ch_offset);
14102                 *ch = cur_ch;
14103                 *bw = cur_bw;
14104                 *offset = cur_ch_offset;
14105         }
14106
14107         return connect_allow == _TRUE ? _SUCCESS : _FAIL;
14108 }
14109
14110 /* Find union about ch, bw, ch_offset of all linked/linking interfaces */
14111 int rtw_get_ch_setting_union(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
14112 {
14113         struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
14114         _adapter *iface;
14115         struct mlme_ext_priv *mlmeext;
14116         int i;
14117         u8 ch_ret = 0;
14118         u8 bw_ret = CHANNEL_WIDTH_20;
14119         u8 offset_ret = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
14120         int num = 0;
14121
14122         if (ch) *ch = 0;
14123         if (bw) *bw = CHANNEL_WIDTH_20;
14124         if (offset) *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
14125
14126         for (i = 0; i<dvobj->iface_nums; i++) {
14127                 iface = dvobj->padapters[i];
14128                 mlmeext = &iface->mlmeextpriv;
14129
14130                 if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING))
14131                         continue;
14132
14133                 if (num == 0) {
14134                         ch_ret = mlmeext->cur_channel;
14135                         bw_ret = mlmeext->cur_bwmode;
14136                         offset_ret = mlmeext->cur_ch_offset;
14137                         num++;
14138                         continue;
14139                 }
14140
14141                 if (ch_ret != mlmeext->cur_channel) {
14142                         num = 0;
14143                         break;
14144                 }
14145
14146                 if (bw_ret < mlmeext->cur_bwmode) {
14147                         bw_ret = mlmeext->cur_bwmode;
14148                         offset_ret = mlmeext->cur_ch_offset;
14149                 } else if (bw_ret == mlmeext->cur_bwmode && offset_ret != mlmeext->cur_ch_offset) {
14150                         num = 0;
14151                         break;
14152                 }
14153
14154                 num++;
14155         }
14156
14157         if (num) {
14158                 if (ch) *ch = ch_ret;
14159                 if (bw) *bw = bw_ret;
14160                 if (offset) *offset = offset_ret;
14161         }
14162
14163         return num;
14164 }
14165
14166 u8 set_ch_hdl(_adapter *padapter, u8 *pbuf)
14167 {
14168         struct set_ch_parm *set_ch_parm;
14169         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
14170         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
14171
14172         if(!pbuf)
14173                 return H2C_PARAMETERS_ERROR;
14174
14175         set_ch_parm = (struct set_ch_parm *)pbuf;
14176
14177         DBG_871X(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
14178                 FUNC_NDEV_ARG(padapter->pnetdev),
14179                 set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
14180
14181         pmlmeext->cur_channel = set_ch_parm->ch;
14182         pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
14183         pmlmeext->cur_bwmode = set_ch_parm->bw;
14184
14185         set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
14186
14187         return  H2C_SUCCESS;
14188 }
14189
14190 u8 set_chplan_hdl(_adapter *padapter, unsigned char *pbuf)
14191 {
14192         struct SetChannelPlan_param *setChannelPlan_param;
14193         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
14194         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
14195
14196         if(!pbuf)
14197                 return H2C_PARAMETERS_ERROR;
14198
14199         setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
14200
14201         pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
14202         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);   
14203
14204 #ifdef CONFIG_IOCTL_CFG80211
14205         if ((padapter->rtw_wdev != NULL) && (padapter->rtw_wdev->wiphy)) {
14206                 struct regulatory_request request;
14207                 request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
14208                 rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request);
14209         }
14210 #endif //CONFIG_IOCTL_CFG80211
14211
14212         return  H2C_SUCCESS;
14213 }
14214
14215 u8 led_blink_hdl(_adapter *padapter, unsigned char *pbuf)
14216 {
14217         struct LedBlink_param *ledBlink_param;
14218
14219         if(!pbuf)
14220                 return H2C_PARAMETERS_ERROR;
14221
14222         ledBlink_param = (struct LedBlink_param *)pbuf;
14223
14224         #ifdef CONFIG_LED_HANDLED_BY_CMD_THREAD
14225         BlinkHandler((PLED_DATA)ledBlink_param->pLed);
14226         #endif
14227
14228         return  H2C_SUCCESS;
14229 }
14230
14231 u8 set_csa_hdl(_adapter *padapter, unsigned char *pbuf)
14232 {
14233 #ifdef CONFIG_DFS
14234         struct SetChannelSwitch_param *setChannelSwitch_param;
14235         u8 new_ch_no;
14236         u8 gval8 = 0x00, sval8 = 0xff;
14237
14238         if(!pbuf)
14239                 return H2C_PARAMETERS_ERROR;
14240
14241         setChannelSwitch_param = (struct SetChannelSwitch_param *)pbuf;
14242         new_ch_no = setChannelSwitch_param->new_ch_no;
14243
14244         rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, &gval8);
14245
14246         rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &sval8);
14247
14248         DBG_871X("DFS detected! Swiching channel to %d!\n", new_ch_no);
14249         SelectChannel(padapter, new_ch_no);
14250
14251         rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &gval8);
14252
14253         rtw_disassoc_cmd(padapter, 0, _FALSE);
14254         rtw_indicate_disconnect(padapter);
14255         rtw_free_assoc_resources(padapter, 1);
14256         rtw_free_network_queue(padapter, _TRUE);
14257
14258         if ( ((new_ch_no >= 52) && (new_ch_no <= 64)) ||((new_ch_no >= 100) && (new_ch_no <= 140)) ) {
14259                 DBG_871X("Switched to DFS band (ch %02x) again!!\n", new_ch_no);
14260         }
14261
14262         return  H2C_SUCCESS;
14263 #else
14264         return  H2C_REJECTED;
14265 #endif //CONFIG_DFS
14266
14267 }
14268
14269 // TDLS_ESTABLISHED     : write RCR DATA BIT
14270 // TDLS_CS_OFF          : go back to the channel linked with AP, terminating channel switch procedure
14271 // TDLS_INIT_CH_SEN     : init channel sensing, receive all data and mgnt frame
14272 // TDLS_DONE_CH_SEN: channel sensing and report candidate channel
14273 // TDLS_OFF_CH          : first time set channel to off channel
14274 // TDLS_BASE_CH         : go back tp the channel linked with AP when set base channel as target channel
14275 // TDLS_P_OFF_CH        : periodically go to off channel
14276 // TDLS_P_BASE_CH       : periodically go back to base channel
14277 // TDLS_RS_RCR          : restore RCR
14278 // TDLS_TEAR_STA        : free tdls sta
14279 u8 tdls_hdl(_adapter *padapter, unsigned char *pbuf)
14280 {
14281 #ifdef CONFIG_TDLS
14282         _irqL irqL;
14283         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
14284         struct TDLSoption_param *TDLSoption;
14285         struct sta_info *ptdls_sta;
14286         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
14287         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
14288         u8 survey_channel, i, min, option;
14289
14290         if(!pbuf)
14291                 return H2C_PARAMETERS_ERROR;
14292
14293         TDLSoption = (struct TDLSoption_param *)pbuf;
14294
14295         ptdls_sta = rtw_get_stainfo( &(padapter->stapriv), TDLSoption->addr );
14296         option = TDLSoption->option;
14297
14298         if( ptdls_sta == NULL )
14299         {
14300                 if( option != TDLS_RS_RCR )
14301                         return H2C_REJECTED;
14302         }
14303
14304         //_enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL);
14305         DBG_871X("[%s] option:%d\n", __FUNCTION__, option);
14306                 
14307         switch(option){
14308                 case TDLS_ESTABLISHED:
14309                 {
14310                         u8 sta_band = 0;
14311                         
14312                         //leave ALL PS when TDLS is established
14313                         rtw_pwr_wakeup(padapter);
14314                         
14315                         //As long as TDLS handshake success, we should set RCR_CBSSID_DATA bit to 0
14316                         //so we can receive all kinds of data frames.                   
14317                         rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_WRCR, 0);
14318                         DBG_871X("Created Direct Link with "MAC_FMT"\n", MAC_ARG(ptdls_sta->hwaddr));
14319
14320                         pmlmeinfo->FW_sta_info[ptdls_sta->mac_id].psta = ptdls_sta;
14321                         //set TDLS sta rate.
14322                         //update station supportRate
14323                         rtw_hal_update_sta_rate_mask(padapter, ptdls_sta);
14324                         if(padapter->mlmeextpriv.cur_channel > 14) {
14325                                 if (ptdls_sta->ra_mask & 0xffff000)
14326                                         sta_band |= WIRELESS_11_5N ;
14327
14328                                 if (ptdls_sta->ra_mask & 0xff0)
14329                                         sta_band |= WIRELESS_11A;
14330
14331                                 // 5G band
14332                                 #ifdef CONFIG_80211AC_VHT
14333                                 if (ptdls_sta->vhtpriv.vht_option)  {
14334                                         sta_band = WIRELESS_11_5AC;
14335                                 }               
14336                                 #endif
14337                                 
14338                         } else {
14339                                 if (ptdls_sta->ra_mask & 0xffff000)
14340                                         sta_band |= WIRELESS_11_24N;
14341
14342                                 if (ptdls_sta->ra_mask & 0xff0)
14343                                         sta_band |= WIRELESS_11G;
14344
14345                                 if (ptdls_sta->ra_mask & 0x0f)
14346                                         sta_band |= WIRELESS_11B;
14347                         }
14348                         ptdls_sta->wireless_mode = sta_band;
14349                         ptdls_sta->raid = rtw_hal_networktype_to_raid(padapter,ptdls_sta);
14350                         set_sta_rate(padapter, ptdls_sta);
14351                         //sta mode
14352                         rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,ptdls_sta,_TRUE);
14353                         break;
14354                 }
14355                 case TDLS_SD_PTI:
14356                         ptdls_sta->tdls_sta_state |= TDLS_WAIT_PTR_STATE;
14357                         issue_tdls_peer_traffic_indication(padapter, ptdls_sta);
14358                         _set_timer(&ptdls_sta->pti_timer, TDLS_PTI_TIME);
14359                         break;
14360                 case TDLS_CS_OFF:
14361                         _cancel_timer_ex(&ptdls_sta->base_ch_timer);
14362                         _cancel_timer_ex(&ptdls_sta->off_ch_timer);
14363                         SelectChannel(padapter, pmlmeext->cur_channel);
14364                         ptdls_sta->tdls_sta_state &= ~(TDLS_CH_SWITCH_ON_STATE | 
14365                                                                 TDLS_PEER_AT_OFF_STATE | 
14366                                                                 TDLS_AT_OFF_CH_STATE);
14367                         DBG_871X("go back to base channel\n ");
14368                         issue_nulldata(padapter, NULL, 0, 0, 0);
14369                         break;
14370                 case TDLS_INIT_CH_SEN:
14371                         rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_INIT_CH_SEN, 0);
14372                         pmlmeext->sitesurvey_res.channel_idx = 0;
14373                         ptdls_sta->option = TDLS_DONE_CH_SEN;
14374                         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_DONE_CH_SEN);
14375                         break;
14376                 case TDLS_DONE_CH_SEN:
14377                         survey_channel = pmlmeext->channel_set[pmlmeext->sitesurvey_res.channel_idx].ChannelNum;
14378                         if(survey_channel){
14379                                 SelectChannel(padapter, survey_channel);
14380                                 ptdlsinfo->cur_channel = survey_channel;
14381                                 pmlmeext->sitesurvey_res.channel_idx++;
14382                                 _set_timer(&ptdls_sta->option_timer, SURVEY_TO);
14383                         }else{
14384                                 SelectChannel(padapter, pmlmeext->cur_channel);
14385
14386                                 rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_DONE_CH_SEN, 0);
14387
14388                                 if(ptdlsinfo->ch_sensing==1){
14389                                         ptdlsinfo->ch_sensing=0;
14390                                         ptdlsinfo->cur_channel=1;
14391                                         min=ptdlsinfo->collect_pkt_num[0];
14392                                         for(i=1; i<MAX_CHANNEL_NUM-1; i++){
14393                                                 if(min > ptdlsinfo->collect_pkt_num[i]){
14394                                                         ptdlsinfo->cur_channel=i+1;
14395                                                         min=ptdlsinfo->collect_pkt_num[i];
14396                                                 }
14397                                                 ptdlsinfo->collect_pkt_num[i]=0;
14398                                         }
14399                                         ptdlsinfo->collect_pkt_num[0]=0;
14400                                         ptdlsinfo->candidate_ch=ptdlsinfo->cur_channel;
14401                                         DBG_871X("TDLS channel sensing done, candidate channel: %02x\n", ptdlsinfo->candidate_ch);
14402                                         ptdlsinfo->cur_channel=0;
14403
14404                                 }
14405
14406                                 if(ptdls_sta->tdls_sta_state & TDLS_PEER_SLEEP_STATE){
14407                                         ptdls_sta->tdls_sta_state |= TDLS_APSD_CHSW_STATE;
14408                                 }else{
14409                                         //send null data with pwrbit==1 before send ch_switching_req to peer STA.
14410                                         issue_nulldata(padapter, NULL, 1, 0, 0);
14411
14412                                         ptdls_sta->tdls_sta_state |= TDLS_CH_SW_INITIATOR_STATE;
14413
14414                                         issue_tdls_ch_switch_req(padapter, ptdls_sta->hwaddr);
14415                                         DBG_871X("issue tdls ch switch req\n");
14416                                 }
14417                         }
14418                         break;
14419                 case TDLS_OFF_CH:
14420                         issue_nulldata(padapter, NULL, 1, 0, 0);
14421                         SelectChannel(padapter, ptdls_sta->off_ch);
14422
14423                         DBG_871X("change channel to tar ch:%02x\n", ptdls_sta->off_ch);
14424                         ptdls_sta->tdls_sta_state |= TDLS_AT_OFF_CH_STATE;
14425                         ptdls_sta->tdls_sta_state &= ~(TDLS_PEER_AT_OFF_STATE);
14426                         _set_timer(&ptdls_sta->option_timer, (u32)ptdls_sta->ch_switch_time);
14427                         break;
14428                 case TDLS_BASE_CH:
14429                         _cancel_timer_ex(&ptdls_sta->base_ch_timer);
14430                         _cancel_timer_ex(&ptdls_sta->off_ch_timer);
14431                         SelectChannel(padapter, pmlmeext->cur_channel);
14432                         ptdls_sta->tdls_sta_state &= ~(TDLS_CH_SWITCH_ON_STATE | 
14433                                                                 TDLS_PEER_AT_OFF_STATE | 
14434                                                                 TDLS_AT_OFF_CH_STATE);
14435                         DBG_871X("go back to base channel\n ");
14436                         issue_nulldata(padapter, NULL, 0, 0, 0);
14437                         _set_timer(&ptdls_sta->option_timer, (u32)ptdls_sta->ch_switch_time);
14438                         break;
14439                 case TDLS_P_OFF_CH:
14440                         SelectChannel(padapter, pmlmeext->cur_channel);
14441                         issue_nulldata(padapter, NULL, 0, 0, 0);
14442                         DBG_871X("change channel to base ch:%02x\n", pmlmeext->cur_channel);
14443                         ptdls_sta->tdls_sta_state &= ~(TDLS_PEER_AT_OFF_STATE| TDLS_AT_OFF_CH_STATE);
14444                         _set_timer(&ptdls_sta->off_ch_timer, TDLS_STAY_TIME);
14445                         break;
14446                 case TDLS_P_BASE_CH:
14447                         issue_nulldata(ptdls_sta->padapter, NULL, 1, 0, 0);
14448                         SelectChannel(padapter, ptdls_sta->off_ch);
14449                         DBG_871X("change channel to off ch:%02x\n", ptdls_sta->off_ch);
14450                         ptdls_sta->tdls_sta_state |= TDLS_AT_OFF_CH_STATE;
14451                         if((ptdls_sta->tdls_sta_state & TDLS_PEER_AT_OFF_STATE) != TDLS_PEER_AT_OFF_STATE){
14452                                 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 3, 300);
14453                         }
14454                         _set_timer(&ptdls_sta->base_ch_timer, TDLS_STAY_TIME);  
14455                         break;
14456                 case TDLS_RS_RCR:
14457                         rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_RS_RCR, 0);
14458                         DBG_871X("wirte REG_RCR, set bit6 on\n");
14459                         break;
14460                 case TDLS_TEAR_STA:
14461                         free_tdls_sta(padapter, ptdls_sta);
14462                         break;
14463                         
14464         }
14465
14466         //_exit_critical_bh(&(ptdlsinfo->hdl_lock), &irqL);
14467
14468         return H2C_SUCCESS;
14469 #else
14470         return H2C_REJECTED;
14471 #endif //CONFIG_TDLS
14472
14473 }
14474