• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2012 Realtek Corporation. */
3 
4 #define _RTW_MLME_EXT_C_
5 
6 #include <linux/ieee80211.h>
7 #include "../include/osdep_service.h"
8 #include "../include/drv_types.h"
9 #include "../include/wifi.h"
10 #include "../include/rtw_mlme_ext.h"
11 #include "../include/wlan_bssdef.h"
12 #include "../include/rtl8188e_xmit.h"
13 #include "../include/rtl8188e_dm.h"
14 
15 /* response function for each management frame subtype, do not reorder */
16 static mlme_handler mlme_sta_tbl[] = {
17 	OnAssocReq,
18 	OnAssocRsp,
19 	OnAssocReq,
20 	OnAssocRsp,
21 	OnProbeReq,
22 	OnProbeRsp,
23 	NULL,
24 	NULL,
25 	OnBeacon,
26 	NULL,
27 	OnDisassoc,
28 	OnAuthClient,
29 	OnDeAuth,
30 	OnAction,
31 };
32 
33 static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
34 
35 /**************************************************
36 OUI definitions for the vendor specific IE
37 ***************************************************/
38 unsigned char	RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
39 unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
40 unsigned char	WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
41 unsigned char	P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
42 unsigned char	WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
43 
44 unsigned char	WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
45 unsigned char	WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
46 
47 unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
48 unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
49 
50 extern unsigned char REALTEK_96B_IE[];
51 
52 /********************************************************
53 MCS rate definitions
54 *********************************************************/
55 unsigned char	MCS_rate_1R[16] = {0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
56 
57 /********************************************************
58 ChannelPlan definitions
59 *********************************************************/
60 static struct rt_channel_plan RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
61 	{{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 */
62 	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},		/*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
63 	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},			/*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
64 	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},	/*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
65 	{{10, 11, 12, 13}, 4},					/*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
66 	{{}, 0},									/*  0x05, RT_CHANNEL_DOMAIN_2G_NULL */
67 };
68 
69 static struct rt_channel_plan_map	RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
70 	/*  0x00 ~ 0x1F , Old Define ===== */
71 	{0x02},	/* 0x00, RT_CHANNEL_DOMAIN_FCC */
72 	{0x02},	/* 0x01, RT_CHANNEL_DOMAIN_IC */
73 	{0x01},	/* 0x02, RT_CHANNEL_DOMAIN_ETSI */
74 	{0x01},	/* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
75 	{0x01},	/* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
76 	{0x03},	/* 0x05, RT_CHANNEL_DOMAIN_MKK */
77 	{0x03},	/* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
78 	{0x01},	/* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
79 	{0x03},	/* 0x08, RT_CHANNEL_DOMAIN_TELEC */
80 	{0x03},	/* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
81 	{0x00},	/* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
82 	{0x02},	/* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
83 	{0x01},	/* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
84 	{0x02},	/* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
85 	{0x02},	/* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
86 	{0x02},	/* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
87 	{0x01},	/* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
88 	{0x02},	/* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
89 	{0x01},	/* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
90 	{0x00}, /* 0x13 */
91 	{0x02},	/* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
92 	{0x00},	/* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
93 	{0x00},	/* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
94 	{0x03},	/* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
95 	{0x05},	/* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
96 	{0x02},	/* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
97 	{0x00},	/* 0x1A, */
98 	{0x00},	/* 0x1B, */
99 	{0x00},	/* 0x1C, */
100 	{0x00},	/* 0x1D, */
101 	{0x00},	/* 0x1E, */
102 	{0x00},	/* 0x1F, */
103 	/*  0x20 ~ 0x7F , New Define ===== */
104 	{0x00},	/* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
105 	{0x01},	/* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
106 	{0x02},	/* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
107 	{0x03},	/* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
108 	{0x04},	/* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
109 	{0x02},	/* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
110 	{0x00},	/* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
111 	{0x03},	/* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
112 	{0x00},	/* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
113 	{0x00},	/* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
114 	{0x00},	/* 0x2A, */
115 	{0x00},	/* 0x2B, */
116 	{0x00},	/* 0x2C, */
117 	{0x00},	/* 0x2D, */
118 	{0x00},	/* 0x2E, */
119 	{0x00},	/* 0x2F, */
120 	{0x00},	/* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
121 	{0x00},	/* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
122 	{0x00},	/* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
123 	{0x00},	/* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
124 	{0x02},	/* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
125 	{0x00},	/* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
126 	{0x00},	/* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
127 	{0x03},	/* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
128 	{0x03},	/* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
129 	{0x02},	/* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
130 	{0x00},	/* 0x3A, */
131 	{0x00},	/* 0x3B, */
132 	{0x00},	/* 0x3C, */
133 	{0x00},	/* 0x3D, */
134 	{0x00},	/* 0x3E, */
135 	{0x00},	/* 0x3F, */
136 	{0x02},	/* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
137 	{0x03},	/* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
138 };
139 
140 static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the conbination for max channel numbers */
141 
142 /*
143  * Search the @param channel_num in given @param channel_set
144  * @ch_set: the given channel set
145  * @ch: the given channel number
146  *
147  * return the index of channel_num in channel_set, -1 if not found
148  */
rtw_ch_set_search_ch(struct rt_channel_info * ch_set,const u32 ch)149 int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
150 {
151 	int i;
152 	for (i = 0; ch_set[i].ChannelNum != 0; i++) {
153 		if (ch == ch_set[i].ChannelNum)
154 			break;
155 	}
156 
157 	if (i >= ch_set[i].ChannelNum)
158 		return -1;
159 	return i;
160 }
161 
162 /****************************************************************************
163 
164 Following are the initialization functions for WiFi MLME
165 
166 *****************************************************************************/
167 
init_hw_mlme_ext(struct adapter * padapter)168 int init_hw_mlme_ext(struct adapter *padapter)
169 {
170 	struct	mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
171 
172 	set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
173 	return _SUCCESS;
174 }
175 
init_mlme_ext_priv_value(struct adapter * padapter)176 static void init_mlme_ext_priv_value(struct adapter *padapter)
177 {
178 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
179 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
180 	unsigned char	mixed_datarate[NumRates] = {
181 		_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
182 		_9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
183 		 _48M_RATE_, _54M_RATE_, 0xff
184 	};
185 	unsigned char	mixed_basicrate[NumRates] = {
186 		_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
187 		_12M_RATE_, _24M_RATE_, 0xff,
188 	};
189 
190 	atomic_set(&pmlmeext->event_seq, 0);
191 	pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
192 
193 	pmlmeext->cur_channel = padapter->registrypriv.channel;
194 	pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
195 	pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
196 	pmlmeext->retry = 0;
197 
198 	pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
199 
200 	memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
201 	memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
202 
203 	pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
204 
205 	pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
206 	pmlmeext->sitesurvey_res.channel_idx = 0;
207 	pmlmeext->sitesurvey_res.bss_cnt = 0;
208 	pmlmeext->scan_abort = false;
209 
210 	pmlmeinfo->state = WIFI_FW_NULL_STATE;
211 	pmlmeinfo->reauth_count = 0;
212 	pmlmeinfo->reassoc_count = 0;
213 	pmlmeinfo->link_count = 0;
214 	pmlmeinfo->auth_seq = 0;
215 	pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
216 	pmlmeinfo->key_index = 0;
217 	pmlmeinfo->iv = 0;
218 
219 	pmlmeinfo->enc_algo = _NO_PRIVACY_;
220 	pmlmeinfo->authModeToggle = 0;
221 
222 	memset(pmlmeinfo->chg_txt, 0, 128);
223 
224 	pmlmeinfo->slotTime = SHORT_SLOT_TIME;
225 	pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
226 
227 	pmlmeinfo->dialogToken = 0;
228 
229 	pmlmeext->action_public_rxseq = 0xffff;
230 	pmlmeext->action_public_dialog_token = 0xff;
231 }
232 
has_channel(struct rt_channel_info * channel_set,u8 chanset_size,u8 chan)233 static int has_channel(struct rt_channel_info *channel_set,
234 					   u8 chanset_size,
235 					   u8 chan)
236 {
237 	int i;
238 
239 	for (i = 0; i < chanset_size; i++) {
240 		if (channel_set[i].ChannelNum == chan)
241 			return 1;
242 	}
243 	return 0;
244 }
245 
init_channel_list(struct adapter * padapter,struct rt_channel_info * channel_set,u8 chanset_size,struct p2p_channels * channel_list)246 static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set,
247 							  u8 chanset_size,
248 							  struct p2p_channels *channel_list)
249 {
250 	struct p2p_oper_class_map op_class[] = {
251 		{ IEEE80211G,  81,   1,  13,  1, BW20 },
252 		{ IEEE80211G,  82,  14,  14,  1, BW20 },
253 		{ -1, 0, 0, 0, 0, BW20 }
254 	};
255 
256 	int cla, op;
257 
258 	cla = 0;
259 
260 	for (op = 0; op_class[op].op_class; op++) {
261 		u8 ch;
262 		struct p2p_oper_class_map *o = &op_class[op];
263 		struct p2p_reg_class *reg = NULL;
264 
265 		for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
266 			if (!has_channel(channel_set, chanset_size, ch)) {
267 				continue;
268 			}
269 
270 			if ((padapter->registrypriv.ht_enable == 0) && (o->inc == 8))
271 				continue;
272 
273 			if (((padapter->registrypriv.cbw40_enable & BIT(1)) == 0) &&
274 			    ((o->bw == BW40MINUS) || (o->bw == BW40PLUS)))
275 				continue;
276 
277 			if (!reg) {
278 				reg = &channel_list->reg_class[cla];
279 				cla++;
280 				reg->reg_class = o->op_class;
281 				reg->channels = 0;
282 			}
283 			reg->channel[reg->channels] = ch;
284 			reg->channels++;
285 		}
286 	}
287 	channel_list->reg_classes = cla;
288 }
289 
init_channel_set(struct adapter * padapter,u8 ChannelPlan,struct rt_channel_info * channel_set)290 static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set)
291 {
292 	u8 index, chanset_size = 0;
293 	u8 b2_4GBand = false;
294 	u8 Index2G = 0;
295 
296 	memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
297 
298 	if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
299 		return chanset_size;
300 
301 	if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
302 		b2_4GBand = true;
303 		if (ChannelPlan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
304 			Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
305 		else
306 			Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
307 	}
308 
309 	if (b2_4GBand) {
310 		for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
311 			channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
312 
313 			if ((ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN) ||/* Channel 1~11 is active, and 12~14 is passive */
314 			    (ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G)) {
315 				if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
316 					channel_set[chanset_size].ScanType = SCAN_ACTIVE;
317 				else if ((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
318 					channel_set[chanset_size].ScanType  = SCAN_PASSIVE;
319 			} else if (ChannelPlan == RT_CHANNEL_DOMAIN_WORLD_WIDE_13 ||
320 				   Index2G == RT_CHANNEL_DOMAIN_2G_WORLD) {/*  channel 12~13, passive scan */
321 				if (channel_set[chanset_size].ChannelNum <= 11)
322 					channel_set[chanset_size].ScanType = SCAN_ACTIVE;
323 				else
324 					channel_set[chanset_size].ScanType = SCAN_PASSIVE;
325 			} else {
326 				channel_set[chanset_size].ScanType = SCAN_ACTIVE;
327 			}
328 
329 			chanset_size++;
330 		}
331 	}
332 	return chanset_size;
333 }
334 
_survey_timer_hdl(struct timer_list * t)335 static void _survey_timer_hdl(struct timer_list *t)
336 {
337 	struct adapter *padapter = from_timer(padapter, t, mlmeextpriv.survey_timer);
338 
339 	survey_timer_hdl(padapter);
340 }
341 
_link_timer_hdl(struct timer_list * t)342 static void _link_timer_hdl(struct timer_list *t)
343 {
344 	struct adapter *padapter = from_timer(padapter, t, mlmeextpriv.link_timer);
345 
346 	link_timer_hdl(padapter);
347 }
348 
init_mlme_ext_timer(struct adapter * padapter)349 static void init_mlme_ext_timer(struct adapter *padapter)
350 {
351 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
352 
353 	timer_setup(&pmlmeext->survey_timer, _survey_timer_hdl, 0);
354 	timer_setup(&pmlmeext->link_timer, _link_timer_hdl, 0);
355 }
356 
init_mlme_ext_priv(struct adapter * padapter)357 void init_mlme_ext_priv(struct adapter *padapter)
358 {
359 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
360 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
361 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
362 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
363 
364 	pmlmeext->padapter = padapter;
365 
366 	init_mlme_ext_priv_value(padapter);
367 	pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
368 
369 	init_mlme_ext_timer(padapter);
370 
371 	init_mlme_ap_info(padapter);
372 
373 	pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
374 	init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
375 
376 	pmlmeext->chan_scan_time = SURVEY_TO;
377 	pmlmeext->mlmeext_init = true;
378 
379 	pmlmeext->active_keep_alive_check = true;
380 }
381 
free_mlme_ext_priv(struct mlme_ext_priv * pmlmeext)382 void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
383 {
384 	struct adapter *padapter = pmlmeext->padapter;
385 
386 	if (!padapter)
387 		return;
388 
389 	if (padapter->bDriverStopped) {
390 		_cancel_timer_ex(&pmlmeext->survey_timer);
391 		_cancel_timer_ex(&pmlmeext->link_timer);
392 		/* _cancel_timer_ex(&pmlmeext->ADDBA_timer); */
393 	}
394 }
395 
mgt_dispatcher(struct adapter * padapter,struct recv_frame * precv_frame)396 void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame)
397 {
398 	int index;
399 	mlme_handler fct;
400 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
401 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)precv_frame->rx_data;
402 	struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, hdr->addr2);
403 
404 	if (!ieee80211_is_mgmt(hdr->frame_control))
405 		return;
406 
407 	/* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
408 	if (memcmp(hdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN) &&
409 	    !is_broadcast_ether_addr(hdr->addr1))
410 		return;
411 
412 	index = (le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
413 	if (index >= ARRAY_SIZE(mlme_sta_tbl))
414 		return;
415 	fct = mlme_sta_tbl[index];
416 
417 	if (psta) {
418 		if (ieee80211_has_retry(hdr->frame_control)) {
419 			if (precv_frame->attrib.seq_num == psta->RxMgmtFrameSeqNum)
420 				/* drop the duplicate management frame */
421 				return;
422 		}
423 		psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
424 	}
425 
426 	if (ieee80211_is_auth(hdr->frame_control)) {
427 		if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
428 			fct = OnAuth;
429 		else
430 			fct = OnAuthClient;
431 	}
432 
433 	if (fct)
434 		fct(padapter, precv_frame);
435 }
436 
p2p_listen_state_process(struct adapter * padapter,unsigned char * da)437 static u32 p2p_listen_state_process(struct adapter *padapter, unsigned char *da)
438 {
439 	bool response = true;
440 
441 	/*	do nothing if the device name is empty */
442 	if (!padapter->wdinfo.device_name_len)
443 		response = false;
444 
445 	if (response)
446 		issue_probersp_p2p(padapter, da);
447 
448 	return _SUCCESS;
449 }
450 
update_TSF(struct mlme_ext_priv * pmlmeext,u8 * pframe)451 static void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe)
452 {
453 	u8 *pIE;
454 	__le32 *pbuf;
455 
456 	pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
457 	pbuf = (__le32 *)pIE;
458 
459 	pmlmeext->TSFValue = le32_to_cpu(*(pbuf + 1));
460 
461 	pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
462 
463 	pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
464 }
465 
correct_TSF(struct adapter * padapter)466 static void correct_TSF(struct adapter *padapter)
467 {
468 	u8 reg;
469 	int res;
470 	u64 tsf;
471 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
472 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
473 
474 	tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue,
475 					  pmlmeinfo->bcn_interval * 1024) - 1024; /* us */
476 
477 	if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
478 	    ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
479 		rtw_stop_tx_beacon(padapter);
480 
481 	/* disable related TSF function */
482 	res = rtw_read8(padapter, REG_BCN_CTRL, &reg);
483 	if (res)
484 		return;
485 
486 	rtw_write8(padapter, REG_BCN_CTRL, reg & (~BIT(3)));
487 
488 	rtw_write32(padapter, REG_TSFTR, tsf);
489 	rtw_write32(padapter, REG_TSFTR + 4, tsf >> 32);
490 
491 	/* enable related TSF function */
492 	res = rtw_read8(padapter, REG_BCN_CTRL, &reg);
493 	if (res)
494 		return;
495 
496 	rtw_write8(padapter, REG_BCN_CTRL, reg | BIT(3));
497 
498 	if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
499 	    ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
500 		rtw_resume_tx_beacon(padapter);
501 }
502 
503 /****************************************************************************
504 
505 Following are the callback functions for each subtype of the management frames
506 
507 *****************************************************************************/
508 
OnProbeReq(struct adapter * padapter,struct recv_frame * precv_frame)509 unsigned int OnProbeReq(struct adapter *padapter, struct recv_frame *precv_frame)
510 {
511 	unsigned int	ielen;
512 	unsigned char	*p;
513 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
514 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
515 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
516 	struct wlan_bssid_ex *cur = &pmlmeinfo->network;
517 	u8 *pframe = precv_frame->rx_data;
518 	uint len = precv_frame->len;
519 	u8 is_valid_p2p_probereq = false;
520 
521 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
522 
523 	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
524 	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
525 	    !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
526 	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
527 	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)) {
528 		/*	mcs_rate = 0 -> CCK 1M rate */
529 		/*	mcs_rate = 1 -> CCK 2M rate */
530 		/*	mcs_rate = 2 -> CCK 5.5M rate */
531 		/*	mcs_rate = 3 -> CCK 11M rate */
532 		/*	In the P2P mode, the driver should not support the CCK rate */
533 
534 		/*	Commented by Kurt 2012/10/16 */
535 		/*	IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */
536 		is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len);
537 		if (is_valid_p2p_probereq) {
538 			if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
539 				/*  FIXME */
540 				report_survey_event(padapter, precv_frame);
541 				p2p_listen_state_process(padapter,  get_sa(pframe));
542 
543 				return _SUCCESS;
544 			}
545 		}
546 	}
547 
548 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
549 		return _SUCCESS;
550 
551 	if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
552 	    !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
553 		return _SUCCESS;
554 
555 	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
556 			len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
557 
558 	/* check (wildcard) SSID */
559 	if (p) {
560 		if (is_valid_p2p_probereq)
561 			goto _issue_probersp;
562 
563 		if ((ielen != 0 && memcmp((void *)(p + 2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) ||
564 		    (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
565 			return _SUCCESS;
566 
567 _issue_probersp:
568 
569 		if (check_fwstate(pmlmepriv, _FW_LINKED) &&
570 		    (pmlmepriv->cur_network.join_res ||
571 		    check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
572 			issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
573 	}
574 	return _SUCCESS;
575 }
576 
OnProbeRsp(struct adapter * padapter,struct recv_frame * precv_frame)577 unsigned int OnProbeRsp(struct adapter *padapter, struct recv_frame *precv_frame)
578 {
579 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
580 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
581 	u8 *pframe = precv_frame->rx_data;
582 
583 	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
584 		if (pwdinfo->tx_prov_disc_info.benable) {
585 			if (!memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
586 				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
587 					pwdinfo->tx_prov_disc_info.benable = false;
588 					issue_p2p_provision_request(padapter,
589 								    pwdinfo->tx_prov_disc_info.ssid.Ssid,
590 								    pwdinfo->tx_prov_disc_info.ssid.SsidLength,
591 								    pwdinfo->tx_prov_disc_info.peerDevAddr);
592 				} else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
593 					pwdinfo->tx_prov_disc_info.benable = false;
594 					issue_p2p_provision_request(padapter, NULL, 0,
595 								    pwdinfo->tx_prov_disc_info.peerDevAddr);
596 				}
597 			}
598 		}
599 		return _SUCCESS;
600 	} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
601 		if (pwdinfo->nego_req_info.benable) {
602 			if (!memcmp(pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
603 				pwdinfo->nego_req_info.benable = false;
604 				issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr);
605 			}
606 		}
607 	} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
608 		if (pwdinfo->invitereq_info.benable) {
609 			if (!memcmp(pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
610 				pwdinfo->invitereq_info.benable = false;
611 				issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr);
612 			}
613 		}
614 	}
615 	if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
616 		report_survey_event(padapter, precv_frame);
617 		return _SUCCESS;
618 	}
619 
620 	return _SUCCESS;
621 }
622 
OnBeacon(struct adapter * padapter,struct recv_frame * precv_frame)623 unsigned int OnBeacon(struct adapter *padapter, struct recv_frame *precv_frame)
624 {
625 	int cam_idx;
626 	struct sta_info	*psta;
627 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
628 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
629 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
630 	struct sta_priv	*pstapriv = &padapter->stapriv;
631 	u8 *pframe = precv_frame->rx_data;
632 	uint len = precv_frame->len;
633 	struct wlan_bssid_ex *pbss;
634 	int ret = _SUCCESS;
635 
636 	if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
637 		report_survey_event(padapter, precv_frame);
638 		return _SUCCESS;
639 	}
640 
641 	if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
642 		if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
643 			/* we should update current network before auth, or some IE is wrong */
644 			pbss = kmalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
645 			if (pbss) {
646 				if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
647 					update_network(&pmlmepriv->cur_network.network, pbss, padapter, true);
648 					rtw_get_bcn_info(&pmlmepriv->cur_network);
649 				}
650 				kfree(pbss);
651 			}
652 
653 			/* check the vendor of the assoc AP */
654 			pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe + sizeof(struct ieee80211_hdr_3addr), len - sizeof(struct ieee80211_hdr_3addr));
655 
656 			/* update TSF Value */
657 			update_TSF(pmlmeext, pframe);
658 
659 			/* start auth */
660 			start_clnt_auth(padapter);
661 
662 			return _SUCCESS;
663 		}
664 
665 		if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
666 			psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
667 			if (psta) {
668 				ret = rtw_check_bcn_info(padapter, pframe, len);
669 				if (!ret) {
670 					receive_disconnect(padapter,
671 							   pmlmeinfo->network.MacAddress, 0);
672 					return _SUCCESS;
673 				}
674 				/* update WMM, ERP in the beacon */
675 				/* todo: the timer is used instead of the number of the beacon received */
676 				if ((sta_rx_pkts(psta) & 0xf) == 0)
677 					update_beacon_info(padapter, pframe, len, psta);
678 				process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
679 			}
680 		} else if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
681 			psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
682 			if (psta) {
683 				/* update WMM, ERP in the beacon */
684 				/* todo: the timer is used instead of the number of the beacon received */
685 				if ((sta_rx_pkts(psta) & 0xf) == 0)
686 					update_beacon_info(padapter, pframe, len, psta);
687 			} else {
688 				/* allocate a new CAM entry for IBSS station */
689 				cam_idx = allocate_fw_sta_entry(padapter);
690 				if (cam_idx == NUM_STA)
691 					goto _END_ONBEACON_;
692 
693 				/* get supported rate */
694 				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) {
695 					pmlmeinfo->FW_sta_info[cam_idx].status = 0;
696 					goto _END_ONBEACON_;
697 				}
698 
699 				/* update TSF Value */
700 				update_TSF(pmlmeext, pframe);
701 
702 				/* report sta add event */
703 				report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
704 			}
705 		}
706 	}
707 
708 _END_ONBEACON_:
709 
710 	return _SUCCESS;
711 }
712 
OnAuth(struct adapter * padapter,struct recv_frame * precv_frame)713 unsigned int OnAuth(struct adapter *padapter, struct recv_frame *precv_frame)
714 {
715 	unsigned int	auth_mode, ie_len;
716 	u16 seq;
717 	unsigned char	*sa, *p;
718 	u16 algorithm;
719 	int	status;
720 	static struct sta_info stat;
721 	struct	sta_info	*pstat = NULL;
722 	struct	sta_priv *pstapriv = &padapter->stapriv;
723 	struct security_priv *psecuritypriv = &padapter->securitypriv;
724 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
725 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
726 	u8 *pframe = precv_frame->rx_data;
727 	uint len = precv_frame->len;
728 
729 	if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
730 		return _FAIL;
731 
732 	sa = GetAddr2Ptr(pframe);
733 
734 	auth_mode = psecuritypriv->dot11AuthAlgrthm;
735 	seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2));
736 	algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN));
737 
738 	if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
739 	    psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
740 		auth_mode = 0;
741 
742 	if ((algorithm > 0 && auth_mode == 0) ||	/*  rx a shared-key auth but shared not enabled */
743 	    (algorithm == 0 && auth_mode == 1)) {	/*  rx a open-system auth but shared-key is enabled */
744 
745 		status = _STATS_NO_SUPP_ALG_;
746 
747 		goto auth_fail;
748 	}
749 
750 	if (!rtw_access_ctrl(padapter, sa)) {
751 		status = _STATS_UNABLE_HANDLE_STA_;
752 		goto auth_fail;
753 	}
754 
755 	pstat = rtw_get_stainfo(pstapriv, sa);
756 	if (!pstat) {
757 		/*  allocate a new one */
758 		pstat = rtw_alloc_stainfo(pstapriv, sa);
759 		if (!pstat) {
760 			status = _STATS_UNABLE_HANDLE_STA_;
761 			goto auth_fail;
762 		}
763 
764 		pstat->state = WIFI_FW_AUTH_NULL;
765 		pstat->auth_seq = 0;
766 	} else {
767 		spin_lock_bh(&pstapriv->asoc_list_lock);
768 		if (!list_empty(&pstat->asoc_list)) {
769 			list_del_init(&pstat->asoc_list);
770 			pstapriv->asoc_list_cnt--;
771 		}
772 		spin_unlock_bh(&pstapriv->asoc_list_lock);
773 
774 		if (seq == 1) {
775 			/* TODO: STA re_auth and auth timeout */
776 		}
777 	}
778 
779 	spin_lock_bh(&pstapriv->auth_list_lock);
780 	if (list_empty(&pstat->auth_list)) {
781 		list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
782 		pstapriv->auth_list_cnt++;
783 	}
784 	spin_unlock_bh(&pstapriv->auth_list_lock);
785 
786 	if (pstat->auth_seq == 0)
787 		pstat->expire_to = pstapriv->auth_to;
788 
789 	if ((pstat->auth_seq + 1) != seq) {
790 		status = _STATS_OUT_OF_AUTH_SEQ_;
791 		goto auth_fail;
792 	}
793 
794 	if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
795 		if (seq == 1) {
796 			pstat->state &= ~WIFI_FW_AUTH_NULL;
797 			pstat->state |= WIFI_FW_AUTH_SUCCESS;
798 			pstat->expire_to = pstapriv->assoc_to;
799 			pstat->authalg = algorithm;
800 		} else {
801 			status = _STATS_OUT_OF_AUTH_SEQ_;
802 			goto auth_fail;
803 		}
804 	} else { /*  shared system or auto authentication */
805 		if (seq == 1) {
806 			/* prepare for the challenging txt... */
807 
808 			pstat->state &= ~WIFI_FW_AUTH_NULL;
809 			pstat->state |= WIFI_FW_AUTH_STATE;
810 			pstat->authalg = algorithm;
811 			pstat->auth_seq = 2;
812 		} else if (seq == 3) {
813 			/* checking for challenging txt... */
814 
815 			p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len,
816 					len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
817 
818 			if (!p || ie_len <= 0) {
819 				status = _STATS_CHALLENGE_FAIL_;
820 				goto auth_fail;
821 			}
822 
823 			if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
824 				pstat->state &= (~WIFI_FW_AUTH_STATE);
825 				pstat->state |= WIFI_FW_AUTH_SUCCESS;
826 				/*  challenging txt is correct... */
827 				pstat->expire_to =  pstapriv->assoc_to;
828 			} else {
829 				status = _STATS_CHALLENGE_FAIL_;
830 				goto auth_fail;
831 			}
832 		} else {
833 			status = _STATS_OUT_OF_AUTH_SEQ_;
834 			goto auth_fail;
835 		}
836 	}
837 
838 	/*  Now, we are going to issue_auth... */
839 	pstat->auth_seq = seq + 1;
840 
841 	issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
842 
843 	if (pstat->state & WIFI_FW_AUTH_SUCCESS)
844 		pstat->auth_seq = 0;
845 
846 	return _SUCCESS;
847 
848 auth_fail:
849 
850 	if (pstat)
851 		rtw_free_stainfo(padapter, pstat);
852 
853 	pstat = &stat;
854 	memset((char *)pstat, '\0', sizeof(stat));
855 	pstat->auth_seq = 2;
856 	memcpy(pstat->hwaddr, sa, 6);
857 
858 	issue_auth(padapter, pstat, (unsigned short)status);
859 	return _FAIL;
860 }
861 
OnAuthClient(struct adapter * padapter,struct recv_frame * precv_frame)862 unsigned int OnAuthClient(struct adapter *padapter, struct recv_frame *precv_frame)
863 {
864 	unsigned int	seq, len, status, offset;
865 	unsigned char	*p;
866 	unsigned int	go2asoc = 0;
867 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
868 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
869 	u8 *pframe = precv_frame->rx_data;
870 	uint pkt_len = precv_frame->len;
871 
872 	/* check A1 matches or not */
873 	if (memcmp(myid(&padapter->eeprompriv), get_da(pframe), ETH_ALEN))
874 		return _SUCCESS;
875 
876 	if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
877 		return _SUCCESS;
878 
879 	offset = (GetPrivacy(pframe)) ? 4 : 0;
880 
881 	seq	= le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2));
882 	status	= le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4));
883 
884 	if (status != 0) {
885 		if (status == 13) { /*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
886 			if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
887 				pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
888 			else
889 				pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
890 		}
891 
892 		set_link_timer(pmlmeext, 1);
893 		goto authclnt_fail;
894 	}
895 
896 	if (seq == 2) {
897 		if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
898 			 /*  legendary shared system */
899 			p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
900 				pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
901 
902 			if (!p)
903 				goto authclnt_fail;
904 
905 			memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
906 			pmlmeinfo->auth_seq = 3;
907 			issue_auth(padapter, NULL, 0);
908 			set_link_timer(pmlmeext, REAUTH_TO);
909 
910 			return _SUCCESS;
911 		} else {
912 			/*  open system */
913 			go2asoc = 1;
914 		}
915 	} else if (seq == 4) {
916 		if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
917 			go2asoc = 1;
918 		else
919 			goto authclnt_fail;
920 	} else {
921 		/*  this is also illegal */
922 		goto authclnt_fail;
923 	}
924 
925 	if (go2asoc) {
926 		start_clnt_assoc(padapter);
927 		return _SUCCESS;
928 	}
929 authclnt_fail:
930 	return _FAIL;
931 }
932 
UpdateBrateTbl(u8 * mbrate)933 static void UpdateBrateTbl(u8 *mbrate)
934 {
935 	u8 i;
936 	u8 rate;
937 
938 	/*  1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
939 	for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
940 		rate = mbrate[i] & 0x7f;
941 		switch (rate) {
942 		case IEEE80211_CCK_RATE_1MB:
943 		case IEEE80211_CCK_RATE_2MB:
944 		case IEEE80211_CCK_RATE_5MB:
945 		case IEEE80211_CCK_RATE_11MB:
946 		case IEEE80211_OFDM_RATE_6MB:
947 		case IEEE80211_OFDM_RATE_12MB:
948 		case IEEE80211_OFDM_RATE_24MB:
949 			mbrate[i] |= IEEE80211_BASIC_RATE_MASK;
950 			break;
951 		}
952 	}
953 }
954 
UpdateBrateTblForSoftAP(u8 * bssrateset,u32 bssratelen)955 static void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen)
956 {
957 	u8 i;
958 	u8 rate;
959 
960 	for (i = 0; i < bssratelen; i++) {
961 		rate = bssrateset[i] & 0x7f;
962 		switch (rate) {
963 		case IEEE80211_CCK_RATE_1MB:
964 		case IEEE80211_CCK_RATE_2MB:
965 		case IEEE80211_CCK_RATE_5MB:
966 		case IEEE80211_CCK_RATE_11MB:
967 			bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
968 			break;
969 		}
970 	}
971 }
972 
OnAssocReq(struct adapter * padapter,struct recv_frame * precv_frame)973 unsigned int OnAssocReq(struct adapter *padapter, struct recv_frame *precv_frame)
974 {
975 	u16 capab_info;
976 	struct rtw_ieee802_11_elems elems;
977 	struct sta_info	*pstat;
978 	unsigned char		*p, *pos, *wpa_ie;
979 	unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
980 	int		i, ie_len, wpa_ie_len, left;
981 	unsigned char		supportRate[16];
982 	int					supportRateNum;
983 	unsigned short		status = _STATS_SUCCESSFUL_;
984 	unsigned short		frame_type, ie_offset = 0;
985 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
986 	struct security_priv *psecuritypriv = &padapter->securitypriv;
987 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
988 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
989 	struct wlan_bssid_ex *cur = &pmlmeinfo->network;
990 	struct sta_priv *pstapriv = &padapter->stapriv;
991 	u8 *pframe = precv_frame->rx_data;
992 	uint pkt_len = precv_frame->len;
993 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
994 	u8 p2p_status_code = P2P_STATUS_SUCCESS;
995 	u8 *p2pie;
996 	u32 p2pielen = 0;
997 
998 	if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
999 		return _FAIL;
1000 
1001 	frame_type = GetFrameSubType(pframe);
1002 	if (frame_type == WIFI_ASSOCREQ)
1003 		ie_offset = _ASOCREQ_IE_OFFSET_;
1004 	else /*  WIFI_REASSOCREQ */
1005 		ie_offset = _REASOCREQ_IE_OFFSET_;
1006 
1007 	if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset)
1008 		return _FAIL;
1009 
1010 	pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1011 	if (pstat == (struct sta_info *)NULL) {
1012 		status = _RSON_CLS2_;
1013 		goto asoc_class2_error;
1014 	}
1015 
1016 	capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
1017 
1018 	left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
1019 	pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
1020 
1021 	/*  check if this stat has been successfully authenticated/assocated */
1022 	if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
1023 		if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
1024 			status = _RSON_CLS2_;
1025 			goto asoc_class2_error;
1026 		} else {
1027 			pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1028 			pstat->state |= WIFI_FW_ASSOC_STATE;
1029 		}
1030 	} else {
1031 		pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1032 		pstat->state |= WIFI_FW_ASSOC_STATE;
1033 	}
1034 	pstat->capability = capab_info;
1035 	/* now parse all ieee802_11 ie to point to elems */
1036 	if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
1037 	    !elems.ssid) {
1038 		status = _STATS_FAILURE_;
1039 		goto OnAssocReqFail;
1040 	}
1041 
1042 	/*  now we should check all the fields... */
1043 	/*  checking SSID */
1044 	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
1045 		pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1046 	if (!p)
1047 		status = _STATS_FAILURE_;
1048 
1049 	if (ie_len == 0) { /*  broadcast ssid, however it is not allowed in assocreq */
1050 		status = _STATS_FAILURE_;
1051 	} else {
1052 		/*  check if ssid match */
1053 		if (memcmp((void *)(p + 2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
1054 			status = _STATS_FAILURE_;
1055 
1056 		if (ie_len != cur->Ssid.SsidLength)
1057 			status = _STATS_FAILURE_;
1058 	}
1059 
1060 	if (status != _STATS_SUCCESSFUL_)
1061 		goto OnAssocReqFail;
1062 
1063 	/*  check if the supported rate is ok */
1064 	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1065 	if (!p) {
1066 		/*  use our own rate set as statoin used */
1067 		/* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1068 		/* supportRateNum = AP_BSSRATE_LEN; */
1069 
1070 		status = _STATS_FAILURE_;
1071 		goto OnAssocReqFail;
1072 	} else {
1073 		memcpy(supportRate, p + 2, ie_len);
1074 		supportRateNum = ie_len;
1075 
1076 		p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
1077 				pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1078 		if (p) {
1079 			if (supportRateNum <= sizeof(supportRate)) {
1080 				memcpy(supportRate + supportRateNum, p + 2, ie_len);
1081 				supportRateNum += ie_len;
1082 			}
1083 		}
1084 	}
1085 
1086 	/* todo: mask supportRate between AP & STA -> move to update raid */
1087 	/* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1088 
1089 	/* update station supportRate */
1090 	pstat->bssratelen = supportRateNum;
1091 	memcpy(pstat->bssrateset, supportRate, supportRateNum);
1092 	UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1093 
1094 	/* check RSN/WPA/WPS */
1095 	pstat->dot8021xalg = 0;
1096 	pstat->wpa_psk = 0;
1097 	pstat->wpa_group_cipher = 0;
1098 	pstat->wpa2_group_cipher = 0;
1099 	pstat->wpa_pairwise_cipher = 0;
1100 	pstat->wpa2_pairwise_cipher = 0;
1101 	memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1102 	if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1103 		int group_cipher = 0, pairwise_cipher = 0;
1104 
1105 		wpa_ie = elems.rsn_ie;
1106 		wpa_ie_len = elems.rsn_ie_len;
1107 
1108 		if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1109 			pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1110 			pstat->wpa_psk |= BIT(1);
1111 
1112 			pstat->wpa2_group_cipher = group_cipher & psecuritypriv->wpa2_group_cipher;
1113 			pstat->wpa2_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa2_pairwise_cipher;
1114 
1115 			if (!pstat->wpa2_group_cipher)
1116 				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1117 
1118 			if (!pstat->wpa2_pairwise_cipher)
1119 				status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1120 		} else {
1121 			status = WLAN_STATUS_INVALID_IE;
1122 		}
1123 	} else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1124 		int group_cipher = 0, pairwise_cipher = 0;
1125 
1126 		wpa_ie = elems.wpa_ie;
1127 		wpa_ie_len = elems.wpa_ie_len;
1128 
1129 		if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1130 			pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1131 			pstat->wpa_psk |= BIT(0);
1132 
1133 			pstat->wpa_group_cipher = group_cipher & psecuritypriv->wpa_group_cipher;
1134 			pstat->wpa_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa_pairwise_cipher;
1135 
1136 			if (!pstat->wpa_group_cipher)
1137 				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1138 
1139 			if (!pstat->wpa_pairwise_cipher)
1140 				status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1141 		} else {
1142 			status = WLAN_STATUS_INVALID_IE;
1143 		}
1144 	} else {
1145 		wpa_ie = NULL;
1146 		wpa_ie_len = 0;
1147 	}
1148 
1149 	if (status != _STATS_SUCCESSFUL_)
1150 		goto OnAssocReqFail;
1151 
1152 	pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1153 	if (!wpa_ie) {
1154 		if (elems.wps_ie)
1155 			pstat->flags |= WLAN_STA_WPS;
1156 			/* wpabuf_free(sta->wps_ie); */
1157 			/* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
1158 			/*				elems.wps_ie_len - 4); */
1159 		else
1160 			pstat->flags |= WLAN_STA_MAYBE_WPS;
1161 
1162 		/*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1163 		/*  that the selected registrar of AP is _FLASE */
1164 		if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
1165 			if (pmlmepriv->wps_beacon_ie) {
1166 				u8 selected_registrar = 0;
1167 
1168 				rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
1169 
1170 				if (!selected_registrar) {
1171 
1172 					status = _STATS_UNABLE_HANDLE_STA_;
1173 
1174 					goto OnAssocReqFail;
1175 				}
1176 			}
1177 		}
1178 	} else {
1179 		int copy_len;
1180 
1181 		if (psecuritypriv->wpa_psk == 0) {
1182 
1183 			status = WLAN_STATUS_INVALID_IE;
1184 
1185 			goto OnAssocReqFail;
1186 		}
1187 
1188 		if (elems.wps_ie) {
1189 			pstat->flags |= WLAN_STA_WPS;
1190 			copy_len = 0;
1191 		} else {
1192 			copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)) : (wpa_ie_len + 2);
1193 		}
1194 		if (copy_len > 0)
1195 			memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
1196 	}
1197 	/*  check if there is WMM IE & support WWM-PS */
1198 	pstat->flags &= ~WLAN_STA_WME;
1199 	pstat->qos_option = 0;
1200 	pstat->qos_info = 0;
1201 	pstat->has_legacy_ac = true;
1202 	pstat->uapsd_vo = 0;
1203 	pstat->uapsd_vi = 0;
1204 	pstat->uapsd_be = 0;
1205 	pstat->uapsd_bk = 0;
1206 	if (pmlmepriv->qospriv.qos_option) {
1207 		p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
1208 		for (;;) {
1209 			p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1210 			if (p) {
1211 				if (!memcmp(p + 2, WMM_IE, 6)) {
1212 					pstat->flags |= WLAN_STA_WME;
1213 
1214 					pstat->qos_option = 1;
1215 					pstat->qos_info = *(p + 8);
1216 
1217 					pstat->max_sp_len = (pstat->qos_info >> 5) & 0x3;
1218 
1219 					if ((pstat->qos_info & 0xf) != 0xf)
1220 						pstat->has_legacy_ac = true;
1221 					else
1222 						pstat->has_legacy_ac = false;
1223 
1224 					if (pstat->qos_info & 0xf) {
1225 						if (pstat->qos_info & BIT(0))
1226 							pstat->uapsd_vo = BIT(0) | BIT(1);
1227 						else
1228 							pstat->uapsd_vo = 0;
1229 
1230 						if (pstat->qos_info & BIT(1))
1231 							pstat->uapsd_vi = BIT(0) | BIT(1);
1232 						else
1233 							pstat->uapsd_vi = 0;
1234 
1235 						if (pstat->qos_info & BIT(2))
1236 							pstat->uapsd_bk = BIT(0) | BIT(1);
1237 						else
1238 							pstat->uapsd_bk = 0;
1239 
1240 						if (pstat->qos_info & BIT(3))
1241 							pstat->uapsd_be = BIT(0) | BIT(1);
1242 						else
1243 							pstat->uapsd_be = 0;
1244 					}
1245 					break;
1246 				}
1247 			} else {
1248 				break;
1249 			}
1250 			p = p + ie_len + 2;
1251 		}
1252 	}
1253 
1254 	/* save HT capabilities in the sta object */
1255 	memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1256 	if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) {
1257 		pstat->flags |= WLAN_STA_HT;
1258 
1259 		pstat->flags |= WLAN_STA_WME;
1260 
1261 		memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
1262 	} else {
1263 		pstat->flags &= ~WLAN_STA_HT;
1264 	}
1265 	if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags & WLAN_STA_HT)) {
1266 		status = _STATS_FAILURE_;
1267 		goto OnAssocReqFail;
1268 	}
1269 
1270 	pstat->flags |= WLAN_STA_NONERP;
1271 	for (i = 0; i < pstat->bssratelen; i++) {
1272 		if ((pstat->bssrateset[i] & 0x7f) > 22) {
1273 			pstat->flags &= ~WLAN_STA_NONERP;
1274 			break;
1275 		}
1276 	}
1277 
1278 	if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1279 		pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1280 	else
1281 		pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1282 
1283 	if (status != _STATS_SUCCESSFUL_)
1284 		goto OnAssocReqFail;
1285 
1286 	pstat->is_p2p_device = false;
1287 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1288 		p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset, NULL, &p2pielen);
1289 		if (p2pie) {
1290 			pstat->is_p2p_device = true;
1291 			p2p_status_code = (u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat);
1292 			if (p2p_status_code > 0) {
1293 				pstat->p2p_status_code = p2p_status_code;
1294 				status = _STATS_CAP_FAIL_;
1295 				goto OnAssocReqFail;
1296 			}
1297 		}
1298 	}
1299 	pstat->p2p_status_code = p2p_status_code;
1300 
1301 	/* TODO: identify_proprietary_vendor_ie(); */
1302 	/*  Realtek proprietary IE */
1303 	/*  identify if this is Broadcom sta */
1304 	/*  identify if this is ralink sta */
1305 	/*  Customer proprietary IE */
1306 
1307 	/* get a unique AID */
1308 	if (pstat->aid == 0) {
1309 		for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1310 			if (!pstapriv->sta_aid[pstat->aid - 1])
1311 				break;
1312 
1313 		/* if (pstat->aid > NUM_STA) { */
1314 		if (pstat->aid > pstapriv->max_num_sta) {
1315 			pstat->aid = 0;
1316 
1317 			status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1318 
1319 			goto OnAssocReqFail;
1320 		} else {
1321 			pstapriv->sta_aid[pstat->aid - 1] = pstat;
1322 		}
1323 	}
1324 
1325 	pstat->state &= (~WIFI_FW_ASSOC_STATE);
1326 	pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1327 
1328 	spin_lock_bh(&pstapriv->auth_list_lock);
1329 	if (!list_empty(&pstat->auth_list)) {
1330 		list_del_init(&pstat->auth_list);
1331 		pstapriv->auth_list_cnt--;
1332 	}
1333 	spin_unlock_bh(&pstapriv->auth_list_lock);
1334 
1335 	spin_lock_bh(&pstapriv->asoc_list_lock);
1336 	if (list_empty(&pstat->asoc_list)) {
1337 		pstat->expire_to = pstapriv->expire_to;
1338 		list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1339 		pstapriv->asoc_list_cnt++;
1340 	}
1341 	spin_unlock_bh(&pstapriv->asoc_list_lock);
1342 
1343 	/*  now the station is qualified to join our BSS... */
1344 	if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (status == _STATS_SUCCESSFUL_)) {
1345 		/* 1 bss_cap_update & sta_info_update */
1346 		bss_cap_update_on_sta_join(padapter, pstat);
1347 		sta_info_update(padapter, pstat);
1348 
1349 		/* issue assoc rsp before notify station join event. */
1350 		if (frame_type == WIFI_ASSOCREQ)
1351 			issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1352 		else
1353 			issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1354 
1355 		/* 2 - report to upper layer */
1356 		rtw_indicate_sta_assoc_event(padapter, pstat);
1357 
1358 		/* 3-(1) report sta add event */
1359 		report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
1360 	}
1361 
1362 	return _SUCCESS;
1363 
1364 asoc_class2_error:
1365 
1366 	issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1367 
1368 	return _FAIL;
1369 
1370 OnAssocReqFail:
1371 
1372 	pstat->aid = 0;
1373 	if (frame_type == WIFI_ASSOCREQ)
1374 		issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1375 	else
1376 		issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1377 
1378 	return _FAIL;
1379 }
1380 
OnAssocRsp(struct adapter * padapter,struct recv_frame * precv_frame)1381 unsigned int OnAssocRsp(struct adapter *padapter, struct recv_frame *precv_frame)
1382 {
1383 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data;
1384 	uint i;
1385 	int res;
1386 	struct ndis_802_11_var_ie *pIE;
1387 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
1388 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
1389 	/* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */
1390 	u8 *pframe = precv_frame->rx_data;
1391 	uint pkt_len = precv_frame->len;
1392 
1393 	/* check A1 matches or not */
1394 	if (memcmp(myid(&padapter->eeprompriv), mgmt->da, ETH_ALEN))
1395 		return _SUCCESS;
1396 
1397 	if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1398 		return _SUCCESS;
1399 
1400 	if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1401 		return _SUCCESS;
1402 
1403 	_cancel_timer_ex(&pmlmeext->link_timer);
1404 
1405 	if (le16_to_cpu(mgmt->u.assoc_resp.status_code) > 0) {
1406 		pmlmeinfo->state = WIFI_FW_NULL_STATE;
1407 		res = -4;
1408 		goto report_assoc_result;
1409 	}
1410 
1411 	pmlmeinfo->capability = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
1412 
1413 	/* set slot time */
1414 	pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
1415 
1416 	pmlmeinfo->aid = le16_to_cpu(mgmt->u.assoc_resp.aid) & 0x3fff;
1417 	res = pmlmeinfo->aid;
1418 
1419 	/* following are moved to join event callback function */
1420 	/* to handle HT, WMM, rate adaptive, update MAC reg */
1421 	/* for not to handle the synchronous IO in the tasklet */
1422 	for (i = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); i < pkt_len;) {
1423 		pIE = (struct ndis_802_11_var_ie *)(pframe + i);
1424 
1425 		switch (pIE->ElementID) {
1426 		case _VENDOR_SPECIFIC_IE_:
1427 			if (!memcmp(pIE->data, WMM_PARA_OUI, 6))	/* WMM */
1428 				WMM_param_handler(padapter, pIE);
1429 			break;
1430 		case _HT_CAPABILITY_IE_:	/* HT caps */
1431 			HT_caps_handler(padapter, pIE);
1432 			break;
1433 		case _HT_EXTRA_INFO_IE_:	/* HT info */
1434 			HT_info_handler(padapter, pIE);
1435 			break;
1436 		case _ERPINFO_IE_:
1437 			ERP_IE_handler(padapter, pIE);
1438 			break;
1439 		default:
1440 			break;
1441 		}
1442 
1443 		i += (pIE->Length + 2);
1444 	}
1445 
1446 	pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1447 	pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1448 
1449 	/* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1450 	UpdateBrateTbl(pmlmeinfo->network.SupportedRates);
1451 
1452 report_assoc_result:
1453 	report_join_res(padapter, res);
1454 
1455 	return _SUCCESS;
1456 }
1457 
OnDeAuth(struct adapter * padapter,struct recv_frame * precv_frame)1458 unsigned int OnDeAuth(struct adapter *padapter, struct recv_frame *precv_frame)
1459 {
1460 	unsigned short	reason;
1461 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1462 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
1463 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
1464 	u8 *pframe = precv_frame->rx_data;
1465 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1466 
1467 	/* check A3 */
1468 	if (!(!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
1469 		return _SUCCESS;
1470 
1471 	if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
1472 		_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
1473 		_set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
1474 	}
1475 
1476 	reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1477 
1478 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1479 		struct sta_info *psta;
1480 		struct sta_priv *pstapriv = &padapter->stapriv;
1481 
1482 		psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1483 		if (psta) {
1484 			u8 updated = 0;
1485 
1486 			spin_lock_bh(&pstapriv->asoc_list_lock);
1487 			if (!list_empty(&psta->asoc_list)) {
1488 				list_del_init(&psta->asoc_list);
1489 				pstapriv->asoc_list_cnt--;
1490 				updated = ap_free_sta(padapter, psta, false, reason);
1491 			}
1492 			spin_unlock_bh(&pstapriv->asoc_list_lock);
1493 
1494 			associated_clients_update(padapter, updated);
1495 		}
1496 
1497 		return _SUCCESS;
1498 	} else {
1499 		int	ignore_received_deauth = 0;
1500 
1501 		/* Before sending the auth frame to start the STA/GC mode connection with AP/GO,
1502 		 *	we will send the deauth first.
1503 		 *	However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth.
1504 		 *	Added the following code to avoid this case.
1505 		 */
1506 		if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||
1507 		    (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {
1508 			if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) {
1509 				ignore_received_deauth = 1;
1510 			} else if (reason == WLAN_REASON_PREV_AUTH_NOT_VALID) {
1511 				// TODO: 802.11r
1512 				ignore_received_deauth = 1;
1513 			}
1514 		}
1515 
1516 		if (!ignore_received_deauth)
1517 			receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1518 	}
1519 	pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1520 	return _SUCCESS;
1521 }
1522 
OnDisassoc(struct adapter * padapter,struct recv_frame * precv_frame)1523 unsigned int OnDisassoc(struct adapter *padapter, struct recv_frame *precv_frame)
1524 {
1525 	u16 reason;
1526 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1527 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
1528 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
1529 	u8 *pframe = precv_frame->rx_data;
1530 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1531 
1532 	/* check A3 */
1533 	if (!(!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
1534 		return _SUCCESS;
1535 
1536 	if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
1537 		_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
1538 		_set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
1539 	}
1540 
1541 	reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1542 
1543 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1544 		struct sta_info *psta;
1545 		struct sta_priv *pstapriv = &padapter->stapriv;
1546 
1547 		psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1548 		if (psta) {
1549 			u8 updated = 0;
1550 
1551 			spin_lock_bh(&pstapriv->asoc_list_lock);
1552 			if (!list_empty(&psta->asoc_list)) {
1553 				list_del_init(&psta->asoc_list);
1554 				pstapriv->asoc_list_cnt--;
1555 				updated = ap_free_sta(padapter, psta, false, reason);
1556 			}
1557 			spin_unlock_bh(&pstapriv->asoc_list_lock);
1558 
1559 			associated_clients_update(padapter, updated);
1560 		}
1561 
1562 		return _SUCCESS;
1563 	} else {
1564 		receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1565 	}
1566 	pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1567 	return _SUCCESS;
1568 }
1569 
OnAction_back(struct adapter * padapter,struct recv_frame * precv_frame)1570 unsigned int OnAction_back(struct adapter *padapter, struct recv_frame *precv_frame)
1571 {
1572 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data;
1573 	struct sta_info *psta = NULL;
1574 	struct recv_reorder_ctrl *preorder_ctrl;
1575 	unsigned char		*frame_body;
1576 	unsigned short	tid;
1577 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
1578 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
1579 	u8 *pframe = precv_frame->rx_data;
1580 	struct sta_priv *pstapriv = &padapter->stapriv;
1581 	/* check RA matches or not */
1582 	if (memcmp(myid(&padapter->eeprompriv), mgmt->da, ETH_ALEN))/* for if1, sta/ap mode */
1583 		return _SUCCESS;
1584 
1585 	if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
1586 		if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1587 			return _SUCCESS;
1588 
1589 	psta = rtw_get_stainfo(pstapriv, mgmt->sa);
1590 
1591 	if (!psta)
1592 		return _SUCCESS;
1593 
1594 	frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1595 
1596 	if (!pmlmeinfo->HT_enable)
1597 		return _SUCCESS;
1598 	/* All union members start with an action code, it's ok to use addba_req. */
1599 	switch (mgmt->u.action.u.addba_req.action_code) {
1600 	case WLAN_ACTION_ADDBA_REQ:
1601 		memcpy(&pmlmeinfo->ADDBA_req, &frame_body[2], sizeof(struct ADDBA_request));
1602 		tid = u16_get_bits(le16_to_cpu(mgmt->u.action.u.addba_req.capab),
1603 				   IEEE80211_ADDBA_PARAM_TID_MASK);
1604 		preorder_ctrl = &psta->recvreorder_ctrl[tid];
1605 		preorder_ctrl->indicate_seq = 0xffff;
1606 		preorder_ctrl->enable = pmlmeinfo->bAcceptAddbaReq;
1607 
1608 		issue_action_BA(padapter, mgmt->sa, WLAN_ACTION_ADDBA_RESP,
1609 				pmlmeinfo->bAcceptAddbaReq ?
1610 					WLAN_STATUS_SUCCESS : WLAN_STATUS_REQUEST_DECLINED);
1611 		break;
1612 	case WLAN_ACTION_ADDBA_RESP:
1613 		tid = u16_get_bits(le16_to_cpu(mgmt->u.action.u.addba_resp.capab),
1614 				   IEEE80211_ADDBA_PARAM_TID_MASK);
1615 		if (mgmt->u.action.u.addba_resp.status == 0) {	/* successful */
1616 			psta->htpriv.agg_enable_bitmap |= BIT(tid);
1617 			psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1618 		} else {
1619 			psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1620 		}
1621 		break;
1622 	case WLAN_ACTION_DELBA:
1623 		tid = u16_get_bits(le16_to_cpu(mgmt->u.action.u.delba.params),
1624 				   IEEE80211_DELBA_PARAM_TID_MASK);
1625 		if (u16_get_bits(le16_to_cpu(mgmt->u.action.u.delba.params),
1626 				 IEEE80211_DELBA_PARAM_INITIATOR_MASK) == WLAN_BACK_RECIPIENT) {
1627 			psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1628 			psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1629 		} else {
1630 			preorder_ctrl =  &psta->recvreorder_ctrl[tid];
1631 			preorder_ctrl->enable = false;
1632 			preorder_ctrl->indicate_seq = 0xffff;
1633 		}
1634 		/* todo: how to notify the host while receiving DELETE BA */
1635 		break;
1636 	default:
1637 		break;
1638 	}
1639 
1640 	return _SUCCESS;
1641 }
1642 
get_reg_classes_full_count(struct p2p_channels * channel_list)1643 static int get_reg_classes_full_count(struct p2p_channels *channel_list)
1644 {
1645 	int cnt = 0;
1646 	int i;
1647 
1648 	for (i = 0; i < channel_list->reg_classes; i++) {
1649 		cnt += channel_list->reg_class[i].channels;
1650 	}
1651 
1652 	return cnt;
1653 }
1654 
issue_p2p_GO_request(struct adapter * padapter,u8 * raddr)1655 void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr)
1656 {
1657 	unsigned char category = WLAN_CATEGORY_PUBLIC;
1658 	u8 action = P2P_PUB_ACTION_ACTION;
1659 	__be32 p2poui = cpu_to_be32(P2POUI);
1660 	u8 oui_subtype = P2P_GO_NEGO_REQ;
1661 	u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
1662 	u8 wpsielen = 0, p2pielen = 0;
1663 	u16 len_channellist_attr = 0;
1664 	struct xmit_frame *pmgntframe;
1665 	struct pkt_attrib *pattrib;
1666 	unsigned char *pframe;
1667 	struct ieee80211_hdr *pwlanhdr;
1668 	__le16 *fctrl;
1669 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1670 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
1671 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
1672 
1673 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1674 	if (!pmgntframe)
1675 		return;
1676 
1677 	/* update attribute */
1678 	pattrib = &pmgntframe->attrib;
1679 	update_mgntframe_attrib(padapter, pattrib);
1680 
1681 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1682 
1683 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1684 	pwlanhdr = (struct ieee80211_hdr *)pframe;
1685 
1686 	fctrl = &pwlanhdr->frame_control;
1687 	*(fctrl) = 0;
1688 
1689 	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
1690 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
1691 	memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
1692 
1693 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1694 	pmlmeext->mgnt_seq++;
1695 	SetFrameSubType(pframe, WIFI_ACTION);
1696 
1697 	pframe += sizeof(struct ieee80211_hdr_3addr);
1698 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
1699 
1700 	pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
1701 	pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
1702 	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
1703 	pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
1704 	pwdinfo->negotiation_dialog_token = 1;	/*	Initialize the dialog value */
1705 	pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen);
1706 
1707 	/*	WPS Section */
1708 	wpsielen = 0;
1709 	/*	WPS OUI */
1710 	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
1711 	wpsielen += 4;
1712 
1713 	/*	WPS version */
1714 	/*	Type: */
1715 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
1716 	wpsielen += 2;
1717 
1718 	/*	Length: */
1719 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
1720 	wpsielen += 2;
1721 
1722 	/*	Value: */
1723 	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
1724 
1725 	/*	Device Password ID */
1726 	/*	Type: */
1727 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
1728 	wpsielen += 2;
1729 
1730 	/*	Length: */
1731 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
1732 	wpsielen += 2;
1733 
1734 	/*	Value: */
1735 
1736 	if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)
1737 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
1738 	else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)
1739 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
1740 	else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
1741 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
1742 
1743 	wpsielen += 2;
1744 
1745 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
1746 
1747 	/*	P2P IE Section. */
1748 
1749 	/*	P2P OUI */
1750 	p2pielen = 0;
1751 	p2pie[p2pielen++] = 0x50;
1752 	p2pie[p2pielen++] = 0x6F;
1753 	p2pie[p2pielen++] = 0x9A;
1754 	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
1755 
1756 	/*	Commented by Albert 20110306 */
1757 	/*	According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
1758 	/*	1. P2P Capability */
1759 	/*	2. Group Owner Intent */
1760 	/*	3. Configuration Timeout */
1761 	/*	4. Listen Channel */
1762 	/*	5. Extended Listen Timing */
1763 	/*	6. Intended P2P Interface Address */
1764 	/*	7. Channel List */
1765 	/*	8. P2P Device Info */
1766 	/*	9. Operating Channel */
1767 
1768 	/*	P2P Capability */
1769 	/*	Type: */
1770 	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
1771 
1772 	/*	Length: */
1773 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
1774 	p2pielen += 2;
1775 
1776 	/*	Value: */
1777 	/*	Device Capability Bitmap, 1 byte */
1778 	p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
1779 
1780 	/*	Group Capability Bitmap, 1 byte */
1781 	if (pwdinfo->persistent_supported)
1782 		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
1783 	else
1784 		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
1785 
1786 	/*	Group Owner Intent */
1787 	/*	Type: */
1788 	p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
1789 
1790 	/*	Length: */
1791 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
1792 	p2pielen += 2;
1793 
1794 	/*	Value: */
1795 	/*	Todo the tie breaker bit. */
1796 	p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
1797 
1798 	/*	Configuration Timeout */
1799 	/*	Type: */
1800 	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
1801 
1802 	/*	Length: */
1803 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
1804 	p2pielen += 2;
1805 
1806 	/*	Value: */
1807 	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P GO */
1808 	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P Client */
1809 
1810 	/*	Listen Channel */
1811 	/*	Type: */
1812 	p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
1813 
1814 	/*	Length: */
1815 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
1816 	p2pielen += 2;
1817 
1818 	/*	Value: */
1819 	/*	Country String */
1820 	p2pie[p2pielen++] = 'X';
1821 	p2pie[p2pielen++] = 'X';
1822 
1823 	/*	The third byte should be set to 0x04. */
1824 	/*	Described in the "Operating Channel Attribute" section. */
1825 	p2pie[p2pielen++] = 0x04;
1826 
1827 	/*	Operating Class */
1828 	p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
1829 
1830 	/*	Channel Number */
1831 	p2pie[p2pielen++] = pwdinfo->listen_channel;	/*	listening channel number */
1832 
1833 	/*	Extended Listen Timing ATTR */
1834 	/*	Type: */
1835 	p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
1836 
1837 	/*	Length: */
1838 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
1839 	p2pielen += 2;
1840 
1841 	/*	Value: */
1842 	/*	Availability Period */
1843 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
1844 	p2pielen += 2;
1845 
1846 	/*	Availability Interval */
1847 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
1848 	p2pielen += 2;
1849 
1850 	/*	Intended P2P Interface Address */
1851 	/*	Type: */
1852 	p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
1853 
1854 	/*	Length: */
1855 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
1856 	p2pielen += 2;
1857 
1858 	/*	Value: */
1859 	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
1860 	p2pielen += ETH_ALEN;
1861 
1862 	/*	Channel List */
1863 	/*	Type: */
1864 	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
1865 
1866 	/*  Length: */
1867 	/*  Country String(3) */
1868 	/*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
1869 	/*  + number of channels in all classes */
1870 	len_channellist_attr = 3
1871 	   + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
1872 	   + get_reg_classes_full_count(&pmlmeext->channel_list);
1873 
1874 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
1875 	p2pielen += 2;
1876 
1877 	/*	Value: */
1878 	/*	Country String */
1879 	p2pie[p2pielen++] = 'X';
1880 	p2pie[p2pielen++] = 'X';
1881 
1882 	/*	The third byte should be set to 0x04. */
1883 	/*	Described in the "Operating Channel Attribute" section. */
1884 	p2pie[p2pielen++] = 0x04;
1885 
1886 	/*	Channel Entry List */
1887 
1888 	{
1889 		int i, j;
1890 		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
1891 			/*	Operating Class */
1892 			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
1893 
1894 			/*	Number of Channels */
1895 			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
1896 
1897 			/*	Channel List */
1898 			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
1899 				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
1900 			}
1901 		}
1902 	}
1903 
1904 	/*	Device Info */
1905 	/*	Type: */
1906 	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
1907 
1908 	/*	Length: */
1909 	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
1910 	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
1911 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
1912 	p2pielen += 2;
1913 
1914 	/*	Value: */
1915 	/*	P2P Device Address */
1916 	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
1917 	p2pielen += ETH_ALEN;
1918 
1919 	/*	Config Method */
1920 	/*	This field should be big endian. Noted by P2P specification. */
1921 
1922 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
1923 
1924 	p2pielen += 2;
1925 
1926 	/*	Primary Device Type */
1927 	/*	Category ID */
1928 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
1929 	p2pielen += 2;
1930 
1931 	/*	OUI */
1932 	*(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
1933 	p2pielen += 4;
1934 
1935 	/*	Sub Category ID */
1936 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
1937 	p2pielen += 2;
1938 
1939 	/*	Number of Secondary Device Types */
1940 	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
1941 
1942 	/*	Device Name */
1943 	/*	Type: */
1944 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
1945 	p2pielen += 2;
1946 
1947 	/*	Length: */
1948 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
1949 	p2pielen += 2;
1950 
1951 	/*	Value: */
1952 	memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
1953 	p2pielen += pwdinfo->device_name_len;
1954 
1955 	/*	Operating Channel */
1956 	/*	Type: */
1957 	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
1958 
1959 	/*	Length: */
1960 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
1961 	p2pielen += 2;
1962 
1963 	/*	Value: */
1964 	/*	Country String */
1965 	p2pie[p2pielen++] = 'X';
1966 	p2pie[p2pielen++] = 'X';
1967 
1968 	/*	The third byte should be set to 0x04. */
1969 	/*	Described in the "Operating Channel Attribute" section. */
1970 	p2pie[p2pielen++] = 0x04;
1971 
1972 	/*	Operating Class */
1973 	p2pie[p2pielen++] = 0x51;
1974 
1975 	/*	Channel Number */
1976 	p2pie[p2pielen++] = pwdinfo->operating_channel;	/*	operating channel number */
1977 
1978 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
1979 
1980 	pattrib->last_txcmdsz = pattrib->pktlen;
1981 
1982 	dump_mgntframe(padapter, pmgntframe);
1983 }
1984 
issue_p2p_GO_response(struct adapter * padapter,u8 * raddr,u8 * frame_body,uint len,u8 result)1985 static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame_body, uint len, u8 result)
1986 {
1987 	unsigned char category = WLAN_CATEGORY_PUBLIC;
1988 	u8 action = P2P_PUB_ACTION_ACTION;
1989 	__be32			p2poui = cpu_to_be32(P2POUI);
1990 	u8 oui_subtype = P2P_GO_NEGO_RESP;
1991 	u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
1992 	u8 p2pielen = 0;
1993 	uint			wpsielen = 0;
1994 	u16 wps_devicepassword_id = 0x0000;
1995 	__be16			be_tmp;
1996 	uint			wps_devicepassword_id_len = 0;
1997 	u16 len_channellist_attr = 0;
1998 
1999 	struct xmit_frame			*pmgntframe;
2000 	struct pkt_attrib			*pattrib;
2001 	unsigned char					*pframe;
2002 	struct ieee80211_hdr *pwlanhdr;
2003 	__le16 *fctrl;
2004 	struct xmit_priv			*pxmitpriv = &padapter->xmitpriv;
2005 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
2006 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
2007 
2008 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2009 	if (!pmgntframe)
2010 		return;
2011 
2012 	/* update attribute */
2013 	pattrib = &pmgntframe->attrib;
2014 	update_mgntframe_attrib(padapter, pattrib);
2015 
2016 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2017 
2018 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2019 	pwlanhdr = (struct ieee80211_hdr *)pframe;
2020 
2021 	fctrl = &pwlanhdr->frame_control;
2022 	*(fctrl) = 0;
2023 
2024 	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2025 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2026 	memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
2027 
2028 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2029 	pmlmeext->mgnt_seq++;
2030 	SetFrameSubType(pframe, WIFI_ACTION);
2031 
2032 	pframe += sizeof(struct ieee80211_hdr_3addr);
2033 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2034 
2035 	pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
2036 	pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
2037 	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
2038 	pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
2039 	pwdinfo->negotiation_dialog_token = frame_body[7];	/*	The Dialog Token of provisioning discovery request frame. */
2040 	pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen);
2041 
2042 	/*	Commented by Albert 20110328 */
2043 	/*	Try to get the device password ID from the WPS IE of group negotiation request frame */
2044 	/*	WiFi Direct test plan 5.1.15 */
2045 	rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
2046 	rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
2047 	wps_devicepassword_id = be16_to_cpu(be_tmp);
2048 
2049 	memset(wpsie, 0x00, 255);
2050 	wpsielen = 0;
2051 
2052 	/*	WPS Section */
2053 	wpsielen = 0;
2054 	/*	WPS OUI */
2055 	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
2056 	wpsielen += 4;
2057 
2058 	/*	WPS version */
2059 	/*	Type: */
2060 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
2061 	wpsielen += 2;
2062 
2063 	/*	Length: */
2064 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
2065 	wpsielen += 2;
2066 
2067 	/*	Value: */
2068 	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
2069 
2070 	/*	Device Password ID */
2071 	/*	Type: */
2072 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
2073 	wpsielen += 2;
2074 
2075 	/*	Length: */
2076 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
2077 	wpsielen += 2;
2078 
2079 	/*	Value: */
2080 	if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2081 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
2082 	else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2083 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
2084 	else
2085 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
2086 	wpsielen += 2;
2087 
2088 	/*	Commented by Kurt 20120113 */
2089 	/*	If some device wants to do p2p handshake without sending prov_disc_req */
2090 	/*	We have to get peer_req_cm from here. */
2091 	if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
2092 		if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2093 			memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2094 		else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2095 			memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2096 		else
2097 			memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2098 	}
2099 
2100 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
2101 
2102 	/*	P2P IE Section. */
2103 
2104 	/*	P2P OUI */
2105 	p2pielen = 0;
2106 	p2pie[p2pielen++] = 0x50;
2107 	p2pie[p2pielen++] = 0x6F;
2108 	p2pie[p2pielen++] = 0x9A;
2109 	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
2110 
2111 	/*	Commented by Albert 20100908 */
2112 	/*	According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */
2113 	/*	1. Status */
2114 	/*	2. P2P Capability */
2115 	/*	3. Group Owner Intent */
2116 	/*	4. Configuration Timeout */
2117 	/*	5. Operating Channel */
2118 	/*	6. Intended P2P Interface Address */
2119 	/*	7. Channel List */
2120 	/*	8. Device Info */
2121 	/*	9. Group ID	(Only GO) */
2122 
2123 	/*	ToDo: */
2124 
2125 	/*	P2P Status */
2126 	/*	Type: */
2127 	p2pie[p2pielen++] = P2P_ATTR_STATUS;
2128 
2129 	/*	Length: */
2130 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2131 	p2pielen += 2;
2132 
2133 	/*	Value: */
2134 	p2pie[p2pielen++] = result;
2135 
2136 	/*	P2P Capability */
2137 	/*	Type: */
2138 	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2139 
2140 	/*	Length: */
2141 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2142 	p2pielen += 2;
2143 
2144 	/*	Value: */
2145 	/*	Device Capability Bitmap, 1 byte */
2146 
2147 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2148 		/*	Commented by Albert 2011/03/08 */
2149 		/*	According to the P2P specification */
2150 		/*	if the sending device will be client, the P2P Capability should be reserved of group negotiation response frame */
2151 		p2pie[p2pielen++] = 0;
2152 	} else {
2153 		/*	Be group owner or meet the error case */
2154 		p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2155 	}
2156 
2157 	/*	Group Capability Bitmap, 1 byte */
2158 	if (pwdinfo->persistent_supported) {
2159 		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2160 	} else {
2161 		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2162 	}
2163 
2164 	/*	Group Owner Intent */
2165 	/*	Type: */
2166 	p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
2167 
2168 	/*	Length: */
2169 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2170 	p2pielen += 2;
2171 
2172 	/*	Value: */
2173 	if (pwdinfo->peer_intent & 0x01) {
2174 		/*	Peer's tie breaker bit is 1, our tie breaker bit should be 0 */
2175 		p2pie[p2pielen++] = (pwdinfo->intent << 1);
2176 	} else {
2177 		/*	Peer's tie breaker bit is 0, our tie breaker bit should be 1 */
2178 		p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
2179 	}
2180 
2181 	/*	Configuration Timeout */
2182 	/*	Type: */
2183 	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2184 
2185 	/*	Length: */
2186 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2187 	p2pielen += 2;
2188 
2189 	/*	Value: */
2190 	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P GO */
2191 	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P Client */
2192 
2193 	/*	Operating Channel */
2194 	/*	Type: */
2195 	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2196 
2197 	/*	Length: */
2198 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2199 	p2pielen += 2;
2200 
2201 	/*	Value: */
2202 	/*	Country String */
2203 	p2pie[p2pielen++] = 'X';
2204 	p2pie[p2pielen++] = 'X';
2205 
2206 	/*	The third byte should be set to 0x04. */
2207 	/*	Described in the "Operating Channel Attribute" section. */
2208 	p2pie[p2pielen++] = 0x04;
2209 
2210 	/*	Operating Class */
2211 	p2pie[p2pielen++] = 0x51;
2212 
2213 	/*	Channel Number */
2214 	p2pie[p2pielen++] = pwdinfo->operating_channel;	/*	operating channel number */
2215 
2216 	/*	Intended P2P Interface Address */
2217 	/*	Type: */
2218 	p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
2219 
2220 	/*	Length: */
2221 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2222 	p2pielen += 2;
2223 
2224 	/*	Value: */
2225 	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2226 	p2pielen += ETH_ALEN;
2227 
2228 	/*	Channel List */
2229 	/*	Type: */
2230 	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2231 
2232 	/*  Country String(3) */
2233 	/*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2234 	/*  + number of channels in all classes */
2235 	len_channellist_attr = 3
2236 	   + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
2237 	   + get_reg_classes_full_count(&pmlmeext->channel_list);
2238 
2239 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2240 
2241 	p2pielen += 2;
2242 
2243 	/*	Value: */
2244 	/*	Country String */
2245 	p2pie[p2pielen++] = 'X';
2246 	p2pie[p2pielen++] = 'X';
2247 
2248 	/*	The third byte should be set to 0x04. */
2249 	/*	Described in the "Operating Channel Attribute" section. */
2250 	p2pie[p2pielen++] = 0x04;
2251 
2252 	/*	Channel Entry List */
2253 
2254 	{
2255 		int i, j;
2256 		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2257 			/*	Operating Class */
2258 			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2259 
2260 			/*	Number of Channels */
2261 			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2262 
2263 			/*	Channel List */
2264 			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2265 				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2266 			}
2267 		}
2268 	}
2269 
2270 	/*	Device Info */
2271 	/*	Type: */
2272 	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2273 
2274 	/*	Length: */
2275 	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2276 	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2277 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2278 	p2pielen += 2;
2279 
2280 	/*	Value: */
2281 	/*	P2P Device Address */
2282 	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2283 	p2pielen += ETH_ALEN;
2284 
2285 	/*	Config Method */
2286 	/*	This field should be big endian. Noted by P2P specification. */
2287 
2288 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
2289 
2290 	p2pielen += 2;
2291 
2292 	/*	Primary Device Type */
2293 	/*	Category ID */
2294 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2295 	p2pielen += 2;
2296 
2297 	/*	OUI */
2298 	*(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2299 	p2pielen += 4;
2300 
2301 	/*	Sub Category ID */
2302 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2303 	p2pielen += 2;
2304 
2305 	/*	Number of Secondary Device Types */
2306 	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
2307 
2308 	/*	Device Name */
2309 	/*	Type: */
2310 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2311 	p2pielen += 2;
2312 
2313 	/*	Length: */
2314 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2315 	p2pielen += 2;
2316 
2317 	/*	Value: */
2318 	memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2319 	p2pielen += pwdinfo->device_name_len;
2320 
2321 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2322 		/*	Group ID Attribute */
2323 		/*	Type: */
2324 		p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2325 
2326 		/*	Length: */
2327 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
2328 		p2pielen += 2;
2329 
2330 		/*	Value: */
2331 		/*	p2P Device Address */
2332 		memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
2333 		p2pielen += ETH_ALEN;
2334 
2335 		/*	SSID */
2336 		memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2337 		p2pielen += pwdinfo->nego_ssidlen;
2338 	}
2339 
2340 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2341 
2342 	pattrib->last_txcmdsz = pattrib->pktlen;
2343 
2344 	dump_mgntframe(padapter, pmgntframe);
2345 }
2346 
issue_p2p_GO_confirm(struct adapter * padapter,u8 * raddr,u8 result)2347 static void issue_p2p_GO_confirm(struct adapter *padapter, u8 *raddr, u8 result)
2348 {
2349 	unsigned char category = WLAN_CATEGORY_PUBLIC;
2350 	u8 action = P2P_PUB_ACTION_ACTION;
2351 	__be32			p2poui = cpu_to_be32(P2POUI);
2352 	u8 oui_subtype = P2P_GO_NEGO_CONF;
2353 	u8 p2pie[255] = { 0x00 };
2354 	u8 p2pielen = 0;
2355 
2356 	struct xmit_frame			*pmgntframe;
2357 	struct pkt_attrib			*pattrib;
2358 	unsigned char					*pframe;
2359 	struct ieee80211_hdr *pwlanhdr;
2360 	__le16 *fctrl;
2361 	struct xmit_priv			*pxmitpriv = &padapter->xmitpriv;
2362 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
2363 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
2364 
2365 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2366 	if (!pmgntframe)
2367 		return;
2368 
2369 	/* update attribute */
2370 	pattrib = &pmgntframe->attrib;
2371 	update_mgntframe_attrib(padapter, pattrib);
2372 
2373 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2374 
2375 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2376 	pwlanhdr = (struct ieee80211_hdr *)pframe;
2377 
2378 	fctrl = &pwlanhdr->frame_control;
2379 	*(fctrl) = 0;
2380 
2381 	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2382 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2383 	memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
2384 
2385 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2386 	pmlmeext->mgnt_seq++;
2387 	SetFrameSubType(pframe, WIFI_ACTION);
2388 
2389 	pframe += sizeof(struct ieee80211_hdr_3addr);
2390 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2391 
2392 	pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
2393 	pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
2394 	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
2395 	pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
2396 	pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen);
2397 
2398 	/*	P2P IE Section. */
2399 
2400 	/*	P2P OUI */
2401 	p2pielen = 0;
2402 	p2pie[p2pielen++] = 0x50;
2403 	p2pie[p2pielen++] = 0x6F;
2404 	p2pie[p2pielen++] = 0x9A;
2405 	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
2406 
2407 	/*	Commented by Albert 20110306 */
2408 	/*	According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */
2409 	/*	1. Status */
2410 	/*	2. P2P Capability */
2411 	/*	3. Operating Channel */
2412 	/*	4. Channel List */
2413 	/*	5. Group ID	(if this WiFi is GO) */
2414 
2415 	/*	P2P Status */
2416 	/*	Type: */
2417 	p2pie[p2pielen++] = P2P_ATTR_STATUS;
2418 
2419 	/*	Length: */
2420 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2421 	p2pielen += 2;
2422 
2423 	/*	Value: */
2424 	p2pie[p2pielen++] = result;
2425 
2426 	/*	P2P Capability */
2427 	/*	Type: */
2428 	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2429 
2430 	/*	Length: */
2431 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2432 	p2pielen += 2;
2433 
2434 	/*	Value: */
2435 	/*	Device Capability Bitmap, 1 byte */
2436 	p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2437 
2438 	/*	Group Capability Bitmap, 1 byte */
2439 	if (pwdinfo->persistent_supported)
2440 		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2441 	else
2442 		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2443 
2444 	/*	Operating Channel */
2445 	/*	Type: */
2446 	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2447 
2448 	/*	Length: */
2449 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2450 	p2pielen += 2;
2451 
2452 	/*	Value: */
2453 	/*	Country String */
2454 	p2pie[p2pielen++] = 'X';
2455 	p2pie[p2pielen++] = 'X';
2456 
2457 	/*	The third byte should be set to 0x04. */
2458 	/*	Described in the "Operating Channel Attribute" section. */
2459 	p2pie[p2pielen++] = 0x04;
2460 
2461 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2462 		/*	Operating Class */
2463 		p2pie[p2pielen++] = 0x51;
2464 		p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
2465 	} else {
2466 		/*	Operating Class */
2467 		p2pie[p2pielen++] = 0x51;
2468 
2469 		/*	Channel Number */
2470 		p2pie[p2pielen++] = pwdinfo->operating_channel;		/*	Use the listen channel as the operating channel */
2471 	}
2472 
2473 	/*	Channel List */
2474 	/*	Type: */
2475 	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2476 
2477 	/*	Length: */
2478 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(pwdinfo->channel_list_attr_len);
2479 	p2pielen += 2;
2480 
2481 	/*	Value: */
2482 	memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len);
2483 	p2pielen += pwdinfo->channel_list_attr_len;
2484 
2485 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2486 		/*	Group ID Attribute */
2487 		/*	Type: */
2488 		p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2489 
2490 		/*	Length: */
2491 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
2492 		p2pielen += 2;
2493 
2494 		/*	Value: */
2495 		/*	p2P Device Address */
2496 		memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
2497 		p2pielen += ETH_ALEN;
2498 
2499 		/*	SSID */
2500 		memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2501 		p2pielen += pwdinfo->nego_ssidlen;
2502 	}
2503 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2504 	pattrib->last_txcmdsz = pattrib->pktlen;
2505 	dump_mgntframe(padapter, pmgntframe);
2506 }
2507 
issue_p2p_invitation_request(struct adapter * padapter,u8 * raddr)2508 void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr)
2509 {
2510 	unsigned char category = WLAN_CATEGORY_PUBLIC;
2511 	u8 action = P2P_PUB_ACTION_ACTION;
2512 	__be32			p2poui = cpu_to_be32(P2POUI);
2513 	u8 oui_subtype = P2P_INVIT_REQ;
2514 	u8 p2pie[255] = { 0x00 };
2515 	u8 p2pielen = 0;
2516 	u8 dialogToken = 3;
2517 	u16 len_channellist_attr = 0;
2518 	struct xmit_frame			*pmgntframe;
2519 	struct pkt_attrib			*pattrib;
2520 	unsigned char					*pframe;
2521 	struct ieee80211_hdr *pwlanhdr;
2522 	__le16 *fctrl;
2523 	struct xmit_priv			*pxmitpriv = &padapter->xmitpriv;
2524 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
2525 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
2526 
2527 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2528 	if (!pmgntframe)
2529 		return;
2530 
2531 	/* update attribute */
2532 	pattrib = &pmgntframe->attrib;
2533 	update_mgntframe_attrib(padapter, pattrib);
2534 
2535 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2536 
2537 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2538 	pwlanhdr = (struct ieee80211_hdr *)pframe;
2539 
2540 	fctrl = &pwlanhdr->frame_control;
2541 	*(fctrl) = 0;
2542 
2543 	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2544 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2545 	memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
2546 
2547 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2548 	pmlmeext->mgnt_seq++;
2549 	SetFrameSubType(pframe, WIFI_ACTION);
2550 
2551 	pframe += sizeof(struct ieee80211_hdr_3addr);
2552 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2553 
2554 	pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
2555 	pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
2556 	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
2557 	pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
2558 	pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
2559 
2560 	/*	P2P IE Section. */
2561 
2562 	/*	P2P OUI */
2563 	p2pielen = 0;
2564 	p2pie[p2pielen++] = 0x50;
2565 	p2pie[p2pielen++] = 0x6F;
2566 	p2pie[p2pielen++] = 0x9A;
2567 	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
2568 
2569 	/*	Commented by Albert 20101011 */
2570 	/*	According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */
2571 	/*	1. Configuration Timeout */
2572 	/*	2. Invitation Flags */
2573 	/*	3. Operating Channel	(Only GO) */
2574 	/*	4. P2P Group BSSID	(Should be included if I am the GO) */
2575 	/*	5. Channel List */
2576 	/*	6. P2P Group ID */
2577 	/*	7. P2P Device Info */
2578 
2579 	/*	Configuration Timeout */
2580 	/*	Type: */
2581 	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2582 
2583 	/*	Length: */
2584 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2585 	p2pielen += 2;
2586 
2587 	/*	Value: */
2588 	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P GO */
2589 	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P Client */
2590 
2591 	/*	Invitation Flags */
2592 	/*	Type: */
2593 	p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;
2594 
2595 	/*	Length: */
2596 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2597 	p2pielen += 2;
2598 
2599 	/*	Value: */
2600 	p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;
2601 
2602 	/*	Operating Channel */
2603 	/*	Type: */
2604 	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2605 
2606 	/*	Length: */
2607 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2608 	p2pielen += 2;
2609 
2610 	/*	Value: */
2611 	/*	Country String */
2612 	p2pie[p2pielen++] = 'X';
2613 	p2pie[p2pielen++] = 'X';
2614 
2615 	/*	The third byte should be set to 0x04. */
2616 	/*	Described in the "Operating Channel Attribute" section. */
2617 	p2pie[p2pielen++] = 0x04;
2618 
2619 	/*	Operating Class */
2620 	p2pie[p2pielen++] = 0x51;
2621 
2622 	/*	Channel Number */
2623 	p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch;	/*	operating channel number */
2624 
2625 	if (!memcmp(myid(&padapter->eeprompriv), pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) {
2626 		/*	P2P Group BSSID */
2627 		/*	Type: */
2628 		p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
2629 
2630 		/*	Length: */
2631 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2632 		p2pielen += 2;
2633 
2634 		/*	Value: */
2635 		/*	P2P Device Address for GO */
2636 		memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
2637 		p2pielen += ETH_ALEN;
2638 	}
2639 
2640 	/*	Channel List */
2641 	/*	Type: */
2642 	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2643 
2644 	/*	Length: */
2645 	/*  Country String(3) */
2646 	/*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2647 	/*  + number of channels in all classes */
2648 	len_channellist_attr = 3
2649 	   + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
2650 	   + get_reg_classes_full_count(&pmlmeext->channel_list);
2651 
2652 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2653 
2654 	p2pielen += 2;
2655 
2656 	/*	Value: */
2657 	/*	Country String */
2658 	p2pie[p2pielen++] = 'X';
2659 	p2pie[p2pielen++] = 'X';
2660 
2661 	/*	The third byte should be set to 0x04. */
2662 	/*	Described in the "Operating Channel Attribute" section. */
2663 	p2pie[p2pielen++] = 0x04;
2664 
2665 	/*	Channel Entry List */
2666 	{
2667 		int i, j;
2668 		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2669 			/*	Operating Class */
2670 			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2671 
2672 			/*	Number of Channels */
2673 			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2674 
2675 			/*	Channel List */
2676 			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2677 				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2678 			}
2679 		}
2680 	}
2681 
2682 	/*	P2P Group ID */
2683 	/*	Type: */
2684 	p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2685 
2686 	/*	Length: */
2687 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);
2688 	p2pielen += 2;
2689 
2690 	/*	Value: */
2691 	/*	P2P Device Address for GO */
2692 	memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
2693 	p2pielen += ETH_ALEN;
2694 
2695 	/*	SSID */
2696 	memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen);
2697 	p2pielen += pwdinfo->invitereq_info.ssidlen;
2698 
2699 	/*	Device Info */
2700 	/*	Type: */
2701 	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2702 
2703 	/*	Length: */
2704 	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2705 	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2706 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2707 	p2pielen += 2;
2708 
2709 	/*	Value: */
2710 	/*	P2P Device Address */
2711 	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2712 	p2pielen += ETH_ALEN;
2713 
2714 	/*	Config Method */
2715 	/*	This field should be big endian. Noted by P2P specification. */
2716 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
2717 	p2pielen += 2;
2718 
2719 	/*	Primary Device Type */
2720 	/*	Category ID */
2721 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2722 	p2pielen += 2;
2723 
2724 	/*	OUI */
2725 	*(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2726 	p2pielen  += 4;
2727 
2728 	/*	Sub Category ID */
2729 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2730 	p2pielen += 2;
2731 
2732 	/*	Number of Secondary Device Types */
2733 	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
2734 
2735 	/*	Device Name */
2736 	/*	Type: */
2737 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2738 	p2pielen += 2;
2739 
2740 	/*	Length: */
2741 	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2742 	p2pielen += 2;
2743 
2744 	/*	Value: */
2745 	memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2746 	p2pielen += pwdinfo->device_name_len;
2747 
2748 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2749 
2750 	pattrib->last_txcmdsz = pattrib->pktlen;
2751 
2752 	dump_mgntframe(padapter, pmgntframe);
2753 }
2754 
issue_p2p_invitation_response(struct adapter * padapter,u8 * raddr,u8 dialogToken,u8 status_code)2755 void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr, u8 dialogToken, u8 status_code)
2756 {
2757 	unsigned char category = WLAN_CATEGORY_PUBLIC;
2758 	u8 action = P2P_PUB_ACTION_ACTION;
2759 	__be32			p2poui = cpu_to_be32(P2POUI);
2760 	u8 oui_subtype = P2P_INVIT_RESP;
2761 	u8 p2pie[255] = { 0x00 };
2762 	u8 p2pielen = 0;
2763 	u16 len_channellist_attr = 0;
2764 	struct xmit_frame			*pmgntframe;
2765 	struct pkt_attrib			*pattrib;
2766 	unsigned char					*pframe;
2767 	struct ieee80211_hdr *pwlanhdr;
2768 	__le16 *fctrl;
2769 	struct xmit_priv			*pxmitpriv = &padapter->xmitpriv;
2770 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
2771 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
2772 
2773 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2774 	if (!pmgntframe)
2775 		return;
2776 
2777 	/* update attribute */
2778 	pattrib = &pmgntframe->attrib;
2779 	update_mgntframe_attrib(padapter, pattrib);
2780 
2781 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2782 
2783 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2784 	pwlanhdr = (struct ieee80211_hdr *)pframe;
2785 
2786 	fctrl = &pwlanhdr->frame_control;
2787 	*(fctrl) = 0;
2788 
2789 	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2790 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2791 	memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
2792 
2793 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2794 	pmlmeext->mgnt_seq++;
2795 	SetFrameSubType(pframe, WIFI_ACTION);
2796 
2797 	pframe += sizeof(struct ieee80211_hdr_3addr);
2798 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2799 
2800 	pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
2801 	pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
2802 	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
2803 	pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
2804 	pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
2805 
2806 	/*	P2P IE Section. */
2807 
2808 	/*	P2P OUI */
2809 	p2pielen = 0;
2810 	p2pie[p2pielen++] = 0x50;
2811 	p2pie[p2pielen++] = 0x6F;
2812 	p2pie[p2pielen++] = 0x9A;
2813 	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
2814 
2815 	/*	Commented by Albert 20101005 */
2816 	/*	According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */
2817 	/*	1. Status */
2818 	/*	2. Configuration Timeout */
2819 	/*	3. Operating Channel	(Only GO) */
2820 	/*	4. P2P Group BSSID	(Only GO) */
2821 	/*	5. Channel List */
2822 
2823 	/*	P2P Status */
2824 	/*	Type: */
2825 	p2pie[p2pielen++] = P2P_ATTR_STATUS;
2826 
2827 	/*	Length: */
2828 	*(__le16  *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2829 	p2pielen += 2;
2830 
2831 	/*	Value: */
2832 	/*	When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
2833 	/*	Sent the event receiving the P2P Invitation Req frame to DMP UI. */
2834 	/*	DMP had to compare the MAC address to find out the profile. */
2835 	/*	So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
2836 	/*	If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */
2837 	/*	to NB to rebuild the persistent group. */
2838 	p2pie[p2pielen++] = status_code;
2839 
2840 	/*	Configuration Timeout */
2841 	/*	Type: */
2842 	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2843 
2844 	/*	Length: */
2845 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2846 	p2pielen += 2;
2847 
2848 	/*	Value: */
2849 	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P GO */
2850 	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P Client */
2851 
2852 	if (status_code == P2P_STATUS_SUCCESS) {
2853 		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2854 			/*	The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */
2855 			/*	In this case, the P2P Invitation response frame should carry the two more P2P attributes. */
2856 			/*	First one is operating channel attribute. */
2857 			/*	Second one is P2P Group BSSID attribute. */
2858 
2859 			/*	Operating Channel */
2860 			/*	Type: */
2861 			p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2862 
2863 			/*	Length: */
2864 			*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2865 			p2pielen += 2;
2866 
2867 			/*	Value: */
2868 			/*	Country String */
2869 			p2pie[p2pielen++] = 'X';
2870 			p2pie[p2pielen++] = 'X';
2871 
2872 			/*	The third byte should be set to 0x04. */
2873 			/*	Described in the "Operating Channel Attribute" section. */
2874 			p2pie[p2pielen++] = 0x04;
2875 
2876 			/*	Operating Class */
2877 			p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
2878 
2879 			/*	Channel Number */
2880 			p2pie[p2pielen++] = pwdinfo->operating_channel;	/*	operating channel number */
2881 
2882 			/*	P2P Group BSSID */
2883 			/*	Type: */
2884 			p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
2885 
2886 			/*	Length: */
2887 			*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2888 			p2pielen += 2;
2889 
2890 			/*	Value: */
2891 			/*	P2P Device Address for GO */
2892 			memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2893 			p2pielen += ETH_ALEN;
2894 		}
2895 
2896 		/*	Channel List */
2897 		/*	Type: */
2898 		p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2899 
2900 		/*	Length: */
2901 		/*  Country String(3) */
2902 		/*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2903 		/*  + number of channels in all classes */
2904 		len_channellist_attr = 3
2905 			+ (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
2906 			+ get_reg_classes_full_count(&pmlmeext->channel_list);
2907 
2908 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2909 		p2pielen += 2;
2910 
2911 		/*	Value: */
2912 		/*	Country String */
2913 		p2pie[p2pielen++] = 'X';
2914 		p2pie[p2pielen++] = 'X';
2915 
2916 		/*	The third byte should be set to 0x04. */
2917 		/*	Described in the "Operating Channel Attribute" section. */
2918 		p2pie[p2pielen++] = 0x04;
2919 
2920 		/*	Channel Entry List */
2921 		{
2922 			int i, j;
2923 			for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2924 				/*	Operating Class */
2925 				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2926 
2927 				/*	Number of Channels */
2928 				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2929 
2930 				/*	Channel List */
2931 				for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2932 					p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2933 				}
2934 			}
2935 		}
2936 	}
2937 
2938 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2939 
2940 	pattrib->last_txcmdsz = pattrib->pktlen;
2941 
2942 	dump_mgntframe(padapter, pmgntframe);
2943 }
2944 
issue_p2p_provision_request(struct adapter * padapter,u8 * pssid,u8 ussidlen,u8 * pdev_raddr)2945 void issue_p2p_provision_request(struct adapter *padapter, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
2946 {
2947 	unsigned char category = WLAN_CATEGORY_PUBLIC;
2948 	u8 action = P2P_PUB_ACTION_ACTION;
2949 	u8 dialogToken = 1;
2950 	u8 oui_subtype = P2P_PROVISION_DISC_REQ;
2951 	u8 wpsie[100] = { 0x00 };
2952 	u8 wpsielen = 0;
2953 	__be32 p2poui = cpu_to_be32(P2POUI);
2954 	u32			p2pielen = 0;
2955 	struct xmit_frame			*pmgntframe;
2956 	struct pkt_attrib			*pattrib;
2957 	unsigned char					*pframe;
2958 	struct ieee80211_hdr *pwlanhdr;
2959 	__le16 *fctrl;
2960 	struct xmit_priv			*pxmitpriv = &padapter->xmitpriv;
2961 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
2962 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
2963 
2964 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2965 	if (!pmgntframe)
2966 		return;
2967 
2968 	/* update attribute */
2969 	pattrib = &pmgntframe->attrib;
2970 	update_mgntframe_attrib(padapter, pattrib);
2971 
2972 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2973 
2974 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2975 	pwlanhdr = (struct ieee80211_hdr *)pframe;
2976 
2977 	fctrl = &pwlanhdr->frame_control;
2978 	*(fctrl) = 0;
2979 
2980 	memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
2981 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2982 	memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
2983 
2984 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2985 	pmlmeext->mgnt_seq++;
2986 	SetFrameSubType(pframe, WIFI_ACTION);
2987 
2988 	pframe += sizeof(struct ieee80211_hdr_3addr);
2989 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2990 
2991 	pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
2992 	pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
2993 	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
2994 	pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
2995 	pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
2996 
2997 	p2pielen = build_prov_disc_request_p2p_ie(pwdinfo, pframe, pssid, ussidlen, pdev_raddr);
2998 
2999 	pframe += p2pielen;
3000 	pattrib->pktlen += p2pielen;
3001 
3002 	wpsielen = 0;
3003 	/*	WPS OUI */
3004 	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3005 	wpsielen += 4;
3006 
3007 	/*	WPS version */
3008 	/*	Type: */
3009 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3010 	wpsielen += 2;
3011 
3012 	/*	Length: */
3013 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3014 	wpsielen += 2;
3015 
3016 	/*	Value: */
3017 	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
3018 
3019 	/*	Config Method */
3020 	/*	Type: */
3021 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3022 	wpsielen += 2;
3023 
3024 	/*	Length: */
3025 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3026 	wpsielen += 2;
3027 
3028 	/*	Value: */
3029 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
3030 	wpsielen += 2;
3031 
3032 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3033 
3034 	pattrib->last_txcmdsz = pattrib->pktlen;
3035 
3036 	dump_mgntframe(padapter, pmgntframe);
3037 }
3038 
is_matched_in_profilelist(u8 * peermacaddr,struct profile_info * profileinfo)3039 static u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profileinfo)
3040 {
3041 	u8 i, match_result = 0;
3042 
3043 	for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
3044 		if (!memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) {
3045 			match_result = 1;
3046 			break;
3047 		}
3048 	}
3049 	return match_result;
3050 }
3051 
issue_probersp_p2p(struct adapter * padapter,unsigned char * da)3052 void issue_probersp_p2p(struct adapter *padapter, unsigned char *da)
3053 {
3054 	struct xmit_frame			*pmgntframe;
3055 	struct pkt_attrib			*pattrib;
3056 	unsigned char					*pframe;
3057 	struct ieee80211_hdr *pwlanhdr;
3058 	__le16 *fctrl;
3059 	unsigned char					*mac;
3060 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
3061 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
3062 	u16 beacon_interval = 100;
3063 	u16 capInfo = 0;
3064 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
3065 	u8 wpsie[255] = { 0x00 };
3066 	u32					wpsielen = 0, p2pielen = 0;
3067 
3068 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3069 	if (!pmgntframe)
3070 		return;
3071 
3072 	/* update attribute */
3073 	pattrib = &pmgntframe->attrib;
3074 	update_mgntframe_attrib(padapter, pattrib);
3075 
3076 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3077 
3078 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3079 	pwlanhdr = (struct ieee80211_hdr *)pframe;
3080 
3081 	mac = myid(&padapter->eeprompriv);
3082 
3083 	fctrl = &pwlanhdr->frame_control;
3084 	*(fctrl) = 0;
3085 	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3086 	memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
3087 
3088 	/*	Use the device address for BSSID field. */
3089 	memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
3090 
3091 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3092 	pmlmeext->mgnt_seq++;
3093 	SetFrameSubType(fctrl, WIFI_PROBERSP);
3094 
3095 	pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3096 	pattrib->pktlen = pattrib->hdrlen;
3097 	pframe += pattrib->hdrlen;
3098 
3099 	/* timestamp will be inserted by hardware */
3100 	pframe += 8;
3101 	pattrib->pktlen += 8;
3102 
3103 	/*  beacon interval: 2 bytes */
3104 	memcpy(pframe, (unsigned char *)&beacon_interval, 2);
3105 	pframe += 2;
3106 	pattrib->pktlen += 2;
3107 
3108 	/*	capability info: 2 bytes */
3109 	/*	ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */
3110 	capInfo |= cap_ShortPremble;
3111 	capInfo |= cap_ShortSlot;
3112 
3113 	memcpy(pframe, (unsigned char *)&capInfo, 2);
3114 	pframe += 2;
3115 	pattrib->pktlen += 2;
3116 
3117 	/*  SSID */
3118 	pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
3119 
3120 	/*  supported rates... */
3121 	/*	Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
3122 	pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
3123 
3124 	/*  DS parameter set */
3125 	pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
3126 
3127 	/*	Todo: WPS IE */
3128 	/*	Noted by Albert 20100907 */
3129 	/*	According to the WPS specification, all the WPS attribute is presented by Big Endian. */
3130 
3131 	wpsielen = 0;
3132 	/*	WPS OUI */
3133 	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3134 	wpsielen += 4;
3135 
3136 	/*	WPS version */
3137 	/*	Type: */
3138 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3139 	wpsielen += 2;
3140 
3141 	/*	Length: */
3142 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3143 	wpsielen += 2;
3144 
3145 	/*	Value: */
3146 	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
3147 
3148 	/*	WiFi Simple Config State */
3149 	/*	Type: */
3150 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
3151 	wpsielen += 2;
3152 
3153 	/*	Length: */
3154 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3155 	wpsielen += 2;
3156 
3157 	/*	Value: */
3158 	wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;	/*	Not Configured. */
3159 
3160 	/*	Response Type */
3161 	/*	Type: */
3162 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
3163 	wpsielen += 2;
3164 
3165 	/*	Length: */
3166 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3167 	wpsielen += 2;
3168 
3169 	/*	Value: */
3170 	wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
3171 
3172 	/*	UUID-E */
3173 	/*	Type: */
3174 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
3175 	wpsielen += 2;
3176 
3177 	/*	Length: */
3178 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
3179 	wpsielen += 2;
3180 
3181 	/*	Value: */
3182 	memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
3183 	wpsielen += 0x10;
3184 
3185 	/*	Manufacturer */
3186 	/*	Type: */
3187 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
3188 	wpsielen += 2;
3189 
3190 	/*	Length: */
3191 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007);
3192 	wpsielen += 2;
3193 
3194 	/*	Value: */
3195 	memcpy(wpsie + wpsielen, "Realtek", 7);
3196 	wpsielen += 7;
3197 
3198 	/*	Model Name */
3199 	/*	Type: */
3200 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
3201 	wpsielen += 2;
3202 
3203 	/*	Length: */
3204 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006);
3205 	wpsielen += 2;
3206 
3207 	/*	Value: */
3208 	memcpy(wpsie + wpsielen, "8188EU", 6);
3209 	wpsielen += 6;
3210 
3211 	/*	Model Number */
3212 	/*	Type: */
3213 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
3214 	wpsielen += 2;
3215 
3216 	/*	Length: */
3217 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3218 	wpsielen += 2;
3219 
3220 	/*	Value: */
3221 	wpsie[wpsielen++] = 0x31;		/*	character 1 */
3222 
3223 	/*	Serial Number */
3224 	/*	Type: */
3225 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
3226 	wpsielen += 2;
3227 
3228 	/*	Length: */
3229 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
3230 	wpsielen += 2;
3231 
3232 	/*	Value: */
3233 	memcpy(wpsie + wpsielen, "123456", ETH_ALEN);
3234 	wpsielen += ETH_ALEN;
3235 
3236 	/*	Primary Device Type */
3237 	/*	Type: */
3238 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
3239 	wpsielen += 2;
3240 
3241 	/*	Length: */
3242 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
3243 	wpsielen += 2;
3244 
3245 	/*	Value: */
3246 	/*	Category ID */
3247 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
3248 	wpsielen += 2;
3249 
3250 	/*	OUI */
3251 	*(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
3252 	wpsielen += 4;
3253 
3254 	/*	Sub Category ID */
3255 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
3256 	wpsielen += 2;
3257 
3258 	/*	Device Name */
3259 	/*	Type: */
3260 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
3261 	wpsielen += 2;
3262 
3263 	/*	Length: */
3264 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
3265 	wpsielen += 2;
3266 
3267 	/*	Value: */
3268 	if (pwdinfo->device_name_len) {
3269 		memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
3270 		wpsielen += pwdinfo->device_name_len;
3271 	}
3272 
3273 	/*	Config Method */
3274 	/*	Type: */
3275 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3276 	wpsielen += 2;
3277 
3278 	/*	Length: */
3279 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3280 	wpsielen += 2;
3281 
3282 	/*	Value: */
3283 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
3284 	wpsielen += 2;
3285 
3286 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3287 
3288 	p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
3289 	pframe += p2pielen;
3290 	pattrib->pktlen += p2pielen;
3291 
3292 	pattrib->last_txcmdsz = pattrib->pktlen;
3293 
3294 	dump_mgntframe(padapter, pmgntframe);
3295 }
3296 
_issue_probereq_p2p(struct adapter * padapter,u8 * da,int wait_ack)3297 static int _issue_probereq_p2p(struct adapter *padapter, u8 *da, int wait_ack)
3298 {
3299 	int ret = _FAIL;
3300 	struct xmit_frame		*pmgntframe;
3301 	struct pkt_attrib		*pattrib;
3302 	unsigned char			*pframe;
3303 	struct ieee80211_hdr *pwlanhdr;
3304 	__le16 *fctrl;
3305 	unsigned char			*mac;
3306 	struct xmit_priv		*pxmitpriv = &padapter->xmitpriv;
3307 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
3308 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
3309 	u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
3310 	u16 wpsielen = 0, p2pielen = 0;
3311 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3312 
3313 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3314 	if (!pmgntframe)
3315 		goto exit;
3316 
3317 	/* update attribute */
3318 	pattrib = &pmgntframe->attrib;
3319 	update_mgntframe_attrib(padapter, pattrib);
3320 
3321 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3322 
3323 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3324 	pwlanhdr = (struct ieee80211_hdr *)pframe;
3325 
3326 	mac = myid(&padapter->eeprompriv);
3327 
3328 	fctrl = &pwlanhdr->frame_control;
3329 	*(fctrl) = 0;
3330 
3331 	if (da) {
3332 		memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3333 		memcpy(pwlanhdr->addr3, da, ETH_ALEN);
3334 	} else {
3335 		if ((pwdinfo->p2p_info.scan_op_ch_only) || (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
3336 			/*	This two flags will be set when this is only the P2P client mode. */
3337 			memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
3338 			memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
3339 		} else {
3340 			/*	broadcast probe request frame */
3341 			eth_broadcast_addr(pwlanhdr->addr1);
3342 			eth_broadcast_addr(pwlanhdr->addr3);
3343 		}
3344 	}
3345 	memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
3346 
3347 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3348 	pmlmeext->mgnt_seq++;
3349 	SetFrameSubType(pframe, WIFI_PROBEREQ);
3350 
3351 	pframe += sizeof(struct ieee80211_hdr_3addr);
3352 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3353 
3354 	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
3355 		pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &pattrib->pktlen);
3356 	else
3357 		pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
3358 
3359 	/*	Use the OFDM rate in the P2P probe request frame. (6(B), 9(B), 12(B), 24(B), 36, 48, 54) */
3360 	pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
3361 
3362 	/*	WPS IE */
3363 	/*	Noted by Albert 20110221 */
3364 	/*	According to the WPS specification, all the WPS attribute is presented by Big Endian. */
3365 
3366 	wpsielen = 0;
3367 	/*	WPS OUI */
3368 	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3369 	wpsielen += 4;
3370 
3371 	/*	WPS version */
3372 	/*	Type: */
3373 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3374 	wpsielen += 2;
3375 
3376 	/*	Length: */
3377 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3378 	wpsielen += 2;
3379 
3380 	/*	Value: */
3381 	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
3382 
3383 	if (!pmlmepriv->wps_probe_req_ie) {
3384 		/*	UUID-E */
3385 		/*	Type: */
3386 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
3387 		wpsielen += 2;
3388 
3389 		/*	Length: */
3390 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
3391 		wpsielen += 2;
3392 
3393 		/*	Value: */
3394 		memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
3395 		wpsielen += 0x10;
3396 
3397 		/*	Config Method */
3398 		/*	Type: */
3399 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3400 		wpsielen += 2;
3401 
3402 		/*	Length: */
3403 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3404 		wpsielen += 2;
3405 
3406 		/*	Value: */
3407 		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
3408 		wpsielen += 2;
3409 	}
3410 
3411 	/*	Device Name */
3412 	/*	Type: */
3413 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
3414 	wpsielen += 2;
3415 
3416 	/*	Length: */
3417 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
3418 	wpsielen += 2;
3419 
3420 	/*	Value: */
3421 	memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
3422 	wpsielen += pwdinfo->device_name_len;
3423 
3424 	/*	Primary Device Type */
3425 	/*	Type: */
3426 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
3427 	wpsielen += 2;
3428 
3429 	/*	Length: */
3430 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
3431 	wpsielen += 2;
3432 
3433 	/*	Value: */
3434 	/*	Category ID */
3435 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);
3436 	wpsielen += 2;
3437 
3438 	/*	OUI */
3439 	*(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
3440 	wpsielen += 4;
3441 
3442 	/*	Sub Category ID */
3443 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);
3444 	wpsielen += 2;
3445 
3446 	/*	Device Password ID */
3447 	/*	Type: */
3448 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
3449 	wpsielen += 2;
3450 
3451 	/*	Length: */
3452 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3453 	wpsielen += 2;
3454 
3455 	/*	Value: */
3456 	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);	/*	Registrar-specified */
3457 	wpsielen += 2;
3458 
3459 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3460 
3461 	/*	P2P OUI */
3462 	p2pielen = 0;
3463 	p2pie[p2pielen++] = 0x50;
3464 	p2pie[p2pielen++] = 0x6F;
3465 	p2pie[p2pielen++] = 0x9A;
3466 	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
3467 
3468 	/*	Commented by Albert 20110221 */
3469 	/*	According to the P2P Specification, the probe request frame should contain 5 P2P attributes */
3470 	/*	1. P2P Capability */
3471 	/*	2. P2P Device ID if this probe request wants to find the specific P2P device */
3472 	/*	3. Listen Channel */
3473 	/*	4. Extended Listen Timing */
3474 	/*	5. Operating Channel if this WiFi is working as the group owner now */
3475 
3476 	/*	P2P Capability */
3477 	/*	Type: */
3478 	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
3479 
3480 	/*	Length: */
3481 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
3482 	p2pielen += 2;
3483 
3484 	/*	Value: */
3485 	/*	Device Capability Bitmap, 1 byte */
3486 	p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
3487 
3488 	/*	Group Capability Bitmap, 1 byte */
3489 	if (pwdinfo->persistent_supported)
3490 		p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
3491 	else
3492 		p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
3493 
3494 	/*	Listen Channel */
3495 	/*	Type: */
3496 	p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
3497 
3498 	/*	Length: */
3499 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
3500 	p2pielen += 2;
3501 
3502 	/*	Value: */
3503 	/*	Country String */
3504 	p2pie[p2pielen++] = 'X';
3505 	p2pie[p2pielen++] = 'X';
3506 
3507 	/*	The third byte should be set to 0x04. */
3508 	/*	Described in the "Operating Channel Attribute" section. */
3509 	p2pie[p2pielen++] = 0x04;
3510 
3511 	/*	Operating Class */
3512 	p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
3513 
3514 	/*	Channel Number */
3515 	p2pie[p2pielen++] = pwdinfo->listen_channel;	/*	listen channel */
3516 
3517 	/*	Extended Listen Timing */
3518 	/*	Type: */
3519 	p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
3520 
3521 	/*	Length: */
3522 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
3523 	p2pielen += 2;
3524 
3525 	/*	Value: */
3526 	/*	Availability Period */
3527 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
3528 	p2pielen += 2;
3529 
3530 	/*	Availability Interval */
3531 	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
3532 	p2pielen += 2;
3533 
3534 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3535 		/*	Operating Channel (if this WiFi is working as the group owner now) */
3536 		/*	Type: */
3537 		p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3538 
3539 		/*	Length: */
3540 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
3541 		p2pielen += 2;
3542 
3543 		/*	Value: */
3544 		/*	Country String */
3545 		p2pie[p2pielen++] = 'X';
3546 		p2pie[p2pielen++] = 'X';
3547 
3548 		/*	The third byte should be set to 0x04. */
3549 		/*	Described in the "Operating Channel Attribute" section. */
3550 		p2pie[p2pielen++] = 0x04;
3551 
3552 		/*	Operating Class */
3553 		p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
3554 
3555 		/*	Channel Number */
3556 		p2pie[p2pielen++] = pwdinfo->operating_channel;	/*	operating channel number */
3557 	}
3558 
3559 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
3560 
3561 	if (pmlmepriv->wps_probe_req_ie) {
3562 		/* WPS IE */
3563 		memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
3564 		pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
3565 		pframe += pmlmepriv->wps_probe_req_ie_len;
3566 	}
3567 
3568 	pattrib->last_txcmdsz = pattrib->pktlen;
3569 
3570 	if (wait_ack) {
3571 		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3572 	} else {
3573 		dump_mgntframe(padapter, pmgntframe);
3574 		ret = _SUCCESS;
3575 	}
3576 
3577 exit:
3578 	return ret;
3579 }
3580 
issue_probereq_p2p(struct adapter * adapter,u8 * da)3581 inline void issue_probereq_p2p(struct adapter *adapter, u8 *da)
3582 {
3583 	_issue_probereq_p2p(adapter, da, false);
3584 }
3585 
rtw_action_public_decache(struct recv_frame * recv_frame,s32 token)3586 static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
3587 {
3588 	struct adapter *adapter = recv_frame->adapter;
3589 	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
3590 	u8 *frame = recv_frame->rx_data;
3591 	u16 seq_ctrl = ((recv_frame->attrib.seq_num & 0xffff) << 4) |
3592 		(recv_frame->attrib.frag_num & 0xf);
3593 
3594 	if (GetRetry(frame)) {
3595 		if (token >= 0) {
3596 			if ((seq_ctrl == mlmeext->action_public_rxseq) &&
3597 			    (token == mlmeext->action_public_dialog_token))
3598 				return _FAIL;
3599 		} else {
3600 			if (seq_ctrl == mlmeext->action_public_rxseq)
3601 				return _FAIL;
3602 		}
3603 	}
3604 
3605 	mlmeext->action_public_rxseq = seq_ctrl;
3606 
3607 	if (token >= 0)
3608 		mlmeext->action_public_dialog_token = token;
3609 
3610 	return _SUCCESS;
3611 }
3612 
on_action_public_p2p(struct recv_frame * precv_frame)3613 static unsigned int on_action_public_p2p(struct recv_frame *precv_frame)
3614 {
3615 	u8 *pframe = precv_frame->rx_data;
3616 	u8 *frame_body;
3617 	u8 dialogToken = 0;
3618 	struct adapter *padapter = precv_frame->adapter;
3619 	uint len = precv_frame->len;
3620 	u8 *p2p_ie;
3621 	u32	p2p_ielen;
3622 	struct	wifidirect_info	*pwdinfo = &padapter->wdinfo;
3623 	u8	result = P2P_STATUS_SUCCESS;
3624 	u8	empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3625 
3626 	frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
3627 
3628 	dialogToken = frame_body[7];
3629 
3630 	if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
3631 		return _FAIL;
3632 
3633 	_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
3634 	/*	Do nothing if the driver doesn't enable the P2P function. */
3635 	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
3636 		return _SUCCESS;
3637 
3638 	len -= sizeof(struct ieee80211_hdr_3addr);
3639 
3640 	switch (frame_body[6]) { /* OUI Subtype */
3641 	case P2P_GO_NEGO_REQ:
3642 		memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
3643 
3644 		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
3645 			rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3646 
3647 		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) {
3648 			/*	Commented by Albert 20110526 */
3649 			/*	In this case, this means the previous nego fail doesn't be reset yet. */
3650 			_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3651 			/*	Restore the previous p2p state */
3652 			rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3653 		}
3654 
3655 		/*	Commented by Kurt 20110902 */
3656 		/* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
3657 		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
3658 			rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3659 
3660 		/*	Commented by Kurt 20120113 */
3661 		/*	Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
3662 		if (!memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN))
3663 			memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
3664 
3665 		result = process_p2p_group_negotation_req(pwdinfo, frame_body, len);
3666 		issue_p2p_GO_response(padapter, GetAddr2Ptr(pframe), frame_body, len, result);
3667 
3668 		/*	Commented by Albert 20110718 */
3669 		/*	No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
3670 		_set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
3671 		break;
3672 	case P2P_GO_NEGO_RESP:
3673 		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
3674 			/*	Commented by Albert 20110425 */
3675 			/*	The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
3676 			_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3677 			pwdinfo->nego_req_info.benable = false;
3678 			result = process_p2p_group_negotation_resp(pwdinfo, frame_body, len);
3679 			issue_p2p_GO_confirm(pwdinfo->padapter, GetAddr2Ptr(pframe), result);
3680 			if (result == P2P_STATUS_SUCCESS) {
3681 				if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
3682 					pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
3683 					pwdinfo->p2p_info.scan_op_ch_only = 1;
3684 					_set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
3685 				}
3686 			}
3687 			/*	Reset the dialog token for group negotiation frames. */
3688 			pwdinfo->negotiation_dialog_token = 1;
3689 			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3690 				_set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
3691 		}
3692 		break;
3693 	case P2P_GO_NEGO_CONF:
3694 		result = process_p2p_group_negotation_confirm(pwdinfo, frame_body, len);
3695 		if (result == P2P_STATUS_SUCCESS) {
3696 			if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
3697 				pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
3698 				pwdinfo->p2p_info.scan_op_ch_only = 1;
3699 				_set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
3700 			}
3701 		}
3702 		break;
3703 	case P2P_INVIT_REQ:
3704 		/*	Added by Albert 2010/10/05 */
3705 		/*	Received the P2P Invite Request frame. */
3706 
3707 		p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
3708 		if (p2p_ie) {
3709 			/*	Parse the necessary information from the P2P Invitation Request frame. */
3710 			/*	For example: The MAC address of sending this P2P Invitation Request frame. */
3711 			u32	attr_contentlen = 0;
3712 			u8	status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
3713 			struct group_id_info group_id;
3714 			u8	invitation_flag = 0;
3715 
3716 			rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
3717 			if (attr_contentlen) {
3718 				rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
3719 				/*	Commented by Albert 20120510 */
3720 				/*	Copy to the pwdinfo->p2p_peer_interface_addr. */
3721 				/*	So that the WFD UI (or Sigma) can get the peer interface address by using the following command. */
3722 				/*	#> iwpriv wlan0 p2p_get peer_ifa */
3723 				/*	After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
3724 
3725 				if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT) {
3726 					/*	Re-invoke the persistent group. */
3727 
3728 					memset(&group_id, 0x00, sizeof(struct group_id_info));
3729 					rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
3730 					if (attr_contentlen) {
3731 						if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
3732 							/*	The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
3733 							rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);
3734 							rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3735 							status_code = P2P_STATUS_SUCCESS;
3736 						} else {
3737 							/*	The p2p device sending this p2p invitation request wants to be the persistent GO. */
3738 							if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[0])) {
3739 								u8 operatingch_info[5] = { 0x00 };
3740 								if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
3741 									if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4])) {
3742 										/*	The operating channel is acceptable for this device. */
3743 										pwdinfo->rx_invitereq_info.operation_ch[0] = operatingch_info[4];
3744 										pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
3745 										_set_timer(&pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH);
3746 										rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
3747 										rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3748 										status_code = P2P_STATUS_SUCCESS;
3749 									} else {
3750 										/*	The operating channel isn't supported by this device. */
3751 										rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
3752 										rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3753 										status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
3754 										_set_timer(&pwdinfo->restore_p2p_state_timer, 3000);
3755 									}
3756 								} else {
3757 									/*	Commented by Albert 20121130 */
3758 									/*	Intel will use the different P2P IE to store the operating channel information */
3759 									/*	Workaround for Intel WiDi 3.5 */
3760 									rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
3761 									rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3762 									status_code = P2P_STATUS_SUCCESS;
3763 								}
3764 							} else {
3765 								rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
3766 								status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
3767 							}
3768 						}
3769 					} else {
3770 						status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
3771 					}
3772 				} else {
3773 					/*	Received the invitation to join a P2P group. */
3774 
3775 					memset(&group_id, 0x00, sizeof(struct group_id_info));
3776 					rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
3777 					if (attr_contentlen) {
3778 						if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
3779 							/*	In this case, the GO can't be myself. */
3780 							rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
3781 							status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
3782 						} else {
3783 							/*	The p2p device sending this p2p invitation request wants to join an existing P2P group */
3784 							/*	Commented by Albert 2012/06/28 */
3785 							/*	In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
3786 							/*	The peer device address should be the destination address for the provisioning discovery request. */
3787 							/*	Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
3788 							/*	The peer interface address should be the address for WPS mac address */
3789 							memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr, ETH_ALEN);
3790 							rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3791 							rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);
3792 							status_code = P2P_STATUS_SUCCESS;
3793 						}
3794 					} else {
3795 						status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
3796 					}
3797 				}
3798 			} else {
3799 				status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
3800 			}
3801 
3802 			pwdinfo->inviteresp_info.token = frame_body[7];
3803 			issue_p2p_invitation_response(padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code);
3804 		}
3805 		break;
3806 	case P2P_INVIT_RESP: {
3807 		u8	attr_content = 0x00;
3808 		u32	attr_contentlen = 0;
3809 
3810 		_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3811 		p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
3812 		if (p2p_ie) {
3813 			rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
3814 
3815 			if (attr_contentlen == 1) {
3816 				pwdinfo->invitereq_info.benable = false;
3817 
3818 				if (attr_content == P2P_STATUS_SUCCESS) {
3819 					if (!memcmp(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv), ETH_ALEN)) {
3820 						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3821 					} else {
3822 						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3823 					}
3824 					rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);
3825 				} else {
3826 					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3827 					rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
3828 				}
3829 			} else {
3830 				rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3831 				rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
3832 			}
3833 		} else {
3834 			rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3835 			rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
3836 		}
3837 
3838 		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL))
3839 			_set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
3840 		break;
3841 	}
3842 	case P2P_DEVDISC_REQ:
3843 		process_p2p_devdisc_req(pwdinfo, pframe, len);
3844 		break;
3845 	case P2P_DEVDISC_RESP:
3846 		process_p2p_devdisc_resp(pwdinfo, pframe, len);
3847 		break;
3848 	case P2P_PROVISION_DISC_REQ:
3849 		process_p2p_provdisc_req(pwdinfo, pframe, len);
3850 		memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
3851 
3852 		/* 20110902 Kurt */
3853 		/* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
3854 		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
3855 			rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3856 
3857 		rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
3858 		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
3859 		break;
3860 	case P2P_PROVISION_DISC_RESP:
3861 		/*	Commented by Albert 20110707 */
3862 		/*	Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
3863 		/*	Commented by Albert 20110426 */
3864 		/*	The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
3865 		_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3866 		rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
3867 		process_p2p_provdisc_resp(pwdinfo, pframe);
3868 		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
3869 		break;
3870 	}
3871 
3872 	return _SUCCESS;
3873 }
3874 
on_action_public_vendor(struct recv_frame * precv_frame)3875 static unsigned int on_action_public_vendor(struct recv_frame *precv_frame)
3876 {
3877 	unsigned int ret = _FAIL;
3878 	u8 *pframe = precv_frame->rx_data;
3879 	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
3880 
3881 	if (!memcmp(frame_body + 2, P2P_OUI, 4)) {
3882 		ret = on_action_public_p2p(precv_frame);
3883 	}
3884 
3885 	return ret;
3886 }
3887 
on_action_public_default(struct recv_frame * precv_frame)3888 static unsigned int on_action_public_default(struct recv_frame *precv_frame)
3889 {
3890 	unsigned int ret = _FAIL;
3891 	u8 *pframe = precv_frame->rx_data;
3892 	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
3893 	u8 token;
3894 
3895 	token = frame_body[2];
3896 
3897 	if (rtw_action_public_decache(precv_frame, token) == _FAIL)
3898 		goto exit;
3899 
3900 	ret = _SUCCESS;
3901 
3902 exit:
3903 	return ret;
3904 }
3905 
on_action_public(struct adapter * padapter,struct recv_frame * precv_frame)3906 unsigned int on_action_public(struct adapter *padapter, struct recv_frame *precv_frame)
3907 {
3908 	unsigned int ret = _FAIL;
3909 	u8 *pframe = precv_frame->rx_data;
3910 	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
3911 	u8 category, action;
3912 
3913 	/* check RA matches or not */
3914 	if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe), ETH_ALEN))
3915 		goto exit;
3916 
3917 	category = frame_body[0];
3918 	if (category != WLAN_CATEGORY_PUBLIC)
3919 		goto exit;
3920 
3921 	action = frame_body[1];
3922 	switch (action) {
3923 	case ACT_PUBLIC_VENDOR:
3924 		ret = on_action_public_vendor(precv_frame);
3925 		break;
3926 	default:
3927 		ret = on_action_public_default(precv_frame);
3928 		break;
3929 	}
3930 
3931 exit:
3932 	return ret;
3933 }
3934 
OnAction_p2p(struct adapter * padapter,struct recv_frame * precv_frame)3935 unsigned int OnAction_p2p(struct adapter *padapter, struct recv_frame *precv_frame)
3936 {
3937 	u8 *frame_body;
3938 	u8 category, OUI_Subtype;
3939 	u8 *pframe = precv_frame->rx_data;
3940 	uint len = precv_frame->len;
3941 	struct	wifidirect_info	*pwdinfo = &padapter->wdinfo;
3942 
3943 	/* check RA matches or not */
3944 	if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
3945 		return _SUCCESS;
3946 
3947 	frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
3948 
3949 	category = frame_body[0];
3950 	if (category != RTW_WLAN_CATEGORY_P2P)
3951 		return _SUCCESS;
3952 
3953 	if (be32_to_cpu(*((__be32 *)(frame_body + 1))) != P2POUI)
3954 		return _SUCCESS;
3955 
3956 	len -= sizeof(struct ieee80211_hdr_3addr);
3957 	OUI_Subtype = frame_body[5];
3958 
3959 	switch (OUI_Subtype) {
3960 	case P2P_NOTICE_OF_ABSENCE:
3961 		break;
3962 	case P2P_PRESENCE_REQUEST:
3963 		process_p2p_presence_req(pwdinfo, pframe, len);
3964 		break;
3965 	case P2P_PRESENCE_RESPONSE:
3966 		break;
3967 	case P2P_GO_DISC_REQUEST:
3968 		break;
3969 	default:
3970 		break;
3971 	}
3972 	return _SUCCESS;
3973 }
3974 
OnAction(struct adapter * padapter,struct recv_frame * precv_frame)3975 unsigned int OnAction(struct adapter *padapter, struct recv_frame *precv_frame)
3976 {
3977 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data;
3978 
3979 	switch (mgmt->u.action.category) {
3980 	case WLAN_CATEGORY_BACK:
3981 		OnAction_back(padapter, precv_frame);
3982 		break;
3983 	case WLAN_CATEGORY_PUBLIC:
3984 		on_action_public(padapter, precv_frame);
3985 		break;
3986 	case RTW_WLAN_CATEGORY_P2P:
3987 		OnAction_p2p(padapter, precv_frame);
3988 		break;
3989 	}
3990 	return _SUCCESS;
3991 }
3992 
alloc_mgtxmitframe(struct xmit_priv * pxmitpriv)3993 struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
3994 {
3995 	struct xmit_frame			*pmgntframe;
3996 	struct xmit_buf				*pxmitbuf;
3997 
3998 	pmgntframe = rtw_alloc_xmitframe(pxmitpriv);
3999 	if (!pmgntframe)
4000 		return NULL;
4001 
4002 	pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
4003 	if (!pxmitbuf) {
4004 		rtw_free_xmitframe(pxmitpriv, pmgntframe);
4005 		return NULL;
4006 	}
4007 	pmgntframe->frame_tag = MGNT_FRAMETAG;
4008 	pmgntframe->pxmitbuf = pxmitbuf;
4009 	pmgntframe->buf_addr = pxmitbuf->pbuf;
4010 	pxmitbuf->priv_data = pmgntframe;
4011 	return pmgntframe;
4012 }
4013 
4014 /****************************************************************************
4015 
4016 Following are some TX fuctions for WiFi MLME
4017 
4018 *****************************************************************************/
4019 
update_mgnt_tx_rate(struct adapter * padapter,u8 rate)4020 void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
4021 {
4022 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
4023 
4024 	pmlmeext->tx_rate = rate;
4025 }
4026 
update_mgntframe_attrib(struct adapter * padapter,struct pkt_attrib * pattrib)4027 void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
4028 {
4029 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
4030 
4031 	memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
4032 
4033 	pattrib->hdrlen = 24;
4034 	pattrib->nr_frags = 1;
4035 	pattrib->priority = 7;
4036 	pattrib->mac_id = 0;
4037 	pattrib->qsel = 0x12;
4038 
4039 	pattrib->pktlen = 0;
4040 
4041 	if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
4042 		pattrib->raid = 6;/* b mode */
4043 	else
4044 		pattrib->raid = 5;/* a/g mode */
4045 
4046 	pattrib->encrypt = _NO_PRIVACY_;
4047 	pattrib->bswenc = false;
4048 
4049 	pattrib->qos_en = false;
4050 	pattrib->ht_en = false;
4051 	pattrib->bwmode = HT_CHANNEL_WIDTH_20;
4052 	pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4053 	pattrib->sgi = false;
4054 
4055 	pattrib->seqnum = pmlmeext->mgnt_seq;
4056 
4057 	pattrib->retry_ctrl = true;
4058 }
4059 
dump_mgntframe(struct adapter * padapter,struct xmit_frame * pmgntframe)4060 void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
4061 {
4062 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4063 		return;
4064 
4065 	rtl8188eu_mgnt_xmit(padapter, pmgntframe);
4066 }
4067 
dump_mgntframe_and_wait(struct adapter * padapter,struct xmit_frame * pmgntframe,int timeout_ms)4068 s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
4069 {
4070 	s32 ret = _FAIL;
4071 	struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
4072 	struct submit_ctx sctx;
4073 
4074 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4075 		return ret;
4076 
4077 	rtw_sctx_init(&sctx, timeout_ms);
4078 	pxmitbuf->sctx = &sctx;
4079 
4080 	ret = rtl8188eu_mgnt_xmit(padapter, pmgntframe);
4081 
4082 	if (ret == _SUCCESS)
4083 		ret = rtw_sctx_wait(&sctx);
4084 
4085 	return ret;
4086 }
4087 
dump_mgntframe_and_wait_ack(struct adapter * padapter,struct xmit_frame * pmgntframe)4088 s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
4089 {
4090 	s32 ret = _FAIL;
4091 	u32 timeout_ms = 500;/*   500ms */
4092 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
4093 
4094 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4095 		return -1;
4096 
4097 	mutex_lock(&pxmitpriv->ack_tx_mutex);
4098 	pxmitpriv->ack_tx = true;
4099 
4100 	pmgntframe->ack_report = 1;
4101 	if (rtl8188eu_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
4102 		ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
4103 	}
4104 
4105 	pxmitpriv->ack_tx = false;
4106 	mutex_unlock(&pxmitpriv->ack_tx_mutex);
4107 
4108 	return ret;
4109 }
4110 
update_hidden_ssid(u8 * ies,u32 ies_len,u8 hidden_ssid_mode)4111 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
4112 {
4113 	u8 *ssid_ie;
4114 	int ssid_len_ori;
4115 	int len_diff = 0;
4116 
4117 	ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
4118 
4119 	if (ssid_ie && ssid_len_ori > 0) {
4120 		switch (hidden_ssid_mode) {
4121 		case 1: {
4122 			u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
4123 			u32 remain_len = 0;
4124 
4125 			remain_len = ies_len - (next_ie - ies);
4126 
4127 			ssid_ie[1] = 0;
4128 			memcpy(ssid_ie + 2, next_ie, remain_len);
4129 			len_diff -= ssid_len_ori;
4130 
4131 			break;
4132 		}
4133 		case 2:
4134 			memset(&ssid_ie[2], 0, ssid_len_ori);
4135 			break;
4136 		default:
4137 			break;
4138 		}
4139 	}
4140 
4141 	return len_diff;
4142 }
4143 
issue_beacon(struct adapter * padapter,int timeout_ms)4144 void issue_beacon(struct adapter *padapter, int timeout_ms)
4145 {
4146 	struct xmit_frame	*pmgntframe;
4147 	struct pkt_attrib	*pattrib;
4148 	unsigned char	*pframe;
4149 	struct ieee80211_hdr *pwlanhdr;
4150 	__le16 *fctrl;
4151 	unsigned int	rate_len;
4152 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
4153 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4154 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
4155 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
4156 	struct wlan_bssid_ex		*cur_network = &pmlmeinfo->network;
4157 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
4158 
4159 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4160 	if (!pmgntframe)
4161 		return;
4162 	spin_lock_bh(&pmlmepriv->bcn_update_lock);
4163 
4164 	/* update attribute */
4165 	pattrib = &pmgntframe->attrib;
4166 	update_mgntframe_attrib(padapter, pattrib);
4167 	pattrib->qsel = 0x10;
4168 
4169 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4170 
4171 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4172 	pwlanhdr = (struct ieee80211_hdr *)pframe;
4173 
4174 	fctrl = &pwlanhdr->frame_control;
4175 	*(fctrl) = 0;
4176 
4177 	eth_broadcast_addr(pwlanhdr->addr1);
4178 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
4179 	memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
4180 
4181 	SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
4182 	/* pmlmeext->mgnt_seq++; */
4183 	SetFrameSubType(pframe, WIFI_BEACON);
4184 
4185 	pframe += sizeof(struct ieee80211_hdr_3addr);
4186 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4187 
4188 	if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
4189 		/*  for P2P : Primary Device Type & Device Name */
4190 		u32 wpsielen = 0, insert_len = 0;
4191 		u8 *wpsie = NULL;
4192 		wpsie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen);
4193 
4194 		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) {
4195 			uint wps_offset, remainder_ielen;
4196 			u8 *premainder_ie, *pframe_wscie;
4197 
4198 			wps_offset = (uint)(wpsie - cur_network->IEs);
4199 			premainder_ie = wpsie + wpsielen;
4200 			remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
4201 			pframe_wscie = pframe + wps_offset;
4202 			memcpy(pframe, cur_network->IEs, wps_offset + wpsielen);
4203 			pframe += (wps_offset + wpsielen);
4204 			pattrib->pktlen += (wps_offset + wpsielen);
4205 
4206 			/* now pframe is end of wsc ie, insert Primary Device Type & Device Name */
4207 			/*	Primary Device Type */
4208 			/*	Type: */
4209 			*(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
4210 			insert_len += 2;
4211 
4212 			/*	Length: */
4213 			*(__be16 *)(pframe + insert_len) = cpu_to_be16(0x0008);
4214 			insert_len += 2;
4215 
4216 			/*	Value: */
4217 			/*	Category ID */
4218 			*(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
4219 			insert_len += 2;
4220 
4221 			/*	OUI */
4222 			*(__be32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI);
4223 			insert_len += 4;
4224 
4225 			/*	Sub Category ID */
4226 			*(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
4227 			insert_len += 2;
4228 
4229 			/*	Device Name */
4230 			/*	Type: */
4231 			*(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
4232 			insert_len += 2;
4233 
4234 			/*	Length: */
4235 			*(__be16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len);
4236 			insert_len += 2;
4237 
4238 			/*	Value: */
4239 			memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len);
4240 			insert_len += pwdinfo->device_name_len;
4241 
4242 			/* update wsc ie length */
4243 			*(pframe_wscie + 1) = (wpsielen - 2) + insert_len;
4244 
4245 			/* pframe move to end */
4246 			pframe += insert_len;
4247 			pattrib->pktlen += insert_len;
4248 
4249 			/* copy remainder_ie to pframe */
4250 			memcpy(pframe, premainder_ie, remainder_ielen);
4251 			pframe += remainder_ielen;
4252 			pattrib->pktlen += remainder_ielen;
4253 		} else {
4254 			int len_diff;
4255 			memcpy(pframe, cur_network->IEs, cur_network->IELength);
4256 			len_diff = update_hidden_ssid(
4257 				pframe + _BEACON_IE_OFFSET_
4258 				, cur_network->IELength - _BEACON_IE_OFFSET_
4259 				, pmlmeinfo->hidden_ssid_mode
4260 			);
4261 			pframe += (cur_network->IELength + len_diff);
4262 			pattrib->pktlen += (cur_network->IELength + len_diff);
4263 		}
4264 
4265 		{
4266 			u8 *wps_ie;
4267 			uint wps_ielen;
4268 			u8 sr = 0;
4269 			wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_,
4270 				pattrib->pktlen - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen);
4271 			if (wps_ie && wps_ielen > 0)
4272 				rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
4273 			if (sr != 0)
4274 				set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
4275 			else
4276 				_clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
4277 		}
4278 
4279 		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
4280 			u32 len;
4281 			len = build_beacon_p2p_ie(pwdinfo, pframe);
4282 
4283 			pframe += len;
4284 			pattrib->pktlen += len;
4285 		}
4286 
4287 		goto _issue_bcn;
4288 	}
4289 
4290 	/* below for ad-hoc mode */
4291 
4292 	/* timestamp will be inserted by hardware */
4293 	pframe += 8;
4294 	pattrib->pktlen += 8;
4295 
4296 	/*  beacon interval: 2 bytes */
4297 
4298 	memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
4299 
4300 	pframe += 2;
4301 	pattrib->pktlen += 2;
4302 
4303 	/*  capability info: 2 bytes */
4304 
4305 	memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
4306 
4307 	pframe += 2;
4308 	pattrib->pktlen += 2;
4309 
4310 	/*  SSID */
4311 	pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
4312 
4313 	/*  supported rates... */
4314 	rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
4315 	pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
4316 
4317 	/*  DS parameter set */
4318 	pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
4319 
4320 	{
4321 		u8 erpinfo = 0;
4322 		u32 ATIMWindow;
4323 		/*  IBSS Parameter Set... */
4324 		ATIMWindow = 0;
4325 		pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
4326 
4327 		/* ERP IE */
4328 		pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
4329 	}
4330 
4331 	/*  EXTERNDED SUPPORTED RATE */
4332 	if (rate_len > 8)
4333 		pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
4334 	/* todo:HT for adhoc */
4335 _issue_bcn:
4336 
4337 	pmlmepriv->update_bcn = false;
4338 
4339 	spin_unlock_bh(&pmlmepriv->bcn_update_lock);
4340 
4341 	if ((pattrib->pktlen + TXDESC_SIZE) > 512)
4342 		return;
4343 
4344 	pattrib->last_txcmdsz = pattrib->pktlen;
4345 
4346 	if (timeout_ms > 0)
4347 		dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
4348 	else
4349 		dump_mgntframe(padapter, pmgntframe);
4350 }
4351 
issue_probersp(struct adapter * padapter,unsigned char * da,u8 is_valid_p2p_probereq)4352 void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
4353 {
4354 	struct xmit_frame			*pmgntframe;
4355 	struct pkt_attrib			*pattrib;
4356 	unsigned char					*pframe;
4357 	struct ieee80211_hdr *pwlanhdr;
4358 	__le16 *fctrl;
4359 	unsigned char					*mac, *bssid;
4360 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
4361 	u8 *pwps_ie;
4362 	uint wps_ielen;
4363 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4364 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
4365 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
4366 	struct wlan_bssid_ex		*cur_network = &pmlmeinfo->network;
4367 	unsigned int	rate_len;
4368 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
4369 
4370 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4371 	if (!pmgntframe)
4372 		return;
4373 
4374 	/* update attribute */
4375 	pattrib = &pmgntframe->attrib;
4376 	update_mgntframe_attrib(padapter, pattrib);
4377 
4378 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4379 
4380 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4381 	pwlanhdr = (struct ieee80211_hdr *)pframe;
4382 
4383 	mac = myid(&padapter->eeprompriv);
4384 	bssid = cur_network->MacAddress;
4385 
4386 	fctrl = &pwlanhdr->frame_control;
4387 	*(fctrl) = 0;
4388 	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
4389 	memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
4390 	memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
4391 
4392 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4393 	pmlmeext->mgnt_seq++;
4394 	SetFrameSubType(fctrl, WIFI_PROBERSP);
4395 
4396 	pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
4397 	pattrib->pktlen = pattrib->hdrlen;
4398 	pframe += pattrib->hdrlen;
4399 
4400 	if (cur_network->IELength > MAX_IE_SZ)
4401 		return;
4402 
4403 	if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
4404 		pwps_ie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
4405 
4406 		/* inerset & update wps_probe_resp_ie */
4407 		if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
4408 			uint wps_offset, remainder_ielen;
4409 			u8 *premainder_ie;
4410 
4411 			wps_offset = (uint)(pwps_ie - cur_network->IEs);
4412 
4413 			premainder_ie = pwps_ie + wps_ielen;
4414 
4415 			remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
4416 
4417 			memcpy(pframe, cur_network->IEs, wps_offset);
4418 			pframe += wps_offset;
4419 			pattrib->pktlen += wps_offset;
4420 
4421 			wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
4422 			if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) {
4423 				memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2);
4424 				pframe += wps_ielen + 2;
4425 				pattrib->pktlen += wps_ielen + 2;
4426 			}
4427 
4428 			if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {
4429 				memcpy(pframe, premainder_ie, remainder_ielen);
4430 				pframe += remainder_ielen;
4431 				pattrib->pktlen += remainder_ielen;
4432 			}
4433 		} else {
4434 			memcpy(pframe, cur_network->IEs, cur_network->IELength);
4435 			pframe += cur_network->IELength;
4436 			pattrib->pktlen += cur_network->IELength;
4437 		}
4438 	} else {
4439 		/* timestamp will be inserted by hardware */
4440 		pframe += 8;
4441 		pattrib->pktlen += 8;
4442 
4443 		/*  beacon interval: 2 bytes */
4444 
4445 		memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
4446 
4447 		pframe += 2;
4448 		pattrib->pktlen += 2;
4449 
4450 		/*  capability info: 2 bytes */
4451 
4452 		memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
4453 
4454 		pframe += 2;
4455 		pattrib->pktlen += 2;
4456 
4457 		/* below for ad-hoc mode */
4458 
4459 		/*  SSID */
4460 		pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
4461 
4462 		/*  supported rates... */
4463 		rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
4464 		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
4465 
4466 		/*  DS parameter set */
4467 		pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
4468 
4469 		if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
4470 			u8 erpinfo = 0;
4471 			u32 ATIMWindow;
4472 			/*  IBSS Parameter Set... */
4473 			/* ATIMWindow = cur->Configuration.ATIMWindow; */
4474 			ATIMWindow = 0;
4475 			pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
4476 
4477 			/* ERP IE */
4478 			pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
4479 		}
4480 
4481 		/*  EXTERNDED SUPPORTED RATE */
4482 		if (rate_len > 8)
4483 			pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
4484 		/* todo:HT for adhoc */
4485 	}
4486 
4487 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) {
4488 		u32 len;
4489 		len = build_probe_resp_p2p_ie(pwdinfo, pframe);
4490 
4491 		pframe += len;
4492 		pattrib->pktlen += len;
4493 	}
4494 
4495 	pattrib->last_txcmdsz = pattrib->pktlen;
4496 
4497 	dump_mgntframe(padapter, pmgntframe);
4498 }
4499 
_issue_probereq(struct adapter * padapter,struct ndis_802_11_ssid * pssid,u8 * da,int wait_ack)4500 static int _issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, int wait_ack)
4501 {
4502 	int ret = _FAIL;
4503 	struct xmit_frame		*pmgntframe;
4504 	struct pkt_attrib		*pattrib;
4505 	unsigned char			*pframe;
4506 	struct ieee80211_hdr *pwlanhdr;
4507 	__le16 *fctrl;
4508 	unsigned char			*mac;
4509 	unsigned char			bssrate[NumRates];
4510 	struct xmit_priv		*pxmitpriv = &padapter->xmitpriv;
4511 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4512 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
4513 	int	bssrate_len = 0;
4514 
4515 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4516 	if (!pmgntframe)
4517 		goto exit;
4518 
4519 	/* update attribute */
4520 	pattrib = &pmgntframe->attrib;
4521 	update_mgntframe_attrib(padapter, pattrib);
4522 
4523 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4524 
4525 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4526 	pwlanhdr = (struct ieee80211_hdr *)pframe;
4527 
4528 	mac = myid(&padapter->eeprompriv);
4529 
4530 	fctrl = &pwlanhdr->frame_control;
4531 	*(fctrl) = 0;
4532 
4533 	if (da) {
4534 		/*	unicast probe request frame */
4535 		memcpy(pwlanhdr->addr1, da, ETH_ALEN);
4536 		memcpy(pwlanhdr->addr3, da, ETH_ALEN);
4537 	} else {
4538 		/*	broadcast probe request frame */
4539 		eth_broadcast_addr(pwlanhdr->addr1);
4540 		eth_broadcast_addr(pwlanhdr->addr3);
4541 	}
4542 
4543 	memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
4544 
4545 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4546 	pmlmeext->mgnt_seq++;
4547 	SetFrameSubType(pframe, WIFI_PROBEREQ);
4548 
4549 	pframe += sizeof(struct ieee80211_hdr_3addr);
4550 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4551 
4552 	if (pssid)
4553 		pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &pattrib->pktlen);
4554 	else
4555 		pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pattrib->pktlen);
4556 
4557 	get_rate_set(padapter, bssrate, &bssrate_len);
4558 
4559 	if (bssrate_len > 8) {
4560 		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen);
4561 		pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
4562 	} else {
4563 		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen);
4564 	}
4565 
4566 	/* add wps_ie for wps2.0 */
4567 	if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
4568 		memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
4569 		pframe += pmlmepriv->wps_probe_req_ie_len;
4570 		pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
4571 	}
4572 
4573 	pattrib->last_txcmdsz = pattrib->pktlen;
4574 
4575 	if (wait_ack) {
4576 		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
4577 	} else {
4578 		dump_mgntframe(padapter, pmgntframe);
4579 		ret = _SUCCESS;
4580 	}
4581 
4582 exit:
4583 	return ret;
4584 }
4585 
issue_probereq(struct adapter * padapter,struct ndis_802_11_ssid * pssid,u8 * da)4586 inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
4587 {
4588 	_issue_probereq(padapter, pssid, da, false);
4589 }
4590 
issue_probereq_ex(struct adapter * padapter,struct ndis_802_11_ssid * pssid,u8 * da,int try_cnt,int wait_ms)4591 int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da,
4592 	int try_cnt, int wait_ms)
4593 {
4594 	int ret;
4595 	int i = 0;
4596 
4597 	do {
4598 		ret = _issue_probereq(padapter, pssid, da, wait_ms > 0);
4599 
4600 		i++;
4601 
4602 		if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
4603 			break;
4604 
4605 		if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
4606 			msleep(wait_ms);
4607 
4608 	} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
4609 
4610 	if (ret != _FAIL) {
4611 		ret = _SUCCESS;
4612 		goto exit;
4613 	}
4614 exit:
4615 	return ret;
4616 }
4617 
4618 /*  if psta == NULL, indiate we are station(client) now... */
issue_auth(struct adapter * padapter,struct sta_info * psta,unsigned short status)4619 void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
4620 {
4621 	struct xmit_frame *pmgntframe;
4622 	struct pkt_attrib *pattrib;
4623 	unsigned char *pframe;
4624 	struct ieee80211_hdr *pwlanhdr;
4625 	__le16 *fctrl;
4626 	unsigned int val32;
4627 	u16 val16;
4628 	__le16 le_val16;
4629 	int use_shared_key = 0;
4630 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4631 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
4632 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
4633 
4634 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4635 	if (!pmgntframe)
4636 		return;
4637 
4638 	/* update attribute */
4639 	pattrib = &pmgntframe->attrib;
4640 	update_mgntframe_attrib(padapter, pattrib);
4641 
4642 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4643 
4644 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4645 	pwlanhdr = (struct ieee80211_hdr *)pframe;
4646 
4647 	fctrl = &pwlanhdr->frame_control;
4648 	*(fctrl) = 0;
4649 
4650 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4651 	pmlmeext->mgnt_seq++;
4652 	SetFrameSubType(pframe, WIFI_AUTH);
4653 
4654 	pframe += sizeof(struct ieee80211_hdr_3addr);
4655 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4656 
4657 	if (psta) {/*  for AP mode */
4658 		memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
4659 		memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
4660 		memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
4661 
4662 		/*  setting auth algo number */
4663 		val16 = (u16)psta->authalg;
4664 
4665 		if (status != _STATS_SUCCESSFUL_)
4666 			val16 = 0;
4667 
4668 		if (val16) {
4669 			le_val16 = cpu_to_le16(val16);
4670 			use_shared_key = 1;
4671 		} else {
4672 			le_val16 = 0;
4673 		}
4674 
4675 		pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_val16, &pattrib->pktlen);
4676 
4677 		/*  setting auth seq number */
4678 		val16 = (u16)psta->auth_seq;
4679 		le_val16 = cpu_to_le16(val16);
4680 		pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_val16, &pattrib->pktlen);
4681 
4682 		/*  setting status code... */
4683 		val16 = status;
4684 		le_val16 = cpu_to_le16(val16);
4685 		pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_val16, &pattrib->pktlen);
4686 
4687 		/*  added challenging text... */
4688 		if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
4689 			pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &pattrib->pktlen);
4690 	} else {
4691 		__le32 le_tmp32;
4692 		__le16 le_tmp16;
4693 		memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
4694 		memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
4695 		memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
4696 
4697 		/*  setting auth algo number */
4698 		val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/*  0:OPEN System, 1:Shared key */
4699 		if (val16)
4700 			use_shared_key = 1;
4701 
4702 		/* setting IV for auth seq #3 */
4703 		if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
4704 			val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
4705 			le_tmp32 = cpu_to_le32(val32);
4706 			pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &pattrib->pktlen);
4707 
4708 			pattrib->iv_len = 4;
4709 		}
4710 
4711 		le_tmp16 = cpu_to_le16(val16);
4712 		pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp16, &pattrib->pktlen);
4713 
4714 		/*  setting auth seq number */
4715 		val16 = pmlmeinfo->auth_seq;
4716 		le_tmp16 = cpu_to_le16(val16);
4717 		pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp16, &pattrib->pktlen);
4718 
4719 		/*  setting status code... */
4720 		le_tmp16 = cpu_to_le16(status);
4721 		pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp16, &pattrib->pktlen);
4722 
4723 		/*  then checking to see if sending challenging text... */
4724 		if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
4725 			pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &pattrib->pktlen);
4726 
4727 			SetPrivacy(fctrl);
4728 
4729 			pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
4730 
4731 			pattrib->encrypt = _WEP40_;
4732 
4733 			pattrib->icv_len = 4;
4734 
4735 			pattrib->pktlen += pattrib->icv_len;
4736 		}
4737 	}
4738 
4739 	pattrib->last_txcmdsz = pattrib->pktlen;
4740 
4741 	rtw_wep_encrypt(padapter, pmgntframe);
4742 	dump_mgntframe(padapter, pmgntframe);
4743 }
4744 
issue_asocrsp(struct adapter * padapter,unsigned short status,struct sta_info * pstat,int pkt_type)4745 void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
4746 {
4747 	struct xmit_frame	*pmgntframe;
4748 	struct ieee80211_hdr *pwlanhdr;
4749 	struct pkt_attrib *pattrib;
4750 	unsigned char	*pbuf, *pframe;
4751 	unsigned short val;
4752 	__le16 *fctrl;
4753 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4754 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4755 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4756 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
4757 	struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4758 	u8 *ie = pnetwork->IEs;
4759 	__le16 lestatus, leval;
4760 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
4761 
4762 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4763 	if (!pmgntframe)
4764 		return;
4765 
4766 	/* update attribute */
4767 	pattrib = &pmgntframe->attrib;
4768 	update_mgntframe_attrib(padapter, pattrib);
4769 
4770 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4771 
4772 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4773 	pwlanhdr = (struct ieee80211_hdr *)pframe;
4774 
4775 	fctrl = &pwlanhdr->frame_control;
4776 	*(fctrl) = 0;
4777 
4778 	memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
4779 	memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&padapter->eeprompriv), ETH_ALEN);
4780 	memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
4781 
4782 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4783 	pmlmeext->mgnt_seq++;
4784 	if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
4785 		SetFrameSubType(pwlanhdr, pkt_type);
4786 	else
4787 		return;
4788 
4789 	pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
4790 	pattrib->pktlen += pattrib->hdrlen;
4791 	pframe += pattrib->hdrlen;
4792 
4793 	/* capability */
4794 	val = *(unsigned short *)rtw_get_capability_from_ie(ie);
4795 
4796 	pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &pattrib->pktlen);
4797 
4798 	lestatus = cpu_to_le16(status);
4799 	pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &pattrib->pktlen);
4800 
4801 	leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
4802 	pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&leval, &pattrib->pktlen);
4803 
4804 	if (pstat->bssratelen <= 8) {
4805 		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &pattrib->pktlen);
4806 	} else {
4807 		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &pattrib->pktlen);
4808 		pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, pstat->bssratelen - 8, pstat->bssrateset + 8, &pattrib->pktlen);
4809 	}
4810 
4811 	if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
4812 		uint ie_len = 0;
4813 
4814 		/* FILL HT CAP INFO IE */
4815 		pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
4816 		if (pbuf && ie_len > 0) {
4817 			memcpy(pframe, pbuf, ie_len + 2);
4818 			pframe += (ie_len + 2);
4819 			pattrib->pktlen += (ie_len + 2);
4820 		}
4821 
4822 		/* FILL HT ADD INFO IE */
4823 		pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
4824 		if (pbuf && ie_len > 0) {
4825 			memcpy(pframe, pbuf, ie_len + 2);
4826 			pframe += (ie_len + 2);
4827 			pattrib->pktlen += (ie_len + 2);
4828 		}
4829 	}
4830 
4831 	/* FILL WMM IE */
4832 	if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
4833 		uint ie_len = 0;
4834 		unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
4835 
4836 		for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
4837 			pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
4838 			if (pbuf && !memcmp(pbuf + 2, WMM_PARA_IE, 6)) {
4839 				memcpy(pframe, pbuf, ie_len + 2);
4840 				pframe += (ie_len + 2);
4841 				pattrib->pktlen += (ie_len + 2);
4842 				break;
4843 			}
4844 
4845 			if (!pbuf || ie_len == 0)
4846 				break;
4847 		}
4848 	}
4849 
4850 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
4851 		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen);
4852 
4853 	/* add WPS IE ie for wps 2.0 */
4854 	if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
4855 		memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
4856 
4857 		pframe += pmlmepriv->wps_assoc_resp_ie_len;
4858 		pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
4859 	}
4860 
4861 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device)) {
4862 		u32 len;
4863 
4864 		len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
4865 
4866 		pframe += len;
4867 		pattrib->pktlen += len;
4868 	}
4869 	pattrib->last_txcmdsz = pattrib->pktlen;
4870 	dump_mgntframe(padapter, pmgntframe);
4871 }
4872 
issue_assocreq(struct adapter * padapter)4873 void issue_assocreq(struct adapter *padapter)
4874 {
4875 	int ret = _FAIL;
4876 	struct xmit_frame	*pmgntframe;
4877 	struct pkt_attrib	*pattrib;
4878 	unsigned char		*pframe, *p;
4879 	struct ieee80211_hdr *pwlanhdr;
4880 	__le16 *fctrl;
4881 	__le16		le_tmp;
4882 	unsigned int	i, j, ie_len, index = 0;
4883 	unsigned char bssrate[NumRates], sta_bssrate[NumRates];
4884 	struct ndis_802_11_var_ie *pIE;
4885 	struct registry_priv	*pregpriv = &padapter->registrypriv;
4886 	struct xmit_priv		*pxmitpriv = &padapter->xmitpriv;
4887 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4888 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
4889 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
4890 	int	bssrate_len = 0, sta_bssrate_len = 0;
4891 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
4892 	u8 p2pie[255] = { 0x00 };
4893 	u16 p2pielen = 0;
4894 
4895 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4896 	if (!pmgntframe)
4897 		goto exit;
4898 
4899 	/* update attribute */
4900 	pattrib = &pmgntframe->attrib;
4901 	update_mgntframe_attrib(padapter, pattrib);
4902 
4903 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4904 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4905 	pwlanhdr = (struct ieee80211_hdr *)pframe;
4906 
4907 	fctrl = &pwlanhdr->frame_control;
4908 	*(fctrl) = 0;
4909 	memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
4910 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
4911 	memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
4912 
4913 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4914 	pmlmeext->mgnt_seq++;
4915 	SetFrameSubType(pframe, WIFI_ASSOCREQ);
4916 
4917 	pframe += sizeof(struct ieee80211_hdr_3addr);
4918 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4919 
4920 	/* caps */
4921 
4922 	memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
4923 
4924 	pframe += 2;
4925 	pattrib->pktlen += 2;
4926 
4927 	/* listen interval */
4928 	/* todo: listen interval for power saving */
4929 	le_tmp = cpu_to_le16(3);
4930 	memcpy(pframe, (unsigned char *)&le_tmp, 2);
4931 	pframe += 2;
4932 	pattrib->pktlen += 2;
4933 
4934 	/* SSID */
4935 	pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &pattrib->pktlen);
4936 
4937 	/* supported rate & extended supported rate */
4938 
4939 	/*  Check if the AP's supported rates are also supported by STA. */
4940 	get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
4941 
4942 	if (pmlmeext->cur_channel == 14)/*  for JAPAN, channel 14 can only uses B Mode(CCK) */
4943 		sta_bssrate_len = 4;
4944 
4945 	for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
4946 		if (pmlmeinfo->network.SupportedRates[i] == 0)
4947 			break;
4948 
4949 		/*  Check if the AP's supported rates are also supported by STA. */
4950 		for (j = 0; j < sta_bssrate_len; j++) {
4951 			 /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
4952 			if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK)
4953 					== (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK))
4954 				break;
4955 		}
4956 
4957 		if (j != sta_bssrate_len)
4958 			/*  the rate is supported by STA */
4959 			bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
4960 	}
4961 
4962 	bssrate_len = index;
4963 
4964 	if (bssrate_len == 0) {
4965 		rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
4966 		rtw_free_xmitframe(pxmitpriv, pmgntframe);
4967 		goto exit; /* don't connect to AP if no joint supported rate */
4968 	}
4969 
4970 	if (bssrate_len > 8) {
4971 		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen);
4972 		pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
4973 	} else {
4974 		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen);
4975 	}
4976 
4977 	/* RSN */
4978 	p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
4979 	if (p)
4980 		pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, p + 2, &pattrib->pktlen);
4981 
4982 	/* HT caps */
4983 	if (padapter->mlmepriv.htpriv.ht_option) {
4984 		p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
4985 		if (p && !is_ap_in_tkip(padapter)) {
4986 			memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct HT_caps_element));
4987 
4988 			/* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
4989 			if (pregpriv->cbw40_enable == 0)
4990 				pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1)));
4991 			else
4992 				pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(BIT(1));
4993 
4994 			/* todo: disable SM power save mode */
4995 			pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x000c);
4996 
4997 			if (pregpriv->rx_stbc)
4998 				pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
4999 			memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16);
5000 
5001 			pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len, (u8 *)(&pmlmeinfo->HT_caps), &pattrib->pktlen);
5002 		}
5003 	}
5004 
5005 	/* vendor specific IE, such as WPA, WMM, WPS */
5006 	for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) {
5007 		pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i);
5008 
5009 		switch (pIE->ElementID) {
5010 		case _VENDOR_SPECIFIC_IE_:
5011 			if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
5012 			    (!memcmp(pIE->data, WMM_OUI, 4)) ||
5013 			    (!memcmp(pIE->data, WPS_OUI, 4))) {
5014 				if (!padapter->registrypriv.wifi_spec) {
5015 					/* Commented by Kurt 20110629 */
5016 					/* In some older APs, WPS handshake */
5017 					/* would be fail if we append vender extensions informations to AP */
5018 					if (!memcmp(pIE->data, WPS_OUI, 4))
5019 						pIE->Length = 14;
5020 				}
5021 				pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &pattrib->pktlen);
5022 			}
5023 			break;
5024 		default:
5025 			break;
5026 		}
5027 		i += (pIE->Length + 2);
5028 	}
5029 
5030 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
5031 		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen);
5032 
5033 	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
5034 		/*	Should add the P2P IE in the association request frame. */
5035 		/*	P2P OUI */
5036 
5037 		p2pielen = 0;
5038 		p2pie[p2pielen++] = 0x50;
5039 		p2pie[p2pielen++] = 0x6F;
5040 		p2pie[p2pielen++] = 0x9A;
5041 		p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
5042 
5043 		/*	Commented by Albert 20101109 */
5044 		/*	According to the P2P Specification, the association request frame should contain 3 P2P attributes */
5045 		/*	1. P2P Capability */
5046 		/*	2. Extended Listen Timing */
5047 		/*	3. Device Info */
5048 		/*	Commented by Albert 20110516 */
5049 		/*	4. P2P Interface */
5050 
5051 		/*	P2P Capability */
5052 		/*	Type: */
5053 		p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
5054 
5055 		/*	Length: */
5056 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
5057 		p2pielen += 2;
5058 
5059 		/*	Value: */
5060 		/*	Device Capability Bitmap, 1 byte */
5061 		p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
5062 
5063 		/*	Group Capability Bitmap, 1 byte */
5064 		if (pwdinfo->persistent_supported)
5065 			p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
5066 		else
5067 			p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
5068 
5069 		/*	Extended Listen Timing */
5070 		/*	Type: */
5071 		p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
5072 
5073 		/*	Length: */
5074 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
5075 		p2pielen += 2;
5076 
5077 		/*	Value: */
5078 		/*	Availability Period */
5079 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
5080 		p2pielen += 2;
5081 
5082 		/*	Availability Interval */
5083 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
5084 		p2pielen += 2;
5085 
5086 		/*	Device Info */
5087 		/*	Type: */
5088 		p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
5089 
5090 		/*	Length: */
5091 		/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
5092 		/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
5093 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
5094 		p2pielen += 2;
5095 
5096 		/*	Value: */
5097 		/*	P2P Device Address */
5098 		memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
5099 		p2pielen += ETH_ALEN;
5100 
5101 		/*	Config Method */
5102 		/*	This field should be big endian. Noted by P2P specification. */
5103 		if ((pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||
5104 		    (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))
5105 			*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
5106 		else
5107 			*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC);
5108 
5109 		p2pielen += 2;
5110 
5111 		/*	Primary Device Type */
5112 		/*	Category ID */
5113 		*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
5114 		p2pielen += 2;
5115 
5116 		/*	OUI */
5117 		*(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
5118 		p2pielen += 4;
5119 
5120 		/*	Sub Category ID */
5121 		*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
5122 		p2pielen += 2;
5123 
5124 		/*	Number of Secondary Device Types */
5125 		p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
5126 
5127 		/*	Device Name */
5128 		/*	Type: */
5129 		*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
5130 		p2pielen += 2;
5131 
5132 		/*	Length: */
5133 		*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
5134 		p2pielen += 2;
5135 
5136 		/*	Value: */
5137 		memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
5138 		p2pielen += pwdinfo->device_name_len;
5139 
5140 		/*	P2P Interface */
5141 		/*	Type: */
5142 		p2pie[p2pielen++] = P2P_ATTR_INTERFACE;
5143 
5144 		/*	Length: */
5145 		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x000D);
5146 		p2pielen += 2;
5147 
5148 		/*	Value: */
5149 		memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);	/*	P2P Device Address */
5150 		p2pielen += ETH_ALEN;
5151 
5152 		p2pie[p2pielen++] = 1;	/*	P2P Interface Address Count */
5153 
5154 		memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);	/*	P2P Interface Address List */
5155 		p2pielen += ETH_ALEN;
5156 
5157 		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
5158 	}
5159 
5160 	pattrib->last_txcmdsz = pattrib->pktlen;
5161 	dump_mgntframe(padapter, pmgntframe);
5162 
5163 	ret = _SUCCESS;
5164 
5165 exit:
5166 	if (ret == _SUCCESS)
5167 		rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
5168 	else
5169 		kfree(pmlmepriv->assoc_req);
5170 }
5171 
5172 /* when wait_ack is ture, this function shoule be called at process context */
_issue_nulldata(struct adapter * padapter,unsigned char * da,unsigned int power_mode,int wait_ack)5173 static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
5174 {
5175 	int ret = _FAIL;
5176 	struct xmit_frame			*pmgntframe;
5177 	struct pkt_attrib			*pattrib;
5178 	unsigned char					*pframe;
5179 	struct ieee80211_hdr *pwlanhdr;
5180 	__le16 *fctrl;
5181 	struct xmit_priv	*pxmitpriv;
5182 	struct mlme_ext_priv	*pmlmeext;
5183 	struct mlme_ext_info	*pmlmeinfo;
5184 
5185 	if (!padapter)
5186 		goto exit;
5187 
5188 	pxmitpriv = &padapter->xmitpriv;
5189 	pmlmeext = &padapter->mlmeextpriv;
5190 	pmlmeinfo = &pmlmeext->mlmext_info;
5191 
5192 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5193 	if (!pmgntframe)
5194 		goto exit;
5195 
5196 	/* update attribute */
5197 	pattrib = &pmgntframe->attrib;
5198 	update_mgntframe_attrib(padapter, pattrib);
5199 	pattrib->retry_ctrl = false;
5200 
5201 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5202 
5203 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5204 	pwlanhdr = (struct ieee80211_hdr *)pframe;
5205 
5206 	fctrl = &pwlanhdr->frame_control;
5207 	*(fctrl) = 0;
5208 
5209 	if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
5210 		SetFrDs(fctrl);
5211 	else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
5212 		SetToDs(fctrl);
5213 
5214 	if (power_mode)
5215 		SetPwrMgt(fctrl);
5216 
5217 	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5218 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
5219 	memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5220 
5221 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5222 	pmlmeext->mgnt_seq++;
5223 	SetFrameSubType(pframe, WIFI_DATA_NULL);
5224 
5225 	pframe += sizeof(struct ieee80211_hdr_3addr);
5226 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
5227 
5228 	pattrib->last_txcmdsz = pattrib->pktlen;
5229 
5230 	if (wait_ack) {
5231 		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5232 	} else {
5233 		dump_mgntframe(padapter, pmgntframe);
5234 		ret = _SUCCESS;
5235 	}
5236 
5237 exit:
5238 	return ret;
5239 }
5240 
5241 /* when wait_ms > 0 , this function shoule be called at process context */
5242 /* da == NULL for station mode */
issue_nulldata(struct adapter * padapter,unsigned char * da,unsigned int power_mode,int try_cnt,int wait_ms)5243 int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
5244 {
5245 	int ret;
5246 	int i = 0;
5247 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
5248 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
5249 
5250 	/* da == NULL, assum it's null data for sta to ap*/
5251 	if (!da)
5252 		da = get_my_bssid(&pmlmeinfo->network);
5253 
5254 	do {
5255 		ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
5256 
5257 		i++;
5258 
5259 		if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5260 			break;
5261 
5262 		if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5263 			msleep(wait_ms);
5264 	} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5265 
5266 	if (ret != _FAIL) {
5267 		ret = _SUCCESS;
5268 		goto exit;
5269 	}
5270 exit:
5271 	return ret;
5272 }
5273 
5274 /* when wait_ack is ture, this function shoule be called at process context */
_issue_qos_nulldata(struct adapter * padapter,unsigned char * da,u16 tid,int wait_ack)5275 static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
5276 {
5277 	int ret = _FAIL;
5278 	struct xmit_frame			*pmgntframe;
5279 	struct pkt_attrib			*pattrib;
5280 	unsigned char					*pframe;
5281 	struct ieee80211_hdr *pwlanhdr;
5282 	__le16 *fctrl;
5283 	unsigned short *qc;
5284 	struct xmit_priv			*pxmitpriv = &padapter->xmitpriv;
5285 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
5286 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
5287 
5288 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5289 	if (!pmgntframe)
5290 		goto exit;
5291 
5292 	/* update attribute */
5293 	pattrib = &pmgntframe->attrib;
5294 	update_mgntframe_attrib(padapter, pattrib);
5295 
5296 	pattrib->hdrlen += 2;
5297 	pattrib->qos_en = true;
5298 	pattrib->eosp = 1;
5299 	pattrib->ack_policy = 0;
5300 	pattrib->mdata = 0;
5301 
5302 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5303 
5304 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5305 	pwlanhdr = (struct ieee80211_hdr *)pframe;
5306 
5307 	fctrl = &pwlanhdr->frame_control;
5308 	*(fctrl) = 0;
5309 
5310 	if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
5311 		SetFrDs(fctrl);
5312 	else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
5313 		SetToDs(fctrl);
5314 
5315 	qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
5316 
5317 	SetPriority(qc, tid);
5318 
5319 	SetEOSP(qc, pattrib->eosp);
5320 
5321 	SetAckpolicy(qc, pattrib->ack_policy);
5322 
5323 	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5324 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
5325 	memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5326 
5327 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5328 	pmlmeext->mgnt_seq++;
5329 	SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
5330 
5331 	pframe += sizeof(struct ieee80211_qos_hdr);
5332 	pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
5333 
5334 	pattrib->last_txcmdsz = pattrib->pktlen;
5335 
5336 	if (wait_ack) {
5337 		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5338 	} else {
5339 		dump_mgntframe(padapter, pmgntframe);
5340 		ret = _SUCCESS;
5341 	}
5342 
5343 exit:
5344 	return ret;
5345 }
5346 
5347 /* when wait_ms > 0 , this function shoule be called at process context */
5348 /* da == NULL for station mode */
issue_qos_nulldata(struct adapter * padapter,unsigned char * da,u16 tid,int try_cnt,int wait_ms)5349 int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
5350 {
5351 	int ret;
5352 	int i = 0;
5353 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
5354 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
5355 
5356 	/* da == NULL, assum it's null data for sta to ap*/
5357 	if (!da)
5358 		da = get_my_bssid(&pmlmeinfo->network);
5359 
5360 	do {
5361 		ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
5362 
5363 		i++;
5364 
5365 		if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5366 			break;
5367 
5368 		if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5369 			msleep(wait_ms);
5370 	} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5371 
5372 	if (ret != _FAIL) {
5373 		ret = _SUCCESS;
5374 		goto exit;
5375 	}
5376 exit:
5377 	return ret;
5378 }
5379 
_issue_deauth(struct adapter * padapter,unsigned char * da,unsigned short reason,u8 wait_ack)5380 static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
5381 {
5382 	struct xmit_frame			*pmgntframe;
5383 	struct pkt_attrib			*pattrib;
5384 	unsigned char					*pframe;
5385 	struct ieee80211_hdr *pwlanhdr;
5386 	__le16 *fctrl;
5387 	struct xmit_priv			*pxmitpriv = &padapter->xmitpriv;
5388 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
5389 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
5390 	int ret = _FAIL;
5391 	__le16 le_tmp;
5392 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
5393 
5394 	if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) && (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
5395 		_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
5396 		_set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
5397 	}
5398 
5399 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5400 	if (!pmgntframe)
5401 		goto exit;
5402 
5403 	/* update attribute */
5404 	pattrib = &pmgntframe->attrib;
5405 	update_mgntframe_attrib(padapter, pattrib);
5406 	pattrib->retry_ctrl = false;
5407 
5408 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5409 
5410 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5411 	pwlanhdr = (struct ieee80211_hdr *)pframe;
5412 
5413 	fctrl = &pwlanhdr->frame_control;
5414 	*(fctrl) = 0;
5415 
5416 	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5417 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
5418 	memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5419 
5420 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5421 	pmlmeext->mgnt_seq++;
5422 	SetFrameSubType(pframe, WIFI_DEAUTH);
5423 
5424 	pframe += sizeof(struct ieee80211_hdr_3addr);
5425 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
5426 
5427 	le_tmp = cpu_to_le16(reason);
5428 	pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &pattrib->pktlen);
5429 
5430 	pattrib->last_txcmdsz = pattrib->pktlen;
5431 
5432 	if (wait_ack) {
5433 		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5434 	} else {
5435 		dump_mgntframe(padapter, pmgntframe);
5436 		ret = _SUCCESS;
5437 	}
5438 
5439 exit:
5440 	return ret;
5441 }
5442 
issue_deauth(struct adapter * padapter,unsigned char * da,unsigned short reason)5443 int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
5444 {
5445 	return _issue_deauth(padapter, da, reason, false);
5446 }
5447 
issue_deauth_ex(struct adapter * padapter,u8 * da,unsigned short reason,int try_cnt,int wait_ms)5448 int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
5449 	int wait_ms)
5450 {
5451 	int ret;
5452 	int i = 0;
5453 
5454 	do {
5455 		ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
5456 
5457 		i++;
5458 
5459 		if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5460 			break;
5461 
5462 		if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5463 			msleep(wait_ms);
5464 	} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5465 
5466 	if (ret != _FAIL) {
5467 		ret = _SUCCESS;
5468 		goto exit;
5469 	}
5470 exit:
5471 	return ret;
5472 }
5473 
issue_action_BA(struct adapter * padapter,unsigned char * raddr,u8 action,u16 status)5474 void issue_action_BA(struct adapter *padapter, unsigned char *raddr, u8 action, u16 status)
5475 {
5476 	u16 start_seq;
5477 	u16 BA_starting_seqctrl = 0;
5478 	struct xmit_frame *pmgntframe;
5479 	struct pkt_attrib *pattrib;
5480 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5481 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5482 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5483 	struct sta_info *psta;
5484 	struct sta_priv *pstapriv = &padapter->stapriv;
5485 	struct registry_priv *pregpriv = &padapter->registrypriv;
5486 	struct ieee80211_mgmt *mgmt;
5487 	u16 capab, params;
5488 
5489 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5490 	if (!pmgntframe)
5491 		return;
5492 
5493 	/* update attribute */
5494 	pattrib = &pmgntframe->attrib;
5495 	update_mgntframe_attrib(padapter, pattrib);
5496 
5497 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5498 
5499 	mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
5500 
5501 	mgmt->frame_control = cpu_to_le16(IEEE80211_STYPE_ACTION | IEEE80211_FTYPE_MGMT);
5502 
5503 	memcpy(mgmt->da, raddr, ETH_ALEN);
5504 	memcpy(mgmt->sa, myid(&padapter->eeprompriv), ETH_ALEN);
5505 	memcpy(mgmt->bssid, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5506 
5507 	mgmt->seq_ctrl = cpu_to_le16(pmlmeext->mgnt_seq);
5508 	pmlmeext->mgnt_seq++;
5509 
5510 	mgmt->u.action.category = WLAN_CATEGORY_BACK;
5511 
5512 	switch (action) {
5513 	case WLAN_ACTION_ADDBA_REQ:
5514 		mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
5515 		do {
5516 			pmlmeinfo->dialogToken++;
5517 		} while (pmlmeinfo->dialogToken == 0);
5518 		mgmt->u.action.u.addba_req.dialog_token = pmlmeinfo->dialogToken;
5519 
5520 		/* immediate ack & 64 buffer size */
5521 		capab = u16_encode_bits(64, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
5522 		capab |= u16_encode_bits(1, IEEE80211_ADDBA_PARAM_POLICY_MASK);
5523 		capab |= u16_encode_bits(status, IEEE80211_ADDBA_PARAM_TID_MASK);
5524 		mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
5525 
5526 		mgmt->u.action.u.addba_req.timeout = cpu_to_le16(5000); /* 5 ms */
5527 
5528 		psta = rtw_get_stainfo(pstapriv, raddr);
5529 		if (psta) {
5530 			start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07] & 0xfff) + 1;
5531 
5532 			psta->BA_starting_seqctrl[status & 0x07] = start_seq;
5533 
5534 			BA_starting_seqctrl = start_seq << 4;
5535 		}
5536 		mgmt->u.action.u.addba_req.start_seq_num = cpu_to_le16(BA_starting_seqctrl);
5537 
5538 		pattrib->pktlen = offsetofend(struct ieee80211_mgmt,
5539 					      u.action.u.addba_req.start_seq_num);
5540 		break;
5541 	case WLAN_ACTION_ADDBA_RESP:
5542 		mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
5543 		mgmt->u.action.u.addba_resp.dialog_token = pmlmeinfo->ADDBA_req.dialog_token;
5544 		mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
5545 		capab = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
5546 		capab |= u16_encode_bits(64, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
5547 		capab |= u16_encode_bits(pregpriv->ampdu_amsdu, IEEE80211_ADDBA_PARAM_AMSDU_MASK);
5548 		mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
5549 		mgmt->u.action.u.addba_resp.timeout = pmlmeinfo->ADDBA_req.BA_timeout_value;
5550 		pattrib->pktlen = offsetofend(struct ieee80211_mgmt, u.action.u.addba_resp.timeout);
5551 		break;
5552 	case WLAN_ACTION_DELBA:
5553 		mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
5554 		mgmt->u.action.u.delba.params = cpu_to_le16((status & 0x1F) << 3);
5555 		params = u16_encode_bits((status & 0x1), IEEE80211_DELBA_PARAM_INITIATOR_MASK);
5556 		params |= u16_encode_bits((status >> 1) & 0xF, IEEE80211_DELBA_PARAM_TID_MASK);
5557 		mgmt->u.action.u.delba.params = cpu_to_le16(params);
5558 		mgmt->u.action.u.delba.reason_code = cpu_to_le16(WLAN_STATUS_REQUEST_DECLINED);
5559 		pattrib->pktlen = offsetofend(struct ieee80211_mgmt, u.action.u.delba.reason_code);
5560 		break;
5561 	default:
5562 		break;
5563 	}
5564 
5565 	pattrib->last_txcmdsz = pattrib->pktlen;
5566 
5567 	dump_mgntframe(padapter, pmgntframe);
5568 }
5569 
issue_action_BSSCoexistPacket(struct adapter * padapter)5570 static void issue_action_BSSCoexistPacket(struct adapter *padapter)
5571 {
5572 	struct list_head *plist, *phead;
5573 	unsigned char category, action;
5574 	struct xmit_frame			*pmgntframe;
5575 	struct pkt_attrib			*pattrib;
5576 	unsigned char				*pframe;
5577 	struct ieee80211_hdr *pwlanhdr;
5578 	__le16 *fctrl;
5579 	struct	wlan_network	*pnetwork = NULL;
5580 	struct xmit_priv			*pxmitpriv = &padapter->xmitpriv;
5581 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5582 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
5583 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
5584 	struct __queue *queue	= &pmlmepriv->scanned_queue;
5585 	u8 InfoContent[16] = {0};
5586 	u8 ICS[8][15];
5587 	if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
5588 		return;
5589 
5590 	if (pmlmeinfo->bwmode_updated)
5591 		return;
5592 
5593 	category = WLAN_CATEGORY_PUBLIC;
5594 	action = ACT_PUBLIC_BSSCOEXIST;
5595 
5596 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5597 	if (!pmgntframe)
5598 		return;
5599 
5600 	/* update attribute */
5601 	pattrib = &pmgntframe->attrib;
5602 	update_mgntframe_attrib(padapter, pattrib);
5603 
5604 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5605 
5606 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5607 	pwlanhdr = (struct ieee80211_hdr *)pframe;
5608 
5609 	fctrl = &pwlanhdr->frame_control;
5610 	*(fctrl) = 0;
5611 
5612 	memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5613 	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
5614 	memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5615 
5616 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5617 	pmlmeext->mgnt_seq++;
5618 	SetFrameSubType(pframe, WIFI_ACTION);
5619 
5620 	pframe += sizeof(struct ieee80211_hdr_3addr);
5621 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
5622 
5623 	pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
5624 	pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
5625 
5626 	/*  */
5627 	if (pmlmepriv->num_FortyMHzIntolerant > 0) {
5628 		u8 iedata = 0;
5629 
5630 		iedata |= BIT(2);/* 20 MHz BSS Width Request */
5631 
5632 		pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &pattrib->pktlen);
5633 	}
5634 
5635 	/*  */
5636 	memset(ICS, 0, sizeof(ICS));
5637 	if (pmlmepriv->num_sta_no_ht > 0) {
5638 		int i;
5639 
5640 		spin_lock_bh(&pmlmepriv->scanned_queue.lock);
5641 
5642 		phead = get_list_head(queue);
5643 		plist = phead->next;
5644 
5645 		while (phead != plist) {
5646 			int len;
5647 			u8 *p;
5648 			struct wlan_bssid_ex *pbss_network;
5649 
5650 			pnetwork = container_of(plist, struct wlan_network, list);
5651 
5652 			plist = plist->next;
5653 
5654 			pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
5655 
5656 			p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
5657 			if (!p || len == 0) { /* non-HT */
5658 				if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
5659 					continue;
5660 
5661 				ICS[0][pbss_network->Configuration.DSConfig] = 1;
5662 
5663 				if (ICS[0][0] == 0)
5664 					ICS[0][0] = 1;
5665 			}
5666 		}
5667 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
5668 
5669 		for (i = 0; i < 8; i++) {
5670 			if (ICS[i][0] == 1) {
5671 				int j, k = 0;
5672 
5673 				InfoContent[k] = i;
5674 				/* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
5675 				k++;
5676 
5677 				for (j = 1; j <= 14; j++) {
5678 					if (ICS[i][j] == 1) {
5679 						if (k < 16) {
5680 							InfoContent[k] = j; /* channel number */
5681 							/* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
5682 							k++;
5683 						}
5684 					}
5685 				}
5686 
5687 				pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &pattrib->pktlen);
5688 			}
5689 		}
5690 	}
5691 
5692 	pattrib->last_txcmdsz = pattrib->pktlen;
5693 
5694 	dump_mgntframe(padapter, pmgntframe);
5695 }
5696 
send_delba(struct adapter * padapter,u8 initiator,u8 * addr)5697 unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
5698 {
5699 	struct sta_priv *pstapriv = &padapter->stapriv;
5700 	struct sta_info *psta = NULL;
5701 	/* struct recv_reorder_ctrl *preorder_ctrl; */
5702 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
5703 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
5704 	u16 tid;
5705 
5706 	if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
5707 		if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
5708 			return _SUCCESS;
5709 
5710 	psta = rtw_get_stainfo(pstapriv, addr);
5711 	if (!psta)
5712 		return _SUCCESS;
5713 
5714 	if (initiator == 0) { /*  recipient */
5715 		for (tid = 0; tid < MAXTID; tid++) {
5716 			if (psta->recvreorder_ctrl[tid].enable) {
5717 				issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F));
5718 				psta->recvreorder_ctrl[tid].enable = false;
5719 				psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
5720 			}
5721 		}
5722 	} else if (initiator == 1) { /*  originator */
5723 		for (tid = 0; tid < MAXTID; tid++) {
5724 			if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
5725 				issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F));
5726 				psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
5727 				psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
5728 			}
5729 		}
5730 	}
5731 
5732 	return _SUCCESS;
5733 }
5734 
send_beacon(struct adapter * padapter)5735 unsigned int send_beacon(struct adapter *padapter)
5736 {
5737 	bool bxmitok = false;
5738 	int	issue = 0;
5739 	int poll = 0;
5740 
5741 	clear_beacon_valid_bit(padapter);
5742 
5743 	do {
5744 		issue_beacon(padapter, 100);
5745 		issue++;
5746 		do {
5747 			yield();
5748 			bxmitok = get_beacon_valid_bit(padapter);
5749 			poll++;
5750 		} while ((poll % 10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
5751 	} while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
5752 
5753 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped || !bxmitok)
5754 		return _FAIL;
5755 
5756 	return _SUCCESS;
5757 }
5758 
get_beacon_valid_bit(struct adapter * adapter)5759 bool get_beacon_valid_bit(struct adapter *adapter)
5760 {
5761 	int res;
5762 	u8 reg;
5763 
5764 	res = rtw_read8(adapter, REG_TDECTRL + 2, &reg);
5765 	if (res)
5766 		return false;
5767 
5768 	/* BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2 */
5769 	return BIT(0) & reg;
5770 }
5771 
clear_beacon_valid_bit(struct adapter * adapter)5772 void clear_beacon_valid_bit(struct adapter *adapter)
5773 {
5774 	int res;
5775 	u8 reg;
5776 
5777 	res = rtw_read8(adapter, REG_TDECTRL + 2, &reg);
5778 	if (res)
5779 		return;
5780 
5781 	/* BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
5782 	rtw_write8(adapter, REG_TDECTRL + 2, reg | BIT(0));
5783 }
5784 
rtw_resume_tx_beacon(struct adapter * adapt)5785 void rtw_resume_tx_beacon(struct adapter *adapt)
5786 {
5787 	struct hal_data_8188e *haldata = &adapt->haldata;
5788 
5789 	/*  2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
5790 	/*  which should be read from register to a global variable. */
5791 
5792 	rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) | BIT(6));
5793 	haldata->RegFwHwTxQCtrl |= BIT(6);
5794 	rtw_write8(adapt, REG_TBTT_PROHIBIT + 1, 0xff);
5795 	haldata->RegReg542 |= BIT(0);
5796 	rtw_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542);
5797 }
5798 
rtw_stop_tx_beacon(struct adapter * adapt)5799 void rtw_stop_tx_beacon(struct adapter *adapt)
5800 {
5801 	struct hal_data_8188e *haldata = &adapt->haldata;
5802 
5803 	/*  2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
5804 	/*  which should be read from register to a global variable. */
5805 
5806 	rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) & (~BIT(6)));
5807 	haldata->RegFwHwTxQCtrl &= (~BIT(6));
5808 	rtw_write8(adapt, REG_TBTT_PROHIBIT + 1, 0x64);
5809 	haldata->RegReg542 &= ~(BIT(0));
5810 	rtw_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542);
5811 
5812 	 /* todo: CheckFwRsvdPageContent(Adapter);  2010.06.23. Added by tynli. */
5813 }
5814 
rtw_set_opmode(struct adapter * adapter,u8 mode)5815 static void rtw_set_opmode(struct adapter *adapter, u8 mode)
5816 {
5817 	u8 val8;
5818 	int res;
5819 
5820 	/*  disable Port0 TSF update */
5821 	res = rtw_read8(adapter, REG_BCN_CTRL, &val8);
5822 	if (res)
5823 		return;
5824 
5825 	rtw_write8(adapter, REG_BCN_CTRL, val8 | BIT(4));
5826 
5827 	/*  set net_type */
5828 	res = rtw_read8(adapter, MSR, &val8);
5829 	if (res)
5830 		return;
5831 
5832 	val8 &= 0x0c;
5833 	val8 |= mode;
5834 	rtw_write8(adapter, MSR, val8);
5835 
5836 	if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
5837 		rtw_stop_tx_beacon(adapter);
5838 
5839 		rtw_write8(adapter, REG_BCN_CTRL, 0x19);/* disable atim wnd */
5840 	} else if (mode == _HW_STATE_ADHOC_) {
5841 		rtw_resume_tx_beacon(adapter);
5842 		rtw_write8(adapter, REG_BCN_CTRL, 0x1a);
5843 	} else if (mode == _HW_STATE_AP_) {
5844 		rtw_resume_tx_beacon(adapter);
5845 
5846 		rtw_write8(adapter, REG_BCN_CTRL, 0x12);
5847 
5848 		/* Set RCR */
5849 		rtw_write32(adapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0,reject ICV_ERR packet */
5850 		/* enable to rx data frame */
5851 		rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
5852 		/* enable to rx ps-poll */
5853 		rtw_write16(adapter, REG_RXFLTMAP1, 0x0400);
5854 
5855 		/* Beacon Control related register for first time */
5856 		rtw_write8(adapter, REG_BCNDMATIM, 0x02); /*  2ms */
5857 
5858 		rtw_write8(adapter, REG_ATIMWND, 0x0a); /*  10ms */
5859 		rtw_write16(adapter, REG_BCNTCFG, 0x00);
5860 		rtw_write16(adapter, REG_TBTT_PROHIBIT, 0xff04);
5861 		rtw_write16(adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/*  +32767 (~32ms) */
5862 
5863 		/* reset TSF */
5864 		rtw_write8(adapter, REG_DUAL_TSF_RST, BIT(0));
5865 
5866 		/* BIT(3) - If set 0, hw will clr bcnq when tx becon ok/fail or port 0 */
5867 		res = rtw_read8(adapter, REG_MBID_NUM, &val8);
5868 		if (res)
5869 			return;
5870 
5871 		rtw_write8(adapter, REG_MBID_NUM, val8 | BIT(3) | BIT(4));
5872 
5873 		/* enable BCN0 Function for if1 */
5874 		/* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */
5875 		rtw_write8(adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | BIT(1)));
5876 
5877 		/* dis BCN1 ATIM  WND if if2 is station */
5878 		res = rtw_read8(adapter, REG_BCN_CTRL_1, &val8);
5879 		if (res)
5880 			return;
5881 
5882 		rtw_write8(adapter, REG_BCN_CTRL_1, val8 | BIT(0));
5883 	}
5884 }
5885 
5886 /****************************************************************************
5887 
5888 Following are some utitity fuctions for WiFi MLME
5889 
5890 *****************************************************************************/
5891 
rtw_set_initial_gain(struct adapter * adapter,u8 gain)5892 static void rtw_set_initial_gain(struct adapter *adapter, u8 gain)
5893 {
5894 	struct hal_data_8188e *haldata = &adapter->haldata;
5895 	struct odm_dm_struct *odmpriv = &haldata->odmpriv;
5896 	struct rtw_dig *digtable = &odmpriv->DM_DigTable;
5897 
5898 	if (gain == 0xff) {
5899 		/* restore rx gain */
5900 		ODM_Write_DIG(odmpriv, digtable->BackupIGValue);
5901 	} else {
5902 		digtable->BackupIGValue = digtable->CurIGValue;
5903 		ODM_Write_DIG(odmpriv, gain);
5904 	}
5905 }
5906 
rtw_mlme_under_site_survey(struct adapter * adapter)5907 void rtw_mlme_under_site_survey(struct adapter *adapter)
5908 {
5909 	/* config RCR to receive different BSSID & not to receive data frame */
5910 
5911 	int res;
5912 	u8 reg;
5913 	u32 v;
5914 
5915 	res = rtw_read32(adapter, REG_RCR, &v);
5916 	if (res)
5917 		return;
5918 
5919 	v &= ~(RCR_CBSSID_BCN);
5920 	rtw_write32(adapter, REG_RCR, v);
5921 	/* reject all data frame */
5922 	rtw_write16(adapter, REG_RXFLTMAP2, 0x00);
5923 
5924 	/* disable update TSF */
5925 	res = rtw_read8(adapter, REG_BCN_CTRL, &reg);
5926 	if (res)
5927 		return;
5928 
5929 	rtw_write8(adapter, REG_BCN_CTRL, reg | BIT(4));
5930 }
5931 
rtw_mlme_site_survey_done(struct adapter * adapter)5932 void rtw_mlme_site_survey_done(struct adapter *adapter)
5933 {
5934 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
5935 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5936 	u32 reg32;
5937 	int res;
5938 	u8 reg;
5939 
5940 	if ((is_client_associated_to_ap(adapter)) ||
5941 	    ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) {
5942 		/* enable to rx data frame */
5943 		rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
5944 
5945 		/* enable update TSF */
5946 		res = rtw_read8(adapter, REG_BCN_CTRL, &reg);
5947 		if (res)
5948 			return;
5949 
5950 		rtw_write8(adapter, REG_BCN_CTRL, reg & (~BIT(4)));
5951 	} else if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
5952 		rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
5953 		/* enable update TSF */
5954 		res = rtw_read8(adapter, REG_BCN_CTRL, &reg);
5955 		if (res)
5956 			return;
5957 
5958 		rtw_write8(adapter, REG_BCN_CTRL, reg & (~BIT(4)));
5959 	}
5960 
5961 	res = rtw_read32(adapter, REG_RCR, &reg32);
5962 	if (res)
5963 		return;
5964 
5965 	rtw_write32(adapter, REG_RCR, reg32 | RCR_CBSSID_BCN);
5966 }
5967 
site_survey(struct adapter * padapter)5968 void site_survey(struct adapter *padapter)
5969 {
5970 	unsigned char survey_channel = 0;
5971 	enum rt_scan_type ScanType = SCAN_PASSIVE;
5972 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
5973 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
5974 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
5975 
5976 	if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
5977 		if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
5978 			survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
5979 		} else {
5980 			survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
5981 		}
5982 		ScanType = SCAN_ACTIVE;
5983 	} else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
5984 		/*	Commented by Albert 2011/06/03 */
5985 		/*	The driver is in the find phase, it should go through the social channel. */
5986 		int ch_set_idx;
5987 		survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
5988 		ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, survey_channel);
5989 		if (ch_set_idx >= 0)
5990 			ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
5991 		else
5992 			ScanType = SCAN_ACTIVE;
5993 	} else {
5994 		struct rtw_ieee80211_channel *ch;
5995 		if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
5996 			ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
5997 			survey_channel = ch->hw_value;
5998 			ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
5999 		}
6000 	}
6001 
6002 	if (survey_channel != 0) {
6003 		if (pmlmeext->sitesurvey_res.channel_idx == 0)
6004 			set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6005 		else
6006 			SelectChannel(padapter, survey_channel);
6007 
6008 		if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
6009 			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) ||
6010 			    rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
6011 				issue_probereq_p2p(padapter, NULL);
6012 				issue_probereq_p2p(padapter, NULL);
6013 				issue_probereq_p2p(padapter, NULL);
6014 			} else {
6015 				int i;
6016 				for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
6017 					if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
6018 						/* todo: to issue two probe req??? */
6019 						issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
6020 						/* msleep(SURVEY_TO>>1); */
6021 						issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
6022 					}
6023 				}
6024 
6025 				if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
6026 					/* todo: to issue two probe req??? */
6027 					issue_probereq(padapter, NULL, NULL);
6028 					/* msleep(SURVEY_TO>>1); */
6029 					issue_probereq(padapter, NULL, NULL);
6030 				}
6031 			}
6032 		}
6033 
6034 		set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
6035 	} else {
6036 		/*	channel number is 0 or this channel is not valid. */
6037 		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
6038 			if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
6039 				/*	Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */
6040 				/*	This will let the following flow to run the scanning end. */
6041 				rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
6042 			}
6043 		}
6044 
6045 		if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) {
6046 			/*	Set the P2P State to the listen state of find phase and set the current channel to the listen channel */
6047 			set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6048 			rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
6049 			pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
6050 
6051 			/* restore RX GAIN */
6052 			rtw_set_initial_gain(padapter, 0xff);
6053 			/* turn on dynamic functions */
6054 			Restore_DM_Func_Flag(padapter);
6055 			/* Switch_DM_Func(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, true); */
6056 
6057 			_set_timer(&pwdinfo->find_phase_timer, (u32)((u32)(pwdinfo->listen_dwell) * 100));
6058 		} else {
6059 			/*  20100721:Interrupt scan operation here. */
6060 			/*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
6061 			/*  It compares the scan result and select beter one to do connection. */
6062 			if (AntDivBeforeLink8188E(padapter)) {
6063 				pmlmeext->sitesurvey_res.bss_cnt = 0;
6064 				pmlmeext->sitesurvey_res.channel_idx = -1;
6065 				pmlmeext->chan_scan_time = SURVEY_TO / 2;
6066 				set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
6067 				return;
6068 			}
6069 			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
6070 				rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
6071 			rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
6072 
6073 			pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
6074 
6075 			/* switch back to the original channel */
6076 
6077 			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN))
6078 				set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6079 			else
6080 				set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6081 
6082 			/* config MSR */
6083 			Set_MSR(padapter, (pmlmeinfo->state & 0x3));
6084 
6085 			/* restore RX GAIN */
6086 			rtw_set_initial_gain(padapter, 0xff);
6087 			/* turn on dynamic functions */
6088 			Restore_DM_Func_Flag(padapter);
6089 			/* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
6090 
6091 			if (is_client_associated_to_ap(padapter))
6092 				issue_nulldata(padapter, NULL, 0, 3, 500);
6093 
6094 			rtw_mlme_site_survey_done(padapter);
6095 
6096 			report_surveydone_event(padapter);
6097 
6098 			pmlmeext->chan_scan_time = SURVEY_TO;
6099 			pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
6100 
6101 			issue_action_BSSCoexistPacket(padapter);
6102 			issue_action_BSSCoexistPacket(padapter);
6103 			issue_action_BSSCoexistPacket(padapter);
6104 		}
6105 	}
6106 }
6107 
6108 /* collect bss info from Beacon and Probe request/response frames. */
collect_bss_info(struct adapter * padapter,struct recv_frame * precv_frame,struct wlan_bssid_ex * bssid)6109 u8 collect_bss_info(struct adapter *padapter, struct recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
6110 {
6111 	int	i;
6112 	u32	len;
6113 	u8 *p;
6114 	u16 val16, subtype;
6115 	u8 *pframe = precv_frame->rx_data;
6116 	u32	packet_len = precv_frame->len;
6117 	u8 ie_offset;
6118 	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
6119 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
6120 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
6121 	__le32 le32_tmp;
6122 
6123 	len = packet_len - sizeof(struct ieee80211_hdr_3addr);
6124 
6125 	if (len > MAX_IE_SZ)
6126 		return _FAIL;
6127 
6128 	memset(bssid, 0, sizeof(struct wlan_bssid_ex));
6129 
6130 	subtype = GetFrameSubType(pframe);
6131 
6132 	if (subtype == WIFI_BEACON) {
6133 		bssid->Reserved[0] = 1;
6134 		ie_offset = _BEACON_IE_OFFSET_;
6135 	} else {
6136 		/*  FIXME : more type */
6137 		if (subtype == WIFI_PROBEREQ) {
6138 			ie_offset = _PROBEREQ_IE_OFFSET_;
6139 			bssid->Reserved[0] = 2;
6140 		} else if (subtype == WIFI_PROBERSP) {
6141 			ie_offset = _PROBERSP_IE_OFFSET_;
6142 			bssid->Reserved[0] = 3;
6143 		} else {
6144 			bssid->Reserved[0] = 0;
6145 			ie_offset = _FIXED_IE_LENGTH_;
6146 		}
6147 	}
6148 
6149 	bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
6150 
6151 	/* below is to copy the information element */
6152 	bssid->IELength = len;
6153 	memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
6154 
6155 	/* get the signal strength */
6156 	bssid->Rssi = precv_frame->attrib.phy_info.recvpower; /*  in dBM.raw data */
6157 	bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
6158 	bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
6159 	bssid->PhyInfo.Optimum_antenna = rtw_current_antenna(padapter);
6160 
6161 	/*  checking SSID */
6162 	p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);
6163 	if (!p)
6164 		return _FAIL;
6165 
6166 	if (*(p + 1)) {
6167 		if (len > NDIS_802_11_LENGTH_SSID)
6168 			return _FAIL;
6169 		memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
6170 		bssid->Ssid.SsidLength = *(p + 1);
6171 	} else {
6172 		bssid->Ssid.SsidLength = 0;
6173 	}
6174 
6175 	memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
6176 
6177 	/* checking rate info... */
6178 	i = 0;
6179 	p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
6180 	if (p) {
6181 		if (len > NDIS_802_11_LENGTH_RATES_EX)
6182 			return _FAIL;
6183 		memcpy(bssid->SupportedRates, (p + 2), len);
6184 		i = len;
6185 	}
6186 
6187 	p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
6188 	if (p) {
6189 		if (len > (NDIS_802_11_LENGTH_RATES_EX - i))
6190 			return _FAIL;
6191 		memcpy(bssid->SupportedRates + i, (p + 2), len);
6192 	}
6193 
6194 	/* todo: */
6195 	bssid->NetworkTypeInUse = Ndis802_11OFDM24;
6196 
6197 	if (bssid->IELength < 12)
6198 		return _FAIL;
6199 
6200 	/*  Checking for DSConfig */
6201 	p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
6202 
6203 	bssid->Configuration.DSConfig = 0;
6204 	bssid->Configuration.Length = 0;
6205 
6206 	if (p) {
6207 		bssid->Configuration.DSConfig = *(p + 2);
6208 	} else {/*  In 5G, some ap do not have DSSET IE */
6209 		/*  checking HT info for channel */
6210 		p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
6211 		if (p) {
6212 			struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
6213 			bssid->Configuration.DSConfig = HT_info->primary_channel;
6214 		} else { /*  use current channel */
6215 			bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
6216 		}
6217 	}
6218 
6219 	memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
6220 	bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp);
6221 
6222 	val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
6223 
6224 	if (val16 & BIT(0)) {
6225 		bssid->InfrastructureMode = Ndis802_11Infrastructure;
6226 		memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
6227 	} else {
6228 		bssid->InfrastructureMode = Ndis802_11IBSS;
6229 		memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
6230 	}
6231 
6232 	if (val16 & BIT(4))
6233 		bssid->Privacy = 1;
6234 	else
6235 		bssid->Privacy = 0;
6236 
6237 	bssid->Configuration.ATIMWindow = 0;
6238 
6239 	/* 20/40 BSS Coexistence check */
6240 	if ((pregistrypriv->wifi_spec == 1) && (!pmlmeinfo->bwmode_updated)) {
6241 		struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6242 		p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
6243 		if (p && len > 0) {
6244 			struct HT_caps_element	*pHT_caps;
6245 			pHT_caps = (struct HT_caps_element *)(p + 2);
6246 
6247 			if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14))
6248 				pmlmepriv->num_FortyMHzIntolerant++;
6249 		} else {
6250 			pmlmepriv->num_sta_no_ht++;
6251 		}
6252 	}
6253 
6254 	/*  mark bss info receiving from nearby channel as SignalQuality 101 */
6255 	if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
6256 		bssid->PhyInfo.SignalQuality = 101;
6257 	return _SUCCESS;
6258 }
6259 
rtw_set_bssid(struct adapter * adapter,u8 * bssid)6260 static void rtw_set_bssid(struct adapter *adapter, u8 *bssid)
6261 {
6262 	int i;
6263 
6264 	for (i = 0; i < ETH_ALEN; i++)
6265 		rtw_write8(adapter, REG_BSSID + i, bssid[i]);
6266 }
6267 
mlme_join(struct adapter * adapter,int type)6268 static void mlme_join(struct adapter *adapter, int type)
6269 {
6270 	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
6271 	u8 retry_limit = 0x30, reg;
6272 	u32 reg32;
6273 	int res;
6274 
6275 	switch (type) {
6276 	case 0:
6277 		/* prepare to join */
6278 		/* enable to rx data frame, accept all data frame */
6279 		rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
6280 
6281 		res = rtw_read32(adapter, REG_RCR, &reg32);
6282 		if (res)
6283 			return;
6284 
6285 		rtw_write32(adapter, REG_RCR,
6286 			    reg32 | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
6287 
6288 		if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
6289 			retry_limit = 48;
6290 		} else {
6291 			/* ad-hoc mode */
6292 			retry_limit = 0x7;
6293 		}
6294 		break;
6295 	case 1:
6296 		/* joinbss_event call back when join res < 0 */
6297 		rtw_write16(adapter, REG_RXFLTMAP2, 0x00);
6298 		break;
6299 	case 2:
6300 		/* sta add event call back */
6301 		/* enable update TSF */
6302 		res = rtw_read8(adapter, REG_BCN_CTRL, &reg);
6303 		if (res)
6304 			return;
6305 
6306 		rtw_write8(adapter, REG_BCN_CTRL, reg & (~BIT(4)));
6307 
6308 		if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))
6309 			retry_limit = 0x7;
6310 		break;
6311 	default:
6312 		break;
6313 	}
6314 
6315 	rtw_write16(adapter, REG_RL,
6316 		    retry_limit << RETRY_LIMIT_SHORT_SHIFT | retry_limit << RETRY_LIMIT_LONG_SHIFT);
6317 }
6318 
start_create_ibss(struct adapter * padapter)6319 void start_create_ibss(struct adapter *padapter)
6320 {
6321 	unsigned short	caps;
6322 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
6323 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
6324 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
6325 	pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
6326 	pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
6327 
6328 	/* update wireless mode */
6329 	update_wireless_mode(padapter);
6330 
6331 	/* udpate capability */
6332 	caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
6333 	update_capinfo(padapter, caps);
6334 	if (caps & cap_IBSS) {/* adhoc master */
6335 		rtw_write8(padapter, REG_SECCFG, 0xcf);
6336 
6337 		/* switch channel */
6338 		/* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
6339 		set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6340 
6341 		beacon_timing_control(padapter);
6342 
6343 		/* set msr to WIFI_FW_ADHOC_STATE */
6344 		pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
6345 		Set_MSR(padapter, (pmlmeinfo->state & 0x3));
6346 
6347 		/* issue beacon */
6348 		if (send_beacon(padapter) == _FAIL) {
6349 			report_join_res(padapter, -1);
6350 			pmlmeinfo->state = WIFI_FW_NULL_STATE;
6351 		} else {
6352 			rtw_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
6353 			mlme_join(padapter, 0);
6354 
6355 			report_join_res(padapter, 1);
6356 			pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
6357 			rtw_indicate_connect(padapter);
6358 		}
6359 	} else {
6360 		return;
6361 	}
6362 	/* update bc/mc sta_info */
6363 	update_bmc_sta(padapter);
6364 }
6365 
start_clnt_join(struct adapter * padapter)6366 void start_clnt_join(struct adapter *padapter)
6367 {
6368 	unsigned short	caps;
6369 	u8 val8;
6370 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
6371 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
6372 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
6373 	int beacon_timeout;
6374 
6375 	pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
6376 	pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
6377 
6378 	/* update wireless mode */
6379 	update_wireless_mode(padapter);
6380 
6381 	/* udpate capability */
6382 	caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
6383 	update_capinfo(padapter, caps);
6384 	if (caps & cap_ESS) {
6385 		Set_MSR(padapter, WIFI_FW_STATION_STATE);
6386 
6387 		val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
6388 
6389 		rtw_write8(padapter, REG_SECCFG, val8);
6390 
6391 		/* switch channel */
6392 		set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6393 
6394 		/* here wait for receiving the beacon to start auth */
6395 		/* and enable a timer */
6396 		beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
6397 		set_link_timer(pmlmeext, beacon_timeout);
6398 		_set_timer(&padapter->mlmepriv.assoc_timer,
6399 			   (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout);
6400 
6401 		pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
6402 	} else if (caps & cap_IBSS) { /* adhoc client */
6403 		Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
6404 
6405 		rtw_write8(padapter, REG_SECCFG, 0xcf);
6406 
6407 		/* switch channel */
6408 		set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6409 
6410 		beacon_timing_control(padapter);
6411 
6412 		pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
6413 
6414 		report_join_res(padapter, 1);
6415 	} else {
6416 		return;
6417 	}
6418 }
6419 
start_clnt_auth(struct adapter * padapter)6420 void start_clnt_auth(struct adapter *padapter)
6421 {
6422 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
6423 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
6424 
6425 	_cancel_timer_ex(&pmlmeext->link_timer);
6426 
6427 	pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
6428 	pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
6429 
6430 	pmlmeinfo->auth_seq = 1;
6431 	pmlmeinfo->reauth_count = 0;
6432 	pmlmeinfo->reassoc_count = 0;
6433 	pmlmeinfo->link_count = 0;
6434 	pmlmeext->retry = 0;
6435 
6436 	/*  Because of AP's not receiving deauth before */
6437 	/*  AP may: 1)not response auth or 2)deauth us after link is complete */
6438 	/*  issue deauth before issuing auth to deal with the situation */
6439 	/*	Commented by Albert 2012/07/21 */
6440 	/*	For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
6441 	issue_deauth(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
6442 
6443 	issue_auth(padapter, NULL, 0);
6444 
6445 	set_link_timer(pmlmeext, REAUTH_TO);
6446 }
6447 
start_clnt_assoc(struct adapter * padapter)6448 void start_clnt_assoc(struct adapter *padapter)
6449 {
6450 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
6451 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
6452 
6453 	_cancel_timer_ex(&pmlmeext->link_timer);
6454 
6455 	pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
6456 	pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
6457 
6458 	issue_assocreq(padapter);
6459 
6460 	set_link_timer(pmlmeext, REASSOC_TO);
6461 }
6462 
receive_disconnect(struct adapter * padapter,unsigned char * MacAddr,unsigned short reason)6463 void receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
6464 {
6465 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
6466 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
6467 
6468 	/* check A3 */
6469 	if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
6470 		return;
6471 
6472 	if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
6473 		if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
6474 			pmlmeinfo->state = WIFI_FW_NULL_STATE;
6475 			report_del_sta_event(padapter, MacAddr, reason);
6476 		} else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
6477 			pmlmeinfo->state = WIFI_FW_NULL_STATE;
6478 			report_join_res(padapter, -2);
6479 		}
6480 	}
6481 }
6482 
process_80211d(struct adapter * padapter,struct wlan_bssid_ex * bssid)6483 static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
6484 {
6485 	struct registry_priv *pregistrypriv;
6486 	struct mlme_ext_priv *pmlmeext;
6487 	struct rt_channel_info *chplan_new;
6488 	u8 channel;
6489 	u8 i;
6490 
6491 	pregistrypriv = &padapter->registrypriv;
6492 	pmlmeext = &padapter->mlmeextpriv;
6493 
6494 	/*  Adjust channel plan by AP Country IE */
6495 	if (pregistrypriv->enable80211d &&
6496 	    (!pmlmeext->update_channel_plan_by_ap_done)) {
6497 		u8 *ie, *p;
6498 		u32 len;
6499 		struct rt_channel_plan chplan_ap;
6500 		struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
6501 		u8 country[4];
6502 		u8 fcn; /*  first channel number */
6503 		u8 noc; /*  number of channel */
6504 		u8 j, k;
6505 
6506 		ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
6507 		if (!ie)
6508 			return;
6509 		if (len < 6)
6510 			return;
6511 		ie += 2;
6512 		p = ie;
6513 		ie += len;
6514 
6515 		memset(country, 0, 4);
6516 		memcpy(country, p, 3);
6517 		p += 3;
6518 
6519 		i = 0;
6520 		while ((ie - p) >= 3) {
6521 			fcn = *(p++);
6522 			noc = *(p++);
6523 			p++;
6524 
6525 			for (j = 0; j < noc; j++) {
6526 				channel = fcn + j;
6527 				chplan_ap.Channel[i++] = channel;
6528 			}
6529 		}
6530 		chplan_ap.Len = i;
6531 
6532 		memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
6533 
6534 		memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
6535 		chplan_new = pmlmeext->channel_set;
6536 
6537 		i = 0;
6538 		j = 0;
6539 		k = 0;
6540 		if (pregistrypriv->wireless_mode & WIRELESS_11G) {
6541 			do {
6542 				if ((i == MAX_CHANNEL_NUM) ||
6543 				    (chplan_sta[i].ChannelNum == 0))
6544 					break;
6545 
6546 				if (j == chplan_ap.Len)
6547 					break;
6548 
6549 				if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
6550 					chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6551 					chplan_new[k].ScanType = SCAN_ACTIVE;
6552 					i++;
6553 					j++;
6554 					k++;
6555 				} else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
6556 					chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6557 					chplan_new[k].ScanType = SCAN_PASSIVE;
6558 					i++;
6559 					k++;
6560 				} else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
6561 					chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6562 					chplan_new[k].ScanType = SCAN_ACTIVE;
6563 					j++;
6564 					k++;
6565 				}
6566 			} while (1);
6567 
6568 			/*  change AP not support channel to Passive scan */
6569 			while ((i < MAX_CHANNEL_NUM) &&
6570 			       (chplan_sta[i].ChannelNum != 0) &&
6571 			       (chplan_sta[i].ChannelNum <= 14)) {
6572 				chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6573 				chplan_new[k].ScanType = SCAN_PASSIVE;
6574 				i++;
6575 				k++;
6576 			}
6577 
6578 			/*  add channel AP supported */
6579 			while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
6580 				chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6581 				chplan_new[k].ScanType = SCAN_ACTIVE;
6582 				j++;
6583 				k++;
6584 			}
6585 		} else {
6586 			/*  keep original STA 2.4G channel plan */
6587 			while ((i < MAX_CHANNEL_NUM) &&
6588 			       (chplan_sta[i].ChannelNum != 0) &&
6589 			       (chplan_sta[i].ChannelNum <= 14)) {
6590 				chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6591 				chplan_new[k].ScanType = chplan_sta[i].ScanType;
6592 				i++;
6593 				k++;
6594 			}
6595 
6596 			/*  skip AP 2.4G channel plan */
6597 			while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
6598 				j++;
6599 		}
6600 
6601 		/*  keep original STA 5G channel plan */
6602 		while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
6603 			chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6604 			chplan_new[k].ScanType = chplan_sta[i].ScanType;
6605 			i++;
6606 			k++;
6607 		}
6608 
6609 		pmlmeext->update_channel_plan_by_ap_done = 1;
6610 	}
6611 
6612 	/*  If channel is used by AP, set channel scan type to active */
6613 	channel = bssid->Configuration.DSConfig;
6614 	chplan_new = pmlmeext->channel_set;
6615 	i = 0;
6616 	while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
6617 		if (chplan_new[i].ChannelNum == channel) {
6618 			if (chplan_new[i].ScanType == SCAN_PASSIVE)
6619 				chplan_new[i].ScanType = SCAN_ACTIVE;
6620 			break;
6621 		}
6622 		i++;
6623 	}
6624 }
6625 
6626 /****************************************************************************
6627 
6628 Following are the functions to report events
6629 
6630 *****************************************************************************/
6631 
report_survey_event(struct adapter * padapter,struct recv_frame * precv_frame)6632 void report_survey_event(struct adapter *padapter, struct recv_frame *precv_frame)
6633 {
6634 	struct cmd_obj *pcmd_obj;
6635 	u8 *pevtcmd;
6636 	u32 cmdsz;
6637 	struct survey_event	*psurvey_evt;
6638 	struct C2HEvent_Header *pc2h_evt_hdr;
6639 	struct mlme_ext_priv *pmlmeext;
6640 	struct cmd_priv *pcmdpriv;
6641 	/* u8 *pframe = precv_frame->rx_data; */
6642 	/* uint len = precv_frame->len; */
6643 
6644 	if (!padapter)
6645 		return;
6646 
6647 	pmlmeext = &padapter->mlmeextpriv;
6648 	pcmdpriv = &padapter->cmdpriv;
6649 
6650 	pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC);
6651 	if (!pcmd_obj)
6652 		return;
6653 
6654 	cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
6655 	pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
6656 	if (!pevtcmd) {
6657 		kfree(pcmd_obj);
6658 		return;
6659 	}
6660 
6661 	INIT_LIST_HEAD(&pcmd_obj->list);
6662 
6663 	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
6664 	pcmd_obj->cmdsz = cmdsz;
6665 	pcmd_obj->parmbuf = pevtcmd;
6666 
6667 	pcmd_obj->rsp = NULL;
6668 	pcmd_obj->rspsz  = 0;
6669 
6670 	pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
6671 	pc2h_evt_hdr->len = sizeof(struct survey_event);
6672 	pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
6673 	pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
6674 
6675 	psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
6676 
6677 	if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
6678 		kfree(pcmd_obj);
6679 		kfree(pevtcmd);
6680 		return;
6681 	}
6682 
6683 	process_80211d(padapter, &psurvey_evt->bss);
6684 
6685 	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
6686 
6687 	pmlmeext->sitesurvey_res.bss_cnt++;
6688 }
6689 
report_surveydone_event(struct adapter * padapter)6690 void report_surveydone_event(struct adapter *padapter)
6691 {
6692 	struct cmd_obj *pcmd_obj;
6693 	u8 *pevtcmd;
6694 	u32 cmdsz;
6695 	struct surveydone_event *psurveydone_evt;
6696 	struct C2HEvent_Header	*pc2h_evt_hdr;
6697 	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
6698 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6699 
6700 	pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_KERNEL);
6701 	if (!pcmd_obj)
6702 		return;
6703 
6704 	cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
6705 	pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
6706 	if (!pevtcmd) {
6707 		kfree(pcmd_obj);
6708 		return;
6709 	}
6710 
6711 	INIT_LIST_HEAD(&pcmd_obj->list);
6712 
6713 	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
6714 	pcmd_obj->cmdsz = cmdsz;
6715 	pcmd_obj->parmbuf = pevtcmd;
6716 
6717 	pcmd_obj->rsp = NULL;
6718 	pcmd_obj->rspsz  = 0;
6719 
6720 	pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
6721 	pc2h_evt_hdr->len = sizeof(struct surveydone_event);
6722 	pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
6723 	pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
6724 
6725 	psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
6726 	psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
6727 
6728 	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
6729 }
6730 
report_join_res(struct adapter * padapter,int res)6731 void report_join_res(struct adapter *padapter, int res)
6732 {
6733 	struct cmd_obj *pcmd_obj;
6734 	u8 *pevtcmd;
6735 	u32 cmdsz;
6736 	struct joinbss_event		*pjoinbss_evt;
6737 	struct C2HEvent_Header	*pc2h_evt_hdr;
6738 	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
6739 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
6740 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6741 
6742 	pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC);
6743 	if (!pcmd_obj)
6744 		return;
6745 
6746 	cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
6747 	pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
6748 	if (!pevtcmd) {
6749 		kfree(pcmd_obj);
6750 		return;
6751 	}
6752 
6753 	INIT_LIST_HEAD(&pcmd_obj->list);
6754 
6755 	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
6756 	pcmd_obj->cmdsz = cmdsz;
6757 	pcmd_obj->parmbuf = pevtcmd;
6758 
6759 	pcmd_obj->rsp = NULL;
6760 	pcmd_obj->rspsz  = 0;
6761 
6762 	pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
6763 	pc2h_evt_hdr->len = sizeof(struct joinbss_event);
6764 	pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
6765 	pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
6766 
6767 	pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
6768 	memcpy((unsigned char *)(&pjoinbss_evt->network.network), &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
6769 	pjoinbss_evt->network.join_res	= res;
6770 	pjoinbss_evt->network.aid = res;
6771 
6772 	rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
6773 
6774 	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
6775 }
6776 
report_del_sta_event(struct adapter * padapter,unsigned char * MacAddr,unsigned short reason)6777 void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
6778 {
6779 	struct cmd_obj *pcmd_obj;
6780 	u8 *pevtcmd;
6781 	u32 cmdsz;
6782 	struct sta_info *psta;
6783 	int	mac_id;
6784 	struct stadel_event			*pdel_sta_evt;
6785 	struct C2HEvent_Header	*pc2h_evt_hdr;
6786 	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
6787 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6788 
6789 	pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC);
6790 	if (!pcmd_obj)
6791 		return;
6792 
6793 	cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
6794 	pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
6795 	if (!pevtcmd) {
6796 		kfree(pcmd_obj);
6797 		return;
6798 	}
6799 
6800 	INIT_LIST_HEAD(&pcmd_obj->list);
6801 
6802 	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
6803 	pcmd_obj->cmdsz = cmdsz;
6804 	pcmd_obj->parmbuf = pevtcmd;
6805 
6806 	pcmd_obj->rsp = NULL;
6807 	pcmd_obj->rspsz  = 0;
6808 
6809 	pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
6810 	pc2h_evt_hdr->len = sizeof(struct stadel_event);
6811 	pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
6812 	pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
6813 
6814 	pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
6815 	memcpy((unsigned char *)(&pdel_sta_evt->macaddr), MacAddr, ETH_ALEN);
6816 	memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
6817 
6818 	psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
6819 	if (psta)
6820 		mac_id = (int)psta->mac_id;
6821 	else
6822 		mac_id = (-1);
6823 
6824 	pdel_sta_evt->mac_id = mac_id;
6825 
6826 	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
6827 }
6828 
report_add_sta_event(struct adapter * padapter,unsigned char * MacAddr,int cam_idx)6829 void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
6830 {
6831 	struct cmd_obj *pcmd_obj;
6832 	u8 *pevtcmd;
6833 	u32 cmdsz;
6834 	struct stassoc_event		*padd_sta_evt;
6835 	struct C2HEvent_Header	*pc2h_evt_hdr;
6836 	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
6837 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6838 
6839 	pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_KERNEL);
6840 	if (!pcmd_obj)
6841 		return;
6842 
6843 	cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
6844 	pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
6845 	if (!pevtcmd) {
6846 		kfree(pcmd_obj);
6847 		return;
6848 	}
6849 
6850 	INIT_LIST_HEAD(&pcmd_obj->list);
6851 
6852 	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
6853 	pcmd_obj->cmdsz = cmdsz;
6854 	pcmd_obj->parmbuf = pevtcmd;
6855 
6856 	pcmd_obj->rsp = NULL;
6857 	pcmd_obj->rspsz  = 0;
6858 
6859 	pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
6860 	pc2h_evt_hdr->len = sizeof(struct stassoc_event);
6861 	pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
6862 	pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
6863 
6864 	padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
6865 	memcpy((unsigned char *)(&padd_sta_evt->macaddr), MacAddr, ETH_ALEN);
6866 	padd_sta_evt->cam_id = cam_idx;
6867 
6868 	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
6869 }
6870 
6871 /****************************************************************************
6872 
6873 Following are the event callback functions
6874 
6875 *****************************************************************************/
6876 
6877 /* for sta/adhoc mode */
update_sta_info(struct adapter * padapter,struct sta_info * psta)6878 void update_sta_info(struct adapter *padapter, struct sta_info *psta)
6879 {
6880 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6881 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
6882 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
6883 
6884 	/* ERP */
6885 	VCS_update(padapter, psta);
6886 
6887 	/* HT */
6888 	if (pmlmepriv->htpriv.ht_option) {
6889 		psta->htpriv.ht_option = true;
6890 
6891 		psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
6892 
6893 		if (support_short_GI(padapter, &pmlmeinfo->HT_caps))
6894 			psta->htpriv.sgi = true;
6895 
6896 		psta->qos_option = true;
6897 	} else {
6898 		psta->htpriv.ht_option = false;
6899 
6900 		psta->htpriv.ampdu_enable = false;
6901 
6902 		psta->htpriv.sgi = false;
6903 		psta->qos_option = false;
6904 	}
6905 	psta->htpriv.bwmode = pmlmeext->cur_bwmode;
6906 	psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
6907 
6908 	psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
6909 	psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
6910 
6911 	/* QoS */
6912 	if (pmlmepriv->qospriv.qos_option)
6913 		psta->qos_option = true;
6914 
6915 	psta->state = _FW_LINKED;
6916 }
6917 
rtw_reset_dm_func_flag(struct adapter * adapter)6918 static void rtw_reset_dm_func_flag(struct adapter *adapter)
6919 {
6920 	struct hal_data_8188e *haldata = &adapter->haldata;
6921 	struct dm_priv *dmpriv = &haldata->dmpriv;
6922 	struct odm_dm_struct *odmpriv = &haldata->odmpriv;
6923 
6924 	odmpriv->SupportAbility = dmpriv->InitODMFlag;
6925 }
6926 
rtw_clear_dm_func_flag(struct adapter * adapter)6927 static void rtw_clear_dm_func_flag(struct adapter *adapter)
6928 {
6929 	struct hal_data_8188e *haldata = &adapter->haldata;
6930 	struct odm_dm_struct *odmpriv = &haldata->odmpriv;
6931 
6932 	odmpriv->SupportAbility = 0;
6933 }
6934 
mlmeext_joinbss_event_callback(struct adapter * padapter,int join_res)6935 void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
6936 {
6937 	struct sta_info		*psta, *psta_bmc;
6938 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
6939 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
6940 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
6941 	struct sta_priv		*pstapriv = &padapter->stapriv;
6942 	u16 media_status;
6943 
6944 	if (join_res < 0) {
6945 		mlme_join(padapter, 1);
6946 		rtw_set_bssid(padapter, null_addr);
6947 
6948 		/* restore to initial setting. */
6949 		update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
6950 
6951 		return;
6952 	}
6953 
6954 	if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
6955 		/* for bc/mc */
6956 		psta_bmc = rtw_get_bcmc_stainfo(padapter);
6957 		if (psta_bmc) {
6958 			pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
6959 			update_bmc_sta_support_rate(padapter, psta_bmc->mac_id);
6960 			Update_RA_Entry(padapter, psta_bmc->mac_id);
6961 		}
6962 	}
6963 
6964 	/* turn on dynamic functions */
6965 	rtw_reset_dm_func_flag(padapter);
6966 
6967 	/*  update IOT-releated issue */
6968 	update_IOT_info(padapter);
6969 
6970 	rtw_set_basic_rate(padapter, cur_network->SupportedRates);
6971 
6972 	/* BCN interval */
6973 	rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
6974 
6975 	/* udpate capability */
6976 	update_capinfo(padapter, pmlmeinfo->capability);
6977 
6978 	/* WMM, Update EDCA param */
6979 	WMMOnAssocRsp(padapter);
6980 
6981 	/* HT */
6982 	HTOnAssocRsp(padapter);
6983 
6984 	set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6985 
6986 	psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
6987 	if (psta) { /* only for infra. mode */
6988 		pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
6989 
6990 		psta->wireless_mode = pmlmeext->cur_wireless_mode;
6991 
6992 		/* set per sta rate after updating HT cap. */
6993 		set_sta_rate(padapter, psta);
6994 		rtw_set_max_rpt_macid(padapter, psta->mac_id);
6995 
6996 		media_status = (psta->mac_id << 8) | 1; /*   MACID|OPMODE: 1 means connect */
6997 		rtl8188e_set_FwMediaStatus_cmd(padapter, media_status);
6998 	}
6999 
7000 	mlme_join(padapter, 2);
7001 
7002 	if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
7003 		/*  correcting TSF */
7004 		correct_TSF(padapter);
7005 	}
7006 	rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
7007 }
7008 
mlmeext_sta_add_event_callback(struct adapter * padapter,struct sta_info * psta)7009 void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
7010 {
7011 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7012 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7013 
7014 	if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
7015 		if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */
7016 			/* nothing to do */
7017 		} else { /* adhoc client */
7018 			/*  correcting TSF */
7019 			correct_TSF(padapter);
7020 
7021 			/* start beacon */
7022 			if (send_beacon(padapter) == _FAIL) {
7023 				pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
7024 				pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
7025 				return;
7026 			}
7027 			pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
7028 		}
7029 		mlme_join(padapter, 2);
7030 	}
7031 
7032 	pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
7033 
7034 	/* rate radaptive */
7035 	Update_RA_Entry(padapter, psta->mac_id);
7036 
7037 	/* update adhoc sta_info */
7038 	update_sta_info(padapter, psta);
7039 }
7040 
mlme_disconnect(struct adapter * adapter)7041 static void mlme_disconnect(struct adapter *adapter)
7042 {
7043 	int res;
7044 	u8 reg;
7045 
7046 	/* Set RCR to not to receive data frame when NO LINK state */
7047 	/* reject all data frames */
7048 	rtw_write16(adapter, REG_RXFLTMAP2, 0x00);
7049 
7050 	/* reset TSF */
7051 	rtw_write8(adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
7052 
7053 	/* disable update TSF */
7054 
7055 	res = rtw_read8(adapter, REG_BCN_CTRL, &reg);
7056 	if (res)
7057 		return;
7058 
7059 	rtw_write8(adapter, REG_BCN_CTRL, reg | BIT(4));
7060 }
7061 
mlmeext_sta_del_event_callback(struct adapter * padapter)7062 void mlmeext_sta_del_event_callback(struct adapter *padapter)
7063 {
7064 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7065 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7066 
7067 	if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) {
7068 		mlme_disconnect(padapter);
7069 		rtw_set_bssid(padapter, null_addr);
7070 
7071 		/* restore to initial setting. */
7072 		update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
7073 
7074 		/* switch to the 20M Hz mode after disconnect */
7075 		pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7076 		pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7077 
7078 		/* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
7079 		set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
7080 
7081 		flush_all_cam_entry(padapter);
7082 
7083 		pmlmeinfo->state = WIFI_FW_NULL_STATE;
7084 
7085 		/* set MSR to no link state -> infra. mode */
7086 		Set_MSR(padapter, _HW_STATE_STATION_);
7087 
7088 		_cancel_timer_ex(&pmlmeext->link_timer);
7089 	}
7090 }
7091 
7092 /****************************************************************************
7093 
7094 Following are the functions for the timer handlers
7095 
7096 *****************************************************************************/
chk_ap_is_alive(struct sta_info * psta)7097 static u8 chk_ap_is_alive(struct sta_info *psta)
7098 {
7099 	u8 ret = false;
7100 
7101 	if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
7102 	    sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
7103 	    sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
7104 		ret = false;
7105 	else
7106 		ret = true;
7107 
7108 	sta_update_last_rx_pkts(psta);
7109 
7110 	return ret;
7111 }
7112 
rtl8188e_sreset_linked_status_check(struct adapter * padapter)7113 static int rtl8188e_sreset_linked_status_check(struct adapter *padapter)
7114 {
7115 	u32 rx_dma_status;
7116 	int res;
7117 	u8 reg;
7118 
7119 	res = rtw_read32(padapter, REG_RXDMA_STATUS, &rx_dma_status);
7120 	if (res)
7121 		return res;
7122 
7123 	if (rx_dma_status != 0x00)
7124 		rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);
7125 
7126 	return rtw_read8(padapter, REG_FMETHR, &reg);
7127 }
7128 
linked_status_chk(struct adapter * padapter)7129 void linked_status_chk(struct adapter *padapter)
7130 {
7131 	u32	i;
7132 	struct sta_info		*psta;
7133 	struct xmit_priv		*pxmitpriv = &padapter->xmitpriv;
7134 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7135 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7136 	struct sta_priv		*pstapriv = &padapter->stapriv;
7137 
7138 	rtl8188e_sreset_linked_status_check(padapter);
7139 
7140 	if (is_client_associated_to_ap(padapter)) {
7141 		/* linked infrastructure client mode */
7142 
7143 		int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
7144 		int rx_chk_limit;
7145 
7146 		rx_chk_limit = 4;
7147 		psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
7148 		if (psta) {
7149 			bool is_p2p_enable = false;
7150 			is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
7151 
7152 			if (!chk_ap_is_alive(psta))
7153 				rx_chk = _FAIL;
7154 
7155 			if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
7156 				tx_chk = _FAIL;
7157 
7158 			if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
7159 				u8 backup_oper_channel = 0;
7160 
7161 				/* switch to correct channel of current network  before issue keep-alive frames */
7162 				if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
7163 					backup_oper_channel = rtw_get_oper_ch(padapter);
7164 					SelectChannel(padapter, pmlmeext->cur_channel);
7165 				}
7166 
7167 				if (rx_chk != _SUCCESS)
7168 					issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
7169 
7170 				if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
7171 					tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
7172 					/* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
7173 					if (tx_chk == _SUCCESS && !is_p2p_enable)
7174 						rx_chk = _SUCCESS;
7175 				}
7176 
7177 				/* back to the original operation channel */
7178 				if (backup_oper_channel > 0)
7179 					SelectChannel(padapter, backup_oper_channel);
7180 			} else {
7181 				if (rx_chk != _SUCCESS) {
7182 					if (pmlmeext->retry == 0) {
7183 						issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7184 						issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7185 						issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7186 					}
7187 				}
7188 
7189 				if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) {
7190 					tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0);
7191 				}
7192 			}
7193 
7194 			if (rx_chk == _FAIL) {
7195 				pmlmeext->retry++;
7196 				if (pmlmeext->retry > rx_chk_limit) {
7197 					receive_disconnect(padapter, pmlmeinfo->network.MacAddress,
7198 							   WLAN_REASON_EXPIRATION_CHK);
7199 					return;
7200 				}
7201 			} else {
7202 				pmlmeext->retry = 0;
7203 			}
7204 
7205 			if (tx_chk == _FAIL) {
7206 				pmlmeinfo->link_count &= 0xf;
7207 			} else {
7208 				pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
7209 				pmlmeinfo->link_count = 0;
7210 			}
7211 		} /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
7212 	} else if (is_client_associated_to_ibss(padapter)) {
7213 		/* linked IBSS mode */
7214 		/* for each assoc list entry to check the rx pkt counter */
7215 		for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
7216 			if (pmlmeinfo->FW_sta_info[i].status == 1) {
7217 				psta = pmlmeinfo->FW_sta_info[i].psta;
7218 
7219 				if (psta == NULL)
7220 					continue;
7221 				if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
7222 					if (pmlmeinfo->FW_sta_info[i].retry < 3) {
7223 						pmlmeinfo->FW_sta_info[i].retry++;
7224 					} else {
7225 						pmlmeinfo->FW_sta_info[i].retry = 0;
7226 						pmlmeinfo->FW_sta_info[i].status = 0;
7227 						report_del_sta_event(padapter, psta->hwaddr
7228 							, 65535/*  indicate disconnect caused by no rx */
7229 					);
7230 					}
7231 				} else {
7232 					pmlmeinfo->FW_sta_info[i].retry = 0;
7233 					pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
7234 				}
7235 			}
7236 		}
7237 	}
7238 }
7239 
survey_timer_hdl(struct adapter * padapter)7240 void survey_timer_hdl(struct adapter *padapter)
7241 {
7242 	struct cmd_obj	*ph2c;
7243 	struct sitesurvey_parm	*psurveyPara;
7244 	struct cmd_priv					*pcmdpriv = &padapter->cmdpriv;
7245 	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
7246 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
7247 
7248 	/* issue rtw_sitesurvey_cmd */
7249 	if (pmlmeext->sitesurvey_res.state > SCAN_START) {
7250 		if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
7251 			pmlmeext->sitesurvey_res.channel_idx++;
7252 
7253 		if (pmlmeext->scan_abort) {
7254 			if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) {
7255 				rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
7256 				pmlmeext->sitesurvey_res.channel_idx = 3;
7257 			} else {
7258 				pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
7259 			}
7260 
7261 			pmlmeext->scan_abort = false;/* reset */
7262 		}
7263 
7264 		ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
7265 		if (!ph2c)
7266 			goto exit_survey_timer_hdl;
7267 
7268 		psurveyPara = kzalloc(sizeof(*psurveyPara), GFP_ATOMIC);
7269 		if (!psurveyPara) {
7270 			kfree(ph2c);
7271 			goto exit_survey_timer_hdl;
7272 		}
7273 
7274 		init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
7275 		rtw_enqueue_cmd(pcmdpriv, ph2c);
7276 	}
7277 
7278 exit_survey_timer_hdl:
7279 	return;
7280 }
7281 
link_timer_hdl(struct adapter * padapter)7282 void link_timer_hdl(struct adapter *padapter)
7283 {
7284 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7285 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7286 
7287 	if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
7288 		pmlmeinfo->state = WIFI_FW_NULL_STATE;
7289 		report_join_res(padapter, -3);
7290 	} else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
7291 		/* re-auth timer */
7292 		if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
7293 			pmlmeinfo->state = 0;
7294 			report_join_res(padapter, -1);
7295 			return;
7296 		}
7297 
7298 		pmlmeinfo->auth_seq = 1;
7299 		issue_auth(padapter, NULL, 0);
7300 		set_link_timer(pmlmeext, REAUTH_TO);
7301 	} else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
7302 		/* re-assoc timer */
7303 		if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
7304 			pmlmeinfo->state = WIFI_FW_NULL_STATE;
7305 			report_join_res(padapter, -2);
7306 			return;
7307 		}
7308 
7309 		issue_assocreq(padapter);
7310 		set_link_timer(pmlmeext, REASSOC_TO);
7311 	}
7312 }
7313 
addba_timer_hdl(struct sta_info * psta)7314 void addba_timer_hdl(struct sta_info *psta)
7315 {
7316 	struct ht_priv	*phtpriv;
7317 
7318 	if (!psta)
7319 		return;
7320 
7321 	phtpriv = &psta->htpriv;
7322 
7323 	if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
7324 		if (phtpriv->candidate_tid_bitmap)
7325 			phtpriv->candidate_tid_bitmap = 0x0;
7326 	}
7327 }
7328 
NULL_hdl(struct adapter * padapter,u8 * pbuf)7329 u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
7330 {
7331 	return H2C_SUCCESS;
7332 }
7333 
setopmode_hdl(struct adapter * padapter,u8 * pbuf)7334 u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
7335 {
7336 	u8 type;
7337 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7338 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7339 	struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
7340 
7341 	if (psetop->mode == Ndis802_11APMode) {
7342 		pmlmeinfo->state = WIFI_FW_AP_STATE;
7343 		type = _HW_STATE_AP_;
7344 	} else if (psetop->mode == Ndis802_11Infrastructure) {
7345 		pmlmeinfo->state &= ~(BIT(0) | BIT(1));/*  clear state */
7346 		pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to	STATION_STATE */
7347 		type = _HW_STATE_STATION_;
7348 	} else if (psetop->mode == Ndis802_11IBSS) {
7349 		type = _HW_STATE_ADHOC_;
7350 	} else {
7351 		type = _HW_STATE_NOLINK_;
7352 	}
7353 
7354 	rtw_set_opmode(padapter, type);
7355 
7356 	return H2C_SUCCESS;
7357 }
7358 
createbss_hdl(struct adapter * padapter,u8 * pbuf)7359 u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
7360 {
7361 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7362 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7363 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
7364 	struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
7365 	/* u32	initialgain; */
7366 
7367 	if (pparm->network.InfrastructureMode == Ndis802_11APMode) {
7368 		if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
7369 			/* todo: */
7370 			return H2C_SUCCESS;
7371 		}
7372 	}
7373 
7374 	/* below is for ad-hoc master */
7375 	if (pparm->network.InfrastructureMode == Ndis802_11IBSS) {
7376 		rtw_joinbss_reset(padapter);
7377 
7378 		pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7379 		pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7380 		pmlmeinfo->ERP_enable = 0;
7381 		pmlmeinfo->WMM_enable = 0;
7382 		pmlmeinfo->HT_enable = 0;
7383 		pmlmeinfo->HT_caps_enable = 0;
7384 		pmlmeinfo->HT_info_enable = 0;
7385 		pmlmeinfo->agg_enable_bitmap = 0;
7386 		pmlmeinfo->candidate_tid_bitmap = 0;
7387 
7388 		/* disable dynamic functions, such as high power, DIG */
7389 		Save_DM_Func_Flag(padapter);
7390 		rtw_clear_dm_func_flag(padapter);
7391 
7392 		/* cancel link timer */
7393 		_cancel_timer_ex(&pmlmeext->link_timer);
7394 
7395 		/* clear CAM */
7396 		flush_all_cam_entry(padapter);
7397 
7398 		memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, IELength));
7399 		pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
7400 
7401 		if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
7402 			return H2C_PARAMETERS_ERROR;
7403 
7404 		memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
7405 
7406 		start_create_ibss(padapter);
7407 	}
7408 
7409 	return H2C_SUCCESS;
7410 }
7411 
join_cmd_hdl(struct adapter * padapter,u8 * pbuf)7412 u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
7413 {
7414 	struct ndis_802_11_var_ie *pIE;
7415 	struct registry_priv	*pregpriv = &padapter->registrypriv;
7416 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7417 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7418 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
7419 	struct joinbss_parm	*pparm = (struct joinbss_parm *)pbuf;
7420 	u32 i;
7421 
7422 	/* check already connecting to AP or not */
7423 	if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
7424 		if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
7425 			issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100);
7426 
7427 		pmlmeinfo->state = WIFI_FW_NULL_STATE;
7428 
7429 		/* clear CAM */
7430 		flush_all_cam_entry(padapter);
7431 
7432 		_cancel_timer_ex(&pmlmeext->link_timer);
7433 
7434 		/* set MSR to nolink -> infra. mode */
7435 		Set_MSR(padapter, _HW_STATE_STATION_);
7436 
7437 		mlme_disconnect(padapter);
7438 	}
7439 
7440 	rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, false);
7441 
7442 	rtw_joinbss_reset(padapter);
7443 
7444 	pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7445 	pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7446 	pmlmeinfo->ERP_enable = 0;
7447 	pmlmeinfo->WMM_enable = 0;
7448 	pmlmeinfo->HT_enable = 0;
7449 	pmlmeinfo->HT_caps_enable = 0;
7450 	pmlmeinfo->HT_info_enable = 0;
7451 	pmlmeinfo->agg_enable_bitmap = 0;
7452 	pmlmeinfo->candidate_tid_bitmap = 0;
7453 	pmlmeinfo->bwmode_updated = false;
7454 
7455 	memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, IELength));
7456 	pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
7457 
7458 	if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
7459 		return H2C_PARAMETERS_ERROR;
7460 
7461 	memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
7462 
7463 	/* Check AP vendor to move rtw_joinbss_cmd() */
7464 
7465 	for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->IELength;) {
7466 		pIE = (struct ndis_802_11_var_ie *)(pnetwork->IEs + i);
7467 
7468 		switch (pIE->ElementID) {
7469 		case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
7470 			if (!memcmp(pIE->data, WMM_OUI, 4))
7471 				pmlmeinfo->WMM_enable = 1;
7472 			break;
7473 		case _HT_CAPABILITY_IE_:	/* Get HT Cap IE. */
7474 			pmlmeinfo->HT_caps_enable = 1;
7475 			break;
7476 		case _HT_EXTRA_INFO_IE_:	/* Get HT Info IE. */
7477 			pmlmeinfo->HT_info_enable = 1;
7478 
7479 			/* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
7480 			{
7481 				struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
7482 
7483 				if ((pregpriv->cbw40_enable) &&	 (pht_info->infos[0] & BIT(2))) {
7484 					/* switch to the 40M Hz mode according to the AP */
7485 					pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
7486 					switch (pht_info->infos[0] & 0x3) {
7487 					case 1:
7488 						pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
7489 						break;
7490 					case 3:
7491 						pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
7492 						break;
7493 					default:
7494 						pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7495 						break;
7496 					}
7497 				}
7498 			}
7499 			break;
7500 		default:
7501 			break;
7502 		}
7503 
7504 		i += (pIE->Length + 2);
7505 	}
7506 	/* disable dynamic functions, such as high power, DIG */
7507 
7508 	/* config the initial gain under linking, need to write the BB registers */
7509 
7510 	rtw_set_bssid(padapter, pmlmeinfo->network.MacAddress);
7511 	mlme_join(padapter, 0);
7512 
7513 	/* cancel link timer */
7514 	_cancel_timer_ex(&pmlmeext->link_timer);
7515 
7516 	start_clnt_join(padapter);
7517 
7518 	return H2C_SUCCESS;
7519 }
7520 
disconnect_hdl(struct adapter * padapter,unsigned char * pbuf)7521 u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
7522 {
7523 	struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
7524 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7525 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7526 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
7527 	u8 val8;
7528 	int res;
7529 
7530 	if (is_client_associated_to_ap(padapter))
7531 		issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms / 100, 100);
7532 
7533 	mlme_disconnect(padapter);
7534 	rtw_set_bssid(padapter, null_addr);
7535 
7536 	/* restore to initial setting. */
7537 	update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
7538 
7539 	if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
7540 		/* Stop BCN */
7541 		res = rtw_read8(padapter, REG_BCN_CTRL, &val8);
7542 		if (res)
7543 			return H2C_DROPPED;
7544 
7545 		rtw_write8(padapter, REG_BCN_CTRL, val8 & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT)));
7546 	}
7547 
7548 	/* set MSR to no link state -> infra. mode */
7549 	Set_MSR(padapter, _HW_STATE_STATION_);
7550 
7551 	pmlmeinfo->state = WIFI_FW_NULL_STATE;
7552 
7553 	/* switch to the 20M Hz mode after disconnect */
7554 	pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7555 	pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7556 
7557 	set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
7558 
7559 	flush_all_cam_entry(padapter);
7560 
7561 	_cancel_timer_ex(&pmlmeext->link_timer);
7562 
7563 	rtw_free_uc_swdec_pending_queue(padapter);
7564 
7565 	return	H2C_SUCCESS;
7566 }
7567 
rtw_scan_ch_decision(struct adapter * padapter,struct rtw_ieee80211_channel * out,u32 out_num,struct rtw_ieee80211_channel * in,u32 in_num)7568 static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
7569 	u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
7570 {
7571 	int i, j;
7572 	int set_idx;
7573 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7574 
7575 	/* clear out first */
7576 	memset(out, 0, sizeof(struct rtw_ieee80211_channel) * out_num);
7577 
7578 	/* acquire channels from in */
7579 	j = 0;
7580 	for (i = 0; i < in_num; i++) {
7581 		set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
7582 		if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) &&
7583 		    set_idx >= 0) {
7584 			memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
7585 
7586 			if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
7587 				out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
7588 
7589 			j++;
7590 		}
7591 		if (j >= out_num)
7592 			break;
7593 	}
7594 
7595 	/* if out is empty, use channel_set as default */
7596 	if (j == 0) {
7597 		for (i = 0; i < pmlmeext->max_chan_nums; i++) {
7598 			out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
7599 
7600 			if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
7601 				out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
7602 
7603 			j++;
7604 		}
7605 	}
7606 
7607 	return j;
7608 }
7609 
sitesurvey_cmd_hdl(struct adapter * padapter,u8 * pbuf)7610 u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
7611 {
7612 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7613 	struct sitesurvey_parm	*pparm = (struct sitesurvey_parm *)pbuf;
7614 	u8 bdelayscan = false;
7615 	u32	i;
7616 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
7617 
7618 	if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
7619 		/* for first time sitesurvey_cmd */
7620 
7621 		pmlmeext->sitesurvey_res.state = SCAN_START;
7622 		pmlmeext->sitesurvey_res.bss_cnt = 0;
7623 		pmlmeext->sitesurvey_res.channel_idx = 0;
7624 
7625 		for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
7626 			if (pparm->ssid[i].SsidLength) {
7627 				memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
7628 				pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
7629 			} else {
7630 				pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
7631 			}
7632 		}
7633 
7634 		pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
7635 			, pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
7636 			, pparm->ch, pparm->ch_num
7637 	);
7638 
7639 		pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
7640 
7641 		/* issue null data if associating to the AP */
7642 		if (is_client_associated_to_ap(padapter)) {
7643 			pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
7644 
7645 			issue_nulldata(padapter, NULL, 1, 3, 500);
7646 
7647 			bdelayscan = true;
7648 		}
7649 		if (bdelayscan) {
7650 			/* delay 50ms to protect nulldata(1). */
7651 			set_survey_timer(pmlmeext, 50);
7652 			return H2C_SUCCESS;
7653 		}
7654 	}
7655 
7656 	if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
7657 		/* disable dynamic functions, such as high power, DIG */
7658 		Save_DM_Func_Flag(padapter);
7659 		rtw_clear_dm_func_flag(padapter);
7660 
7661 		/* config the initial gain under scanning, need to write the BB registers */
7662 		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
7663 			rtw_set_initial_gain(padapter, 0x1e);
7664 		else
7665 			rtw_set_initial_gain(padapter, 0x28);
7666 
7667 
7668 		/* set MSR to no link state */
7669 		Set_MSR(padapter, _HW_STATE_NOLINK_);
7670 
7671 		rtw_mlme_under_site_survey(padapter);
7672 
7673 		pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
7674 	}
7675 
7676 	site_survey(padapter);
7677 
7678 	return H2C_SUCCESS;
7679 }
7680 
setauth_hdl(struct adapter * padapter,unsigned char * pbuf)7681 u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
7682 {
7683 	struct setauth_parm		*pparm = (struct setauth_parm *)pbuf;
7684 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7685 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7686 
7687 	if (pparm->mode < 4)
7688 		pmlmeinfo->auth_algo = pparm->mode;
7689 	return	H2C_SUCCESS;
7690 }
7691 
setkey_hdl(struct adapter * padapter,u8 * pbuf)7692 u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
7693 {
7694 	unsigned short				ctrl;
7695 	struct setkey_parm		*pparm = (struct setkey_parm *)pbuf;
7696 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7697 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7698 	unsigned char					null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
7699 
7700 	/* main tx key for wep. */
7701 	if (pparm->set_tx)
7702 		pmlmeinfo->key_index = pparm->keyid;
7703 
7704 	/* write cam */
7705 	ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
7706 
7707 	write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
7708 
7709 	return H2C_SUCCESS;
7710 }
7711 
set_stakey_hdl(struct adapter * padapter,u8 * pbuf)7712 u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
7713 {
7714 	u16 ctrl = 0;
7715 	u8 cam_id;/* cam_entry */
7716 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7717 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7718 	struct set_stakey_parm	*pparm = (struct set_stakey_parm *)pbuf;
7719 
7720 	/* cam_entry: */
7721 	/* 0~3 for default key */
7722 
7723 	/* for concurrent mode (ap+sta): */
7724 	/* default key is disable, using sw encrypt/decrypt */
7725 	/* cam_entry = 4 for sta mode (macid = 0) */
7726 	/* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
7727 
7728 	/* for concurrent mode (sta+sta): */
7729 	/* default key is disable, using sw encrypt/decrypt */
7730 	/* cam_entry = 4 mapping to macid = 0 */
7731 	/* cam_entry = 5 mapping to macid = 2 */
7732 
7733 	cam_id = 4;
7734 
7735 	if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
7736 		struct sta_info *psta;
7737 		struct sta_priv *pstapriv = &padapter->stapriv;
7738 
7739 		if (pparm->algorithm == _NO_PRIVACY_)	/*  clear cam entry */ {
7740 			clear_cam_entry(padapter, pparm->id);
7741 			return H2C_SUCCESS_RSP;
7742 		}
7743 
7744 		psta = rtw_get_stainfo(pstapriv, pparm->addr);
7745 		if (psta) {
7746 			ctrl = (BIT(15) | ((pparm->algorithm) << 2));
7747 
7748 			if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA - 4)))
7749 				return H2C_REJECTED;
7750 
7751 			cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
7752 
7753 			write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
7754 
7755 			return H2C_SUCCESS_RSP;
7756 		} else {
7757 			return H2C_REJECTED;
7758 		}
7759 	}
7760 
7761 	/* below for sta mode */
7762 
7763 	if (pparm->algorithm == _NO_PRIVACY_) {	/*  clear cam entry */
7764 		clear_cam_entry(padapter, pparm->id);
7765 		return H2C_SUCCESS;
7766 	}
7767 	ctrl = BIT(15) | ((pparm->algorithm) << 2);
7768 	write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
7769 	pmlmeinfo->enc_algo = pparm->algorithm;
7770 	return H2C_SUCCESS;
7771 }
7772 
add_ba_hdl(struct adapter * padapter,unsigned char * pbuf)7773 u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
7774 {
7775 	struct addBaReq_parm	*pparm = (struct addBaReq_parm *)pbuf;
7776 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7777 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7778 
7779 	struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
7780 
7781 	if (!psta)
7782 		return	H2C_SUCCESS;
7783 
7784 	if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
7785 	    ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
7786 		issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
7787 		_set_timer(&psta->addba_retry_timer, ADDBA_TO);
7788 	} else {
7789 		psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
7790 	}
7791 	return	H2C_SUCCESS;
7792 }
7793 
set_tx_beacon_cmd(struct adapter * padapter)7794 u8 set_tx_beacon_cmd(struct adapter *padapter)
7795 {
7796 	struct cmd_obj	*ph2c;
7797 	struct Tx_Beacon_param	*ptxBeacon_parm;
7798 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
7799 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7800 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
7801 	u8 res = _SUCCESS;
7802 	int len_diff = 0;
7803 
7804 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
7805 	if (!ph2c) {
7806 		res = _FAIL;
7807 		goto exit;
7808 	}
7809 
7810 	ptxBeacon_parm = kzalloc(sizeof(*ptxBeacon_parm), GFP_ATOMIC);
7811 	if (!ptxBeacon_parm) {
7812 		kfree(ph2c);
7813 		res = _FAIL;
7814 		goto exit;
7815 	}
7816 
7817 	memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
7818 
7819 	len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs + _BEACON_IE_OFFSET_,
7820 				      ptxBeacon_parm->network.IELength - _BEACON_IE_OFFSET_,
7821 				      pmlmeinfo->hidden_ssid_mode);
7822 	ptxBeacon_parm->network.IELength += len_diff;
7823 
7824 	init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
7825 
7826 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
7827 
7828 exit:
7829 
7830 	return res;
7831 }
7832 
mlme_evt_hdl(struct adapter * padapter,unsigned char * pbuf)7833 u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
7834 {
7835 	u8 evt_code;
7836 	u16 evt_sz;
7837 	uint	*peventbuf;
7838 	void (*event_callback)(struct adapter *dev, u8 *pbuf);
7839 	struct evt_priv *pevt_priv = &padapter->evtpriv;
7840 
7841 	peventbuf = (uint *)pbuf;
7842 	evt_sz = (u16)(*peventbuf & 0xffff);
7843 	evt_code = (u8)((*peventbuf >> 16) & 0xff);
7844 
7845 	/*  checking if event code is valid */
7846 	if (evt_code >= MAX_C2HEVT)
7847 		goto _abort_event_;
7848 
7849 	/*  checking if event size match the event parm size */
7850 	if ((wlanevents[evt_code].parmsize != 0) &&
7851 	    (wlanevents[evt_code].parmsize != evt_sz))
7852 		goto _abort_event_;
7853 
7854 	atomic_inc(&pevt_priv->event_seq);
7855 
7856 	peventbuf += 2;
7857 
7858 	if (peventbuf) {
7859 		event_callback = wlanevents[evt_code].event_callback;
7860 		event_callback(padapter, (u8 *)peventbuf);
7861 	}
7862 
7863 _abort_event_:
7864 	return H2C_SUCCESS;
7865 }
7866 
h2c_msg_hdl(struct adapter * padapter,unsigned char * pbuf)7867 u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
7868 {
7869 	if (!pbuf)
7870 		return H2C_PARAMETERS_ERROR;
7871 
7872 	return H2C_SUCCESS;
7873 }
7874 
tx_beacon_hdl(struct adapter * padapter,unsigned char * pbuf)7875 u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
7876 {
7877 	if (send_beacon(padapter) == _FAIL) {
7878 		return H2C_PARAMETERS_ERROR;
7879 	} else {
7880 		/* tx bc/mc frames after update TIM */
7881 		struct sta_info *psta_bmc;
7882 		struct list_head *xmitframe_plist, *xmitframe_phead;
7883 		struct xmit_frame *pxmitframe = NULL;
7884 		struct sta_priv  *pstapriv = &padapter->stapriv;
7885 
7886 		/* for BC/MC Frames */
7887 		psta_bmc = rtw_get_bcmc_stainfo(padapter);
7888 		if (!psta_bmc)
7889 			return H2C_SUCCESS;
7890 
7891 		if ((pstapriv->tim_bitmap & BIT(0)) && (psta_bmc->sleepq_len > 0)) {
7892 			msleep(10);/*  10ms, ATIM(HIQ) Windows */
7893 			spin_lock_bh(&psta_bmc->sleep_q.lock);
7894 
7895 			xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
7896 			xmitframe_plist = xmitframe_phead->next;
7897 
7898 			while (xmitframe_phead != xmitframe_plist) {
7899 				pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
7900 
7901 				xmitframe_plist = xmitframe_plist->next;
7902 
7903 				list_del_init(&pxmitframe->list);
7904 
7905 				psta_bmc->sleepq_len--;
7906 				if (psta_bmc->sleepq_len > 0)
7907 					pxmitframe->attrib.mdata = 1;
7908 				else
7909 					pxmitframe->attrib.mdata = 0;
7910 
7911 				pxmitframe->attrib.triggered = 1;
7912 
7913 				pxmitframe->attrib.qsel = 0x11;/* HIQ */
7914 
7915 				spin_unlock_bh(&psta_bmc->sleep_q.lock);
7916 				if (rtl8188eu_hal_xmit(padapter, pxmitframe))
7917 					rtw_xmit_complete(padapter, pxmitframe);
7918 				spin_lock_bh(&psta_bmc->sleep_q.lock);
7919 			}
7920 			spin_unlock_bh(&psta_bmc->sleep_q.lock);
7921 		}
7922 	}
7923 	return H2C_SUCCESS;
7924 }
7925 
set_ch_hdl(struct adapter * padapter,u8 * pbuf)7926 u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
7927 {
7928 	struct set_ch_parm *set_ch_parm;
7929 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7930 
7931 	if (!pbuf)
7932 		return H2C_PARAMETERS_ERROR;
7933 
7934 	set_ch_parm = (struct set_ch_parm *)pbuf;
7935 
7936 	pmlmeext->cur_channel = set_ch_parm->ch;
7937 	pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
7938 	pmlmeext->cur_bwmode = set_ch_parm->bw;
7939 
7940 	set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
7941 
7942 	return	H2C_SUCCESS;
7943 }
7944 
set_chplan_hdl(struct adapter * padapter,unsigned char * pbuf)7945 u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
7946 {
7947 	struct SetChannelPlan_param *setChannelPlan_param;
7948 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
7949 
7950 	if (!pbuf)
7951 		return H2C_PARAMETERS_ERROR;
7952 
7953 	setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
7954 
7955 	pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
7956 	init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
7957 
7958 	return	H2C_SUCCESS;
7959 }
7960 
led_blink_hdl(struct adapter * padapter,unsigned char * pbuf)7961 u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf)
7962 {
7963 	if (!pbuf)
7964 		return H2C_PARAMETERS_ERROR;
7965 	return	H2C_SUCCESS;
7966 }
7967 
set_csa_hdl(struct adapter * padapter,unsigned char * pbuf)7968 u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
7969 {
7970 	return	H2C_REJECTED;
7971 }
7972 
7973 /*  TDLS_WRCR		: write RCR DATA BIT */
7974 /*  TDLS_SD_PTI		: issue peer traffic indication */
7975 /*  TDLS_CS_OFF		: go back to the channel linked with AP, terminating channel switch procedure */
7976 /*  TDLS_INIT_CH_SEN	: init channel sensing, receive all data and mgnt frame */
7977 /*  TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
7978 /*  TDLS_OFF_CH		: first time set channel to off channel */
7979 /*  TDLS_BASE_CH		: go back tp the channel linked with AP when set base channel as target channel */
7980 /*  TDLS_P_OFF_CH	: periodically go to off channel */
7981 /*  TDLS_P_BASE_CH	: periodically go back to base channel */
7982 /*  TDLS_RS_RCR		: restore RCR */
7983 /*  TDLS_CKALV_PH1	: check alive timer phase1 */
7984 /*  TDLS_CKALV_PH2	: check alive timer phase2 */
7985 /*  TDLS_FREE_STA	: free tdls sta */
tdls_hdl(struct adapter * padapter,unsigned char * pbuf)7986 u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
7987 {
7988 	return H2C_REJECTED;
7989 }
7990