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