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
14static 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
36static 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
52static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
53
54/**************************************************
55OUI definitions for the vendor specific IE
56***************************************************/
57unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
58unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
59unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
60unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
61unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
62
63unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
64unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
65
66static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
67
68/********************************************************
69ChannelPlan definitions
70*********************************************************/
71static 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
81static 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 */
169static 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 */
177int 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
193Following are the initialization functions for WiFi MLME
194
195*****************************************************************************/
196
197int 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
205void 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
219static 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
268static 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
281static 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
333static 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
378void 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
408void 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
422static 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
436void 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
504Following are the callback functions for each subtype of the management frames
505
506*****************************************************************************/
507
508unsigned 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
553unsigned 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
566unsigned 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
677unsigned 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
843auth_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
859unsigned 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
928authclnt_fail:
929
930	/* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
931
932	return _FAIL;
933
934}
935
936unsigned 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
1354asoc_class2_error:
1355
1356	issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1357
1358	return _FAIL;
1359
1360OnAssocReqFail:
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
1371unsigned 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
1450report_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
1461unsigned 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
1533unsigned 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
1586unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame)
1587{
1588	return _SUCCESS;
1589}
1590
1591unsigned 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
1621exit:
1622	return _FAIL;
1623}
1624
1625unsigned 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
1717static 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
1744static 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
1760static 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
1772static 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
1792exit:
1793	return ret;
1794}
1795
1796unsigned 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
1821exit:
1822	return ret;
1823}
1824
1825unsigned 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
1847exit:
1848
1849	return _SUCCESS;
1850}
1851
1852unsigned 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
1883unsigned 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
1907unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame)
1908{
1909	return _SUCCESS;
1910}
1911
1912static 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
1937exit:
1938	return pmgntframe;
1939
1940}
1941
1942inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
1943{
1944	return _alloc_mgtxmitframe(pxmitpriv, false);
1945}
1946
1947/****************************************************************************
1948
1949Following are some TX functions for WiFi MLME
1950
1951*****************************************************************************/
1952
1953void 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
1960void 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
1999void 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
2010void 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
2022s32 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
2052s32 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
2080static 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
2114void 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
2259void 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
2453static 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
2543exit:
2544	return ret;
2545}
2546
2547inline 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
2552int 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
2579exit:
2580	return ret;
2581}
2582
2583/*  if psta == NULL, indicate we are station(client) now... */
2584void 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
2713void 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
2840void 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
3008exit:
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 */
3016static 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
3081exit:
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 */
3091int 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
3134exit:
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 */
3144s32 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 */
3161static 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
3230exit:
3231	return ret;
3232}
3233
3234/* when wait_ms >0 , this function should be called at process context */
3235/* da == NULL for station mode */
3236int 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
3267exit:
3268	return ret;
3269}
3270
3271static 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
3326exit:
3327	return ret;
3328}
3329
3330int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
3331{
3332	return _issue_deauth(padapter, da, reason, false);
3333}
3334
3335int 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
3361exit:
3362	return ret;
3363}
3364
3365void 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
3432void 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
3583static 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
3726unsigned 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
3766unsigned 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
3796Following are some utility functions for WiFi MLME
3797
3798*****************************************************************************/
3799
3800void 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. */
3916u8 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
4071void 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
4126void 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
4184void 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
4209void 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
4224unsigned 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
4247static 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
4392Following are the functions to report events
4393
4394*****************************************************************************/
4395
4396void 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
4457void 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
4501void 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
4551void 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
4595void 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
4648void 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
4692Following are the event callback functions
4693
4694*****************************************************************************/
4695
4696/* for sta/adhoc mode */
4697void 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
4757static 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
4804void 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 */
4881void 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
4933void 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
4941Following are the functions for the timer handlers
4942
4943*****************************************************************************/
4944void _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
4968static 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
4986void 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
5091void 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
5126void 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
5165void 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
5182void 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
5199u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
5200{
5201	return H2C_SUCCESS;
5202}
5203
5204u8 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
5238u8 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
5295u8 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
5439u8 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
5463static 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
5523u8 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
5595u8 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
5607u8 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
5647u8 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
5674write_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
5693exit:
5694	return ret;
5695}
5696
5697u8 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
5723u8 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
5739exit:
5740	return res;
5741}
5742
5743u8 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
5777exit:
5778	return res;
5779}
5780
5781static 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
5812u8 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
5855u8 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
5863u8 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
5913u8 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
5924int 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
5946u8 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
5965u8 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
5988u8 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 */
6003u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
6004{
6005	return H2C_REJECTED;
6006}
6007
6008u8 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}
6022