GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / staging / rtl8723bs / 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  ******************************************************************************/
15 #define _RTW_MLME_EXT_C_
16
17 #include <drv_types.h>
18 #include <rtw_debug.h>
19 #include <rtw_wifi_regd.h>
20
21
22 static struct mlme_handler mlme_sta_tbl[] = {
23         {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
24         {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
25         {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
26         {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
27         {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
28         {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
29
30         /*----------------------------------------------------------
31                                         below 2 are reserved
32         -----------------------------------------------------------*/
33         {0,                                     "DoReserved",           &DoReserved},
34         {0,                                     "DoReserved",           &DoReserved},
35         {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
36         {WIFI_ATIM,                     "OnATIM",               &OnAtim},
37         {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
38         {WIFI_AUTH,                     "OnAuth",               &OnAuthClient},
39         {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
40         {WIFI_ACTION,           "OnAction",             &OnAction},
41         {WIFI_ACTION_NOACK, "OnActionNoAck",    &OnAction},
42 };
43
44 static struct action_handler OnAction_tbl[] = {
45         {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,        "ACTION_SPECTRUM_MGMT", on_action_spct},
46         {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &DoReserved},
47         {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &DoReserved},
48         {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
49         {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
50         {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
51         {RTW_WLAN_CATEGORY_FT, "ACTION_FT",     &DoReserved},
52         {RTW_WLAN_CATEGORY_HT,  "ACTION_HT",    &OnAction_ht},
53         {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},
54         {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved},
55         {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved},
56         {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &DoReserved},
57         {RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &DoReserved},
58         {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved},
59 };
60
61
62 static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
63
64 /**************************************************
65 OUI definitions for the vendor specific IE
66 ***************************************************/
67 unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
68 unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
69 unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
70 unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
71 unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
72
73 unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
74 unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
75
76 static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
77
78 /********************************************************
79 ChannelPlan definitions
80 *********************************************************/
81 static RT_CHANNEL_PLAN_2G       RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
82         {{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 */
83         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
84         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},                      /*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
85         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
86         {{10, 11, 12, 13}, 4},                                          /*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
87         {{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 */
88         {{}, 0},                                                                /*  0x06, RT_CHANNEL_DOMAIN_2G_NULL */
89 };
90
91 static RT_CHANNEL_PLAN_5G       RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
92         {{}, 0},                                                                                                                                                                        /*  0x00, RT_CHANNEL_DOMAIN_5G_NULL */
93         {{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 */
94         {{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 */
95         {{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 */
96         {{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 */
97         {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},                                                                                                         /*  0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
98         {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},                                                                                        /*  0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
99         {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12},                                                                                             /*  0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
100         {{149, 153, 157, 161, 165}, 5},                                                                                                                                 /*  0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
101         {{36, 40, 44, 48, 52, 56, 60, 64}, 8},                                                                                                                          /*  0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
102         {{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 */
103         {{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 */
104         {{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 */
105         {{36, 40, 44, 48, 52, 56, 60, 64}, 8},                                                                                                                          /*  0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
106         {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},                                                                                  /*  0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
107         {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15},                                                         /*  0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
108         {{56, 60, 64, 149, 153, 157, 161, 165}, 8},                                                                                                                     /*  0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
109         {{149, 153, 157, 161, 165}, 5},                                                                                                                                 /*  0x11, RT_CHANNEL_DOMAIN_5G_NCC3 */
110         {{36, 40, 44, 48}, 4},                                                                                                                                                  /*  0x12, RT_CHANNEL_DOMAIN_5G_ETSI4 */
111         {{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 */
112         {{149, 153, 157, 161}, 4},                                                                                                                                              /*  0x14, RT_CHANNEL_DOMAIN_5G_FCC8 */
113         {{36, 40, 44, 48, 52, 56, 60, 64}, 8},                                                                                                                          /*  0x15, RT_CHANNEL_DOMAIN_5G_ETSI6 */
114         {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},                                                                                        /*  0x16, RT_CHANNEL_DOMAIN_5G_ETSI7 */
115         {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},                                                                                                         /*  0x17, RT_CHANNEL_DOMAIN_5G_ETSI8 */
116         {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},                                                                                  /*  0x18, RT_CHANNEL_DOMAIN_5G_ETSI9 */
117         {{149, 153, 157, 161, 165}, 5},                                                                                                                                 /*  0x19, RT_CHANNEL_DOMAIN_5G_ETSI10 */
118         {{36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165}, 16},                                                                 /*  0x1A, RT_CHANNEL_DOMAIN_5G_ETSI11 */
119         {{52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17},                                                        /*  0x1B, RT_CHANNEL_DOMAIN_5G_NCC4 */
120         {{149, 153, 157, 161}, 4},                                                                                                                                              /*  0x1C, RT_CHANNEL_DOMAIN_5G_ETSI12 */
121         {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17},                                                        /*  0x1D, RT_CHANNEL_DOMAIN_5G_FCC9 */
122         {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140}, 12},                                                                                 /*  0x1E, RT_CHANNEL_DOMAIN_5G_ETSI13 */
123         {{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 */
124
125         /*  Driver self defined for old channel plan Compatible , Remember to modify if have new channel plan definition ===== */
126         {{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 */
127         {{36, 40, 44, 48}, 4},                                                                                                                                                  /*  0x21, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
128         {{36, 40, 44, 48, 149, 153, 157, 161}, 8},                                                                                                                      /*  0x22, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
129 };
130
131 static RT_CHANNEL_PLAN_MAP      RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
132         /*  0x00 ~ 0x1F , Old Define ===== */
133         {0x02, 0x20},   /* 0x00, RT_CHANNEL_DOMAIN_FCC */
134         {0x02, 0x0A},   /* 0x01, RT_CHANNEL_DOMAIN_IC */
135         {0x01, 0x01},   /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
136         {0x01, 0x00},   /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
137         {0x01, 0x00},   /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
138         {0x03, 0x00},   /* 0x05, RT_CHANNEL_DOMAIN_MKK */
139         {0x03, 0x00},   /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
140         {0x01, 0x09},   /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
141         {0x03, 0x09},   /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
142         {0x03, 0x00},   /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
143         {0x00, 0x00},   /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
144         {0x02, 0x0F},   /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
145         {0x01, 0x08},   /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
146         {0x02, 0x06},   /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
147         {0x02, 0x0B},   /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
148         {0x02, 0x09},   /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
149         {0x01, 0x01},   /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
150         {0x02, 0x05},   /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
151         {0x01, 0x21},   /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
152         {0x00, 0x04},   /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
153         {0x02, 0x10},   /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
154         {0x00, 0x21},   /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
155         {0x00, 0x22},   /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
156         {0x03, 0x21},   /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
157         {0x06, 0x08},   /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
158         {0x02, 0x08},   /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
159         {0x00, 0x00},   /* 0x1A, */
160         {0x00, 0x00},   /* 0x1B, */
161         {0x00, 0x00},   /* 0x1C, */
162         {0x00, 0x00},   /* 0x1D, */
163         {0x00, 0x00},   /* 0x1E, */
164         {0x06, 0x04},   /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
165         /*  0x20 ~ 0x7F , New Define ===== */
166         {0x00, 0x00},   /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
167         {0x01, 0x00},   /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
168         {0x02, 0x00},   /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
169         {0x03, 0x00},   /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
170         {0x04, 0x00},   /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
171         {0x02, 0x04},   /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
172         {0x00, 0x01},   /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
173         {0x03, 0x0C},   /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
174         {0x00, 0x0B},   /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
175         {0x00, 0x05},   /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
176         {0x00, 0x00},   /* 0x2A, */
177         {0x00, 0x00},   /* 0x2B, */
178         {0x00, 0x00},   /* 0x2C, */
179         {0x00, 0x00},   /* 0x2D, */
180         {0x00, 0x00},   /* 0x2E, */
181         {0x00, 0x00},   /* 0x2F, */
182         {0x00, 0x06},   /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
183         {0x00, 0x07},   /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
184         {0x00, 0x08},   /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
185         {0x00, 0x09},   /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
186         {0x02, 0x0A},   /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
187         {0x00, 0x02},   /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
188         {0x00, 0x03},   /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
189         {0x03, 0x0D},   /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
190         {0x03, 0x0E},   /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
191         {0x02, 0x0F},   /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
192         {0x00, 0x00},   /* 0x3A, */
193         {0x00, 0x00},   /* 0x3B, */
194         {0x00, 0x00},   /* 0x3C, */
195         {0x00, 0x00},   /* 0x3D, */
196         {0x00, 0x00},   /* 0x3E, */
197         {0x00, 0x00},   /* 0x3F, */
198         {0x02, 0x10},   /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
199         {0x05, 0x00},   /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */
200         {0x01, 0x12},   /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */
201         {0x02, 0x05},   /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */
202         {0x02, 0x11},   /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */
203         {0x00, 0x13},   /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */
204         {0x02, 0x14},   /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */
205         {0x00, 0x15},   /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */
206         {0x00, 0x16},   /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */
207         {0x00, 0x17},   /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */
208         {0x00, 0x18},   /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */
209         {0x00, 0x19},   /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */
210         {0x00, 0x1A},   /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */
211         {0x02, 0x1B},   /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */
212         {0x00, 0x1C},   /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */
213         {0x02, 0x1D},   /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */
214         {0x00, 0x1E},   /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */
215         {0x02, 0x1F},   /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */
216 };
217
218 static RT_CHANNEL_PLAN_MAP      RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; /* use the conbination for max channel numbers */
219
220 /*
221  * Search the @param ch in given @param ch_set
222  * @ch_set: the given channel set
223  * @ch: the given channel number
224  *
225  * return the index of channel_num in channel_set, -1 if not found
226  */
227 int rtw_ch_set_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch)
228 {
229         int i;
230         for (i = 0; ch_set[i].ChannelNum != 0; i++) {
231                 if (ch == ch_set[i].ChannelNum)
232                         break;
233         }
234
235         if (i >= ch_set[i].ChannelNum)
236                 return -1;
237         return i;
238 }
239
240 /*
241  * Check the @param ch is fit with setband setting of @param adapter
242  * @adapter: the given adapter
243  * @ch: the given channel number
244  *
245  * return true when check valid, false not valid
246  */
247 bool rtw_mlme_band_check(struct adapter *adapter, const u32 ch)
248 {
249         if (adapter->setband == GHZ24_50 /* 2.4G and 5G */
250                 || (adapter->setband == GHZ_24 && ch < 35) /* 2.4G only */
251                 || (adapter->setband == GHZ_50 && ch > 35) /* 5G only */
252         ) {
253                 return true;
254         }
255         return false;
256 }
257
258 /****************************************************************************
259
260 Following are the initialization functions for WiFi MLME
261
262 *****************************************************************************/
263
264 int init_hw_mlme_ext(struct adapter *padapter)
265 {
266         struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
267
268         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
269         return _SUCCESS;
270 }
271
272 void init_mlme_default_rate_set(struct adapter *padapter)
273 {
274         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
275
276         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};
277         unsigned char mixed_basicrate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,};
278         unsigned char supported_mcs_set[16] = {0xff, 0xff, 0x00, 0x00, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
279
280         memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
281         memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
282
283         memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set));
284 }
285
286 static void init_mlme_ext_priv_value(struct adapter *padapter)
287 {
288         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
289         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
290
291         atomic_set(&pmlmeext->event_seq, 0);
292         pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
293         pmlmeext->sa_query_seq = 0;
294         pmlmeext->mgnt_80211w_IPN = 0;
295         pmlmeext->mgnt_80211w_IPN_rx = 0;
296         pmlmeext->cur_channel = padapter->registrypriv.channel;
297         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
298         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
299
300         pmlmeext->retry = 0;
301
302         pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
303
304         init_mlme_default_rate_set(padapter);
305
306         if (pmlmeext->cur_channel > 14)
307                 pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
308         else
309                 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
310
311         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
312         pmlmeext->sitesurvey_res.channel_idx = 0;
313         pmlmeext->sitesurvey_res.bss_cnt = 0;
314         pmlmeext->scan_abort = false;
315
316         pmlmeinfo->state = WIFI_FW_NULL_STATE;
317         pmlmeinfo->reauth_count = 0;
318         pmlmeinfo->reassoc_count = 0;
319         pmlmeinfo->link_count = 0;
320         pmlmeinfo->auth_seq = 0;
321         pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
322         pmlmeinfo->key_index = 0;
323         pmlmeinfo->iv = 0;
324
325         pmlmeinfo->enc_algo = _NO_PRIVACY_;
326         pmlmeinfo->authModeToggle = 0;
327
328         memset(pmlmeinfo->chg_txt, 0, 128);
329
330         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
331         pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
332
333         pmlmeinfo->dialogToken = 0;
334
335         pmlmeext->action_public_rxseq = 0xffff;
336         pmlmeext->action_public_dialog_token = 0xff;
337 }
338
339 static int has_channel(RT_CHANNEL_INFO *channel_set,
340                                            u8 chanset_size,
341                                            u8 chan) {
342         int i;
343
344         for (i = 0; i < chanset_size; i++) {
345                 if (channel_set[i].ChannelNum == chan) {
346                         return 1;
347                 }
348         }
349
350         return 0;
351 }
352
353 static void init_channel_list(struct adapter *padapter, RT_CHANNEL_INFO *channel_set,
354                                                           u8 chanset_size,
355                                                           struct p2p_channels *channel_list) {
356
357         struct p2p_oper_class_map op_class[] = {
358                 { IEEE80211G,  81,   1,  13,  1, BW20 },
359                 { IEEE80211G,  82,  14,  14,  1, BW20 },
360                 { IEEE80211A, 115,  36,  48,  4, BW20 },
361                 { IEEE80211A, 116,  36,  44,  8, BW40PLUS },
362                 { IEEE80211A, 117,  40,  48,  8, BW40MINUS },
363                 { IEEE80211A, 124, 149, 161,  4, BW20 },
364                 { IEEE80211A, 125, 149, 169,  4, BW20 },
365                 { IEEE80211A, 126, 149, 157,  8, BW40PLUS },
366                 { IEEE80211A, 127, 153, 161,  8, BW40MINUS },
367                 { -1, 0, 0, 0, 0, BW20 }
368         };
369
370         int cla, op;
371
372         cla = 0;
373
374         for (op = 0; op_class[op].op_class; op++) {
375                 u8 ch;
376                 struct p2p_oper_class_map *o = &op_class[op];
377                 struct p2p_reg_class *reg = NULL;
378
379                 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
380                         if (!has_channel(channel_set, chanset_size, ch)) {
381                                 continue;
382                         }
383
384                         if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
385                                 continue;
386
387                         if ((0 < (padapter->registrypriv.bw_mode & 0xf0)) &&
388                                 ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
389                                 continue;
390
391                         if (reg == NULL) {
392                                 reg = &channel_list->reg_class[cla];
393                                 cla++;
394                                 reg->reg_class = o->op_class;
395                                 reg->channels = 0;
396                         }
397                         reg->channel[reg->channels] = ch;
398                         reg->channels++;
399                 }
400         }
401         channel_list->reg_classes = cla;
402
403 }
404
405 static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, RT_CHANNEL_INFO *channel_set)
406 {
407         u8 index, chanset_size = 0;
408         u8 b5GBand = false, b2_4GBand = false;
409         u8 Index2G = 0, Index5G = 0;
410
411         memset(channel_set, 0, sizeof(RT_CHANNEL_INFO)*MAX_CHANNEL_NUM);
412
413         if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
414                 DBG_871X("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
415                 return chanset_size;
416         }
417
418         if (IsSupported24G(padapter->registrypriv.wireless_mode)) {
419                 b2_4GBand = true;
420                 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
421                         Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
422                 else
423                         Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
424         }
425
426         if (b2_4GBand) {
427                 for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
428                         channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
429
430                         if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */
431                                 (RT_CHANNEL_DOMAIN_GLOBAL_NULL == ChannelPlan)) {
432                                 if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
433                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
434                                 else if ((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
435                                         channel_set[chanset_size].ScanType  = SCAN_PASSIVE;
436                         } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan ||
437                                 RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan ||
438                                 RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { /*  channel 12~13, passive scan */
439                                 if (channel_set[chanset_size].ChannelNum <= 11)
440                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
441                                 else
442                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
443                         } else
444                                 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
445
446                         chanset_size++;
447                 }
448         }
449
450         if (b5GBand) {
451                 for (index = 0; index < RTW_ChannelPlan5G[Index5G].Len; index++) {
452                         if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48
453                                 || RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) {
454                                 channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index];
455                                 if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)/* passive scan for all 5G channels */
456                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
457                                 else
458                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
459                                 DBG_871X("%s(): channel_set[%d].ChannelNum = %d\n", __func__, chanset_size, channel_set[chanset_size].ChannelNum);
460                                 chanset_size++;
461                         }
462                 }
463         }
464
465         DBG_871X("%s ChannelPlan ID %x Chan num:%d \n", __func__, ChannelPlan, chanset_size);
466         return chanset_size;
467 }
468
469 int     init_mlme_ext_priv(struct adapter *padapter)
470 {
471         int     res = _SUCCESS;
472         struct registry_priv *pregistrypriv = &padapter->registrypriv;
473         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
474         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
475         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
476
477         /*  We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
478         /* memset((u8 *)pmlmeext, 0, sizeof(struct mlme_ext_priv)); */
479
480         pmlmeext->padapter = padapter;
481
482         /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */
483
484         init_mlme_ext_priv_value(padapter);
485         pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
486
487         init_mlme_ext_timer(padapter);
488
489         init_mlme_ap_info(padapter);
490
491         pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
492         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
493         pmlmeext->last_scan_time = 0;
494         pmlmeext->chan_scan_time = SURVEY_TO;
495         pmlmeext->mlmeext_init = true;
496         pmlmeext->active_keep_alive_check = true;
497
498 #ifdef DBG_FIXED_CHAN
499         pmlmeext->fixed_chan = 0xFF;
500 #endif
501
502         return res;
503
504 }
505
506 void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
507 {
508         struct adapter *padapter = pmlmeext->padapter;
509
510         if (!padapter)
511                 return;
512
513         if (padapter->bDriverStopped == true) {
514                 del_timer_sync(&pmlmeext->survey_timer);
515                 del_timer_sync(&pmlmeext->link_timer);
516                 /* del_timer_sync(&pmlmeext->ADDBA_timer); */
517         }
518 }
519
520 static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
521 {
522         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
523         u8 *pframe = precv_frame->u.hdr.rx_data;
524
525         if (ptable->func) {
526                 /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
527                 if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
528                     memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
529                         return;
530
531                 ptable->func(padapter, precv_frame);
532         }
533 }
534
535 void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
536 {
537         int index;
538         struct mlme_handler *ptable;
539         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
540         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
541         u8 *pframe = precv_frame->u.hdr.rx_data;
542         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
543         struct dvobj_priv *psdpriv = padapter->dvobj;
544         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
545
546         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
547                  ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n",
548                   GetFrameType(pframe), GetFrameSubType(pframe)));
549
550         if (GetFrameType(pframe) != WIFI_MGT_TYPE) {
551                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe)));
552                 return;
553         }
554
555         /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
556         if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
557                 memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) {
558                 return;
559         }
560
561         ptable = mlme_sta_tbl;
562
563         index = GetFrameSubType(pframe) >> 4;
564
565         if (index >= (sizeof(mlme_sta_tbl) / sizeof(struct mlme_handler))) {
566                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type =%d\n", index));
567                 return;
568         }
569         ptable += index;
570
571         if (psta != NULL) {
572                 if (GetRetry(pframe)) {
573                         if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {
574                                 /* drop the duplicate management frame */
575                                 pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++;
576                                 DBG_871X("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num);
577                                 return;
578                         }
579                 }
580                 psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
581         }
582
583         switch (GetFrameSubType(pframe)) {
584         case WIFI_AUTH:
585                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
586                         ptable->func = &OnAuth;
587                 else
588                         ptable->func = &OnAuthClient;
589                 /* pass through */
590         case WIFI_ASSOCREQ:
591         case WIFI_REASSOCREQ:
592                 _mgt_dispatcher(padapter, ptable, precv_frame);
593                 break;
594         case WIFI_PROBEREQ:
595                 _mgt_dispatcher(padapter, ptable, precv_frame);
596                 break;
597         case WIFI_BEACON:
598                 _mgt_dispatcher(padapter, ptable, precv_frame);
599                 break;
600         case WIFI_ACTION:
601                 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */
602                 _mgt_dispatcher(padapter, ptable, precv_frame);
603                 break;
604         default:
605                 _mgt_dispatcher(padapter, ptable, precv_frame);
606                 break;
607         }
608 }
609
610 /****************************************************************************
611
612 Following are the callback functions for each subtype of the management frames
613
614 *****************************************************************************/
615
616 unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
617 {
618         unsigned int    ielen;
619         unsigned char *p;
620         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
621         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
622         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
623         struct wlan_bssid_ex    *cur = &(pmlmeinfo->network);
624         u8 *pframe = precv_frame->u.hdr.rx_data;
625         uint len = precv_frame->u.hdr.len;
626         u8 is_valid_p2p_probereq = false;
627
628         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
629                 return _SUCCESS;
630
631         if (check_fwstate(pmlmepriv, _FW_LINKED) == false &&
632                 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) {
633                 return _SUCCESS;
634         }
635
636
637         /* DBG_871X("+OnProbeReq\n"); */
638
639 #ifdef CONFIG_AUTO_AP_MODE
640         if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
641                         pmlmepriv->cur_network.join_res == true) {
642                 struct sta_info *psta;
643                 u8 *mac_addr, *peer_addr;
644                 struct sta_priv *pstapriv = &padapter->stapriv;
645                 u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A};
646                 /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */
647
648                 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, (int *)&ielen,
649                         len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
650
651                 if (!p || ielen != 14)
652                         goto _non_rc_device;
653
654                 if (memcmp(p+2, RC_OUI, sizeof(RC_OUI)))
655                         goto _non_rc_device;
656
657                 if (memcmp(p+6, get_sa(pframe), ETH_ALEN)) {
658                         DBG_871X("%s, do rc pairing ("MAC_FMT"), but mac addr mismatch!("MAC_FMT")\n", __func__,
659                                 MAC_ARG(get_sa(pframe)), MAC_ARG(p+6));
660
661                         goto _non_rc_device;
662                 }
663
664                 DBG_871X("%s, got the pairing device("MAC_FMT")\n", __func__,  MAC_ARG(get_sa(pframe)));
665
666                 /* new a station */
667                 psta = rtw_get_stainfo(pstapriv, get_sa(pframe));
668                 if (psta == NULL) {
669                         /*  allocate a new one */
670                         DBG_871X("going to alloc stainfo for rc ="MAC_FMT"\n",  MAC_ARG(get_sa(pframe)));
671                         psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe));
672                         if (psta == NULL) {
673                                 /* TODO: */
674                                 DBG_871X(" Exceed the upper limit of supported clients...\n");
675                                 return _SUCCESS;
676                         }
677
678                         spin_lock_bh(&pstapriv->asoc_list_lock);
679                         if (list_empty(&psta->asoc_list)) {
680                                 psta->expire_to = pstapriv->expire_to;
681                                 list_add_tail(&psta->asoc_list, &pstapriv->asoc_list);
682                                 pstapriv->asoc_list_cnt++;
683                         }
684                         spin_unlock_bh(&pstapriv->asoc_list_lock);
685
686                         /* generate pairing ID */
687                         mac_addr = myid(&(padapter->eeprompriv));
688                         peer_addr = psta->hwaddr;
689                         psta->pid = (u16)(((mac_addr[4]<<8) + mac_addr[5]) + ((peer_addr[4]<<8) + peer_addr[5]));
690
691                         /* update peer stainfo */
692                         psta->isrc = true;
693                         /* psta->aid = 0; */
694                         /* psta->mac_id = 2; */
695
696                         /* get a unique AID */
697                         if (psta->aid > 0) {
698                                 DBG_871X("old AID %d\n", psta->aid);
699                         } else {
700                                 for (psta->aid = 1; psta->aid <= NUM_STA; psta->aid++)
701                                         if (pstapriv->sta_aid[psta->aid - 1] == NULL)
702                                                 break;
703
704                                 if (psta->aid > pstapriv->max_num_sta) {
705                                         psta->aid = 0;
706                                         DBG_871X("no room for more AIDs\n");
707                                         return _SUCCESS;
708                                 } else {
709                                         pstapriv->sta_aid[psta->aid - 1] = psta;
710                                         DBG_871X("allocate new AID = (%d)\n", psta->aid);
711                                 }
712                         }
713
714                         psta->qos_option = 1;
715                         psta->bw_mode = CHANNEL_WIDTH_20;
716                         psta->ieee8021x_blocked = false;
717                         psta->htpriv.ht_option = true;
718                         psta->htpriv.ampdu_enable = false;
719                         psta->htpriv.sgi_20m = false;
720                         psta->htpriv.sgi_40m = false;
721                         psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
722                         psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
723                         psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
724
725                         rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
726
727                         memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
728
729                         spin_lock_bh(&psta->lock);
730                         psta->state |= _FW_LINKED;
731                         spin_unlock_bh(&psta->lock);
732
733                         report_add_sta_event(padapter, psta->hwaddr, psta->aid);
734
735                 }
736
737                 issue_probersp(padapter, get_sa(pframe), false);
738
739                 return _SUCCESS;
740
741         }
742
743 _non_rc_device:
744
745         return _SUCCESS;
746
747 #endif /* CONFIG_AUTO_AP_MODE */
748
749         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
750                         len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
751
752
753         /* check (wildcard) SSID */
754         if (p != NULL) {
755                 if (is_valid_p2p_probereq == true)
756                         goto _issue_probersp;
757
758                 if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength))
759                         || (ielen == 0 && pmlmeinfo->hidden_ssid_mode)
760                 )
761                         return _SUCCESS;
762
763 _issue_probersp:
764                 if (((check_fwstate(pmlmepriv, _FW_LINKED) == true &&
765                         pmlmepriv->cur_network.join_res == true)) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
766                         /* DBG_871X("+issue_probersp during ap mode\n"); */
767                         issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
768                 }
769
770         }
771
772         return _SUCCESS;
773
774 }
775
776 unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
777 {
778         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
779
780         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
781                 report_survey_event(padapter, precv_frame);
782                 return _SUCCESS;
783         }
784
785         return _SUCCESS;
786
787 }
788
789 unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
790 {
791         int cam_idx;
792         struct sta_info *psta;
793         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
794         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
795         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
796         struct sta_priv *pstapriv = &padapter->stapriv;
797         u8 *pframe = precv_frame->u.hdr.rx_data;
798         uint len = precv_frame->u.hdr.len;
799         struct wlan_bssid_ex *pbss;
800         int ret = _SUCCESS;
801         u8 *p = NULL;
802         u32 ielen = 0;
803
804         p = rtw_get_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ielen, precv_frame->u.hdr.len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_);
805         if ((p != NULL) && (ielen > 0)) {
806                 if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) {
807                         /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */
808                         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)));
809                         *(p + 1) = ielen - 1;
810                 }
811         }
812
813         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
814                 report_survey_event(padapter, precv_frame);
815                 return _SUCCESS;
816         }
817
818         if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
819                 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
820                         /* we should update current network before auth, or some IE is wrong */
821                         pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex));
822                         if (pbss) {
823                                 if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
824                                         update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
825                                         rtw_get_bcn_info(&(pmlmepriv->cur_network));
826                                 }
827                                 kfree((u8 *)pbss);
828                         }
829
830                         /* check the vendor of the assoc AP */
831                         pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
832
833                         /* update TSF Value */
834                         update_TSF(pmlmeext, pframe, len);
835
836                         /* reset for adaptive_early_32k */
837                         pmlmeext->adaptive_tsf_done = false;
838                         pmlmeext->DrvBcnEarly = 0xff;
839                         pmlmeext->DrvBcnTimeOut = 0xff;
840                         pmlmeext->bcn_cnt = 0;
841                         memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt));
842                         memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio));
843
844                         /* start auth */
845                         start_clnt_auth(padapter);
846
847                         return _SUCCESS;
848                 }
849
850                 if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
851                         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
852                         if (psta != NULL) {
853                                 ret = rtw_check_bcn_info(padapter, pframe, len);
854                                 if (!ret) {
855                                                 DBG_871X_LEVEL(_drv_always_, "ap has changed, disconnect now\n ");
856                                                 receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 0);
857                                                 return _SUCCESS;
858                                 }
859                                 /* update WMM, ERP in the beacon */
860                                 /* todo: the timer is used instead of the number of the beacon received */
861                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
862                                         /* DBG_871X("update_bcn_info\n"); */
863                                         update_beacon_info(padapter, pframe, len, psta);
864
865                                 adaptive_early_32k(pmlmeext, pframe, len);
866                         }
867                 } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
868                         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
869                         if (psta != NULL) {
870                                 /* update WMM, ERP in the beacon */
871                                 /* todo: the timer is used instead of the number of the beacon received */
872                                 if ((sta_rx_pkts(psta) & 0xf) == 0) {
873                                         /* DBG_871X("update_bcn_info\n"); */
874                                         update_beacon_info(padapter, pframe, len, psta);
875                                 }
876                         } else{
877                                 /* allocate a new CAM entry for IBSS station */
878                                 cam_idx = allocate_fw_sta_entry(padapter);
879                                 if (cam_idx == NUM_STA)
880                                         goto _END_ONBEACON_;
881
882                                 /* get supported rate */
883                                 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) {
884                                         pmlmeinfo->FW_sta_info[cam_idx].status = 0;
885                                         goto _END_ONBEACON_;
886                                 }
887
888                                 /* update TSF Value */
889                                 update_TSF(pmlmeext, pframe, len);
890
891                                 /* report sta add event */
892                                 report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
893                         }
894                 }
895         }
896
897 _END_ONBEACON_:
898
899         return _SUCCESS;
900
901 }
902
903 unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
904 {
905         unsigned int    auth_mode, seq, ie_len;
906         unsigned char *sa, *p;
907         u16 algorithm;
908         int     status;
909         static struct sta_info stat;
910         struct  sta_info *pstat = NULL;
911         struct  sta_priv *pstapriv = &padapter->stapriv;
912         struct security_priv *psecuritypriv = &padapter->securitypriv;
913         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
914         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
915         u8 *pframe = precv_frame->u.hdr.rx_data;
916         uint len = precv_frame->u.hdr.len;
917         u8 offset = 0;
918
919         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
920                 return _FAIL;
921
922         DBG_871X("+OnAuth\n");
923
924         sa = GetAddr2Ptr(pframe);
925
926         auth_mode = psecuritypriv->dot11AuthAlgrthm;
927
928         if (GetPrivacy(pframe)) {
929                 u8 *iv;
930                 struct rx_pkt_attrib     *prxattrib = &(precv_frame->u.hdr.attrib);
931
932                 prxattrib->hdrlen = WLAN_HDR_A3_LEN;
933                 prxattrib->encrypt = _WEP40_;
934
935                 iv = pframe+prxattrib->hdrlen;
936                 prxattrib->key_index = ((iv[3]>>6)&0x3);
937
938                 prxattrib->iv_len = 4;
939                 prxattrib->icv_len = 4;
940
941                 rtw_wep_decrypt(padapter, (u8 *)precv_frame);
942
943                 offset = 4;
944         }
945
946         algorithm = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
947         seq     = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
948
949         DBG_871X("auth alg =%x, seq =%X\n", algorithm, seq);
950
951         if (auth_mode == 2 &&
952                         psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
953                         psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
954                 auth_mode = 0;
955
956         if ((algorithm > 0 && auth_mode == 0) ||        /*  rx a shared-key auth but shared not enabled */
957                 (algorithm == 0 && auth_mode == 1)) {   /*  rx a open-system auth but shared-key is enabled */
958                 DBG_871X("auth rejected due to bad alg [alg =%d, auth_mib =%d] %02X%02X%02X%02X%02X%02X\n",
959                         algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
960
961                 status = _STATS_NO_SUPP_ALG_;
962
963                 goto auth_fail;
964         }
965
966         if (rtw_access_ctrl(padapter, sa) == false) {
967                 status = _STATS_UNABLE_HANDLE_STA_;
968                 goto auth_fail;
969         }
970
971         pstat = rtw_get_stainfo(pstapriv, sa);
972         if (pstat == NULL) {
973
974                 /*  allocate a new one */
975                 DBG_871X("going to alloc stainfo for sa ="MAC_FMT"\n",  MAC_ARG(sa));
976                 pstat = rtw_alloc_stainfo(pstapriv, sa);
977                 if (pstat == NULL) {
978                         DBG_871X(" Exceed the upper limit of supported clients...\n");
979                         status = _STATS_UNABLE_HANDLE_STA_;
980                         goto auth_fail;
981                 }
982
983                 pstat->state = WIFI_FW_AUTH_NULL;
984                 pstat->auth_seq = 0;
985
986                 /* pstat->flags = 0; */
987                 /* pstat->capability = 0; */
988         } else{
989
990                 spin_lock_bh(&pstapriv->asoc_list_lock);
991                 if (list_empty(&pstat->asoc_list) == false) {
992                         list_del_init(&pstat->asoc_list);
993                         pstapriv->asoc_list_cnt--;
994                         if (pstat->expire_to > 0) {
995                                 /* TODO: STA re_auth within expire_to */
996                         }
997                 }
998                 spin_unlock_bh(&pstapriv->asoc_list_lock);
999
1000                 if (seq == 1) {
1001                         /* TODO: STA re_auth and auth timeout */
1002                 }
1003         }
1004
1005         spin_lock_bh(&pstapriv->auth_list_lock);
1006         if (list_empty(&pstat->auth_list)) {
1007
1008                 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
1009                 pstapriv->auth_list_cnt++;
1010         }
1011         spin_unlock_bh(&pstapriv->auth_list_lock);
1012
1013         if (pstat->auth_seq == 0)
1014                 pstat->expire_to = pstapriv->auth_to;
1015
1016
1017         if ((pstat->auth_seq + 1) != seq) {
1018                 DBG_871X("(1)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n",
1019                         seq, pstat->auth_seq+1);
1020                 status = _STATS_OUT_OF_AUTH_SEQ_;
1021                 goto auth_fail;
1022         }
1023
1024         if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) {
1025                 if (seq == 1) {
1026                         pstat->state &= ~WIFI_FW_AUTH_NULL;
1027                         pstat->state |= WIFI_FW_AUTH_SUCCESS;
1028                         pstat->expire_to = pstapriv->assoc_to;
1029                         pstat->authalg = algorithm;
1030                 } else{
1031                         DBG_871X("(2)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n",
1032                                 seq, pstat->auth_seq+1);
1033                         status = _STATS_OUT_OF_AUTH_SEQ_;
1034                         goto auth_fail;
1035                 }
1036         } else{ /*  shared system or auto authentication */
1037                 if (seq == 1) {
1038                         /* prepare for the challenging txt... */
1039                         memset((void *)pstat->chg_txt, 78, 128);
1040
1041                         pstat->state &= ~WIFI_FW_AUTH_NULL;
1042                         pstat->state |= WIFI_FW_AUTH_STATE;
1043                         pstat->authalg = algorithm;
1044                         pstat->auth_seq = 2;
1045                 } else if (seq == 3) {
1046                         /* checking for challenging txt... */
1047                         DBG_871X("checking for challenging txt...\n");
1048
1049                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len,
1050                                         len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
1051
1052                         if ((p == NULL) || (ie_len <= 0)) {
1053                                 DBG_871X("auth rejected because challenge failure!(1)\n");
1054                                 status = _STATS_CHALLENGE_FAIL_;
1055                                 goto auth_fail;
1056                         }
1057
1058                         if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
1059                                 pstat->state &= (~WIFI_FW_AUTH_STATE);
1060                                 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1061                                 /*  challenging txt is correct... */
1062                                 pstat->expire_to =  pstapriv->assoc_to;
1063                         } else{
1064                                 DBG_871X("auth rejected because challenge failure!\n");
1065                                 status = _STATS_CHALLENGE_FAIL_;
1066                                 goto auth_fail;
1067                         }
1068                 } else{
1069                         DBG_871X("(3)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n",
1070                                 seq, pstat->auth_seq+1);
1071                         status = _STATS_OUT_OF_AUTH_SEQ_;
1072                         goto auth_fail;
1073                 }
1074         }
1075
1076
1077         /*  Now, we are going to issue_auth... */
1078         pstat->auth_seq = seq + 1;
1079
1080         issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
1081
1082         if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1083                 pstat->auth_seq = 0;
1084
1085
1086         return _SUCCESS;
1087
1088 auth_fail:
1089
1090         if (pstat)
1091                 rtw_free_stainfo(padapter, pstat);
1092
1093         pstat = &stat;
1094         memset((char *)pstat, '\0', sizeof(stat));
1095         pstat->auth_seq = 2;
1096         memcpy(pstat->hwaddr, sa, 6);
1097
1098         issue_auth(padapter, pstat, (unsigned short)status);
1099
1100         return _FAIL;
1101
1102 }
1103
1104 unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame)
1105 {
1106         unsigned int    seq, len, status, algthm, offset;
1107         unsigned char *p;
1108         unsigned int    go2asoc = 0;
1109         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1110         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1111         u8 *pframe = precv_frame->u.hdr.rx_data;
1112         uint pkt_len = precv_frame->u.hdr.len;
1113
1114         DBG_871X("%s\n", __func__);
1115
1116         /* check A1 matches or not */
1117         if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1118                 return _SUCCESS;
1119
1120         if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1121                 return _SUCCESS;
1122
1123         offset = (GetPrivacy(pframe)) ? 4 : 0;
1124
1125         algthm  = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
1126         seq     = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
1127         status  = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4));
1128
1129         if (status != 0) {
1130                 DBG_871X("clnt auth fail, status: %d\n", status);
1131                 if (status == 13) { /*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
1132                         if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1133                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
1134                         else
1135                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1136                         /* pmlmeinfo->reauth_count = 0; */
1137                 }
1138
1139                 set_link_timer(pmlmeext, 1);
1140                 goto authclnt_fail;
1141         }
1142
1143         if (seq == 2) {
1144                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
1145                          /*  legendary shared system */
1146                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
1147                                 pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
1148
1149                         if (p == NULL) {
1150                                 /* DBG_871X("marc: no challenge text?\n"); */
1151                                 goto authclnt_fail;
1152                         }
1153
1154                         memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
1155                         pmlmeinfo->auth_seq = 3;
1156                         issue_auth(padapter, NULL, 0);
1157                         set_link_timer(pmlmeext, REAUTH_TO);
1158
1159                         return _SUCCESS;
1160                 } else{
1161                         /*  open system */
1162                         go2asoc = 1;
1163                 }
1164         } else if (seq == 4) {
1165                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
1166                         go2asoc = 1;
1167                 } else{
1168                         goto authclnt_fail;
1169                 }
1170         } else{
1171                 /*  this is also illegal */
1172                 /* DBG_871X("marc: clnt auth failed due to illegal seq =%x\n", seq); */
1173                 goto authclnt_fail;
1174         }
1175
1176         if (go2asoc) {
1177                 DBG_871X_LEVEL(_drv_always_, "auth success, start assoc\n");
1178                 start_clnt_assoc(padapter);
1179                 return _SUCCESS;
1180         }
1181
1182 authclnt_fail:
1183
1184         /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
1185
1186         return _FAIL;
1187
1188 }
1189
1190 unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
1191 {
1192         u16 capab_info, listen_interval;
1193         struct rtw_ieee802_11_elems elems;
1194         struct sta_info *pstat;
1195         unsigned char   reassoc, *p, *pos, *wpa_ie;
1196         unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
1197         int             i, ie_len, wpa_ie_len, left;
1198         unsigned char   supportRate[16];
1199         int                                     supportRateNum;
1200         unsigned short          status = _STATS_SUCCESSFUL_;
1201         unsigned short          frame_type, ie_offset = 0;
1202         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1203         struct security_priv *psecuritypriv = &padapter->securitypriv;
1204         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1205         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1206         struct wlan_bssid_ex    *cur = &(pmlmeinfo->network);
1207         struct sta_priv *pstapriv = &padapter->stapriv;
1208         u8 *pframe = precv_frame->u.hdr.rx_data;
1209         uint pkt_len = precv_frame->u.hdr.len;
1210
1211         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1212                 return _FAIL;
1213
1214         frame_type = GetFrameSubType(pframe);
1215         if (frame_type == WIFI_ASSOCREQ) {
1216                 reassoc = 0;
1217                 ie_offset = _ASOCREQ_IE_OFFSET_;
1218         } else{ /*  WIFI_REASSOCREQ */
1219                 reassoc = 1;
1220                 ie_offset = _REASOCREQ_IE_OFFSET_;
1221         }
1222
1223
1224         if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
1225                 DBG_871X("handle_assoc(reassoc =%d) - too short payload (len =%lu)"
1226                        "\n", reassoc, (unsigned long)pkt_len);
1227                 return _FAIL;
1228         }
1229
1230         pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1231         if (pstat == NULL) {
1232                 status = _RSON_CLS2_;
1233                 goto asoc_class2_error;
1234         }
1235
1236         capab_info = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN);
1237         /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */
1238         /* listen_interval = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN+2)); */
1239         listen_interval = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN+2);
1240
1241         left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
1242         pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
1243
1244
1245         DBG_871X("%s\n", __func__);
1246
1247         /*  check if this stat has been successfully authenticated/assocated */
1248         if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
1249                 if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
1250                         status = _RSON_CLS2_;
1251                         goto asoc_class2_error;
1252                 } else{
1253                         pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1254                         pstat->state |= WIFI_FW_ASSOC_STATE;
1255                 }
1256         } else{
1257                 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1258                 pstat->state |= WIFI_FW_ASSOC_STATE;
1259         }
1260
1261
1262         pstat->capability = capab_info;
1263
1264         /* now parse all ieee802_11 ie to point to elems */
1265         if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
1266             !elems.ssid) {
1267                 DBG_871X("STA " MAC_FMT " sent invalid association request\n",
1268                        MAC_ARG(pstat->hwaddr));
1269                 status = _STATS_FAILURE_;
1270                 goto OnAssocReqFail;
1271         }
1272
1273
1274         /*  now we should check all the fields... */
1275         /*  checking SSID */
1276         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
1277                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1278         if (p == NULL) {
1279                 status = _STATS_FAILURE_;
1280         }
1281
1282         if (ie_len == 0) /*  broadcast ssid, however it is not allowed in assocreq */
1283                 status = _STATS_FAILURE_;
1284         else {
1285                 /*  check if ssid match */
1286                 if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
1287                         status = _STATS_FAILURE_;
1288
1289                 if (ie_len != cur->Ssid.SsidLength)
1290                         status = _STATS_FAILURE_;
1291         }
1292
1293         if (_STATS_SUCCESSFUL_ != status)
1294                 goto OnAssocReqFail;
1295
1296         /*  check if the supported rate is ok */
1297         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1298         if (p == NULL) {
1299                 DBG_871X("Rx a sta assoc-req which supported rate is empty!\n");
1300                 /*  use our own rate set as statoin used */
1301                 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1302                 /* supportRateNum = AP_BSSRATE_LEN; */
1303
1304                 status = _STATS_FAILURE_;
1305                 goto OnAssocReqFail;
1306         } else {
1307                 memcpy(supportRate, p+2, ie_len);
1308                 supportRateNum = ie_len;
1309
1310                 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
1311                                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1312                 if (p !=  NULL) {
1313
1314                         if (supportRateNum <= sizeof(supportRate)) {
1315                                 memcpy(supportRate+supportRateNum, p+2, ie_len);
1316                                 supportRateNum += ie_len;
1317                         }
1318                 }
1319         }
1320
1321         /* todo: mask supportRate between AP & STA -> move to update raid */
1322         /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1323
1324         /* update station supportRate */
1325         pstat->bssratelen = supportRateNum;
1326         memcpy(pstat->bssrateset, supportRate, supportRateNum);
1327         UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1328
1329         /* check RSN/WPA/WPS */
1330         pstat->dot8021xalg = 0;
1331         pstat->wpa_psk = 0;
1332         pstat->wpa_group_cipher = 0;
1333         pstat->wpa2_group_cipher = 0;
1334         pstat->wpa_pairwise_cipher = 0;
1335         pstat->wpa2_pairwise_cipher = 0;
1336         memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1337         if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1338
1339                 int group_cipher = 0, pairwise_cipher = 0;
1340
1341                 wpa_ie = elems.rsn_ie;
1342                 wpa_ie_len = elems.rsn_ie_len;
1343
1344                 if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1345                         pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1346                         pstat->wpa_psk |= BIT(1);
1347
1348                         pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
1349                         pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
1350
1351                         if (!pstat->wpa2_group_cipher)
1352                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1353
1354                         if (!pstat->wpa2_pairwise_cipher)
1355                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1356                 } else{
1357                         status = WLAN_STATUS_INVALID_IE;
1358                 }
1359
1360         } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1361
1362                 int group_cipher = 0, pairwise_cipher = 0;
1363
1364                 wpa_ie = elems.wpa_ie;
1365                 wpa_ie_len = elems.wpa_ie_len;
1366
1367                 if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1368                         pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1369                         pstat->wpa_psk |= BIT(0);
1370
1371                         pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
1372                         pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
1373
1374                         if (!pstat->wpa_group_cipher)
1375                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1376
1377                         if (!pstat->wpa_pairwise_cipher)
1378                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1379
1380                 } else{
1381                         status = WLAN_STATUS_INVALID_IE;
1382                 }
1383
1384         } else {
1385                 wpa_ie = NULL;
1386                 wpa_ie_len = 0;
1387         }
1388
1389         if (_STATS_SUCCESSFUL_ != status)
1390                 goto OnAssocReqFail;
1391
1392         pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1393         if (wpa_ie == NULL) {
1394                 if (elems.wps_ie) {
1395                         DBG_871X("STA included WPS IE in "
1396                                    "(Re)Association Request - assume WPS is "
1397                                    "used\n");
1398                         pstat->flags |= WLAN_STA_WPS;
1399                         /* wpabuf_free(sta->wps_ie); */
1400                         /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
1401                         /*                              elems.wps_ie_len - 4); */
1402                 } else {
1403                         DBG_871X("STA did not include WPA/RSN IE "
1404                                    "in (Re)Association Request - possible WPS "
1405                                    "use\n");
1406                         pstat->flags |= WLAN_STA_MAYBE_WPS;
1407                 }
1408
1409
1410                 /*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1411                 /*  that the selected registrar of AP is _FLASE */
1412                 if ((psecuritypriv->wpa_psk > 0)
1413                         && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
1414                         if (pmlmepriv->wps_beacon_ie) {
1415                                 u8 selected_registrar = 0;
1416
1417                                 rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
1418
1419                                 if (!selected_registrar) {
1420                                         DBG_871X("selected_registrar is false , or AP is not ready to do WPS\n");
1421
1422                                         status = _STATS_UNABLE_HANDLE_STA_;
1423
1424                                         goto OnAssocReqFail;
1425                                 }
1426                         }
1427                 }
1428
1429         } else{
1430                 int copy_len;
1431
1432                 if (psecuritypriv->wpa_psk == 0) {
1433                         DBG_871X("STA " MAC_FMT ": WPA/RSN IE in association "
1434                         "request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr));
1435
1436                         status = WLAN_STATUS_INVALID_IE;
1437
1438                         goto OnAssocReqFail;
1439
1440                 }
1441
1442                 if (elems.wps_ie) {
1443                         DBG_871X("STA included WPS IE in "
1444                                    "(Re)Association Request - WPS is "
1445                                    "used\n");
1446                         pstat->flags |= WLAN_STA_WPS;
1447                         copy_len = 0;
1448                 } else{
1449                         copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
1450                 }
1451
1452
1453                 if (copy_len > 0)
1454                         memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
1455
1456         }
1457
1458
1459         /*  check if there is WMM IE & support WWM-PS */
1460         pstat->flags &= ~WLAN_STA_WME;
1461         pstat->qos_option = 0;
1462         pstat->qos_info = 0;
1463         pstat->has_legacy_ac = true;
1464         pstat->uapsd_vo = 0;
1465         pstat->uapsd_vi = 0;
1466         pstat->uapsd_be = 0;
1467         pstat->uapsd_bk = 0;
1468         if (pmlmepriv->qospriv.qos_option) {
1469                 p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
1470                 for (;;) {
1471                         p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1472                         if (p != NULL) {
1473                                 if (!memcmp(p+2, WMM_IE, 6)) {
1474
1475                                         pstat->flags |= WLAN_STA_WME;
1476
1477                                         pstat->qos_option = 1;
1478                                         pstat->qos_info = *(p+8);
1479
1480                                         pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
1481
1482                                         if ((pstat->qos_info&0xf) != 0xf)
1483                                                 pstat->has_legacy_ac = true;
1484                                         else
1485                                                 pstat->has_legacy_ac = false;
1486
1487                                         if (pstat->qos_info&0xf) {
1488                                                 if (pstat->qos_info&BIT(0))
1489                                                         pstat->uapsd_vo = BIT(0)|BIT(1);
1490                                                 else
1491                                                         pstat->uapsd_vo = 0;
1492
1493                                                 if (pstat->qos_info&BIT(1))
1494                                                         pstat->uapsd_vi = BIT(0)|BIT(1);
1495                                                 else
1496                                                         pstat->uapsd_vi = 0;
1497
1498                                                 if (pstat->qos_info&BIT(2))
1499                                                         pstat->uapsd_bk = BIT(0)|BIT(1);
1500                                                 else
1501                                                         pstat->uapsd_bk = 0;
1502
1503                                                 if (pstat->qos_info&BIT(3))
1504                                                         pstat->uapsd_be = BIT(0)|BIT(1);
1505                                                 else
1506                                                         pstat->uapsd_be = 0;
1507
1508                                         }
1509
1510                                         break;
1511                                 }
1512                         } else {
1513                                 break;
1514                         }
1515                         p = p + ie_len + 2;
1516                 }
1517         }
1518
1519         /* save HT capabilities in the sta object */
1520         memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
1521         if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) {
1522                 pstat->flags |= WLAN_STA_HT;
1523
1524                 pstat->flags |= WLAN_STA_WME;
1525
1526                 memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));
1527
1528         } else
1529                 pstat->flags &= ~WLAN_STA_HT;
1530
1531
1532         if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT)) {
1533                 status = _STATS_FAILURE_;
1534                 goto OnAssocReqFail;
1535         }
1536
1537
1538         if ((pstat->flags & WLAN_STA_HT) &&
1539                     ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1540                       (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) {
1541                 DBG_871X("HT: " MAC_FMT " tried to "
1542                                    "use TKIP with HT association\n", MAC_ARG(pstat->hwaddr));
1543
1544                 /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1545                 /* goto OnAssocReqFail; */
1546         }
1547         pstat->flags |= WLAN_STA_NONERP;
1548         for (i = 0; i < pstat->bssratelen; i++) {
1549                 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1550                         pstat->flags &= ~WLAN_STA_NONERP;
1551                         break;
1552                 }
1553         }
1554
1555         if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1556                 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1557         else
1558                 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1559
1560
1561
1562         if (status != _STATS_SUCCESSFUL_)
1563                 goto OnAssocReqFail;
1564
1565         /* TODO: identify_proprietary_vendor_ie(); */
1566         /*  Realtek proprietary IE */
1567         /*  identify if this is Broadcom sta */
1568         /*  identify if this is ralink sta */
1569         /*  Customer proprietary IE */
1570
1571
1572
1573         /* get a unique AID */
1574         if (pstat->aid > 0) {
1575                 DBG_871X("  old AID %d\n", pstat->aid);
1576         } else {
1577                 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1578                         if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1579                                 break;
1580
1581                 /* if (pstat->aid > NUM_STA) { */
1582                 if (pstat->aid > pstapriv->max_num_sta) {
1583
1584                         pstat->aid = 0;
1585
1586                         DBG_871X("  no room for more AIDs\n");
1587
1588                         status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1589
1590                         goto OnAssocReqFail;
1591
1592
1593                 } else {
1594                         pstapriv->sta_aid[pstat->aid - 1] = pstat;
1595                         DBG_871X("allocate new AID = (%d)\n", pstat->aid);
1596                 }
1597         }
1598
1599
1600         pstat->state &= (~WIFI_FW_ASSOC_STATE);
1601         pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1602
1603         spin_lock_bh(&pstapriv->auth_list_lock);
1604         if (!list_empty(&pstat->auth_list)) {
1605                 list_del_init(&pstat->auth_list);
1606                 pstapriv->auth_list_cnt--;
1607         }
1608         spin_unlock_bh(&pstapriv->auth_list_lock);
1609
1610         spin_lock_bh(&pstapriv->asoc_list_lock);
1611         if (list_empty(&pstat->asoc_list)) {
1612                 pstat->expire_to = pstapriv->expire_to;
1613                 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1614                 pstapriv->asoc_list_cnt++;
1615         }
1616         spin_unlock_bh(&pstapriv->asoc_list_lock);
1617
1618         /*  now the station is qualified to join our BSS... */
1619         if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
1620                 /* 1 bss_cap_update & sta_info_update */
1621                 bss_cap_update_on_sta_join(padapter, pstat);
1622                 sta_info_update(padapter, pstat);
1623
1624                 /* 2 issue assoc rsp before notify station join event. */
1625                 if (frame_type == WIFI_ASSOCREQ)
1626                         issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1627                 else
1628                         issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1629
1630                 spin_lock_bh(&pstat->lock);
1631                 if (pstat->passoc_req) {
1632                         kfree(pstat->passoc_req);
1633                         pstat->passoc_req = NULL;
1634                         pstat->assoc_req_len = 0;
1635                 }
1636
1637                 pstat->passoc_req =  rtw_zmalloc(pkt_len);
1638                 if (pstat->passoc_req) {
1639                         memcpy(pstat->passoc_req, pframe, pkt_len);
1640                         pstat->assoc_req_len = pkt_len;
1641                 }
1642                 spin_unlock_bh(&pstat->lock);
1643
1644                 /* 3-(1) report sta add event */
1645                 report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
1646         }
1647
1648         return _SUCCESS;
1649
1650 asoc_class2_error:
1651
1652         issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1653
1654         return _FAIL;
1655
1656 OnAssocReqFail:
1657
1658         pstat->aid = 0;
1659         if (frame_type == WIFI_ASSOCREQ)
1660                 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1661         else
1662                 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1663
1664         return _FAIL;
1665 }
1666
1667 unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
1668 {
1669         uint i;
1670         int res;
1671         unsigned short  status;
1672         struct ndis_80211_var_ie *pIE;
1673         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1674         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1675         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1676         /* struct wlan_bssid_ex                 *cur_network = &(pmlmeinfo->network); */
1677         u8 *pframe = precv_frame->u.hdr.rx_data;
1678         uint pkt_len = precv_frame->u.hdr.len;
1679
1680         DBG_871X("%s\n", __func__);
1681
1682         /* check A1 matches or not */
1683         if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1684                 return _SUCCESS;
1685
1686         if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1687                 return _SUCCESS;
1688
1689         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1690                 return _SUCCESS;
1691
1692         del_timer_sync(&pmlmeext->link_timer);
1693
1694         /* status */
1695         status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
1696         if (status > 0) {
1697                 DBG_871X("assoc reject, status code: %d\n", status);
1698                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
1699                 res = -4;
1700                 goto report_assoc_result;
1701         }
1702
1703         /* get capabilities */
1704         pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1705
1706         /* set slot time */
1707         pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
1708
1709         /* AID */
1710         res = pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
1711
1712         /* following are moved to join event callback function */
1713         /* to handle HT, WMM, rate adaptive, update MAC reg */
1714         /* for not to handle the synchronous IO in the tasklet */
1715         for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
1716                 pIE = (struct ndis_80211_var_ie *)(pframe + i);
1717
1718                 switch (pIE->ElementID) {
1719                 case _VENDOR_SPECIFIC_IE_:
1720                         if (!memcmp(pIE->data, WMM_PARA_OUI, 6))        /* WMM */
1721                                 WMM_param_handler(padapter, pIE);
1722                         break;
1723
1724                 case _HT_CAPABILITY_IE_:        /* HT caps */
1725                         HT_caps_handler(padapter, pIE);
1726                         break;
1727
1728                 case _HT_EXTRA_INFO_IE_:        /* HT info */
1729                         HT_info_handler(padapter, pIE);
1730                         break;
1731
1732                 case _ERPINFO_IE_:
1733                         ERP_IE_handler(padapter, pIE);
1734
1735                 default:
1736                         break;
1737                 }
1738
1739                 i += (pIE->Length + 2);
1740         }
1741
1742         pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1743         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1744
1745         /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1746         UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
1747
1748 report_assoc_result:
1749         if (res > 0) {
1750                 rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
1751         } else {
1752                 rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
1753         }
1754
1755         report_join_res(padapter, res);
1756
1757         return _SUCCESS;
1758 }
1759
1760 unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
1761 {
1762         unsigned short  reason;
1763         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1764         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1765         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1766         u8 *pframe = precv_frame->u.hdr.rx_data;
1767
1768         /* check A3 */
1769         if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1770                 return _SUCCESS;
1771
1772         reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1773
1774         DBG_871X("%s Reason code(%d)\n", __func__, reason);
1775
1776         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1777                 struct sta_info *psta;
1778                 struct sta_priv *pstapriv = &padapter->stapriv;
1779
1780                 /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
1781                 /* rtw_free_stainfo(padapter, psta); */
1782                 /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
1783
1784                 DBG_871X_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
1785                                 reason, GetAddr2Ptr(pframe));
1786
1787                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1788                 if (psta) {
1789                         u8 updated = false;
1790
1791                         spin_lock_bh(&pstapriv->asoc_list_lock);
1792                         if (list_empty(&psta->asoc_list) == false) {
1793                                 list_del_init(&psta->asoc_list);
1794                                 pstapriv->asoc_list_cnt--;
1795                                 updated = ap_free_sta(padapter, psta, false, reason);
1796
1797                         }
1798                         spin_unlock_bh(&pstapriv->asoc_list_lock);
1799
1800                         associated_clients_update(padapter, updated);
1801                 }
1802
1803
1804                 return _SUCCESS;
1805         } else{
1806                 int     ignore_received_deauth = 0;
1807
1808                 /*      Commented by Albert 20130604 */
1809                 /*      Before sending the auth frame to start the STA/GC mode connection with AP/GO, */
1810                 /*      we will send the deauth first. */
1811                 /*      However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */
1812                 /*      Added the following code to avoid this case. */
1813                 if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||
1814                         (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {
1815                         if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) {
1816                                 ignore_received_deauth = 1;
1817                         } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) {
1818                                 /*  TODO: 802.11r */
1819                                 ignore_received_deauth = 1;
1820                         }
1821                 }
1822
1823                 DBG_871X_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n",
1824                                 reason, GetAddr3Ptr(pframe), ignore_received_deauth);
1825
1826                 if (0 == ignore_received_deauth) {
1827                         receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1828                 }
1829         }
1830         pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1831         return _SUCCESS;
1832
1833 }
1834
1835 unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame)
1836 {
1837         unsigned short  reason;
1838         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1839         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1840         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1841         u8 *pframe = precv_frame->u.hdr.rx_data;
1842
1843         /* check A3 */
1844         if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1845                 return _SUCCESS;
1846
1847         reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1848
1849         DBG_871X("%s Reason code(%d)\n", __func__, reason);
1850
1851         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1852                 struct sta_info *psta;
1853                 struct sta_priv *pstapriv = &padapter->stapriv;
1854
1855                 /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
1856                 /* rtw_free_stainfo(padapter, psta); */
1857                 /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
1858
1859                 DBG_871X_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
1860                                 reason, GetAddr2Ptr(pframe));
1861
1862                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1863                 if (psta) {
1864                         u8 updated = false;
1865
1866                         spin_lock_bh(&pstapriv->asoc_list_lock);
1867                         if (list_empty(&psta->asoc_list) == false) {
1868                                 list_del_init(&psta->asoc_list);
1869                                 pstapriv->asoc_list_cnt--;
1870                                 updated = ap_free_sta(padapter, psta, false, reason);
1871
1872                         }
1873                         spin_unlock_bh(&pstapriv->asoc_list_lock);
1874
1875                         associated_clients_update(padapter, updated);
1876                 }
1877
1878                 return _SUCCESS;
1879         } else{
1880                 DBG_871X_LEVEL(_drv_always_, "sta recv disassoc reason code(%d) sta:%pM\n",
1881                                 reason, GetAddr3Ptr(pframe));
1882
1883                 receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1884         }
1885         pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1886         return _SUCCESS;
1887
1888 }
1889
1890 unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame)
1891 {
1892         DBG_871X("%s\n", __func__);
1893         return _SUCCESS;
1894 }
1895
1896 unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame)
1897 {
1898         unsigned int ret = _FAIL;
1899         struct sta_info *psta = NULL;
1900         struct sta_priv *pstapriv = &padapter->stapriv;
1901         u8 *pframe = precv_frame->u.hdr.rx_data;
1902         u8 *frame_body = (u8 *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1903         u8 category;
1904         u8 action;
1905
1906         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
1907
1908         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1909
1910         if (!psta)
1911                 goto exit;
1912
1913         category = frame_body[0];
1914         if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
1915                 goto exit;
1916
1917         action = frame_body[1];
1918         switch (action) {
1919         case RTW_WLAN_ACTION_SPCT_MSR_REQ:
1920         case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
1921         case RTW_WLAN_ACTION_SPCT_TPC_REQ:
1922         case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
1923         case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
1924                 break;
1925         default:
1926                 break;
1927         }
1928
1929 exit:
1930         return ret;
1931 }
1932
1933 unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame)
1934 {
1935         u8 *addr;
1936         struct sta_info *psta = NULL;
1937         struct recv_reorder_ctrl *preorder_ctrl;
1938         unsigned char   *frame_body;
1939         unsigned char   category, action;
1940         unsigned short  tid, status, reason_code = 0;
1941         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1942         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1943         u8 *pframe = precv_frame->u.hdr.rx_data;
1944         struct sta_priv *pstapriv = &padapter->stapriv;
1945
1946         DBG_871X("%s\n", __func__);
1947
1948         /* check RA matches or not */
1949         if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
1950                 return _SUCCESS;
1951
1952         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1953                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1954                         return _SUCCESS;
1955
1956         addr = GetAddr2Ptr(pframe);
1957         psta = rtw_get_stainfo(pstapriv, addr);
1958
1959         if (psta == NULL)
1960                 return _SUCCESS;
1961
1962         frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1963
1964         category = frame_body[0];
1965         if (category == RTW_WLAN_CATEGORY_BACK) {/*  representing Block Ack */
1966                 if (!pmlmeinfo->HT_enable) {
1967                         return _SUCCESS;
1968                 }
1969
1970                 action = frame_body[1];
1971                 DBG_871X("%s, action =%d\n", __func__, action);
1972                 switch (action) {
1973                 case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
1974
1975                         memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
1976                         /* process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */
1977                         process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
1978
1979                         if (pmlmeinfo->bAcceptAddbaReq == true) {
1980                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
1981                         } else{
1982                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
1983                         }
1984
1985                         break;
1986
1987                 case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
1988                         status = RTW_GET_LE16(&frame_body[3]);
1989                         tid = ((frame_body[5] >> 2) & 0x7);
1990
1991                         if (status == 0) {
1992                                 /* successful */
1993                                 DBG_871X("agg_enable for TID =%d\n", tid);
1994                                 psta->htpriv.agg_enable_bitmap |= 1 << tid;
1995                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1996                         } else{
1997                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1998                         }
1999
2000                         if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
2001                                 DBG_871X("%s alive check - rx ADDBA response\n", __func__);
2002                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2003                                 psta->expire_to = pstapriv->expire_to;
2004                                 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
2005                         }
2006
2007                         /* DBG_871X("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap); */
2008                         break;
2009
2010                 case RTW_WLAN_ACTION_DELBA: /* DELBA */
2011                         if ((frame_body[3] & BIT(3)) == 0) {
2012                                 psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
2013                                 psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
2014
2015                                 /* reason_code = frame_body[4] | (frame_body[5] << 8); */
2016                                 reason_code = RTW_GET_LE16(&frame_body[4]);
2017                         } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
2018                                 tid = (frame_body[3] >> 4) & 0x0F;
2019
2020                                 preorder_ctrl =  &psta->recvreorder_ctrl[tid];
2021                                 preorder_ctrl->enable = false;
2022                                 preorder_ctrl->indicate_seq = 0xffff;
2023                                 #ifdef DBG_RX_SEQ
2024                                 DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__,
2025                                         preorder_ctrl->indicate_seq);
2026                                 #endif
2027                         }
2028
2029                         DBG_871X("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code);
2030                         /* todo: how to notify the host while receiving DELETE BA */
2031                         break;
2032
2033                 default:
2034                         break;
2035                 }
2036         }
2037         return _SUCCESS;
2038 }
2039
2040 static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
2041 {
2042         struct adapter *adapter = recv_frame->u.hdr.adapter;
2043         struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
2044         u8 *frame = recv_frame->u.hdr.rx_data;
2045         u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
2046                 (recv_frame->u.hdr.attrib.frag_num & 0xf);
2047
2048         if (GetRetry(frame)) {
2049                 if (token >= 0) {
2050                         if ((seq_ctrl == mlmeext->action_public_rxseq)
2051                                 && (token == mlmeext->action_public_dialog_token)) {
2052                                 DBG_871X(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n",
2053                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
2054                                 return _FAIL;
2055                         }
2056                 } else {
2057                         if (seq_ctrl == mlmeext->action_public_rxseq) {
2058                                 DBG_871X(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n",
2059                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
2060                                 return _FAIL;
2061                         }
2062                 }
2063         }
2064
2065         mlmeext->action_public_rxseq = seq_ctrl;
2066
2067         if (token >= 0)
2068                 mlmeext->action_public_dialog_token = token;
2069
2070         return _SUCCESS;
2071 }
2072
2073 static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
2074 {
2075         u8 *pframe = precv_frame->u.hdr.rx_data;
2076         u8 *frame_body;
2077         u8 dialogToken = 0;
2078
2079         frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
2080
2081         dialogToken = frame_body[7];
2082
2083         if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
2084                 return _FAIL;
2085
2086         return _SUCCESS;
2087 }
2088
2089 static unsigned int on_action_public_vendor(union recv_frame *precv_frame)
2090 {
2091         unsigned int ret = _FAIL;
2092         u8 *pframe = precv_frame->u.hdr.rx_data;
2093         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2094
2095         if (!memcmp(frame_body + 2, P2P_OUI, 4)) {
2096                 ret = on_action_public_p2p(precv_frame);
2097         }
2098
2099         return ret;
2100 }
2101
2102 static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
2103 {
2104         unsigned int ret = _FAIL;
2105         u8 *pframe = precv_frame->u.hdr.rx_data;
2106         uint frame_len = precv_frame->u.hdr.len;
2107         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2108         u8 token;
2109         struct adapter *adapter = precv_frame->u.hdr.adapter;
2110         int cnt = 0;
2111         char msg[64];
2112
2113         token = frame_body[2];
2114
2115         if (rtw_action_public_decache(precv_frame, token) == _FAIL)
2116                 goto exit;
2117
2118         cnt += sprintf((msg+cnt), "%s(token:%u)", action_public_str(action), token);
2119         rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
2120
2121         ret = _SUCCESS;
2122
2123 exit:
2124         return ret;
2125 }
2126
2127 unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame)
2128 {
2129         unsigned int ret = _FAIL;
2130         u8 *pframe = precv_frame->u.hdr.rx_data;
2131         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2132         u8 category, action;
2133
2134         /* check RA matches or not */
2135         if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
2136                 goto exit;
2137
2138         category = frame_body[0];
2139         if (category != RTW_WLAN_CATEGORY_PUBLIC)
2140                 goto exit;
2141
2142         action = frame_body[1];
2143         switch (action) {
2144         case ACT_PUBLIC_VENDOR:
2145                 ret = on_action_public_vendor(precv_frame);
2146                 break;
2147         default:
2148                 ret = on_action_public_default(precv_frame, action);
2149                 break;
2150         }
2151
2152 exit:
2153         return ret;
2154 }
2155
2156 unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame)
2157 {
2158         u8 *pframe = precv_frame->u.hdr.rx_data;
2159         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2160         u8 category, action;
2161
2162         /* check RA matches or not */
2163         if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
2164                 goto exit;
2165
2166         category = frame_body[0];
2167         if (category != RTW_WLAN_CATEGORY_HT)
2168                 goto exit;
2169
2170         action = frame_body[1];
2171         switch (action) {
2172         case RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING:
2173                 break;
2174         default:
2175                 break;
2176         }
2177
2178 exit:
2179
2180         return _SUCCESS;
2181 }
2182
2183 unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv_frame)
2184 {
2185         u8 *pframe = precv_frame->u.hdr.rx_data;
2186         struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
2187         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2188         unsigned short tid;
2189         /* Baron */
2190
2191         DBG_871X("OnAction_sa_query\n");
2192
2193         switch (pframe[WLAN_HDR_A3_LEN+1]) {
2194         case 0: /* SA Query req */
2195                 memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short));
2196                 DBG_871X("OnAction_sa_query request, action =%d, tid =%04x\n", pframe[WLAN_HDR_A3_LEN+1], tid);
2197                 issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid);
2198                 break;
2199
2200         case 1: /* SA Query rsp */
2201                 del_timer_sync(&pmlmeext->sa_query_timer);
2202                 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]);
2203                 break;
2204         default:
2205                 break;
2206         }
2207         if (0) {
2208                 int pp;
2209                 printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
2210                 for (pp = 0; pp < pattrib->pkt_len; pp++)
2211                         printk(" %02x ", pframe[pp]);
2212                 printk("\n");
2213         }
2214
2215         return _SUCCESS;
2216 }
2217
2218 unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame)
2219 {
2220         int i;
2221         unsigned char category;
2222         struct action_handler *ptable;
2223         unsigned char *frame_body;
2224         u8 *pframe = precv_frame->u.hdr.rx_data;
2225
2226         frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
2227
2228         category = frame_body[0];
2229
2230         for (i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++) {
2231                 ptable = &OnAction_tbl[i];
2232
2233                 if (category == ptable->num)
2234                         ptable->func(padapter, precv_frame);
2235
2236         }
2237
2238         return _SUCCESS;
2239
2240 }
2241
2242 unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame)
2243 {
2244
2245         /* DBG_871X("rcvd mgt frame(%x, %x)\n", (GetFrameSubType(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe)); */
2246         return _SUCCESS;
2247 }
2248
2249 static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
2250 {
2251         struct xmit_frame *pmgntframe;
2252         struct xmit_buf *pxmitbuf;
2253
2254         if (once)
2255                 pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
2256         else
2257                 pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
2258
2259         if (pmgntframe == NULL) {
2260                 DBG_871X(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once);
2261                 goto exit;
2262         }
2263
2264         pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
2265         if (pxmitbuf == NULL) {
2266                 DBG_871X(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter));
2267                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
2268                 pmgntframe = NULL;
2269                 goto exit;
2270         }
2271
2272         pmgntframe->frame_tag = MGNT_FRAMETAG;
2273         pmgntframe->pxmitbuf = pxmitbuf;
2274         pmgntframe->buf_addr = pxmitbuf->pbuf;
2275         pxmitbuf->priv_data = pmgntframe;
2276
2277 exit:
2278         return pmgntframe;
2279
2280 }
2281
2282 inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
2283 {
2284         return _alloc_mgtxmitframe(pxmitpriv, false);
2285 }
2286
2287 /****************************************************************************
2288
2289 Following are some TX fuctions for WiFi MLME
2290
2291 *****************************************************************************/
2292
2293 void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
2294 {
2295         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2296
2297         pmlmeext->tx_rate = rate;
2298         /* DBG_871X("%s(): rate = %x\n", __func__, rate); */
2299 }
2300
2301 void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
2302 {
2303         u8 wireless_mode;
2304         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2305
2306         /* memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */
2307
2308         pattrib->hdrlen = 24;
2309         pattrib->nr_frags = 1;
2310         pattrib->priority = 7;
2311         pattrib->mac_id = 0;
2312         pattrib->qsel = 0x12;
2313
2314         pattrib->pktlen = 0;
2315
2316         if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
2317                 wireless_mode = WIRELESS_11B;
2318         else
2319                 wireless_mode = WIRELESS_11G;
2320         pattrib->raid =  rtw_get_mgntframe_raid(padapter, wireless_mode);
2321         pattrib->rate = pmlmeext->tx_rate;
2322
2323         pattrib->encrypt = _NO_PRIVACY_;
2324         pattrib->bswenc = false;
2325
2326         pattrib->qos_en = false;
2327         pattrib->ht_en = false;
2328         pattrib->bwmode = CHANNEL_WIDTH_20;
2329         pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2330         pattrib->sgi = false;
2331
2332         pattrib->seqnum = pmlmeext->mgnt_seq;
2333
2334         pattrib->retry_ctrl = true;
2335
2336         pattrib->mbssid = 0;
2337
2338 }
2339
2340 void update_mgntframe_attrib_addr(struct adapter *padapter, struct xmit_frame *pmgntframe)
2341 {
2342         u8 *pframe;
2343         struct pkt_attrib       *pattrib = &pmgntframe->attrib;
2344
2345         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2346
2347         memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);
2348         memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN);
2349 }
2350
2351 void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
2352 {
2353         if (padapter->bSurpriseRemoved == true ||
2354                 padapter->bDriverStopped == true) {
2355                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2356                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2357                 return;
2358         }
2359
2360         rtw_hal_mgnt_xmit(padapter, pmgntframe);
2361 }
2362
2363 s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
2364 {
2365         s32 ret = _FAIL;
2366         _irqL irqL;
2367         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2368         struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2369         struct submit_ctx sctx;
2370
2371         if (padapter->bSurpriseRemoved == true ||
2372                 padapter->bDriverStopped == true) {
2373                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2374                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2375                 return ret;
2376         }
2377
2378         rtw_sctx_init(&sctx, timeout_ms);
2379         pxmitbuf->sctx = &sctx;
2380
2381         ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
2382
2383         if (ret == _SUCCESS)
2384                 ret = rtw_sctx_wait(&sctx, __func__);
2385
2386         spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2387         pxmitbuf->sctx = NULL;
2388         spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2389
2390         return ret;
2391 }
2392
2393 s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
2394 {
2395         static u8 seq_no;
2396         s32 ret = _FAIL;
2397         u32 timeout_ms = 500;/*   500ms */
2398         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2399
2400         if (padapter->bSurpriseRemoved == true ||
2401                 padapter->bDriverStopped == true) {
2402                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2403                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2404                 return -1;
2405         }
2406
2407         if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex) == 0) {
2408                 pxmitpriv->ack_tx = true;
2409                 pxmitpriv->seq_no = seq_no++;
2410                 pmgntframe->ack_report = 1;
2411                 if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
2412                         ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
2413                 }
2414
2415                 pxmitpriv->ack_tx = false;
2416                 mutex_unlock(&pxmitpriv->ack_tx_mutex);
2417         }
2418
2419         return ret;
2420 }
2421
2422 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2423 {
2424         u8 *ssid_ie;
2425         sint ssid_len_ori;
2426         int len_diff = 0;
2427
2428         ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
2429
2430         /* DBG_871X("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
2431
2432         if (ssid_ie && ssid_len_ori > 0) {
2433                 switch (hidden_ssid_mode) {
2434                 case 1:
2435                 {
2436                         u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
2437                         u32 remain_len = 0;
2438
2439                         remain_len = ies_len - (next_ie-ies);
2440
2441                         ssid_ie[1] = 0;
2442                         memcpy(ssid_ie+2, next_ie, remain_len);
2443                         len_diff -= ssid_len_ori;
2444
2445                         break;
2446                 }
2447                 case 2:
2448                         memset(&ssid_ie[2], 0, ssid_len_ori);
2449                         break;
2450                 default:
2451                         break;
2452         }
2453         }
2454
2455         return len_diff;
2456 }
2457
2458 void issue_beacon(struct adapter *padapter, int timeout_ms)
2459 {
2460         struct xmit_frame       *pmgntframe;
2461         struct pkt_attrib       *pattrib;
2462         unsigned char *pframe;
2463         struct ieee80211_hdr *pwlanhdr;
2464         __le16 *fctrl;
2465         unsigned int    rate_len;
2466         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2467         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2468         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2469         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2470         struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
2471         u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2472
2473         /* DBG_871X("%s\n", __func__); */
2474
2475         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2476         if (pmgntframe == NULL) {
2477                 DBG_871X("%s, alloc mgnt frame fail\n", __func__);
2478                 return;
2479         }
2480
2481         spin_lock_bh(&pmlmepriv->bcn_update_lock);
2482
2483         /* update attribute */
2484         pattrib = &pmgntframe->attrib;
2485         update_mgntframe_attrib(padapter, pattrib);
2486         pattrib->qsel = 0x10;
2487
2488         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2489
2490         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2491         pwlanhdr = (struct ieee80211_hdr *)pframe;
2492
2493
2494         fctrl = &(pwlanhdr->frame_control);
2495         *(fctrl) = 0;
2496
2497         memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
2498         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2499         memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
2500
2501         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
2502         /* pmlmeext->mgnt_seq++; */
2503         SetFrameSubType(pframe, WIFI_BEACON);
2504
2505         pframe += sizeof(struct ieee80211_hdr_3addr);
2506         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2507
2508         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2509                 /* DBG_871X("ie len =%d\n", cur_network->IELength); */
2510                 {
2511                         int len_diff;
2512                         memcpy(pframe, cur_network->IEs, cur_network->IELength);
2513                         len_diff = update_hidden_ssid(
2514                                 pframe+_BEACON_IE_OFFSET_
2515                                 , cur_network->IELength-_BEACON_IE_OFFSET_
2516                                 , pmlmeinfo->hidden_ssid_mode
2517                         );
2518                         pframe += (cur_network->IELength+len_diff);
2519                         pattrib->pktlen += (cur_network->IELength+len_diff);
2520                 }
2521
2522                 {
2523                         u8 *wps_ie;
2524                         uint wps_ielen;
2525                         u8 sr = 0;
2526                         wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
2527                                 pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
2528                         if (wps_ie && wps_ielen > 0) {
2529                                 rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
2530                         }
2531                         if (sr != 0)
2532                                 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2533                         else
2534                                 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2535                 }
2536
2537                 goto _issue_bcn;
2538
2539         }
2540
2541         /* below for ad-hoc mode */
2542
2543         /* timestamp will be inserted by hardware */
2544         pframe += 8;
2545         pattrib->pktlen += 8;
2546
2547         /*  beacon interval: 2 bytes */
2548
2549         memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
2550
2551         pframe += 2;
2552         pattrib->pktlen += 2;
2553
2554         /*  capability info: 2 bytes */
2555
2556         memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
2557
2558         pframe += 2;
2559         pattrib->pktlen += 2;
2560
2561         /*  SSID */
2562         pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
2563
2564         /*  supported rates... */
2565         rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
2566         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
2567
2568         /*  DS parameter set */
2569         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
2570
2571         /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
2572         {
2573                 u8 erpinfo = 0;
2574                 u32 ATIMWindow;
2575                 /*  IBSS Parameter Set... */
2576                 /* ATIMWindow = cur->Configuration.ATIMWindow; */
2577                 ATIMWindow = 0;
2578                 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
2579
2580                 /* ERP IE */
2581                 pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
2582         }
2583
2584
2585         /*  EXTERNDED SUPPORTED RATE */
2586         if (rate_len > 8) {
2587                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
2588         }
2589
2590
2591         /* todo:HT for adhoc */
2592
2593 _issue_bcn:
2594
2595         pmlmepriv->update_bcn = false;
2596
2597         spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2598
2599         if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
2600                 DBG_871X("beacon frame too large\n");
2601                 return;
2602         }
2603
2604         pattrib->last_txcmdsz = pattrib->pktlen;
2605
2606         /* DBG_871X("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
2607         if (timeout_ms > 0)
2608                 dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
2609         else
2610                 dump_mgntframe(padapter, pmgntframe);
2611
2612 }
2613
2614 void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
2615 {
2616         struct xmit_frame                       *pmgntframe;
2617         struct pkt_attrib                       *pattrib;
2618         unsigned char                           *pframe;
2619         struct ieee80211_hdr    *pwlanhdr;
2620         __le16 *fctrl;
2621         unsigned char                           *mac, *bssid;
2622         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2623
2624         u8 *pwps_ie;
2625         uint wps_ielen;
2626         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2627         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2628         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2629         struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
2630         unsigned int    rate_len;
2631
2632         /* DBG_871X("%s\n", __func__); */
2633
2634         if (da == NULL)
2635                 return;
2636
2637         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2638         if (pmgntframe == NULL) {
2639                 DBG_871X("%s, alloc mgnt frame fail\n", __func__);
2640                 return;
2641         }
2642
2643
2644         /* update attribute */
2645         pattrib = &pmgntframe->attrib;
2646         update_mgntframe_attrib(padapter, pattrib);
2647
2648         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2649
2650         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2651         pwlanhdr = (struct ieee80211_hdr *)pframe;
2652
2653         mac = myid(&(padapter->eeprompriv));
2654         bssid = cur_network->MacAddress;
2655
2656         fctrl = &(pwlanhdr->frame_control);
2657         *(fctrl) = 0;
2658         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
2659         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
2660         memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
2661
2662         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2663         pmlmeext->mgnt_seq++;
2664         SetFrameSubType(fctrl, WIFI_PROBERSP);
2665
2666         pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2667         pattrib->pktlen = pattrib->hdrlen;
2668         pframe += pattrib->hdrlen;
2669
2670
2671         if (cur_network->IELength > MAX_IE_SZ)
2672                 return;
2673
2674         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2675                 pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
2676
2677                 /* inerset & update wps_probe_resp_ie */
2678                 if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
2679                         uint wps_offset, remainder_ielen;
2680                         u8 *premainder_ie;
2681
2682                         wps_offset = (uint)(pwps_ie - cur_network->IEs);
2683
2684                         premainder_ie = pwps_ie + wps_ielen;
2685
2686                         remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
2687
2688                         memcpy(pframe, cur_network->IEs, wps_offset);
2689                         pframe += wps_offset;
2690                         pattrib->pktlen += wps_offset;
2691
2692                         wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
2693                         if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
2694                                 memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
2695                                 pframe += wps_ielen+2;
2696                                 pattrib->pktlen += wps_ielen+2;
2697                         }
2698
2699                         if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
2700                                 memcpy(pframe, premainder_ie, remainder_ielen);
2701                                 pframe += remainder_ielen;
2702                                 pattrib->pktlen += remainder_ielen;
2703                         }
2704                 } else{
2705                         memcpy(pframe, cur_network->IEs, cur_network->IELength);
2706                         pframe += cur_network->IELength;
2707                         pattrib->pktlen += cur_network->IELength;
2708                 }
2709
2710                 /* retrieve SSID IE from cur_network->Ssid */
2711                 {
2712                         u8 *ssid_ie;
2713                         sint ssid_ielen;
2714                         sint ssid_ielen_diff;
2715                         u8 buf[MAX_IE_SZ];
2716                         u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr);
2717
2718                         ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
2719                                 (pframe-ies)-_FIXED_IE_LENGTH_);
2720
2721                         ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
2722
2723                         if (ssid_ie &&  cur_network->Ssid.SsidLength) {
2724                                 uint remainder_ielen;
2725                                 u8 *remainder_ie;
2726                                 remainder_ie = ssid_ie+2;
2727                                 remainder_ielen = (pframe-remainder_ie);
2728
2729                                 if (remainder_ielen > MAX_IE_SZ) {
2730                                         DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));
2731                                         remainder_ielen = MAX_IE_SZ;
2732                                 }
2733
2734                                 memcpy(buf, remainder_ie, remainder_ielen);
2735                                 memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
2736                                 *(ssid_ie+1) = cur_network->Ssid.SsidLength;
2737                                 memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
2738
2739                                 pframe += ssid_ielen_diff;
2740                                 pattrib->pktlen += ssid_ielen_diff;
2741                         }
2742                 }
2743         } else{
2744                 /* timestamp will be inserted by hardware */
2745                 pframe += 8;
2746                 pattrib->pktlen += 8;
2747
2748                 /*  beacon interval: 2 bytes */
2749
2750                 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
2751
2752                 pframe += 2;
2753                 pattrib->pktlen += 2;
2754
2755                 /*  capability info: 2 bytes */
2756
2757                 memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
2758
2759                 pframe += 2;
2760                 pattrib->pktlen += 2;
2761
2762                 /* below for ad-hoc mode */
2763
2764                 /*  SSID */
2765                 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
2766
2767                 /*  supported rates... */
2768                 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
2769                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
2770
2771                 /*  DS parameter set */
2772                 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
2773
2774                 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
2775                         u8 erpinfo = 0;
2776                         u32 ATIMWindow;
2777                         /*  IBSS Parameter Set... */
2778                         /* ATIMWindow = cur->Configuration.ATIMWindow; */
2779                         ATIMWindow = 0;
2780                         pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
2781
2782                         /* ERP IE */
2783                         pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
2784                 }
2785
2786
2787                 /*  EXTERNDED SUPPORTED RATE */
2788                 if (rate_len > 8) {
2789                         pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
2790                 }
2791
2792
2793                 /* todo:HT for adhoc */
2794
2795         }
2796
2797 #ifdef CONFIG_AUTO_AP_MODE
2798 {
2799         struct sta_info *psta;
2800         struct sta_priv *pstapriv = &padapter->stapriv;
2801
2802         DBG_871X("(%s)\n", __func__);
2803
2804         /* check rc station */
2805         psta = rtw_get_stainfo(pstapriv, da);
2806         if (psta && psta->isrc && psta->pid > 0) {
2807                 u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A};
2808                 u8 RC_INFO[14] = {0};
2809                 /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */
2810                 u16 cu_ch = (u16)cur_network->Configuration.DSConfig;
2811
2812                 DBG_871X("%s, reply rc(pid = 0x%x) device "MAC_FMT" in ch =%d\n", __func__,
2813                         psta->pid, MAC_ARG(psta->hwaddr), cu_ch);
2814
2815                 /* append vendor specific ie */
2816                 memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI));
2817                 memcpy(&RC_INFO[4], mac, ETH_ALEN);
2818                 memcpy(&RC_INFO[10], (u8 *)&psta->pid, 2);
2819                 memcpy(&RC_INFO[12], (u8 *)&cu_ch, 2);
2820
2821                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen);
2822         }
2823 }
2824 #endif /* CONFIG_AUTO_AP_MODE */
2825
2826
2827         pattrib->last_txcmdsz = pattrib->pktlen;
2828
2829
2830         dump_mgntframe(padapter, pmgntframe);
2831
2832         return;
2833
2834 }
2835
2836 static int _issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps, int wait_ack)
2837 {
2838         int ret = _FAIL;
2839         struct xmit_frame               *pmgntframe;
2840         struct pkt_attrib               *pattrib;
2841         unsigned char           *pframe;
2842         struct ieee80211_hdr    *pwlanhdr;
2843         __le16 *fctrl;
2844         unsigned char           *mac;
2845         unsigned char           bssrate[NumRates];
2846         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
2847         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2848         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2849         int     bssrate_len = 0;
2850         u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2851
2852         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+issue_probereq\n"));
2853
2854         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2855         if (pmgntframe == NULL)
2856                 goto exit;
2857
2858         /* update attribute */
2859         pattrib = &pmgntframe->attrib;
2860         update_mgntframe_attrib(padapter, pattrib);
2861
2862
2863         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2864
2865         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2866         pwlanhdr = (struct ieee80211_hdr *)pframe;
2867
2868         mac = myid(&(padapter->eeprompriv));
2869
2870         fctrl = &(pwlanhdr->frame_control);
2871         *(fctrl) = 0;
2872
2873         if (da) {
2874                 /*      unicast probe request frame */
2875                 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
2876                 memcpy(pwlanhdr->addr3, da, ETH_ALEN);
2877         } else{
2878                 /*      broadcast probe request frame */
2879                 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
2880                 memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
2881         }
2882
2883         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
2884
2885         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2886         pmlmeext->mgnt_seq++;
2887         SetFrameSubType(pframe, WIFI_PROBEREQ);
2888
2889         pframe += sizeof(struct ieee80211_hdr_3addr);
2890         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2891
2892         if (pssid)
2893                 pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
2894         else
2895                 pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
2896
2897         get_rate_set(padapter, bssrate, &bssrate_len);
2898
2899         if (bssrate_len > 8) {
2900                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen));
2901                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
2902         } else{
2903                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen));
2904         }
2905
2906         if (ch)
2907                 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, &ch, &pattrib->pktlen);
2908
2909         if (append_wps) {
2910                 /* add wps_ie for wps2.0 */
2911                 if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
2912                         memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
2913                         pframe += pmlmepriv->wps_probe_req_ie_len;
2914                         pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2915                 }
2916         }
2917
2918         pattrib->last_txcmdsz = pattrib->pktlen;
2919
2920         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz));
2921
2922         if (wait_ack) {
2923                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
2924         } else {
2925                 dump_mgntframe(padapter, pmgntframe);
2926                 ret = _SUCCESS;
2927         }
2928
2929 exit:
2930         return ret;
2931 }
2932
2933 inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
2934 {
2935         _issue_probereq(padapter, pssid, da, 0, 1, false);
2936 }
2937
2938 int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps,
2939         int try_cnt, int wait_ms)
2940 {
2941         int ret;
2942         int i = 0;
2943
2944         do {
2945                 ret = _issue_probereq(padapter, pssid, da, ch, append_wps, wait_ms > 0?true:false);
2946
2947                 i++;
2948
2949                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2950                         break;
2951
2952                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2953                         msleep(wait_ms);
2954
2955         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2956
2957         if (ret != _FAIL) {
2958                 ret = _SUCCESS;
2959                 #ifndef DBG_XMIT_ACK
2960                 goto exit;
2961                 #endif
2962         }
2963
2964         if (try_cnt && wait_ms) {
2965                 if (da)
2966                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
2967                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
2968                                 ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
2969                 else
2970                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
2971                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
2972                                 ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
2973         }
2974 exit:
2975         return ret;
2976 }
2977
2978 /*  if psta == NULL, indiate we are station(client) now... */
2979 void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
2980 {
2981         struct xmit_frame                       *pmgntframe;
2982         struct pkt_attrib                       *pattrib;
2983         unsigned char                           *pframe;
2984         struct ieee80211_hdr    *pwlanhdr;
2985         __le16 *fctrl;
2986         unsigned int                                    val32;
2987         unsigned short                          val16;
2988         int use_shared_key = 0;
2989         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
2990         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2991         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2992         __le16 le_tmp;
2993
2994         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2995         if (pmgntframe == NULL)
2996                 return;
2997
2998         /* update attribute */
2999         pattrib = &pmgntframe->attrib;
3000         update_mgntframe_attrib(padapter, pattrib);
3001
3002         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3003
3004         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3005         pwlanhdr = (struct ieee80211_hdr *)pframe;
3006
3007         fctrl = &(pwlanhdr->frame_control);
3008         *(fctrl) = 0;
3009
3010         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3011         pmlmeext->mgnt_seq++;
3012         SetFrameSubType(pframe, WIFI_AUTH);
3013
3014         pframe += sizeof(struct ieee80211_hdr_3addr);
3015         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3016
3017
3018         if (psta) { /*  for AP mode */
3019                 memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
3020                 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3021                 memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
3022
3023                 /*  setting auth algo number */
3024                 val16 = (u16)psta->authalg;
3025
3026                 if (status != _STATS_SUCCESSFUL_)
3027                         val16 = 0;
3028
3029                 if (val16)
3030                         use_shared_key = 1;
3031
3032                 le_tmp = cpu_to_le16(val16);
3033
3034                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3035
3036                 /*  setting auth seq number */
3037                 val16 = (u16)psta->auth_seq;
3038                 le_tmp = cpu_to_le16(val16);
3039                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3040
3041                 /*  setting status code... */
3042                 val16 = status;
3043                 le_tmp = cpu_to_le16(val16);
3044                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3045
3046                 /*  added challenging text... */
3047                 if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
3048                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
3049
3050         } else{
3051                 memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
3052                 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
3053                 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
3054
3055                 /*  setting auth algo number */
3056                 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/*  0:OPEN System, 1:Shared key */
3057                 if (val16) {
3058                         use_shared_key = 1;
3059                 }
3060                 le_tmp = cpu_to_le16(val16);
3061                 /* DBG_871X("%s auth_algo = %s auth_seq =%d\n", __func__, (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED", pmlmeinfo->auth_seq); */
3062
3063                 /* setting IV for auth seq #3 */
3064                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
3065                         __le32 le_tmp32;
3066
3067                         /* DBG_871X("==> iv(%d), key_index(%d)\n", pmlmeinfo->iv, pmlmeinfo->key_index); */
3068                         val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
3069                         le_tmp32 = cpu_to_le32(val32);
3070                         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen));
3071
3072                         pattrib->iv_len = 4;
3073                 }
3074
3075                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3076
3077                 /*  setting auth seq number */
3078                 le_tmp = cpu_to_le16(pmlmeinfo->auth_seq);
3079                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3080
3081
3082                 /*  setting status code... */
3083                 le_tmp = cpu_to_le16(status);
3084                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3085
3086                 /*  then checking to see if sending challenging text... */
3087                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
3088                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
3089
3090                         SetPrivacy(fctrl);
3091
3092                         pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3093
3094                         pattrib->encrypt = _WEP40_;
3095
3096                         pattrib->icv_len = 4;
3097
3098                         pattrib->pktlen += pattrib->icv_len;
3099
3100                 }
3101
3102         }
3103
3104         pattrib->last_txcmdsz = pattrib->pktlen;
3105
3106         rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
3107         DBG_871X("%s\n", __func__);
3108         dump_mgntframe(padapter, pmgntframe);
3109
3110         return;
3111 }
3112
3113
3114 void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
3115 {
3116         struct xmit_frame       *pmgntframe;
3117         struct ieee80211_hdr    *pwlanhdr;
3118         struct pkt_attrib *pattrib;
3119         unsigned char *pbuf, *pframe;
3120         unsigned short val;
3121         __le16 *fctrl;
3122         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
3123         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3124         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3125         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3126         struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
3127         u8 *ie = pnetwork->IEs;
3128         __le16 lestatus, le_tmp;
3129
3130         DBG_871X("%s\n", __func__);
3131
3132         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3133         if (pmgntframe == NULL)
3134                 return;
3135
3136         /* update attribute */
3137         pattrib = &pmgntframe->attrib;
3138         update_mgntframe_attrib(padapter, pattrib);
3139
3140
3141         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3142
3143         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3144         pwlanhdr = (struct ieee80211_hdr *)pframe;
3145
3146         fctrl = &(pwlanhdr->frame_control);
3147         *(fctrl) = 0;
3148
3149         memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
3150         memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
3151         memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3152
3153
3154         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3155         pmlmeext->mgnt_seq++;
3156         if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
3157                 SetFrameSubType(pwlanhdr, pkt_type);
3158         else
3159                 return;
3160
3161         pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3162         pattrib->pktlen += pattrib->hdrlen;
3163         pframe += pattrib->hdrlen;
3164
3165         /* capability */
3166         val = *(unsigned short *)rtw_get_capability_from_ie(ie);
3167
3168         pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &(pattrib->pktlen));
3169
3170         lestatus = cpu_to_le16(status);
3171         pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &(pattrib->pktlen));
3172
3173         le_tmp = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
3174         pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3175
3176         if (pstat->bssratelen <= 8) {
3177                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
3178         } else{
3179                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
3180                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
3181         }
3182
3183         if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
3184                 uint ie_len = 0;
3185
3186                 /* FILL HT CAP INFO IE */
3187                 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
3188                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
3189                 if (pbuf && ie_len > 0) {
3190                         memcpy(pframe, pbuf, ie_len+2);
3191                         pframe += (ie_len+2);
3192                         pattrib->pktlen += (ie_len+2);
3193                 }
3194
3195                 /* FILL HT ADD INFO IE */
3196                 /* p = hostapd_eid_ht_operation(hapd, p); */
3197                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
3198                 if (pbuf && ie_len > 0) {
3199                         memcpy(pframe, pbuf, ie_len+2);
3200                         pframe += (ie_len+2);
3201                         pattrib->pktlen += (ie_len+2);
3202                 }
3203
3204         }
3205
3206         /* FILL WMM IE */
3207         if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
3208                 uint ie_len = 0;
3209                 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
3210
3211                 for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
3212                         pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
3213                         if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
3214                                 memcpy(pframe, pbuf, ie_len+2);
3215                                 pframe += (ie_len+2);
3216                                 pattrib->pktlen += (ie_len+2);
3217
3218                                 break;
3219                         }
3220
3221                         if ((pbuf == NULL) || (ie_len == 0)) {
3222                                 break;
3223                         }
3224                 }
3225
3226         }
3227
3228
3229         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
3230                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen));
3231         }
3232
3233         /* add WPS IE ie for wps 2.0 */
3234         if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
3235                 memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
3236
3237                 pframe += pmlmepriv->wps_assoc_resp_ie_len;
3238                 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
3239         }
3240
3241         pattrib->last_txcmdsz = pattrib->pktlen;
3242
3243         dump_mgntframe(padapter, pmgntframe);
3244 }
3245
3246 void issue_assocreq(struct adapter *padapter)
3247 {
3248         int ret = _FAIL;
3249         struct xmit_frame                               *pmgntframe;
3250         struct pkt_attrib                               *pattrib;
3251         unsigned char                           *pframe;
3252         struct ieee80211_hdr                    *pwlanhdr;
3253         __le16 *fctrl;
3254         __le16 val16;
3255         unsigned int                                    i, j, index = 0;
3256         unsigned char bssrate[NumRates], sta_bssrate[NumRates];
3257         struct ndis_80211_var_ie *pIE;
3258         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3259         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3260         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3261         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3262         int     bssrate_len = 0, sta_bssrate_len = 0;
3263         u8 vs_ie_length = 0;
3264
3265         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3266         if (pmgntframe == NULL)
3267                 goto exit;
3268
3269         /* update attribute */
3270         pattrib = &pmgntframe->attrib;
3271         update_mgntframe_attrib(padapter, pattrib);
3272
3273
3274         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3275
3276         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3277         pwlanhdr = (struct ieee80211_hdr *)pframe;
3278
3279         fctrl = &(pwlanhdr->frame_control);
3280         *(fctrl) = 0;
3281         memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3282         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3283         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3284
3285         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3286         pmlmeext->mgnt_seq++;
3287         SetFrameSubType(pframe, WIFI_ASSOCREQ);
3288
3289         pframe += sizeof(struct ieee80211_hdr_3addr);
3290         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3291
3292         /* caps */
3293         memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
3294
3295         pframe += 2;
3296         pattrib->pktlen += 2;
3297
3298         /* listen interval */
3299         /* todo: listen interval for power saving */
3300         val16 = cpu_to_le16(3);
3301         memcpy(pframe, (unsigned char *)&val16, 2);
3302         pframe += 2;
3303         pattrib->pktlen += 2;
3304
3305         /* SSID */
3306         pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
3307
3308         /* supported rate & extended supported rate */
3309
3310         /*  Check if the AP's supported rates are also supported by STA. */
3311         get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
3312         /* DBG_871X("sta_bssrate_len =%d\n", sta_bssrate_len); */
3313
3314         if (pmlmeext->cur_channel == 14) /*  for JAPAN, channel 14 can only uses B Mode(CCK) */
3315                 sta_bssrate_len = 4;
3316
3317
3318         /* for (i = 0; i < sta_bssrate_len; i++) { */
3319         /*      DBG_871X("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
3320         /*  */
3321
3322         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3323                 if (pmlmeinfo->network.SupportedRates[i] == 0)
3324                         break;
3325                 DBG_871X("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
3326         }
3327
3328
3329         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3330                 if (pmlmeinfo->network.SupportedRates[i] == 0)
3331                         break;
3332
3333
3334                 /*  Check if the AP's supported rates are also supported by STA. */
3335                 for (j = 0; j < sta_bssrate_len; j++) {
3336                          /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
3337                         if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
3338                                         == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) {
3339                                 /* DBG_871X("match i = %d, j =%d\n", i, j); */
3340                                 break;
3341                         } else {
3342                                 /* DBG_871X("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)); */
3343                         }
3344                 }
3345
3346                 if (j == sta_bssrate_len) {
3347                         /*  the rate is not supported by STA */
3348                         DBG_871X("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]);
3349                 } else {
3350                         /*  the rate is supported by STA */
3351                         bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
3352                 }
3353         }
3354
3355         bssrate_len = index;
3356         DBG_871X("bssrate_len = %d\n", bssrate_len);
3357
3358         if (bssrate_len == 0) {
3359                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
3360                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
3361                 goto exit; /* don't connect to AP if no joint supported rate */
3362         }
3363
3364
3365         if (bssrate_len > 8) {
3366                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen));
3367                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
3368         } else
3369                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen));
3370
3371         /* vendor specific IE, such as WPA, WMM, WPS */
3372         for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) {
3373                 pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i);
3374
3375                 switch (pIE->ElementID) {
3376                 case _VENDOR_SPECIFIC_IE_:
3377                         if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
3378                                         (!memcmp(pIE->data, WMM_OUI, 4)) ||
3379                                         (!memcmp(pIE->data, WPS_OUI, 4))) {
3380                                 vs_ie_length = pIE->Length;
3381                                 if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) {
3382                                         /* Commented by Kurt 20110629 */
3383                                         /* In some older APs, WPS handshake */
3384                                         /* would be fail if we append vender extensions informations to AP */
3385
3386                                         vs_ie_length = 14;
3387                                 }
3388
3389                                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, vs_ie_length, pIE->data, &(pattrib->pktlen));
3390                         }
3391                         break;
3392
3393                 case EID_WPA2:
3394                         pframe = rtw_set_ie(pframe, EID_WPA2, pIE->Length, pIE->data, &(pattrib->pktlen));
3395                         break;
3396                 case EID_HTCapability:
3397                         if (padapter->mlmepriv.htpriv.ht_option == true) {
3398                                 if (!(is_ap_in_tkip(padapter))) {
3399                                         memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
3400                                         pframe = rtw_set_ie(pframe, EID_HTCapability, pIE->Length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
3401                                 }
3402                         }
3403                         break;
3404
3405                 case EID_EXTCapability:
3406                         if (padapter->mlmepriv.htpriv.ht_option == true)
3407                                 pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
3408                         break;
3409                 default:
3410                         break;
3411                 }
3412
3413                 i += (pIE->Length + 2);
3414         }
3415
3416         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
3417                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen));
3418
3419
3420         pattrib->last_txcmdsz = pattrib->pktlen;
3421         dump_mgntframe(padapter, pmgntframe);
3422
3423         ret = _SUCCESS;
3424
3425 exit:
3426         if (ret == _SUCCESS)
3427                 rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
3428         else
3429                 rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
3430
3431         return;
3432 }
3433
3434 /* when wait_ack is ture, this function shoule be called at process context */
3435 static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
3436 {
3437         int ret = _FAIL;
3438         struct xmit_frame                       *pmgntframe;
3439         struct pkt_attrib                       *pattrib;
3440         unsigned char                           *pframe;
3441         struct ieee80211_hdr    *pwlanhdr;
3442         __le16 *fctrl;
3443         struct xmit_priv *pxmitpriv;
3444         struct mlme_ext_priv *pmlmeext;
3445         struct mlme_ext_info *pmlmeinfo;
3446
3447         /* DBG_871X("%s:%d\n", __func__, power_mode); */
3448
3449         if (!padapter)
3450                 goto exit;
3451
3452         pxmitpriv = &(padapter->xmitpriv);
3453         pmlmeext = &(padapter->mlmeextpriv);
3454         pmlmeinfo = &(pmlmeext->mlmext_info);
3455
3456         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3457         if (pmgntframe == NULL)
3458                 goto exit;
3459
3460         /* update attribute */
3461         pattrib = &pmgntframe->attrib;
3462         update_mgntframe_attrib(padapter, pattrib);
3463         pattrib->retry_ctrl = false;
3464
3465         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3466
3467         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3468         pwlanhdr = (struct ieee80211_hdr *)pframe;
3469
3470         fctrl = &(pwlanhdr->frame_control);
3471         *(fctrl) = 0;
3472
3473         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3474                 SetFrDs(fctrl);
3475         else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3476                 SetToDs(fctrl);
3477
3478         if (power_mode)
3479                 SetPwrMgt(fctrl);
3480
3481         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3482         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3483         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3484
3485         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3486         pmlmeext->mgnt_seq++;
3487         SetFrameSubType(pframe, WIFI_DATA_NULL);
3488
3489         pframe += sizeof(struct ieee80211_hdr_3addr);
3490         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3491
3492         pattrib->last_txcmdsz = pattrib->pktlen;
3493
3494         if (wait_ack) {
3495                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3496         } else{
3497                 dump_mgntframe(padapter, pmgntframe);
3498                 ret = _SUCCESS;
3499         }
3500
3501 exit:
3502         return ret;
3503 }
3504
3505 /*
3506  * [IMPORTANT] Don't call this function in interrupt context
3507  *
3508  * When wait_ms > 0, this function shoule be called at process context
3509  * da == NULL for station mode
3510  */
3511 int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
3512 {
3513         int ret;
3514         int i = 0;
3515         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3516         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3517         struct sta_info *psta;
3518
3519
3520         /* da == NULL, assum it's null data for sta to ap*/
3521         if (da == NULL)
3522                 da = get_my_bssid(&(pmlmeinfo->network));
3523
3524         psta = rtw_get_stainfo(&padapter->stapriv, da);
3525         if (psta) {
3526                 if (power_mode)
3527                         rtw_hal_macid_sleep(padapter, psta->mac_id);
3528                 else
3529                         rtw_hal_macid_wakeup(padapter, psta->mac_id);
3530         } else {
3531                 DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",
3532                         FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup");
3533                 rtw_warn_on(1);
3534         }
3535
3536         do {
3537                 ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0?true:false);
3538
3539                 i++;
3540
3541                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3542                         break;
3543
3544                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3545                         msleep(wait_ms);
3546
3547         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3548
3549         if (ret != _FAIL) {
3550                 ret = _SUCCESS;
3551                 #ifndef DBG_XMIT_ACK
3552                 goto exit;
3553                 #endif
3554         }
3555
3556         if (try_cnt && wait_ms) {
3557                 if (da)
3558                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
3559                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
3560                                 ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3561                 else
3562                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
3563                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
3564                                 ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3565         }
3566 exit:
3567         return ret;
3568 }
3569
3570 /*
3571  * [IMPORTANT] This function run in interrupt context
3572  *
3573  * The null data packet would be sent without power bit,
3574  * and not guarantee success.
3575  */
3576 s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da)
3577 {
3578         int ret;
3579         struct mlme_ext_priv *pmlmeext;
3580         struct mlme_ext_info *pmlmeinfo;
3581
3582
3583         pmlmeext = &padapter->mlmeextpriv;
3584         pmlmeinfo = &pmlmeext->mlmext_info;
3585
3586         /* da == NULL, assum it's null data for sta to ap*/
3587         if (da == NULL)
3588                 da = get_my_bssid(&(pmlmeinfo->network));
3589
3590         ret = _issue_nulldata(padapter, da, 0, false);
3591
3592         return ret;
3593 }
3594
3595 /* when wait_ack is ture, this function shoule be called at process context */
3596 static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
3597 {
3598         int ret = _FAIL;
3599         struct xmit_frame                       *pmgntframe;
3600         struct pkt_attrib                       *pattrib;
3601         unsigned char                           *pframe;
3602         struct ieee80211_hdr    *pwlanhdr;
3603         __le16 *fctrl;
3604         u16 *qc;
3605         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3606         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3607         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3608
3609         DBG_871X("%s\n", __func__);
3610
3611         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3612         if (pmgntframe == NULL)
3613                 goto exit;
3614
3615         /* update attribute */
3616         pattrib = &pmgntframe->attrib;
3617         update_mgntframe_attrib(padapter, pattrib);
3618
3619         pattrib->hdrlen += 2;
3620         pattrib->qos_en = true;
3621         pattrib->eosp = 1;
3622         pattrib->ack_policy = 0;
3623         pattrib->mdata = 0;
3624
3625         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3626
3627         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3628         pwlanhdr = (struct ieee80211_hdr *)pframe;
3629
3630         fctrl = &(pwlanhdr->frame_control);
3631         *(fctrl) = 0;
3632
3633         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3634                 SetFrDs(fctrl);
3635         else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3636                 SetToDs(fctrl);
3637
3638         if (pattrib->mdata)
3639                 SetMData(fctrl);
3640
3641         qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
3642
3643         SetPriority(qc, tid);
3644
3645         SetEOSP(qc, pattrib->eosp);
3646
3647         SetAckpolicy(qc, pattrib->ack_policy);
3648
3649         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3650         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3651         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3652
3653         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3654         pmlmeext->mgnt_seq++;
3655         SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
3656
3657         pframe += sizeof(struct ieee80211_qos_hdr);
3658         pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3659
3660         pattrib->last_txcmdsz = pattrib->pktlen;
3661
3662         if (wait_ack) {
3663                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3664         } else{
3665                 dump_mgntframe(padapter, pmgntframe);
3666                 ret = _SUCCESS;
3667         }
3668
3669 exit:
3670         return ret;
3671 }
3672
3673 /* when wait_ms >0 , this function shoule be called at process context */
3674 /* da == NULL for station mode */
3675 int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
3676 {
3677         int ret;
3678         int i = 0;
3679         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3680         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3681
3682         /* da == NULL, assum it's null data for sta to ap*/
3683         if (da == NULL)
3684                 da = get_my_bssid(&(pmlmeinfo->network));
3685
3686         do {
3687                 ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0?true:false);
3688
3689                 i++;
3690
3691                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3692                         break;
3693
3694                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3695                         msleep(wait_ms);
3696
3697         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3698
3699         if (ret != _FAIL) {
3700                 ret = _SUCCESS;
3701                 #ifndef DBG_XMIT_ACK
3702                 goto exit;
3703                 #endif
3704         }
3705
3706         if (try_cnt && wait_ms) {
3707                 if (da)
3708                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
3709                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
3710                                 ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3711                 else
3712                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
3713                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
3714                                 ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3715         }
3716 exit:
3717         return ret;
3718 }
3719
3720 static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
3721 {
3722         struct xmit_frame                       *pmgntframe;
3723         struct pkt_attrib                       *pattrib;
3724         unsigned char                           *pframe;
3725         struct ieee80211_hdr    *pwlanhdr;
3726         __le16 *fctrl;
3727         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3728         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3729         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3730         int ret = _FAIL;
3731         __le16 le_tmp;
3732
3733         /* DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */
3734
3735         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3736         if (pmgntframe == NULL) {
3737                 goto exit;
3738         }
3739
3740         /* update attribute */
3741         pattrib = &pmgntframe->attrib;
3742         update_mgntframe_attrib(padapter, pattrib);
3743         pattrib->retry_ctrl = false;
3744
3745         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3746
3747         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3748         pwlanhdr = (struct ieee80211_hdr *)pframe;
3749
3750         fctrl = &(pwlanhdr->frame_control);
3751         *(fctrl) = 0;
3752
3753         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3754         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3755         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3756
3757         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3758         pmlmeext->mgnt_seq++;
3759         SetFrameSubType(pframe, WIFI_DEAUTH);
3760
3761         pframe += sizeof(struct ieee80211_hdr_3addr);
3762         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3763
3764         le_tmp = cpu_to_le16(reason);
3765         pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3766
3767         pattrib->last_txcmdsz = pattrib->pktlen;
3768
3769
3770         if (wait_ack) {
3771                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3772         } else{
3773                 dump_mgntframe(padapter, pmgntframe);
3774                 ret = _SUCCESS;
3775         }
3776
3777 exit:
3778         return ret;
3779 }
3780
3781 int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
3782 {
3783         DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
3784         return _issue_deauth(padapter, da, reason, false);
3785 }
3786
3787 int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
3788         int wait_ms)
3789 {
3790         int ret;
3791         int i = 0;
3792
3793         do {
3794                 ret = _issue_deauth(padapter, da, reason, wait_ms > 0?true:false);
3795
3796                 i++;
3797
3798                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3799                         break;
3800
3801                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3802                         msleep(wait_ms);
3803
3804         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3805
3806         if (ret != _FAIL) {
3807                 ret = _SUCCESS;
3808                 #ifndef DBG_XMIT_ACK
3809                 goto exit;
3810                 #endif
3811         }
3812
3813         if (try_cnt && wait_ms) {
3814                 if (da)
3815                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
3816                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
3817                                 ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3818                 else
3819                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
3820                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
3821                                 ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3822         }
3823 exit:
3824         return ret;
3825 }
3826
3827 void issue_action_SA_Query(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid)
3828 {
3829         u8 category = RTW_WLAN_CATEGORY_SA_QUERY;
3830         struct xmit_frame               *pmgntframe;
3831         struct pkt_attrib               *pattrib;
3832         u8                      *pframe;
3833         struct ieee80211_hdr    *pwlanhdr;
3834         __le16 *fctrl;
3835         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3836         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3837         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3838         __le16 le_tmp;
3839
3840         DBG_871X("%s\n", __func__);
3841
3842         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3843         if (pmgntframe == NULL) {
3844                 DBG_871X("%s: alloc_mgtxmitframe fail\n", __func__);
3845                 return;
3846         }
3847
3848         /* update attribute */
3849         pattrib = &pmgntframe->attrib;
3850         update_mgntframe_attrib(padapter, pattrib);
3851
3852         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3853
3854         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3855         pwlanhdr = (struct ieee80211_hdr *)pframe;
3856
3857         fctrl = &(pwlanhdr->frame_control);
3858         *(fctrl) = 0;
3859
3860         if (raddr)
3861                 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3862         else
3863                 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3864         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3865         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3866
3867         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3868         pmlmeext->mgnt_seq++;
3869         SetFrameSubType(pframe, WIFI_ACTION);
3870
3871         pframe += sizeof(struct ieee80211_hdr_3addr);
3872         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3873
3874         pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
3875         pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
3876
3877         switch (action) {
3878         case 0: /* SA Query req */
3879                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);
3880                 pmlmeext->sa_query_seq++;
3881                 /* send sa query request to AP, AP should reply sa query response in 1 second */
3882                 set_sa_query_timer(pmlmeext, 1000);
3883                 break;
3884
3885         case 1: /* SA Query rsp */
3886                 le_tmp = cpu_to_le16(tid);
3887                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
3888                 break;
3889         default:
3890                 break;
3891         }
3892
3893         pattrib->last_txcmdsz = pattrib->pktlen;
3894
3895         dump_mgntframe(padapter, pmgntframe);
3896 }
3897
3898 void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
3899 {
3900         u8 category = RTW_WLAN_CATEGORY_BACK;
3901         u16 start_seq;
3902         u16 BA_para_set;
3903         u16 reason_code;
3904         u16 BA_timeout_value;
3905         u16 BA_starting_seqctrl = 0;
3906         enum HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;
3907         struct xmit_frame               *pmgntframe;
3908         struct pkt_attrib               *pattrib;
3909         u8                      *pframe;
3910         struct ieee80211_hdr    *pwlanhdr;
3911         __le16 *fctrl;
3912         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3913         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3914         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3915         struct sta_info         *psta;
3916         struct sta_priv         *pstapriv = &padapter->stapriv;
3917         struct registry_priv    *pregpriv = &padapter->registrypriv;
3918         __le16 le_tmp;
3919
3920         DBG_871X("%s, category =%d, action =%d, status =%d\n", __func__, category, action, status);
3921
3922         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3923         if (pmgntframe == NULL)
3924                 return;
3925
3926         /* update attribute */
3927         pattrib = &pmgntframe->attrib;
3928         update_mgntframe_attrib(padapter, pattrib);
3929
3930         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3931
3932         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3933         pwlanhdr = (struct ieee80211_hdr *)pframe;
3934
3935         fctrl = &(pwlanhdr->frame_control);
3936         *(fctrl) = 0;
3937
3938         /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
3939         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3940         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3941         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3942
3943         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3944         pmlmeext->mgnt_seq++;
3945         SetFrameSubType(pframe, WIFI_ACTION);
3946
3947         pframe += sizeof(struct ieee80211_hdr_3addr);
3948         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3949
3950         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3951         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3952
3953         if (category == 3) {
3954                 switch (action) {
3955                 case 0: /* ADDBA req */
3956                         do {
3957                                 pmlmeinfo->dialogToken++;
3958                         } while (pmlmeinfo->dialogToken == 0);
3959                         pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
3960
3961                         if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(padapter)) {
3962                                 /*  A-MSDU NOT Supported */
3963                                 BA_para_set = 0;
3964                                 /*  immediate Block Ack */
3965                                 BA_para_set |= (1 << 1) & IEEE80211_ADDBA_PARAM_POLICY_MASK;
3966                                 /*  TID */
3967                                 BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
3968                                 /*  max buffer size is 8 MSDU */
3969                                 BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3970                         } else {
3971                                 BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
3972                         }
3973                         le_tmp = cpu_to_le16(BA_para_set);
3974                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3975
3976                         BA_timeout_value = 5000;/*  5ms */
3977                         le_tmp = cpu_to_le16(BA_timeout_value);
3978                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3979
3980                         /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */
3981                         psta = rtw_get_stainfo(pstapriv, raddr);
3982                         if (psta != NULL) {
3983                                 start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
3984
3985                                 DBG_871X("BA_starting_seqctrl = %d for TID =%d\n", start_seq, status & 0x07);
3986
3987                                 psta->BA_starting_seqctrl[status & 0x07] = start_seq;
3988
3989                                 BA_starting_seqctrl = start_seq << 4;
3990                         }
3991
3992                         le_tmp = cpu_to_le16(BA_starting_seqctrl);
3993                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3994                         break;
3995
3996                 case 1: /* ADDBA rsp */
3997                         pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
3998                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
3999                         if (padapter->driver_rx_ampdu_factor != 0xFF)
4000                                 max_rx_ampdu_factor =
4001                                   (enum HT_CAP_AMPDU_FACTOR)padapter->driver_rx_ampdu_factor;
4002                         else
4003                                 rtw_hal_get_def_var(padapter,
4004                                                     HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
4005
4006                         if (MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)
4007                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
4008                         else if (MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)
4009                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
4010                         else if (MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)
4011                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
4012                         else if (MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)
4013                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
4014                         else
4015                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
4016
4017                         if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(padapter) &&
4018                             padapter->driver_rx_ampdu_factor == 0xFF) {
4019                                 /*  max buffer size is 8 MSDU */
4020                                 BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
4021                                 BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
4022                         }
4023
4024                         if (pregpriv->ampdu_amsdu == 0)/* disabled */
4025                                 le_tmp = cpu_to_le16(BA_para_set & ~BIT(0));
4026                         else if (pregpriv->ampdu_amsdu == 1)/* enabled */
4027                                 le_tmp = cpu_to_le16(BA_para_set | BIT(0));
4028                         else /* auto */
4029                                 le_tmp = cpu_to_le16(BA_para_set);
4030
4031                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
4032                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
4033                         break;
4034                 case 2:/* DELBA */
4035                         BA_para_set = (status & 0x1F) << 3;
4036                         le_tmp = cpu_to_le16(BA_para_set);
4037                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
4038
4039                         reason_code = 37;
4040                         le_tmp = cpu_to_le16(reason_code);
4041                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
4042                         break;
4043                 default:
4044                         break;
4045                 }
4046         }
4047
4048         pattrib->last_txcmdsz = pattrib->pktlen;
4049
4050         dump_mgntframe(padapter, pmgntframe);
4051 }
4052
4053 static void issue_action_BSSCoexistPacket(struct adapter *padapter)
4054 {
4055         struct list_head                *plist, *phead;
4056         unsigned char category, action;
4057         struct xmit_frame                       *pmgntframe;
4058         struct pkt_attrib                       *pattrib;
4059         unsigned char                   *pframe;
4060         struct ieee80211_hdr    *pwlanhdr;
4061         __le16 *fctrl;
4062         struct  wlan_network    *pnetwork = NULL;
4063         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
4064         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4065         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
4066         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4067         struct __queue          *queue  = &(pmlmepriv->scanned_queue);
4068         u8 InfoContent[16] = {0};
4069         u8 ICS[8][15];
4070
4071         if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
4072                 return;
4073
4074         if (true == pmlmeinfo->bwmode_updated)
4075                 return;
4076
4077
4078         DBG_871X("%s\n", __func__);
4079
4080
4081         category = RTW_WLAN_CATEGORY_PUBLIC;
4082         action = ACT_PUBLIC_BSSCOEXIST;
4083
4084         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4085         if (pmgntframe == NULL) {
4086                 return;
4087         }
4088
4089         /* update attribute */
4090         pattrib = &pmgntframe->attrib;
4091         update_mgntframe_attrib(padapter, pattrib);
4092
4093         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4094
4095         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4096         pwlanhdr = (struct ieee80211_hdr *)pframe;
4097
4098         fctrl = &(pwlanhdr->frame_control);
4099         *(fctrl) = 0;
4100
4101         memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
4102         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4103         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
4104
4105         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4106         pmlmeext->mgnt_seq++;
4107         SetFrameSubType(pframe, WIFI_ACTION);
4108
4109         pframe += sizeof(struct ieee80211_hdr_3addr);
4110         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4111
4112         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4113         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4114
4115
4116         /*  */
4117         if (pmlmepriv->num_FortyMHzIntolerant > 0) {
4118                 u8 iedata = 0;
4119
4120                 iedata |= BIT(2);/* 20 MHz BSS Width Request */
4121
4122                 pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));
4123
4124         }
4125
4126
4127         /*  */
4128         memset(ICS, 0, sizeof(ICS));
4129         if (pmlmepriv->num_sta_no_ht > 0) {
4130                 int i;
4131
4132                 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
4133
4134                 phead = get_list_head(queue);
4135                 plist = get_next(phead);
4136
4137                 while (1) {
4138                         int len;
4139                         u8 *p;
4140                         struct wlan_bssid_ex *pbss_network;
4141
4142                         if (phead == plist)
4143                                 break;
4144
4145                         pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4146
4147                         plist = get_next(plist);
4148
4149                         pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
4150
4151                         p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
4152                         if ((p == NULL) || (len == 0)) {/* non-HT */
4153
4154                                 if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
4155                                         continue;
4156
4157                                 ICS[0][pbss_network->Configuration.DSConfig] = 1;
4158
4159                                 if (ICS[0][0] == 0)
4160                                         ICS[0][0] = 1;
4161                         }
4162
4163                 }
4164
4165                 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
4166
4167
4168                 for (i = 0; i < 8; i++) {
4169                         if (ICS[i][0] == 1) {
4170                                 int j, k = 0;
4171
4172                                 InfoContent[k] = i;
4173                                 /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
4174                                 k++;
4175
4176                                 for (j = 1; j <= 14; j++) {
4177                                         if (ICS[i][j] == 1) {
4178                                                 if (k < 16) {
4179                                                         InfoContent[k] = j; /* channel number */
4180                                                         /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
4181                                                         k++;
4182                                                 }
4183                                         }
4184                                 }
4185
4186                                 pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
4187
4188                         }
4189
4190                 }
4191
4192
4193         }
4194
4195
4196         pattrib->last_txcmdsz = pattrib->pktlen;
4197
4198         dump_mgntframe(padapter, pmgntframe);
4199 }
4200
4201 unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
4202 {
4203         struct sta_priv *pstapriv = &padapter->stapriv;
4204         struct sta_info *psta = NULL;
4205         /* struct recv_reorder_ctrl *preorder_ctrl; */
4206         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4207         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4208         u16 tid;
4209
4210         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
4211                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
4212                         return _SUCCESS;
4213
4214         psta = rtw_get_stainfo(pstapriv, addr);
4215         if (psta == NULL)
4216                 return _SUCCESS;
4217
4218         /* DBG_871X("%s:%s\n", __func__, (initiator == 0)?"RX_DIR":"TX_DIR"); */
4219
4220         if (initiator == 0) {/*  recipient */
4221                 for (tid = 0; tid < MAXTID; tid++) {
4222                         if (psta->recvreorder_ctrl[tid].enable == true) {
4223                                 DBG_871X("rx agg disable tid(%d)\n", tid);
4224                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
4225                                 psta->recvreorder_ctrl[tid].enable = false;
4226                                 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
4227                                 #ifdef DBG_RX_SEQ
4228                                 DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__,
4229                                         psta->recvreorder_ctrl[tid].indicate_seq);
4230                                 #endif
4231                         }
4232                 }
4233         } else if (initiator == 1) {/*  originator */
4234                 /* DBG_871X("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap); */
4235                 for (tid = 0; tid < MAXTID; tid++) {
4236                         if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
4237                                 DBG_871X("tx agg disable tid(%d)\n", tid);
4238                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
4239                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
4240                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
4241
4242                         }
4243                 }
4244         }
4245
4246         return _SUCCESS;
4247
4248 }
4249
4250 unsigned int send_beacon(struct adapter *padapter)
4251 {
4252         u8 bxmitok = false;
4253         int     issue = 0;
4254         int poll = 0;
4255         unsigned long start = jiffies;
4256
4257         rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
4258         rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
4259         do {
4260                 issue_beacon(padapter, 100);
4261                 issue++;
4262                 do {
4263                         yield();
4264                         rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
4265                         poll++;
4266                 } while ((poll%10) != 0 && false == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
4267
4268         } while (false == bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
4269
4270         if (padapter->bSurpriseRemoved || padapter->bDriverStopped) {
4271                 return _FAIL;
4272         }
4273
4274
4275         if (false == bxmitok) {
4276                 DBG_871X("%s fail! %u ms\n", __func__, jiffies_to_msecs(jiffies - start));
4277                 return _FAIL;
4278         } else{
4279                 unsigned long passing_time = jiffies_to_msecs(jiffies - start);
4280
4281                 if (passing_time > 100 || issue > 3)
4282                         DBG_871X("%s success, issue:%d, poll:%d, %lu ms\n", __func__, issue, poll, passing_time);
4283                 /* else */
4284                 /*      DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __func__, issue, poll, passing_time); */
4285
4286                 return _SUCCESS;
4287         }
4288 }
4289
4290 /****************************************************************************
4291
4292 Following are some utitity fuctions for WiFi MLME
4293
4294 *****************************************************************************/
4295
4296 void site_survey(struct adapter *padapter)
4297 {
4298         unsigned char   survey_channel = 0, val8;
4299         RT_SCAN_TYPE    ScanType = SCAN_PASSIVE;
4300         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4301         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4302         u32 initialgain = 0;
4303         u32 channel_scan_time_ms = 0;
4304
4305         {
4306                 struct rtw_ieee80211_channel *ch;
4307                 if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
4308                         ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
4309                         survey_channel = ch->hw_value;
4310                         ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
4311                 }
4312         }
4313
4314         DBG_871X(FUNC_ADPT_FMT" ch:%u (cnt:%u) at %dms, %c%c%c\n"
4315                  , FUNC_ADPT_ARG(padapter)
4316                  , survey_channel
4317                  , pmlmeext->sitesurvey_res.channel_idx
4318                  , jiffies_to_msecs(jiffies - padapter->mlmepriv.scan_start_time)
4319                  , ScanType?'A':'P', pmlmeext->sitesurvey_res.scan_mode?'A':'P'
4320                  , pmlmeext->sitesurvey_res.ssid[0].SsidLength?'S':' '
4321                 );
4322 #ifdef DBG_FIXED_CHAN
4323         DBG_871X(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan);
4324 #endif
4325
4326         if (survey_channel != 0) {
4327                 /* PAUSE 4-AC Queue when site_survey */
4328                 /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
4329                 /* val8 |= 0x0f; */
4330                 /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
4331                 if (pmlmeext->sitesurvey_res.channel_idx == 0) {
4332 #ifdef DBG_FIXED_CHAN
4333                         if (pmlmeext->fixed_chan != 0xff)
4334                                 set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4335                         else
4336 #endif
4337                                 set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4338                 } else{
4339 #ifdef DBG_FIXED_CHAN
4340                         if (pmlmeext->fixed_chan != 0xff)
4341                                 SelectChannel(padapter, pmlmeext->fixed_chan);
4342                         else
4343 #endif
4344                                 SelectChannel(padapter, survey_channel);
4345                 }
4346
4347                 if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
4348                         {
4349                                 int i;
4350                                 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
4351                                         if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
4352                                                 /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
4353                                                 if (padapter->registrypriv.wifi_spec)
4354                                                         issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
4355                                                 else
4356                                                         issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
4357                                                 issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
4358                                         }
4359                                 }
4360
4361                                 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
4362                                         /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
4363                                         if (padapter->registrypriv.wifi_spec)
4364                                                 issue_probereq(padapter, NULL, NULL);
4365                                         else
4366                                                 issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
4367                                         issue_probereq(padapter, NULL, NULL);
4368                                 }
4369                         }
4370                 }
4371
4372                 channel_scan_time_ms = pmlmeext->chan_scan_time;
4373
4374                 set_survey_timer(pmlmeext, channel_scan_time_ms);
4375 #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
4376                 {
4377                         struct noise_info info;
4378                         info.bPauseDIG = false;
4379                         info.IGIValue = 0;
4380                         info.max_time = channel_scan_time_ms/2;/* ms */
4381                         info.chan = survey_channel;
4382                         rtw_hal_set_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &info, false);
4383                 }
4384 #endif
4385
4386         } else{
4387
4388                 /*      channel number is 0 or this channel is not valid. */
4389
4390                 {
4391                         pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
4392
4393                         /* switch back to the original channel */
4394                         /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
4395
4396                         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4397
4398                         /* flush 4-AC Queue after site_survey */
4399                         /* val8 = 0; */
4400                         /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
4401
4402                         /* config MSR */
4403                         Set_MSR(padapter, (pmlmeinfo->state & 0x3));
4404
4405                         initialgain = 0xff; /* restore RX GAIN */
4406                         rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
4407                         /* turn on dynamic functions */
4408                         Restore_DM_Func_Flag(padapter);
4409                         /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
4410
4411                         if (is_client_associated_to_ap(padapter) == true)
4412                                 issue_nulldata(padapter, NULL, 0, 3, 500);
4413
4414                         val8 = 0; /* survey done */
4415                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
4416
4417                         report_surveydone_event(padapter);
4418
4419                         pmlmeext->chan_scan_time = SURVEY_TO;
4420                         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
4421
4422                         issue_action_BSSCoexistPacket(padapter);
4423                         issue_action_BSSCoexistPacket(padapter);
4424                         issue_action_BSSCoexistPacket(padapter);
4425                 }
4426         }
4427
4428         return;
4429
4430 }
4431
4432 /* collect bss info from Beacon and Probe request/response frames. */
4433 u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
4434 {
4435         int     i;
4436         u32 len;
4437         u8 *p;
4438         u16 val16, subtype;
4439         u8 *pframe = precv_frame->u.hdr.rx_data;
4440         u32 packet_len = precv_frame->u.hdr.len;
4441         u8 ie_offset;
4442         struct registry_priv *pregistrypriv = &padapter->registrypriv;
4443         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4444         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4445         __le32 le32_tmp;
4446
4447         len = packet_len - sizeof(struct ieee80211_hdr_3addr);
4448
4449         if (len > MAX_IE_SZ) {
4450                 /* DBG_871X("IE too long for survey event\n"); */
4451                 return _FAIL;
4452         }
4453
4454         memset(bssid, 0, sizeof(struct wlan_bssid_ex));
4455
4456         subtype = GetFrameSubType(pframe);
4457
4458         if (subtype == WIFI_BEACON) {
4459                 bssid->Reserved[0] = 1;
4460                 ie_offset = _BEACON_IE_OFFSET_;
4461         } else {
4462                 /*  FIXME : more type */
4463                 if (subtype == WIFI_PROBERSP) {
4464                         ie_offset = _PROBERSP_IE_OFFSET_;
4465                         bssid->Reserved[0] = 3;
4466                 } else if (subtype == WIFI_PROBEREQ) {
4467                         ie_offset = _PROBEREQ_IE_OFFSET_;
4468                         bssid->Reserved[0] = 2;
4469                 } else {
4470                         bssid->Reserved[0] = 0;
4471                         ie_offset = _FIXED_IE_LENGTH_;
4472                 }
4473         }
4474
4475         bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
4476
4477         /* below is to copy the information element */
4478         bssid->IELength = len;
4479         memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
4480
4481         /* get the signal strength */
4482         bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /*  in dBM.raw data */
4483         bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
4484         bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
4485
4486         /*  checking SSID */
4487         p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);
4488         if (p == NULL) {
4489                 DBG_871X("marc: cannot find SSID for survey event\n");
4490                 return _FAIL;
4491         }
4492
4493         if (*(p + 1)) {
4494                 if (len > NDIS_802_11_LENGTH_SSID) {
4495                         DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
4496                         return _FAIL;
4497                 }
4498                 memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
4499                 bssid->Ssid.SsidLength = *(p + 1);
4500         } else
4501                 bssid->Ssid.SsidLength = 0;
4502
4503         memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
4504
4505         /* checking rate info... */
4506         i = 0;
4507         p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
4508         if (p != NULL) {
4509                 if (len > NDIS_802_11_LENGTH_RATES_EX) {
4510                         DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
4511                         return _FAIL;
4512                 }
4513                 memcpy(bssid->SupportedRates, (p + 2), len);
4514                 i = len;
4515         }
4516
4517         p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
4518         if (p != NULL) {
4519                 if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) {
4520                         DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
4521                         return _FAIL;
4522                 }
4523                 memcpy(bssid->SupportedRates + i, (p + 2), len);
4524         }
4525
4526         bssid->NetworkTypeInUse = Ndis802_11OFDM24;
4527
4528         if (bssid->IELength < 12)
4529                 return _FAIL;
4530
4531         /*  Checking for DSConfig */
4532         p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
4533
4534         bssid->Configuration.DSConfig = 0;
4535         bssid->Configuration.Length = 0;
4536
4537         if (p) {
4538                 bssid->Configuration.DSConfig = *(p + 2);
4539         } else {
4540                 /*  In 5G, some ap do not have DSSET IE */
4541                 /*  checking HT info for channel */
4542                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
4543                 if (p) {
4544                         struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
4545                         bssid->Configuration.DSConfig = HT_info->primary_channel;
4546                 } else { /*  use current channel */
4547                         bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
4548                 }
4549         }
4550
4551         memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
4552         bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp);
4553
4554         val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
4555
4556         if (val16 & BIT(0)) {
4557                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
4558                 memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
4559         } else {
4560                 bssid->InfrastructureMode = Ndis802_11IBSS;
4561                 memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
4562         }
4563
4564         if (val16 & BIT(4))
4565                 bssid->Privacy = 1;
4566         else
4567                 bssid->Privacy = 0;
4568
4569         bssid->Configuration.ATIMWindow = 0;
4570
4571         /* 20/40 BSS Coexistence check */
4572         if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) {
4573                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4574
4575                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
4576                 if (p && len > 0) {
4577                         struct HT_caps_element  *pHT_caps;
4578                         pHT_caps = (struct HT_caps_element      *)(p + 2);
4579
4580                         if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14))
4581                                 pmlmepriv->num_FortyMHzIntolerant++;
4582                 } else
4583                         pmlmepriv->num_sta_no_ht++;
4584         }
4585
4586 #ifdef CONFIG_INTEL_WIDI
4587         /* process_intel_widi_query_or_tigger(padapter, bssid); */
4588         if (process_intel_widi_query_or_tigger(padapter, bssid))
4589                 return _FAIL;
4590 #endif /*  CONFIG_INTEL_WIDI */
4591
4592         #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1
4593         if (strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
4594                 DBG_871X("Receiving %s("MAC_FMT", DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n"
4595                         , bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig
4596                         , rtw_get_oper_ch(padapter)
4597                         , bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi
4598                 );
4599         }
4600         #endif
4601
4602         /*  mark bss info receving from nearby channel as SignalQuality 101 */
4603         if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
4604                 bssid->PhyInfo.SignalQuality = 101;
4605
4606         return _SUCCESS;
4607 }
4608
4609 void start_create_ibss(struct adapter *padapter)
4610 {
4611         unsigned short  caps;
4612         u8 val8;
4613         u8 join_type;
4614         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4615         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4616         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4617         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
4618         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
4619
4620         /* update wireless mode */
4621         update_wireless_mode(padapter);
4622
4623         /* udpate capability */
4624         caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
4625         update_capinfo(padapter, caps);
4626         if (caps&cap_IBSS) {/* adhoc master */
4627                 val8 = 0xcf;
4628                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4629
4630                 rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
4631
4632                 /* switch channel */
4633                 /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
4634                 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4635
4636                 beacon_timing_control(padapter);
4637
4638                 /* set msr to WIFI_FW_ADHOC_STATE */
4639                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4640                 Set_MSR(padapter, (pmlmeinfo->state & 0x3));
4641
4642                 /* issue beacon */
4643                 if (send_beacon(padapter) == _FAIL) {
4644                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
4645
4646                         report_join_res(padapter, -1);
4647                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4648                 } else{
4649                         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
4650                         join_type = 0;
4651                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4652
4653                         report_join_res(padapter, 1);
4654                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4655                         rtw_indicate_connect(padapter);
4656                 }
4657         } else{
4658                 DBG_871X("start_create_ibss, invalid cap:%x\n", caps);
4659                 return;
4660         }
4661         /* update bc/mc sta_info */
4662         update_bmc_sta(padapter);
4663
4664 }
4665
4666 void start_clnt_join(struct adapter *padapter)
4667 {
4668         unsigned short  caps;
4669         u8 val8;
4670         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4671         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4672         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4673         int beacon_timeout;
4674
4675         /* update wireless mode */
4676         update_wireless_mode(padapter);
4677
4678         /* udpate capability */
4679         caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
4680         update_capinfo(padapter, caps);
4681         if (caps&cap_ESS) {
4682                 Set_MSR(padapter, WIFI_FW_STATION_STATE);
4683
4684                 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
4685
4686                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4687
4688                 /*  Because of AP's not receiving deauth before */
4689                 /*  AP may: 1)not response auth or 2)deauth us after link is complete */
4690                 /*  issue deauth before issuing auth to deal with the situation */
4691
4692                 /*      Commented by Albert 2012/07/21 */
4693                 /*      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
4694                 {
4695                                 /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */
4696                                 issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
4697                 }
4698
4699                 /* here wait for receiving the beacon to start auth */
4700                 /* and enable a timer */
4701                 beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
4702                 set_link_timer(pmlmeext, beacon_timeout);
4703                 _set_timer(&padapter->mlmepriv.assoc_timer,
4704                         (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout);
4705
4706                 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
4707         } else if (caps&cap_IBSS) { /* adhoc client */
4708                 Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
4709
4710                 val8 = 0xcf;
4711                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4712
4713                 beacon_timing_control(padapter);
4714
4715                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4716
4717                 report_join_res(padapter, 1);
4718         } else{
4719                 /* DBG_871X("marc: invalid cap:%x\n", caps); */
4720                 return;
4721         }
4722
4723 }
4724
4725 void start_clnt_auth(struct adapter *padapter)
4726 {
4727         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4728         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4729
4730         del_timer_sync(&pmlmeext->link_timer);
4731
4732         pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4733         pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4734
4735         pmlmeinfo->auth_seq = 1;
4736         pmlmeinfo->reauth_count = 0;
4737         pmlmeinfo->reassoc_count = 0;
4738         pmlmeinfo->link_count = 0;
4739         pmlmeext->retry = 0;
4740
4741
4742         DBG_871X_LEVEL(_drv_always_, "start auth\n");
4743         issue_auth(padapter, NULL, 0);
4744
4745         set_link_timer(pmlmeext, REAUTH_TO);
4746
4747 }
4748
4749
4750 void start_clnt_assoc(struct adapter *padapter)
4751 {
4752         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4753         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4754
4755         del_timer_sync(&pmlmeext->link_timer);
4756
4757         pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4758         pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4759
4760         issue_assocreq(padapter);
4761
4762         set_link_timer(pmlmeext, REASSOC_TO);
4763 }
4764
4765 unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
4766 {
4767         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4768         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4769
4770         /* check A3 */
4771         if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
4772                 return _SUCCESS;
4773
4774         DBG_871X("%s\n", __func__);
4775
4776         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
4777                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4778                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4779                         report_del_sta_event(padapter, MacAddr, reason);
4780
4781                 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
4782                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4783                         report_join_res(padapter, -2);
4784                 }
4785         }
4786
4787         return _SUCCESS;
4788 }
4789
4790 static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
4791 {
4792         struct registry_priv *pregistrypriv;
4793         struct mlme_ext_priv *pmlmeext;
4794         RT_CHANNEL_INFO *chplan_new;
4795         u8 channel;
4796         u8 i;
4797
4798
4799         pregistrypriv = &padapter->registrypriv;
4800         pmlmeext = &padapter->mlmeextpriv;
4801
4802         /*  Adjust channel plan by AP Country IE */
4803         if (pregistrypriv->enable80211d &&
4804                 (!pmlmeext->update_channel_plan_by_ap_done)) {
4805                 u8 *ie, *p;
4806                 u32 len;
4807                 RT_CHANNEL_PLAN chplan_ap;
4808                 RT_CHANNEL_INFO chplan_sta[MAX_CHANNEL_NUM];
4809                 u8 country[4];
4810                 u8 fcn; /*  first channel number */
4811                 u8 noc; /*  number of channel */
4812                 u8 j, k;
4813
4814                 ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
4815                 if (!ie)
4816                         return;
4817                 if (len < 6)
4818                         return;
4819
4820                 ie += 2;
4821                 p = ie;
4822                 ie += len;
4823
4824                 memset(country, 0, 4);
4825                 memcpy(country, p, 3);
4826                 p += 3;
4827                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4828                                 ("%s: 802.11d country =%s\n", __func__, country));
4829
4830                 i = 0;
4831                 while ((ie - p) >= 3) {
4832                         fcn = *(p++);
4833                         noc = *(p++);
4834                         p++;
4835
4836                         for (j = 0; j < noc; j++) {
4837                                 if (fcn <= 14)
4838                                         channel = fcn + j; /*  2.4 GHz */
4839                                 else
4840                                         channel = fcn + j*4; /*  5 GHz */
4841
4842                                 chplan_ap.Channel[i++] = channel;
4843                         }
4844                 }
4845                 chplan_ap.Len = i;
4846
4847 #ifdef DEBUG_RTL871X
4848                 i = 0;
4849                 DBG_871X("%s: AP[%s] channel plan {", __func__, bssid->Ssid.Ssid);
4850                 while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0)) {
4851                         DBG_8192C("%02d,", chplan_ap.Channel[i]);
4852                         i++;
4853                 }
4854                 DBG_871X("}\n");
4855 #endif
4856
4857                 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4858 #ifdef DEBUG_RTL871X
4859                 i = 0;
4860                 DBG_871X("%s: STA channel plan {", __func__);
4861                 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
4862                         DBG_871X("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType == SCAN_PASSIVE?'p':'a');
4863                         i++;
4864                 }
4865                 DBG_871X("}\n");
4866 #endif
4867
4868                 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4869                 chplan_new = pmlmeext->channel_set;
4870
4871                 i = j = k = 0;
4872                 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4873                         do {
4874                                 if ((i == MAX_CHANNEL_NUM) ||
4875                                         (chplan_sta[i].ChannelNum == 0) ||
4876                                         (chplan_sta[i].ChannelNum > 14))
4877                                         break;
4878
4879                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
4880                                         break;
4881
4882                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
4883                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4884                                         chplan_new[k].ScanType = SCAN_ACTIVE;
4885                                         i++;
4886                                         j++;
4887                                         k++;
4888                                 } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
4889                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4890 /*                                      chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4891                                         chplan_new[k].ScanType = SCAN_PASSIVE;
4892                                         i++;
4893                                         k++;
4894                                 } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
4895                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4896                                         chplan_new[k].ScanType = SCAN_ACTIVE;
4897                                         j++;
4898                                         k++;
4899                                 }
4900                         } while (1);
4901
4902                         /*  change AP not support channel to Passive scan */
4903                         while ((i < MAX_CHANNEL_NUM) &&
4904                                 (chplan_sta[i].ChannelNum != 0) &&
4905                                 (chplan_sta[i].ChannelNum <= 14)) {
4906
4907                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4908 /*                              chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4909                                 chplan_new[k].ScanType = SCAN_PASSIVE;
4910                                 i++;
4911                                 k++;
4912                         }
4913
4914                         /*  add channel AP supported */
4915                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
4916                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4917                                 chplan_new[k].ScanType = SCAN_ACTIVE;
4918                                 j++;
4919                                 k++;
4920                         }
4921                 } else{
4922                         /*  keep original STA 2.4G channel plan */
4923                         while ((i < MAX_CHANNEL_NUM) &&
4924                                 (chplan_sta[i].ChannelNum != 0) &&
4925                                 (chplan_sta[i].ChannelNum <= 14)) {
4926                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4927                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4928                                 i++;
4929                                 k++;
4930                         }
4931
4932                         /*  skip AP 2.4G channel plan */
4933                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
4934                                 j++;
4935                         }
4936                 }
4937
4938                 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
4939                         do {
4940                                 if ((i == MAX_CHANNEL_NUM) ||
4941                                         (chplan_sta[i].ChannelNum == 0))
4942                                         break;
4943
4944                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
4945                                         break;
4946
4947                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
4948                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4949                                         chplan_new[k].ScanType = SCAN_ACTIVE;
4950                                         i++;
4951                                         j++;
4952                                         k++;
4953                                 } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
4954                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4955 /*                                      chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4956                                         chplan_new[k].ScanType = SCAN_PASSIVE;
4957                                         i++;
4958                                         k++;
4959                                 } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
4960                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4961                                         chplan_new[k].ScanType = SCAN_ACTIVE;
4962                                         j++;
4963                                         k++;
4964                                 }
4965                         } while (1);
4966
4967                         /*  change AP not support channel to Passive scan */
4968                         while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
4969                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4970 /*                              chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4971                                 chplan_new[k].ScanType = SCAN_PASSIVE;
4972                                 i++;
4973                                 k++;
4974                         }
4975
4976                         /*  add channel AP supported */
4977                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) {
4978                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4979                                 chplan_new[k].ScanType = SCAN_ACTIVE;
4980                                 j++;
4981                                 k++;
4982                         }
4983                 } else{
4984                         /*  keep original STA 5G channel plan */
4985                         while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
4986                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4987                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4988                                 i++;
4989                                 k++;
4990                         }
4991                 }
4992
4993                 pmlmeext->update_channel_plan_by_ap_done = 1;
4994
4995 #ifdef DEBUG_RTL871X
4996                 k = 0;
4997                 DBG_871X("%s: new STA channel plan {", __func__);
4998                 while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) {
4999                         DBG_871X("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType == SCAN_PASSIVE?'p':'c');
5000                         k++;
5001                 }
5002                 DBG_871X("}\n");
5003 #endif
5004         }
5005
5006         /*  If channel is used by AP, set channel scan type to active */
5007         channel = bssid->Configuration.DSConfig;
5008         chplan_new = pmlmeext->channel_set;
5009         i = 0;
5010         while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
5011                 if (chplan_new[i].ChannelNum == channel) {
5012                         if (chplan_new[i].ScanType == SCAN_PASSIVE) {
5013                                 /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */
5014                                 if (channel >= 52 && channel <= 144)
5015                                         break;
5016
5017                                 chplan_new[i].ScanType = SCAN_ACTIVE;
5018                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
5019                                                  ("%s: change channel %d scan type from passive to active\n",
5020                                                   __func__, channel));
5021                         }
5022                         break;
5023                 }
5024                 i++;
5025         }
5026 }
5027
5028 /****************************************************************************
5029
5030 Following are the functions to report events
5031
5032 *****************************************************************************/
5033
5034 void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame)
5035 {
5036         struct cmd_obj *pcmd_obj;
5037         u8 *pevtcmd;
5038         u32 cmdsz;
5039         struct survey_event     *psurvey_evt;
5040         struct C2HEvent_Header *pc2h_evt_hdr;
5041         struct mlme_ext_priv *pmlmeext;
5042         struct cmd_priv *pcmdpriv;
5043         /* u8 *pframe = precv_frame->u.hdr.rx_data; */
5044         /* uint len = precv_frame->u.hdr.len; */
5045
5046         if (!padapter)
5047                 return;
5048
5049         pmlmeext = &padapter->mlmeextpriv;
5050         pcmdpriv = &padapter->cmdpriv;
5051
5052         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5053         if (pcmd_obj == NULL)
5054                 return;
5055
5056         cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
5057         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
5058         if (pevtcmd == NULL) {
5059                 kfree((u8 *)pcmd_obj);
5060                 return;
5061         }
5062
5063         INIT_LIST_HEAD(&pcmd_obj->list);
5064
5065         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5066         pcmd_obj->cmdsz = cmdsz;
5067         pcmd_obj->parmbuf = pevtcmd;
5068
5069         pcmd_obj->rsp = NULL;
5070         pcmd_obj->rspsz  = 0;
5071
5072         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5073         pc2h_evt_hdr->len = sizeof(struct survey_event);
5074         pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
5075         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5076
5077         psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5078
5079         if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
5080                 kfree((u8 *)pcmd_obj);
5081                 kfree((u8 *)pevtcmd);
5082                 return;
5083         }
5084
5085         process_80211d(padapter, &psurvey_evt->bss);
5086
5087         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5088
5089         pmlmeext->sitesurvey_res.bss_cnt++;
5090
5091         return;
5092
5093 }
5094
5095 void report_surveydone_event(struct adapter *padapter)
5096 {
5097         struct cmd_obj *pcmd_obj;
5098         u8 *pevtcmd;
5099         u32 cmdsz;
5100         struct surveydone_event *psurveydone_evt;
5101         struct C2HEvent_Header  *pc2h_evt_hdr;
5102         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5103         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5104
5105         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5106         if (pcmd_obj == NULL)
5107                 return;
5108
5109         cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
5110         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
5111         if (pevtcmd == NULL) {
5112                 kfree((u8 *)pcmd_obj);
5113                 return;
5114         }
5115
5116         INIT_LIST_HEAD(&pcmd_obj->list);
5117
5118         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5119         pcmd_obj->cmdsz = cmdsz;
5120         pcmd_obj->parmbuf = pevtcmd;
5121
5122         pcmd_obj->rsp = NULL;
5123         pcmd_obj->rspsz  = 0;
5124
5125         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5126         pc2h_evt_hdr->len = sizeof(struct surveydone_event);
5127         pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
5128         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5129
5130         psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5131         psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
5132
5133         DBG_871X("survey done event(%x) band:%d for "ADPT_FMT"\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter));
5134
5135         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5136
5137         return;
5138
5139 }
5140
5141 void report_join_res(struct adapter *padapter, int res)
5142 {
5143         struct cmd_obj *pcmd_obj;
5144         u8 *pevtcmd;
5145         u32 cmdsz;
5146         struct joinbss_event            *pjoinbss_evt;
5147         struct C2HEvent_Header  *pc2h_evt_hdr;
5148         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5149         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5150         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5151
5152         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5153         if (pcmd_obj == NULL)
5154                 return;
5155
5156         cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
5157         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
5158         if (pevtcmd == NULL) {
5159                 kfree((u8 *)pcmd_obj);
5160                 return;
5161         }
5162
5163         INIT_LIST_HEAD(&pcmd_obj->list);
5164
5165         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5166         pcmd_obj->cmdsz = cmdsz;
5167         pcmd_obj->parmbuf = pevtcmd;
5168
5169         pcmd_obj->rsp = NULL;
5170         pcmd_obj->rspsz  = 0;
5171
5172         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5173         pc2h_evt_hdr->len = sizeof(struct joinbss_event);
5174         pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
5175         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5176
5177         pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5178         memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
5179         pjoinbss_evt->network.join_res  = pjoinbss_evt->network.aid = res;
5180
5181         DBG_871X("report_join_res(%d)\n", res);
5182
5183
5184         rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
5185
5186
5187         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5188
5189         return;
5190
5191 }
5192
5193 void report_wmm_edca_update(struct adapter *padapter)
5194 {
5195         struct cmd_obj *pcmd_obj;
5196         u8 *pevtcmd;
5197         u32 cmdsz;
5198         struct wmm_event                *pwmm_event;
5199         struct C2HEvent_Header  *pc2h_evt_hdr;
5200         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5201         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5202
5203         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5204         if (pcmd_obj == NULL)
5205                 return;
5206
5207         cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));
5208         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
5209         if (pevtcmd == NULL) {
5210                 kfree((u8 *)pcmd_obj);
5211                 return;
5212         }
5213
5214         INIT_LIST_HEAD(&pcmd_obj->list);
5215
5216         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5217         pcmd_obj->cmdsz = cmdsz;
5218         pcmd_obj->parmbuf = pevtcmd;
5219
5220         pcmd_obj->rsp = NULL;
5221         pcmd_obj->rspsz  = 0;
5222
5223         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5224         pc2h_evt_hdr->len = sizeof(struct wmm_event);
5225         pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM);
5226         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5227
5228         pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5229         pwmm_event->wmm = 0;
5230
5231         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5232
5233         return;
5234
5235 }
5236
5237 void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
5238 {
5239         struct cmd_obj *pcmd_obj;
5240         u8 *pevtcmd;
5241         u32 cmdsz;
5242         struct sta_info *psta;
5243         int     mac_id;
5244         struct stadel_event                     *pdel_sta_evt;
5245         struct C2HEvent_Header  *pc2h_evt_hdr;
5246         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5247         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5248
5249         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5250         if (pcmd_obj == NULL) {
5251                 return;
5252         }
5253
5254         cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
5255         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
5256         if (pevtcmd == NULL) {
5257                 kfree((u8 *)pcmd_obj);
5258                 return;
5259         }
5260
5261         INIT_LIST_HEAD(&pcmd_obj->list);
5262
5263         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5264         pcmd_obj->cmdsz = cmdsz;
5265         pcmd_obj->parmbuf = pevtcmd;
5266
5267         pcmd_obj->rsp = NULL;
5268         pcmd_obj->rspsz  = 0;
5269
5270         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5271         pc2h_evt_hdr->len = sizeof(struct stadel_event);
5272         pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
5273         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5274
5275         pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5276         memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
5277         memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
5278
5279
5280         psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
5281         if (psta)
5282                 mac_id = (int)psta->mac_id;
5283         else
5284                 mac_id = (-1);
5285
5286         pdel_sta_evt->mac_id = mac_id;
5287
5288         DBG_871X("report_del_sta_event: delete STA, mac_id =%d\n", mac_id);
5289
5290         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5291
5292         return;
5293 }
5294
5295 void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
5296 {
5297         struct cmd_obj *pcmd_obj;
5298         u8 *pevtcmd;
5299         u32 cmdsz;
5300         struct stassoc_event            *padd_sta_evt;
5301         struct C2HEvent_Header  *pc2h_evt_hdr;
5302         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5303         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5304
5305         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5306         if (pcmd_obj == NULL)
5307                 return;
5308
5309         cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
5310         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
5311         if (pevtcmd == NULL) {
5312                 kfree((u8 *)pcmd_obj);
5313                 return;
5314         }
5315
5316         INIT_LIST_HEAD(&pcmd_obj->list);
5317
5318         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5319         pcmd_obj->cmdsz = cmdsz;
5320         pcmd_obj->parmbuf = pevtcmd;
5321
5322         pcmd_obj->rsp = NULL;
5323         pcmd_obj->rspsz  = 0;
5324
5325         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5326         pc2h_evt_hdr->len = sizeof(struct stassoc_event);
5327         pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
5328         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5329
5330         padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5331         memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
5332         padd_sta_evt->cam_id = cam_idx;
5333
5334         DBG_871X("report_add_sta_event: add STA\n");
5335
5336         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5337
5338         return;
5339 }
5340
5341
5342 bool rtw_port_switch_chk(struct adapter *adapter)
5343 {
5344         bool switch_needed = false;
5345         return switch_needed;
5346 }
5347
5348 /****************************************************************************
5349
5350 Following are the event callback functions
5351
5352 *****************************************************************************/
5353
5354 /* for sta/adhoc mode */
5355 void update_sta_info(struct adapter *padapter, struct sta_info *psta)
5356 {
5357         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5358         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5359         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5360
5361         /* ERP */
5362         VCS_update(padapter, psta);
5363
5364         /* HT */
5365         if (pmlmepriv->htpriv.ht_option) {
5366                 psta->htpriv.ht_option = true;
5367
5368                 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
5369
5370                 psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2;
5371
5372                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))
5373                         psta->htpriv.sgi_20m = true;
5374
5375                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))
5376                         psta->htpriv.sgi_40m = true;
5377
5378                 psta->qos_option = true;
5379
5380                 psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;
5381                 psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;
5382                 psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
5383
5384                 memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct rtw_ieee80211_ht_cap));
5385         } else{
5386                 psta->htpriv.ht_option = false;
5387
5388                 psta->htpriv.ampdu_enable = false;
5389
5390                 psta->htpriv.sgi_20m = false;
5391                 psta->htpriv.sgi_40m = false;
5392                 psta->qos_option = false;
5393
5394         }
5395
5396         psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
5397
5398         psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
5399         psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
5400
5401         psta->bw_mode = pmlmeext->cur_bwmode;
5402
5403         /* QoS */
5404         if (pmlmepriv->qospriv.qos_option)
5405                 psta->qos_option = true;
5406
5407         update_ldpc_stbc_cap(psta);
5408
5409         spin_lock_bh(&psta->lock);
5410         psta->state = _FW_LINKED;
5411         spin_unlock_bh(&psta->lock);
5412
5413 }
5414
5415 static void rtw_mlmeext_disconnect(struct adapter *padapter)
5416 {
5417         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
5418         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5419         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5420         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5421         u8 state_backup = (pmlmeinfo->state&0x03);
5422
5423         /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5424
5425         /*
5426          * For safety, prevent from keeping macid sleep.
5427          * If we can sure all power mode enter/leave are paired,
5428          * this check can be removed.
5429          * Lucas@20131113
5430          */
5431         /* wakeup macid after disconnect. */
5432         {
5433                 struct sta_info *psta;
5434                 psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
5435                 if (psta)
5436                         rtw_hal_macid_wakeup(padapter, psta->mac_id);
5437         }
5438
5439         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
5440         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
5441
5442         /* set MSR to no link state -> infra. mode */
5443         Set_MSR(padapter, _HW_STATE_STATION_);
5444
5445         pmlmeinfo->state = WIFI_FW_NULL_STATE;
5446
5447         if (state_backup == WIFI_FW_STATION_STATE) {
5448                 if (rtw_port_switch_chk(padapter) == true) {
5449                         rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
5450                         {
5451                                 struct adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
5452                                 if (port0_iface)
5453                                         rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
5454                         }
5455                 }
5456         }
5457
5458         /* switch to the 20M Hz mode after disconnect */
5459         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5460         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5461
5462         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5463
5464         flush_all_cam_entry(padapter);
5465
5466         del_timer_sync(&pmlmeext->link_timer);
5467
5468         /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */
5469         pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
5470         pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
5471
5472 }
5473
5474 void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
5475 {
5476         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5477         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5478         struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
5479         struct sta_priv         *pstapriv = &padapter->stapriv;
5480         u8 join_type;
5481         struct sta_info *psta;
5482         if (join_res < 0) {
5483                 join_type = 1;
5484                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5485                 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
5486
5487                 goto exit_mlmeext_joinbss_event_callback;
5488         }
5489
5490         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
5491                 /* update bc/mc sta_info */
5492                 update_bmc_sta(padapter);
5493
5494
5495         /* turn on dynamic functions */
5496         Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
5497
5498         /*  update IOT-releated issue */
5499         update_IOT_info(padapter);
5500
5501         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
5502
5503         /* BCN interval */
5504         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
5505
5506         /* udpate capability */
5507         update_capinfo(padapter, pmlmeinfo->capability);
5508
5509         /* WMM, Update EDCA param */
5510         WMMOnAssocRsp(padapter);
5511
5512         /* HT */
5513         HTOnAssocRsp(padapter);
5514
5515         /* Set cur_channel&cur_bwmode&cur_ch_offset */
5516         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5517
5518         psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
5519         if (psta) { /* only for infra. mode */
5520
5521                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5522
5523                 /* DBG_871X("set_sta_rate\n"); */
5524
5525                 psta->wireless_mode = pmlmeext->cur_wireless_mode;
5526
5527                 /* set per sta rate after updating HT cap. */
5528                 set_sta_rate(padapter, psta);
5529
5530                 rtw_sta_media_status_rpt(padapter, psta, 1);
5531
5532                 /* wakeup macid after join bss successfully to ensure
5533                         the subsequent data frames can be sent out normally */
5534                 rtw_hal_macid_wakeup(padapter, psta->mac_id);
5535         }
5536
5537         if (rtw_port_switch_chk(padapter) == true)
5538                 rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
5539
5540         join_type = 2;
5541         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5542
5543         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
5544                 /*  correcting TSF */
5545                 correct_TSF(padapter, pmlmeext);
5546
5547                 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5548         }
5549
5550         if (get_iface_type(padapter) == IFACE_PORT0)
5551                 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
5552
5553 exit_mlmeext_joinbss_event_callback:
5554
5555         DBG_871X("=>%s\n", __func__);
5556
5557 }
5558
5559 /* currently only adhoc mode will go here */
5560 void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
5561 {
5562         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
5563         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5564         u8 join_type;
5565
5566         DBG_871X("%s\n", __func__);
5567
5568         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
5569                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */
5570
5571                         /* nothing to do */
5572                 } else{ /* adhoc client */
5573                         /* update TSF Value */
5574                         /* update_TSF(pmlmeext, pframe, len); */
5575
5576                         /*  correcting TSF */
5577                         correct_TSF(padapter, pmlmeext);
5578
5579                         /* start beacon */
5580                         if (send_beacon(padapter) == _FAIL) {
5581                                 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
5582
5583                                 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
5584
5585                                 return;
5586                         }
5587
5588                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
5589
5590                 }
5591
5592                 join_type = 2;
5593                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5594         }
5595
5596         pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5597
5598         psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates);
5599         memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen);
5600
5601         /* update adhoc sta_info */
5602         update_sta_info(padapter, psta);
5603
5604         rtw_hal_update_sta_rate_mask(padapter, psta);
5605
5606         /*  ToDo: HT for Ad-hoc */
5607         psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);
5608         psta->raid = rtw_hal_networktype_to_raid(padapter, psta);
5609
5610         /* rate radaptive */
5611         Update_RA_Entry(padapter, psta);
5612 }
5613
5614 void mlmeext_sta_del_event_callback(struct adapter *padapter)
5615 {
5616         if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
5617                 rtw_mlmeext_disconnect(padapter);
5618 }
5619
5620 /****************************************************************************
5621
5622 Following are the functions for the timer handlers
5623
5624 *****************************************************************************/
5625 void _linked_info_dump(struct adapter *padapter)
5626 {
5627         int i;
5628         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5629         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5630         int UndecoratedSmoothedPWDB;
5631         struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
5632
5633         if (padapter->bLinkInfoDump) {
5634
5635                 DBG_871X("\n ============["ADPT_FMT"] linked status check ===================\n", ADPT_ARG(padapter));
5636
5637                 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
5638                         rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
5639
5640                         DBG_871X("AP[" MAC_FMT "] - UndecoratedSmoothedPWDB:%d\n",
5641                                 MAC_ARG(padapter->mlmepriv.cur_network.network.MacAddress), UndecoratedSmoothedPWDB);
5642                 } else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_) {
5643                         struct list_head        *phead, *plist;
5644
5645                         struct sta_info *psta = NULL;
5646                         struct sta_priv *pstapriv = &padapter->stapriv;
5647
5648                         spin_lock_bh(&pstapriv->asoc_list_lock);
5649                         phead = &pstapriv->asoc_list;
5650                         plist = get_next(phead);
5651                         while (phead != plist) {
5652                                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
5653                                 plist = get_next(plist);
5654
5655                                 DBG_871X("STA[" MAC_FMT "]:UndecoratedSmoothedPWDB:%d\n",
5656                                         MAC_ARG(psta->hwaddr), psta->rssi_stat.UndecoratedSmoothedPWDB);
5657                         }
5658                         spin_unlock_bh(&pstapriv->asoc_list_lock);
5659
5660                 }
5661                 for (i = 0; i < NUM_STA; i++) {
5662                         if (pdvobj->macid[i] == true) {
5663                                 if (i != 1) /* skip bc/mc sta */
5664                                         /*   tx info ============ */
5665                                         rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i);
5666                         }
5667                 }
5668                 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL);
5669
5670
5671         }
5672
5673
5674 }
5675
5676 static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
5677 {
5678         u8 ret = false;
5679
5680         #ifdef DBG_EXPIRATION_CHK
5681         DBG_871X(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"
5682                                 /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/
5683                                 ", retry:%u\n"
5684                 , FUNC_ADPT_ARG(padapter)
5685                 , STA_RX_PKTS_DIFF_ARG(psta)
5686                 , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts
5687                 , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts
5688                 /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts
5689                 , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts
5690                 , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts
5691                 , pmlmeinfo->bcn_interval*/
5692                 , pmlmeext->retry
5693         );
5694
5695         DBG_871X(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter)
5696                 , padapter->xmitpriv.tx_pkts
5697                 , pmlmeinfo->link_count
5698         );
5699         #endif
5700
5701         if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
5702                 && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
5703                 && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
5704         ) {
5705                 ret = false;
5706         } else{
5707                 ret = true;
5708         }
5709
5710         sta_update_last_rx_pkts(psta);
5711
5712         return ret;
5713 }
5714
5715 void linked_status_chk(struct adapter *padapter)
5716 {
5717         u32 i;
5718         struct sta_info         *psta;
5719         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
5720         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5721         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5722         struct sta_priv         *pstapriv = &padapter->stapriv;
5723
5724
5725         if (is_client_associated_to_ap(padapter)) {
5726                 /* linked infrastructure client mode */
5727
5728                 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
5729                 int rx_chk_limit;
5730                 int link_count_limit;
5731
5732                 #if defined(DBG_ROAMING_TEST)
5733                 rx_chk_limit = 1;
5734                 #else
5735                 rx_chk_limit = 8;
5736                 #endif
5737                 link_count_limit = 7; /*  16 sec */
5738
5739                 /*  Marked by Kurt 20130715 */
5740                 /*  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. */
5741                 /*  todo: To check why we under miracast session, rx_chk would be false */
5742                 /* ifdef CONFIG_INTEL_WIDI */
5743                 /* if (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_NONE) */
5744                 /*      rx_chk_limit = 1; */
5745                 /* endif */
5746
5747                 psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
5748                 if (psta != NULL) {
5749                         if (chk_ap_is_alive(padapter, psta) == false)
5750                                 rx_chk = _FAIL;
5751
5752                         if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
5753                                 tx_chk = _FAIL;
5754
5755                         {
5756                                 if (rx_chk != _SUCCESS) {
5757                                         if (pmlmeext->retry == 0) {
5758                                                 #ifdef DBG_EXPIRATION_CHK
5759                                                 DBG_871X("issue_probereq to trigger probersp, retry =%d\n", pmlmeext->retry);
5760                                                 #endif
5761                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
5762                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
5763                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
5764                                         }
5765                                 }
5766
5767                                 if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) {
5768                                         #ifdef DBG_EXPIRATION_CHK
5769                                         DBG_871X("%s issue_nulldata 0\n", __func__);
5770                                         #endif
5771                                         tx_chk = issue_nulldata_in_interrupt(padapter, NULL);
5772                                 }
5773                         }
5774
5775                         if (rx_chk == _FAIL) {
5776                                 pmlmeext->retry++;
5777                                 if (pmlmeext->retry > rx_chk_limit) {
5778                                         DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
5779                                                 FUNC_ADPT_ARG(padapter));
5780                                         receive_disconnect(padapter, pmlmeinfo->network.MacAddress
5781                                                 , WLAN_REASON_EXPIRATION_CHK);
5782                                         return;
5783                                 }
5784                         } else {
5785                                 pmlmeext->retry = 0;
5786                         }
5787
5788                         if (tx_chk == _FAIL) {
5789                                 pmlmeinfo->link_count %= (link_count_limit+1);
5790                         } else {
5791                                 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5792                                 pmlmeinfo->link_count = 0;
5793                         }
5794
5795                 } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
5796         } else if (is_client_associated_to_ibss(padapter)) {
5797                 /* linked IBSS mode */
5798                 /* for each assoc list entry to check the rx pkt counter */
5799                 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5800                         if (pmlmeinfo->FW_sta_info[i].status == 1) {
5801                                 psta = pmlmeinfo->FW_sta_info[i].psta;
5802
5803                                 if (NULL == psta)
5804                                         continue;
5805
5806                                 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
5807
5808                                         if (pmlmeinfo->FW_sta_info[i].retry < 3) {
5809                                                 pmlmeinfo->FW_sta_info[i].retry++;
5810                                         } else{
5811                                                 pmlmeinfo->FW_sta_info[i].retry = 0;
5812                                                 pmlmeinfo->FW_sta_info[i].status = 0;
5813                                                 report_del_sta_event(padapter, psta->hwaddr
5814                                                         , 65535/*  indicate disconnect caused by no rx */
5815                                                 );
5816                                         }
5817                                 } else{
5818                                         pmlmeinfo->FW_sta_info[i].retry = 0;
5819                                         pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5820                                 }
5821                         }
5822                 }
5823
5824                 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5825
5826         }
5827
5828 }
5829
5830 void survey_timer_hdl(struct adapter *padapter)
5831 {
5832         struct cmd_obj  *ph2c;
5833         struct sitesurvey_parm  *psurveyPara;
5834         struct cmd_priv                                 *pcmdpriv = &padapter->cmdpriv;
5835         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5836
5837         /* DBG_871X("marc: survey timer\n"); */
5838
5839         /* issue rtw_sitesurvey_cmd */
5840         if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5841                 if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS) {
5842                         pmlmeext->sitesurvey_res.channel_idx++;
5843                 }
5844
5845                 if (pmlmeext->scan_abort == true) {
5846                         {
5847                                 pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
5848                                 DBG_871X("%s idx:%d\n", __func__
5849                                         , pmlmeext->sitesurvey_res.channel_idx
5850                                 );
5851                         }
5852
5853                         pmlmeext->scan_abort = false;/* reset */
5854                 }
5855
5856                 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5857                 if (ph2c == NULL) {
5858                         goto exit_survey_timer_hdl;
5859                 }
5860
5861                 psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
5862                 if (psurveyPara == NULL) {
5863                         kfree((unsigned char *)ph2c);
5864                         goto exit_survey_timer_hdl;
5865                 }
5866
5867                 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
5868                 rtw_enqueue_cmd(pcmdpriv, ph2c);
5869         }
5870
5871
5872 exit_survey_timer_hdl:
5873
5874         return;
5875 }
5876
5877 void link_timer_hdl(struct adapter *padapter)
5878 {
5879         /* static unsigned int          rx_pkt = 0; */
5880         /* static u64                           tx_cnt = 0; */
5881         /* struct xmit_priv     *pxmitpriv = &(padapter->xmitpriv); */
5882         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5883         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5884         /* struct sta_priv      *pstapriv = &padapter->stapriv; */
5885
5886
5887         if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
5888                 DBG_871X("link_timer_hdl:no beacon while connecting\n");
5889                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
5890                 report_join_res(padapter, -3);
5891         } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
5892                 /* re-auth timer */
5893                 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
5894                         /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
5895                         /*  */
5896                                 pmlmeinfo->state = 0;
5897                                 report_join_res(padapter, -1);
5898                                 return;
5899                         /*  */
5900                         /* else */
5901                         /*  */
5902                         /*      pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
5903                         /*      pmlmeinfo->reauth_count = 0; */
5904                         /*  */
5905                 }
5906
5907                 DBG_871X("link_timer_hdl: auth timeout and try again\n");
5908                 pmlmeinfo->auth_seq = 1;
5909                 issue_auth(padapter, NULL, 0);
5910                 set_link_timer(pmlmeext, REAUTH_TO);
5911         } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
5912                 /* re-assoc timer */
5913                 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
5914                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
5915                         report_join_res(padapter, -2);
5916                         return;
5917                 }
5918
5919                 DBG_871X("link_timer_hdl: assoc timeout and try again\n");
5920                 issue_assocreq(padapter);
5921                 set_link_timer(pmlmeext, REASSOC_TO);
5922         }
5923
5924         return;
5925 }
5926
5927 void addba_timer_hdl(struct sta_info *psta)
5928 {
5929         struct ht_priv *phtpriv;
5930
5931         if (!psta)
5932                 return;
5933
5934         phtpriv = &psta->htpriv;
5935
5936         if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true)) {
5937                 if (phtpriv->candidate_tid_bitmap)
5938                         phtpriv->candidate_tid_bitmap = 0x0;
5939
5940         }
5941 }
5942
5943 void sa_query_timer_hdl(struct adapter *padapter)
5944 {
5945         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5946         /* disconnect */
5947         spin_lock_bh(&pmlmepriv->lock);
5948
5949         if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
5950                 rtw_disassoc_cmd(padapter, 0, true);
5951                 rtw_indicate_disconnect(padapter);
5952                 rtw_free_assoc_resources(padapter, 1);
5953         }
5954
5955         spin_unlock_bh(&pmlmepriv->lock);
5956         DBG_871X("SA query timeout disconnect\n");
5957 }
5958
5959 u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
5960 {
5961         return H2C_SUCCESS;
5962 }
5963
5964 #ifdef CONFIG_AUTO_AP_MODE
5965 static int rtw_auto_ap_start_beacon(struct adapter *adapter)
5966 {
5967         int ret = 0;
5968         u8 *pbuf = NULL;
5969         uint len;
5970         u8 supportRate[16];
5971         int     sz = 0, rateLen;
5972         u8 *ie;
5973         u8 wireless_mode, oper_channel;
5974         u8 ssid[3] = {0}; /* hidden ssid */
5975         u32 ssid_len = sizeof(ssid);
5976         struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
5977
5978
5979         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5980                 return -EINVAL;
5981
5982
5983         len = 128;
5984         pbuf = rtw_zmalloc(len);
5985         if (!pbuf)
5986                 return -ENOMEM;
5987
5988
5989         /* generate beacon */
5990         ie = pbuf;
5991
5992         /* timestamp will be inserted by hardware */
5993         sz += 8;
5994         ie += sz;
5995
5996         /* beacon interval : 2bytes */
5997         *(u16 *)ie = cpu_to_le16((u16)100);/* BCN_INTERVAL = 100; */
5998         sz += 2;
5999         ie += 2;
6000
6001         /* capability info */
6002         *(u16 *)ie = 0;
6003         *(u16 *)ie |= cpu_to_le16(cap_ESS);
6004         *(u16 *)ie |= cpu_to_le16(cap_ShortPremble);
6005         /* u16*)ie |= cpu_to_le16(cap_Privacy); */
6006         sz += 2;
6007         ie += 2;
6008
6009         /* SSID */
6010         ie = rtw_set_ie(ie, _SSID_IE_, ssid_len, ssid, &sz);
6011
6012         /* supported rates */
6013         wireless_mode = WIRELESS_11BG_24N;
6014         rtw_set_supported_rate(supportRate, wireless_mode);
6015         rateLen = rtw_get_rateset_len(supportRate);
6016         if (rateLen > 8) {
6017                 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, supportRate, &sz);
6018         } else{
6019                 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, supportRate, &sz);
6020         }
6021
6022
6023         /* DS parameter set */
6024         if (check_buddy_fwstate(adapter, _FW_LINKED) &&
6025                 check_buddy_fwstate(adapter, WIFI_STATION_STATE)) {
6026                 struct adapter *pbuddystruct adapter = adapter->pbuddystruct adapter;
6027                 struct mlme_ext_priv *pbuddy_mlmeext  = &pbuddystruct adapter->mlmeextpriv;
6028
6029                 oper_channel = pbuddy_mlmeext->cur_channel;
6030         } else{
6031                 oper_channel = adapter_to_dvobj(adapter)->oper_channel;
6032         }
6033         ie = rtw_set_ie(ie, _DSSET_IE_, 1, &oper_channel, &sz);
6034
6035         /* ext supported rates */
6036         if (rateLen > 8) {
6037                 ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz);
6038         }
6039
6040         DBG_871X("%s, start auto ap beacon sz =%d\n", __func__, sz);
6041
6042         /* lunch ap mode & start to issue beacon */
6043         if (rtw_check_beacon_data(adapter, pbuf,  sz) == _SUCCESS) {
6044
6045         } else{
6046                 ret = -EINVAL;
6047         }
6048
6049
6050         kfree(pbuf);
6051
6052         return ret;
6053
6054 }
6055 #endif/* CONFIG_AUTO_AP_MODE */
6056
6057 u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
6058 {
6059         u8 type;
6060         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6061         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6062         struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
6063
6064         if (psetop->mode == Ndis802_11APMode) {
6065                 pmlmeinfo->state = WIFI_FW_AP_STATE;
6066                 type = _HW_STATE_AP_;
6067                 /* start_ap_mode(padapter); */
6068         } else if (psetop->mode == Ndis802_11Infrastructure) {
6069                 pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
6070                 pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to     STATION_STATE */
6071                 type = _HW_STATE_STATION_;
6072         } else if (psetop->mode == Ndis802_11IBSS) {
6073                 type = _HW_STATE_ADHOC_;
6074         } else{
6075                 type = _HW_STATE_NOLINK_;
6076         }
6077
6078         rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
6079         /* Set_NETYPE0_MSR(padapter, type); */
6080
6081
6082 #ifdef CONFIG_AUTO_AP_MODE
6083         if (psetop->mode == Ndis802_11APMode)
6084                 rtw_auto_ap_start_beacon(padapter);
6085 #endif
6086
6087         if (rtw_port_switch_chk(padapter) == true) {
6088                 rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
6089
6090                 if (psetop->mode == Ndis802_11APMode)
6091                         adapter_to_pwrctl(padapter)->fw_psmode_iface_id = 0xff; /* ap mode won't dowload rsvd pages */
6092                 else if (psetop->mode == Ndis802_11Infrastructure) {
6093                         struct adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
6094                         if (port0_iface)
6095                                 rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
6096                 }
6097         }
6098
6099         if (psetop->mode == Ndis802_11APMode) {
6100                 /*  Do this after port switch to */
6101                 /*  prevent from downloading rsvd page to wrong port */
6102                 rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */
6103         }
6104
6105         return H2C_SUCCESS;
6106
6107 }
6108
6109 u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
6110 {
6111         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6112         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6113         struct wlan_bssid_ex    *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
6114         struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
6115         /* u32 initialgain; */
6116
6117         if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
6118                 struct wlan_bssid_ex *network = &padapter->mlmepriv.cur_network.network;
6119                 start_bss_network(padapter, (u8 *)network);
6120                 return H2C_SUCCESS;
6121         }
6122
6123         /* below is for ad-hoc master */
6124         if (pparm->network.InfrastructureMode == Ndis802_11IBSS) {
6125                 rtw_joinbss_reset(padapter);
6126
6127                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
6128                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6129                 pmlmeinfo->ERP_enable = 0;
6130                 pmlmeinfo->WMM_enable = 0;
6131                 pmlmeinfo->HT_enable = 0;
6132                 pmlmeinfo->HT_caps_enable = 0;
6133                 pmlmeinfo->HT_info_enable = 0;
6134                 pmlmeinfo->agg_enable_bitmap = 0;
6135                 pmlmeinfo->candidate_tid_bitmap = 0;
6136
6137                 /* disable dynamic functions, such as high power, DIG */
6138                 Save_DM_Func_Flag(padapter);
6139                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
6140
6141                 /* config the initial gain under linking, need to write the BB registers */
6142                 /* initialgain = 0x1E; */
6143                 /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
6144
6145                 /* cancel link timer */
6146                 del_timer_sync(&pmlmeext->link_timer);
6147
6148                 /* clear CAM */
6149                 flush_all_cam_entry(padapter);
6150
6151                 memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
6152                 pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
6153
6154                 if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
6155                         return H2C_PARAMETERS_ERROR;
6156
6157                 memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
6158
6159                 start_create_ibss(padapter);
6160
6161         }
6162
6163         return H2C_SUCCESS;
6164
6165 }
6166
6167 u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
6168 {
6169         u8 join_type;
6170         struct ndis_80211_var_ie *pIE;
6171         struct registry_priv *pregpriv = &padapter->registrypriv;
6172         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6173         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6174         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
6175         u32 i;
6176         u8 cbw40_enable = 0;
6177         /* u32 initialgain; */
6178         /* u32 acparm; */
6179         u8 ch, bw, offset;
6180
6181         /* check already connecting to AP or not */
6182         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
6183                 if (pmlmeinfo->state & WIFI_FW_STATION_STATE) {
6184                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
6185                 }
6186                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
6187
6188                 /* clear CAM */
6189                 flush_all_cam_entry(padapter);
6190
6191                 del_timer_sync(&pmlmeext->link_timer);
6192
6193                 /* set MSR to nolink -> infra. mode */
6194                 /* Set_MSR(padapter, _HW_STATE_NOLINK_); */
6195                 Set_MSR(padapter, _HW_STATE_STATION_);
6196
6197
6198                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
6199         }
6200
6201         rtw_joinbss_reset(padapter);
6202
6203         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
6204         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6205         pmlmeinfo->ERP_enable = 0;
6206         pmlmeinfo->WMM_enable = 0;
6207         pmlmeinfo->HT_enable = 0;
6208         pmlmeinfo->HT_caps_enable = 0;
6209         pmlmeinfo->HT_info_enable = 0;
6210         pmlmeinfo->agg_enable_bitmap = 0;
6211         pmlmeinfo->candidate_tid_bitmap = 0;
6212         pmlmeinfo->bwmode_updated = false;
6213         /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
6214         pmlmeinfo->VHT_enable = 0;
6215
6216         memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
6217         pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
6218
6219         if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
6220                 return H2C_PARAMETERS_ERROR;
6221
6222         memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
6223
6224         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
6225         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
6226
6227         /* Check AP vendor to move rtw_joinbss_cmd() */
6228         /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */
6229
6230         /* sizeof(struct ndis_802_11_fix_ie) */
6231         for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) {
6232                 pIE = (struct ndis_80211_var_ie *)(pnetwork->IEs + i);
6233
6234                 switch (pIE->ElementID) {
6235                 case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
6236                         if (!memcmp(pIE->data, WMM_OUI, 4))
6237                                 WMM_param_handler(padapter, pIE);
6238                         break;
6239
6240                 case _HT_CAPABILITY_IE_:        /* Get HT Cap IE. */
6241                         pmlmeinfo->HT_caps_enable = 1;
6242                         break;
6243
6244                 case _HT_EXTRA_INFO_IE_:        /* Get HT Info IE. */
6245                         pmlmeinfo->HT_info_enable = 1;
6246
6247                         /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
6248                         {
6249                                 struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
6250
6251                                 if (pnetwork->Configuration.DSConfig > 14) {
6252                                         if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20)
6253                                                 cbw40_enable = 1;
6254                                 } else {
6255                                         if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20)
6256                                                 cbw40_enable = 1;
6257                                 }
6258
6259                                 if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
6260                                         /* switch to the 40M Hz mode according to the AP */
6261                                         pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
6262                                         switch (pht_info->infos[0] & 0x3) {
6263                                         case 1:
6264                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
6265                                                 break;
6266
6267                                         case 3:
6268                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
6269                                                 break;
6270
6271                                         default:
6272                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6273                                                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
6274                                                 break;
6275                                         }
6276
6277                                         DBG_871X("set HT ch/bw before connected\n");
6278                                 }
6279                         }
6280                         break;
6281                 default:
6282                         break;
6283                 }
6284
6285                 i += (pIE->Length + 2);
6286         }
6287
6288         /* check channel, bandwidth, offset and switch */
6289         if (rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) {
6290                 report_join_res(padapter, (-4));
6291                 return H2C_SUCCESS;
6292         }
6293
6294         /* disable dynamic functions, such as high power, DIG */
6295         /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */
6296
6297         /* config the initial gain under linking, need to write the BB registers */
6298         /* initialgain = 0x1E; */
6299         /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
6300
6301         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
6302         join_type = 0;
6303         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
6304         rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
6305
6306         set_channel_bwmode(padapter, ch, offset, bw);
6307
6308         /* cancel link timer */
6309         del_timer_sync(&pmlmeext->link_timer);
6310
6311         start_clnt_join(padapter);
6312
6313         return H2C_SUCCESS;
6314
6315 }
6316
6317 u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
6318 {
6319         struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
6320         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6321         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6322         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
6323         u8 val8;
6324
6325         if (is_client_associated_to_ap(padapter)) {
6326                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
6327         }
6328
6329         if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
6330                 /* Stop BCN */
6331                 val8 = 0;
6332                 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
6333         }
6334
6335         rtw_mlmeext_disconnect(padapter);
6336
6337         rtw_free_uc_swdec_pending_queue(padapter);
6338
6339         return  H2C_SUCCESS;
6340 }
6341
6342 static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
6343         u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
6344 {
6345         int i, j;
6346         int set_idx;
6347         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6348
6349         /* clear first */
6350         memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
6351
6352         /* acquire channels from in */
6353         j = 0;
6354         for (i = 0; i < in_num; i++) {
6355
6356                 DBG_871X(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
6357
6358                 set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
6359                 if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED)
6360                         && set_idx >= 0
6361                         && rtw_mlme_band_check(padapter, in[i].hw_value) == true
6362                 ) {
6363                         if (j >= out_num) {
6364                                 DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
6365                                         FUNC_ADPT_ARG(padapter), out_num);
6366                                 break;
6367                         }
6368
6369                         memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
6370
6371                         if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
6372                                 out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
6373
6374                         j++;
6375                 }
6376                 if (j >= out_num)
6377                         break;
6378         }
6379
6380         /* if out is empty, use channel_set as default */
6381         if (j == 0) {
6382                 for (i = 0; i < pmlmeext->max_chan_nums; i++) {
6383
6384                         DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), pmlmeext->channel_set[i].ChannelNum);
6385
6386                         if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum) == true) {
6387
6388                                 if (j >= out_num) {
6389                                         DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
6390                                                 FUNC_ADPT_ARG(padapter), out_num);
6391                                         break;
6392                                 }
6393
6394                                 out[j].hw_value = pmlmeext->channel_set[i].ChannelNum;
6395
6396                                 if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
6397                                         out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
6398
6399                                 j++;
6400                         }
6401                 }
6402         }
6403
6404         return j;
6405 }
6406
6407 u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
6408 {
6409         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6410         struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
6411         u8 bdelayscan = false;
6412         u8 val8;
6413         u32 initialgain;
6414         u32 i;
6415
6416         if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
6417                 pmlmeext->sitesurvey_res.state = SCAN_START;
6418                 pmlmeext->sitesurvey_res.bss_cnt = 0;
6419                 pmlmeext->sitesurvey_res.channel_idx = 0;
6420
6421                 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
6422                         if (pparm->ssid[i].SsidLength) {
6423                                 memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
6424                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
6425                         } else {
6426                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
6427                         }
6428                 }
6429
6430                 pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
6431                         , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
6432                         , pparm->ch, pparm->ch_num
6433                 );
6434
6435                 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
6436
6437                 /* issue null data if associating to the AP */
6438                 if (is_client_associated_to_ap(padapter) == true) {
6439                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
6440
6441                         issue_nulldata(padapter, NULL, 1, 3, 500);
6442
6443                         bdelayscan = true;
6444                 }
6445                 if (bdelayscan) {
6446                         /* delay 50ms to protect nulldata(1). */
6447                         set_survey_timer(pmlmeext, 50);
6448                         return H2C_SUCCESS;
6449                 }
6450         }
6451
6452         if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
6453                 /* disable dynamic functions, such as high power, DIG */
6454                 Save_DM_Func_Flag(padapter);
6455                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
6456
6457                 /* config the initial gain under scaning, need to write the BB registers */
6458                 initialgain = 0x1e;
6459
6460                 rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
6461
6462                 /* set MSR to no link state */
6463                 Set_MSR(padapter, _HW_STATE_NOLINK_);
6464
6465                 val8 = 1; /* under site survey */
6466                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
6467
6468                 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
6469         }
6470
6471         site_survey(padapter);
6472
6473         return H2C_SUCCESS;
6474
6475 }
6476
6477 u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
6478 {
6479         struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
6480         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6481         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6482
6483         if (pparm->mode < 4) {
6484                 pmlmeinfo->auth_algo = pparm->mode;
6485         }
6486
6487         return  H2C_SUCCESS;
6488 }
6489
6490 u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
6491 {
6492         u16 ctrl = 0;
6493         s16 cam_id = 0;
6494         struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
6495         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6496         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6497         unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
6498         u8 *addr;
6499
6500         /* main tx key for wep. */
6501         if (pparm->set_tx)
6502                 pmlmeinfo->key_index = pparm->keyid;
6503
6504         cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid);
6505
6506         if (cam_id < 0) {
6507         } else {
6508                 if (cam_id > 3) /* not default key, searched by A2 */
6509                         addr = get_bssid(&padapter->mlmepriv);
6510                 else
6511                         addr = null_addr;
6512
6513                 ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid;
6514                 write_cam(padapter, cam_id, ctrl, addr, pparm->key);
6515                 DBG_871X_LEVEL(_drv_always_, "set group key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n"
6516                         , cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm));
6517         }
6518
6519         if (cam_id >= 0 && cam_id <= 3)
6520                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true);
6521
6522         /* allow multicast packets to driver */
6523         padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
6524
6525         return H2C_SUCCESS;
6526 }
6527
6528 u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
6529 {
6530         u16 ctrl = 0;
6531         s16 cam_id = 0;
6532         u8 ret = H2C_SUCCESS;
6533         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6534         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6535         struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
6536         struct sta_priv *pstapriv = &padapter->stapriv;
6537         struct sta_info *psta;
6538
6539         if (pparm->algorithm == _NO_PRIVACY_)
6540                 goto write_to_cam;
6541
6542         psta = rtw_get_stainfo(pstapriv, pparm->addr);
6543         if (!psta) {
6544                 DBG_871X_LEVEL(_drv_always_, "%s sta:"MAC_FMT" not found\n", __func__, MAC_ARG(pparm->addr));
6545                 ret = H2C_REJECTED;
6546                 goto exit;
6547         }
6548
6549         pmlmeinfo->enc_algo = pparm->algorithm;
6550         cam_id = rtw_camid_alloc(padapter, psta, 0);
6551         if (cam_id < 0)
6552                 goto exit;
6553
6554 write_to_cam:
6555         if (pparm->algorithm == _NO_PRIVACY_) {
6556                 while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) {
6557                         DBG_871X_LEVEL(_drv_always_, "clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), cam_id);
6558                         clear_cam_entry(padapter, cam_id);
6559                         rtw_camid_free(padapter, cam_id);
6560                 }
6561         } else {
6562                 DBG_871X_LEVEL(_drv_always_, "set pairwise key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n",
6563                         cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm));
6564                 ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
6565                 write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
6566         }
6567         ret = H2C_SUCCESS_RSP;
6568
6569 exit:
6570         return ret;
6571 }
6572
6573 u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
6574 {
6575         struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
6576         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6577         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6578
6579         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
6580
6581         if (!psta)
6582                 return  H2C_SUCCESS;
6583
6584         if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
6585                 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
6586                 /* pmlmeinfo->ADDBA_retry_count = 0; */
6587                 /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */
6588                 /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */
6589                 issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
6590                 /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */
6591                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
6592         } else{
6593                 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
6594         }
6595         return  H2C_SUCCESS;
6596 }
6597
6598
6599 u8 chk_bmc_sleepq_cmd(struct adapter *padapter)
6600 {
6601         struct cmd_obj *ph2c;
6602         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
6603         u8 res = _SUCCESS;
6604
6605         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
6606         if (ph2c == NULL) {
6607                 res = _FAIL;
6608                 goto exit;
6609         }
6610
6611         init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));
6612
6613         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
6614
6615 exit:
6616         return res;
6617 }
6618
6619 u8 set_tx_beacon_cmd(struct adapter *padapter)
6620 {
6621         struct cmd_obj  *ph2c;
6622         struct Tx_Beacon_param  *ptxBeacon_parm;
6623         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
6624         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6625         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6626         u8 res = _SUCCESS;
6627         int len_diff = 0;
6628
6629         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
6630         if (ph2c == NULL) {
6631                 res = _FAIL;
6632                 goto exit;
6633         }
6634
6635         ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param));
6636         if (ptxBeacon_parm == NULL) {
6637                 kfree((unsigned char *)ph2c);
6638                 res = _FAIL;
6639                 goto exit;
6640         }
6641
6642         memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
6643
6644         len_diff = update_hidden_ssid(
6645                 ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_
6646                 , ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_
6647                 , pmlmeinfo->hidden_ssid_mode
6648         );
6649         ptxBeacon_parm->network.IELength += len_diff;
6650
6651         init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
6652
6653         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
6654
6655 exit:
6656         return res;
6657 }
6658
6659
6660 u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
6661 {
6662         u8 evt_code, evt_seq;
6663         u16 evt_sz;
6664         uint    *peventbuf;
6665         void (*event_callback)(struct adapter *dev, u8 *pbuf);
6666         struct evt_priv *pevt_priv = &(padapter->evtpriv);
6667
6668         if (pbuf == NULL)
6669                 goto _abort_event_;
6670
6671         peventbuf = (uint *)pbuf;
6672         evt_sz = (u16)(*peventbuf&0xffff);
6673         evt_seq = (u8)((*peventbuf>>24)&0x7f);
6674         evt_code = (u8)((*peventbuf>>16)&0xff);
6675
6676
6677         #ifdef CHECK_EVENT_SEQ
6678         /*  checking event sequence... */
6679         if (evt_seq != (atomic_read(&pevt_priv->event_seq) & 0x7f)) {
6680                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
6681                          ("Event Seq Error! %d vs %d\n", (evt_seq & 0x7f),
6682                           (atomic_read(&pevt_priv->event_seq) & 0x7f)));
6683
6684                 pevt_priv->event_seq = (evt_seq+1)&0x7f;
6685
6686                 goto _abort_event_;
6687         }
6688         #endif
6689
6690         /*  checking if event code is valid */
6691         if (evt_code >= MAX_C2HEVT) {
6692                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
6693                 goto _abort_event_;
6694         }
6695
6696         /*  checking if event size match the event parm size */
6697         if ((wlanevents[evt_code].parmsize != 0) &&
6698                         (wlanevents[evt_code].parmsize != evt_sz)) {
6699
6700                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
6701                         evt_code, wlanevents[evt_code].parmsize, evt_sz));
6702                 goto _abort_event_;
6703
6704         }
6705
6706         atomic_inc(&pevt_priv->event_seq);
6707
6708         peventbuf += 2;
6709
6710         if (peventbuf) {
6711                 event_callback = wlanevents[evt_code].event_callback;
6712                 event_callback(padapter, (u8 *)peventbuf);
6713
6714                 pevt_priv->evt_done_cnt++;
6715         }
6716
6717
6718 _abort_event_:
6719
6720
6721         return H2C_SUCCESS;
6722
6723 }
6724
6725 u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
6726 {
6727         if (!pbuf)
6728                 return H2C_PARAMETERS_ERROR;
6729
6730         return H2C_SUCCESS;
6731 }
6732
6733 u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
6734 {
6735         struct sta_info *psta_bmc;
6736         struct list_head        *xmitframe_plist, *xmitframe_phead;
6737         struct xmit_frame *pxmitframe = NULL;
6738         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6739         struct sta_priv  *pstapriv = &padapter->stapriv;
6740
6741         /* for BC/MC Frames */
6742         psta_bmc = rtw_get_bcmc_stainfo(padapter);
6743         if (!psta_bmc)
6744                 return H2C_SUCCESS;
6745
6746         if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
6747                 msleep(10);/*  10ms, ATIM(HIQ) Windows */
6748
6749                 /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
6750                 spin_lock_bh(&pxmitpriv->lock);
6751
6752                 xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
6753                 xmitframe_plist = get_next(xmitframe_phead);
6754
6755                 while (xmitframe_phead != xmitframe_plist) {
6756                         pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
6757
6758                         xmitframe_plist = get_next(xmitframe_plist);
6759
6760                         list_del_init(&pxmitframe->list);
6761
6762                         psta_bmc->sleepq_len--;
6763                         if (psta_bmc->sleepq_len > 0)
6764                                 pxmitframe->attrib.mdata = 1;
6765                         else
6766                                 pxmitframe->attrib.mdata = 0;
6767
6768                         pxmitframe->attrib.triggered = 1;
6769
6770                         if (xmitframe_hiq_filter(pxmitframe) == true)
6771                                 pxmitframe->attrib.qsel = 0x11;/* HIQ */
6772
6773                         rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
6774                 }
6775
6776                 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
6777                 spin_unlock_bh(&pxmitpriv->lock);
6778
6779                 /* check hi queue and bmc_sleepq */
6780                 rtw_chk_hi_queue_cmd(padapter);
6781         }
6782
6783         return H2C_SUCCESS;
6784 }
6785
6786 u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
6787 {
6788         if (send_beacon(padapter) == _FAIL) {
6789                 DBG_871X("issue_beacon, fail!\n");
6790                 return H2C_PARAMETERS_ERROR;
6791         }
6792
6793         /* tx bc/mc frames after update TIM */
6794         chk_bmc_sleepq_hdl(padapter, NULL);
6795
6796         return H2C_SUCCESS;
6797 }
6798
6799 int rtw_chk_start_clnt_join(struct adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
6800 {
6801         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6802         unsigned char cur_ch = pmlmeext->cur_channel;
6803         unsigned char cur_bw = pmlmeext->cur_bwmode;
6804         unsigned char cur_ch_offset = pmlmeext->cur_ch_offset;
6805         bool connect_allow = true;
6806
6807         if (!ch || !bw || !offset) {
6808                 rtw_warn_on(1);
6809                 connect_allow = false;
6810         }
6811
6812         if (connect_allow == true) {
6813                 DBG_871X("start_join_set_ch_bw: ch =%d, bwmode =%d, ch_offset =%d\n", cur_ch, cur_bw, cur_ch_offset);
6814                 *ch = cur_ch;
6815                 *bw = cur_bw;
6816                 *offset = cur_ch_offset;
6817         }
6818
6819         return connect_allow == true ? _SUCCESS : _FAIL;
6820 }
6821
6822 /* Find union about ch, bw, ch_offset of all linked/linking interfaces */
6823 int rtw_get_ch_setting_union(struct adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
6824 {
6825         struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
6826         struct adapter *iface;
6827         struct mlme_ext_priv *mlmeext;
6828         u8 ch_ret = 0;
6829         u8 bw_ret = CHANNEL_WIDTH_20;
6830         u8 offset_ret = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6831
6832         if (ch)
6833                 *ch = 0;
6834         if (bw)
6835                 *bw = CHANNEL_WIDTH_20;
6836         if (offset)
6837                 *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6838
6839         iface = dvobj->padapters;
6840         mlmeext = &iface->mlmeextpriv;
6841
6842         if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING))
6843                 return 0;
6844
6845         ch_ret = mlmeext->cur_channel;
6846         bw_ret = mlmeext->cur_bwmode;
6847         offset_ret = mlmeext->cur_ch_offset;
6848
6849         return 1;
6850 }
6851
6852 u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
6853 {
6854         struct set_ch_parm *set_ch_parm;
6855         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6856
6857         if (!pbuf)
6858                 return H2C_PARAMETERS_ERROR;
6859
6860         set_ch_parm = (struct set_ch_parm *)pbuf;
6861
6862         DBG_871X(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
6863                 FUNC_NDEV_ARG(padapter->pnetdev),
6864                 set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
6865
6866         pmlmeext->cur_channel = set_ch_parm->ch;
6867         pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
6868         pmlmeext->cur_bwmode = set_ch_parm->bw;
6869
6870         set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
6871
6872         return  H2C_SUCCESS;
6873 }
6874
6875 u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
6876 {
6877         struct SetChannelPlan_param *setChannelPlan_param;
6878         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6879
6880         if (!pbuf)
6881                 return H2C_PARAMETERS_ERROR;
6882
6883         setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
6884
6885         pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
6886         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
6887
6888         if ((padapter->rtw_wdev != NULL) && (padapter->rtw_wdev->wiphy)) {
6889                 struct regulatory_request request;
6890                 request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
6891                 rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request);
6892         }
6893
6894         return  H2C_SUCCESS;
6895 }
6896
6897 u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf)
6898 {
6899         struct LedBlink_param *ledBlink_param;
6900
6901         if (!pbuf)
6902                 return H2C_PARAMETERS_ERROR;
6903
6904         ledBlink_param = (struct LedBlink_param *)pbuf;
6905         return  H2C_SUCCESS;
6906 }
6907
6908 u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
6909 {
6910         return  H2C_REJECTED;
6911 }
6912
6913 /*  TDLS_ESTABLISHED    : write RCR DATA BIT */
6914 /*  TDLS_CS_OFF         : go back to the channel linked with AP, terminating channel switch procedure */
6915 /*  TDLS_INIT_CH_SEN    : init channel sensing, receive all data and mgnt frame */
6916 /*  TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
6917 /*  TDLS_OFF_CH         : first time set channel to off channel */
6918 /*  TDLS_BASE_CH                : go back tp the channel linked with AP when set base channel as target channel */
6919 /*  TDLS_P_OFF_CH       : periodically go to off channel */
6920 /*  TDLS_P_BASE_CH      : periodically go back to base channel */
6921 /*  TDLS_RS_RCR         : restore RCR */
6922 /*  TDLS_TEAR_STA       : free tdls sta */
6923 u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
6924 {
6925         return H2C_REJECTED;
6926 }
6927
6928 u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf)
6929 {
6930         struct RunInThread_param *p;
6931
6932
6933         if (NULL == pbuf)
6934                 return H2C_PARAMETERS_ERROR;
6935         p = (struct RunInThread_param *)pbuf;
6936
6937         if (p->func)
6938                 p->func(p->context);
6939
6940         return H2C_SUCCESS;
6941 }