xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_p2p.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTW_P2P_C_
21 
22 #include <drv_types.h>
23 
24 #ifdef CONFIG_P2P
25 
rtw_p2p_is_channel_list_ok(u8 desired_ch,u8 * ch_list,u8 ch_cnt)26 int rtw_p2p_is_channel_list_ok( u8 desired_ch, u8* ch_list, u8 ch_cnt )
27 {
28 	int found = 0, i = 0;
29 
30 	for( i = 0; i < ch_cnt; i++ )
31 	{
32 		if ( ch_list[ i ] == desired_ch )
33 		{
34 			found = 1;
35 			break;
36 		}
37 	}
38 	return( found );
39 }
40 
is_any_client_associated(_adapter * padapter)41 int is_any_client_associated(_adapter *padapter)
42 {
43 	return padapter->stapriv.asoc_list_cnt ? _TRUE : _FALSE;
44 }
45 
go_add_group_info_attr(struct wifidirect_info * pwdinfo,u8 * pbuf)46 static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
47 {
48 	_irqL irqL;
49 	_list	*phead, *plist;
50 	u32 len=0;
51 	u16 attr_len = 0;
52 	u8 tmplen, *pdata_attr, *pstart, *pcur;
53 	struct sta_info *psta = NULL;
54 	_adapter *padapter = pwdinfo->padapter;
55 	struct sta_priv *pstapriv = &padapter->stapriv;
56 
57 	DBG_871X("%s\n", __FUNCTION__);
58 
59 	pdata_attr = rtw_zmalloc(MAX_P2P_IE_LEN);
60 
61 	if(NULL == pdata_attr){
62 		DBG_871X("%s pdata_attr malloc failed \n", __FUNCTION__);
63 		goto _exit;
64 	}
65 
66 	pstart = pdata_attr;
67 	pcur = pdata_attr;
68 
69 	_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
70 	phead = &pstapriv->asoc_list;
71 	plist = get_next(phead);
72 
73 	//look up sta asoc_queue
74 	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
75 	{
76 		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
77 
78 		plist = get_next(plist);
79 
80 
81 		if(psta->is_p2p_device)
82 		{
83 			tmplen = 0;
84 
85 			pcur++;
86 
87 			//P2P device address
88 			_rtw_memcpy(pcur, psta->dev_addr, ETH_ALEN);
89 			pcur += ETH_ALEN;
90 
91 			//P2P interface address
92 			_rtw_memcpy(pcur, psta->hwaddr, ETH_ALEN);
93 			pcur += ETH_ALEN;
94 
95 			*pcur = psta->dev_cap;
96 			pcur++;
97 
98 			//*(u16*)(pcur) = cpu_to_be16(psta->config_methods);
99 			RTW_PUT_BE16(pcur, psta->config_methods);
100 			pcur += 2;
101 
102 			_rtw_memcpy(pcur, psta->primary_dev_type, 8);
103 			pcur += 8;
104 
105 			*pcur = psta->num_of_secdev_type;
106 			pcur++;
107 
108 			_rtw_memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type*8);
109 			pcur += psta->num_of_secdev_type*8;
110 
111 			if(psta->dev_name_len>0)
112 			{
113 				//*(u16*)(pcur) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
114 				RTW_PUT_BE16(pcur, WPS_ATTR_DEVICE_NAME);
115 				pcur += 2;
116 
117 				//*(u16*)(pcur) = cpu_to_be16( psta->dev_name_len );
118 				RTW_PUT_BE16(pcur, psta->dev_name_len);
119 				pcur += 2;
120 
121 				_rtw_memcpy(pcur, psta->dev_name, psta->dev_name_len);
122 				pcur += psta->dev_name_len;
123 			}
124 
125 
126 			tmplen = (u8)(pcur-pstart);
127 
128 			*pstart = (tmplen-1);
129 
130 			attr_len += tmplen;
131 
132 			//pstart += tmplen;
133 			pstart = pcur;
134 
135 		}
136 
137 
138 	}
139 	_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
140 
141 	if(attr_len>0)
142 	{
143 		len = rtw_set_p2p_attr_content(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
144 	}
145 
146 	rtw_mfree(pdata_attr, MAX_P2P_IE_LEN);
147 
148 _exit:
149 	return len;
150 
151 }
152 
issue_group_disc_req(struct wifidirect_info * pwdinfo,u8 * da)153 static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
154 {
155 	struct xmit_frame			*pmgntframe;
156 	struct pkt_attrib			*pattrib;
157 	unsigned char					*pframe;
158 	struct rtw_ieee80211_hdr	*pwlanhdr;
159 	unsigned short				*fctrl;
160 	_adapter *padapter = pwdinfo->padapter;
161 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
162 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
163 	unsigned char category = RTW_WLAN_CATEGORY_P2P;//P2P action frame
164 	u32	p2poui = cpu_to_be32(P2POUI);
165 	u8	oui_subtype = P2P_GO_DISC_REQUEST;
166 	u8	dialogToken=0;
167 
168 	DBG_871X("[%s]\n", __FUNCTION__);
169 
170 	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
171 	{
172 		return;
173 	}
174 
175 	//update attribute
176 	pattrib = &pmgntframe->attrib;
177 	update_mgntframe_attrib(padapter, pattrib);
178 
179 	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
180 
181 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
182 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
183 
184 	fctrl = &(pwlanhdr->frame_ctl);
185 	*(fctrl) = 0;
186 
187 	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
188 	_rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
189 	_rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
190 
191 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
192 	pmlmeext->mgnt_seq++;
193 	SetFrameSubType(pframe, WIFI_ACTION);
194 
195 	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
196 	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
197 
198 	//Build P2P action frame header
199 	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
200 	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
201 	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
202 	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
203 
204 	//there is no IE in this P2P action frame
205 
206 	pattrib->last_txcmdsz = pattrib->pktlen;
207 
208 	dump_mgntframe(padapter, pmgntframe);
209 
210 }
211 
issue_p2p_devdisc_resp(struct wifidirect_info * pwdinfo,u8 * da,u8 status,u8 dialogToken)212 static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
213 {
214 	struct xmit_frame			*pmgntframe;
215 	struct pkt_attrib			*pattrib;
216 	unsigned char					*pframe;
217 	struct rtw_ieee80211_hdr	*pwlanhdr;
218 	unsigned short				*fctrl;
219 	_adapter *padapter = pwdinfo->padapter;
220 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
221 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
222 	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
223 	u8			action = P2P_PUB_ACTION_ACTION;
224 	u32			p2poui = cpu_to_be32(P2POUI);
225 	u8			oui_subtype = P2P_DEVDISC_RESP;
226 	u8 p2pie[8] = { 0x00 };
227 	u32 p2pielen = 0;
228 
229 	DBG_871X("[%s]\n", __FUNCTION__);
230 
231 	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
232 	{
233 		return;
234 	}
235 
236 	//update attribute
237 	pattrib = &pmgntframe->attrib;
238 	update_mgntframe_attrib(padapter, pattrib);
239 
240 	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
241 
242 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
243 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
244 
245 	fctrl = &(pwlanhdr->frame_ctl);
246 	*(fctrl) = 0;
247 
248 	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
249 	_rtw_memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
250 	_rtw_memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
251 
252 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
253 	pmlmeext->mgnt_seq++;
254 	SetFrameSubType(pframe, WIFI_ACTION);
255 
256 	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
257 	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
258 
259 	//Build P2P public action frame header
260 	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
261 	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
262 	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
263 	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
264 	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
265 
266 
267 	//Build P2P IE
268 	//	P2P OUI
269 	p2pielen = 0;
270 	p2pie[ p2pielen++ ] = 0x50;
271 	p2pie[ p2pielen++ ] = 0x6F;
272 	p2pie[ p2pielen++ ] = 0x9A;
273 	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
274 
275 	// P2P_ATTR_STATUS
276 	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
277 
278 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
279 
280 	pattrib->last_txcmdsz = pattrib->pktlen;
281 
282 	dump_mgntframe(padapter, pmgntframe);
283 
284 }
285 
issue_p2p_provision_resp(struct wifidirect_info * pwdinfo,u8 * raddr,u8 * frame_body,u16 config_method)286 static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8* raddr, u8* frame_body, u16 config_method)
287 {
288 	_adapter *padapter = pwdinfo->padapter;
289 	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
290 	u8			action = P2P_PUB_ACTION_ACTION;
291 	u8			dialogToken = frame_body[7];	//	The Dialog Token of provisioning discovery request frame.
292 	u32			p2poui = cpu_to_be32(P2POUI);
293 	u8			oui_subtype = P2P_PROVISION_DISC_RESP;
294 	u8			wpsie[ 100 ] = { 0x00 };
295 	u8			wpsielen = 0;
296 #ifdef CONFIG_WFD
297 	u32					wfdielen = 0;
298 #endif //CONFIG_WFD
299 
300 	struct xmit_frame			*pmgntframe;
301 	struct pkt_attrib			*pattrib;
302 	unsigned char					*pframe;
303 	struct rtw_ieee80211_hdr	*pwlanhdr;
304 	unsigned short				*fctrl;
305 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
306 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
307 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
308 
309 
310 	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
311 	{
312 		return;
313 	}
314 
315 	//update attribute
316 	pattrib = &pmgntframe->attrib;
317 	update_mgntframe_attrib(padapter, pattrib);
318 
319 	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
320 
321 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
322 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
323 
324 	fctrl = &(pwlanhdr->frame_ctl);
325 	*(fctrl) = 0;
326 
327 	_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
328 	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
329 	_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
330 
331 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
332 	pmlmeext->mgnt_seq++;
333 	SetFrameSubType(pframe, WIFI_ACTION);
334 
335 	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
336 	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
337 
338 	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
339 	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
340 	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
341 	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
342 	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
343 
344 	wpsielen = 0;
345 	//	WPS OUI
346 	//*(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
347 	RTW_PUT_BE32(wpsie, WPSOUI);
348 	wpsielen += 4;
349 
350 #if 0
351 	//	WPS version
352 	//	Type:
353 	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
354 	wpsielen += 2;
355 
356 	//	Length:
357 	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
358 	wpsielen += 2;
359 
360 	//	Value:
361 	wpsie[wpsielen++] = WPS_VERSION_1;	//	Version 1.0
362 #endif
363 
364 	//	Config Method
365 	//	Type:
366 	//*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
367 	RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD);
368 	wpsielen += 2;
369 
370 	//	Length:
371 	//*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
372 	RTW_PUT_BE16(wpsie + wpsielen, 0x0002);
373 	wpsielen += 2;
374 
375 	//	Value:
376 	//*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( config_method );
377 	RTW_PUT_BE16(wpsie + wpsielen, config_method);
378 	wpsielen += 2;
379 
380 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
381 
382 #ifdef CONFIG_WFD
383 	wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe);
384 	pframe += wfdielen;
385 	pattrib->pktlen += wfdielen;
386 #endif //CONFIG_WFD
387 
388 	pattrib->last_txcmdsz = pattrib->pktlen;
389 
390 	dump_mgntframe(padapter, pmgntframe);
391 
392 	return;
393 
394 }
395 
issue_p2p_presence_resp(struct wifidirect_info * pwdinfo,u8 * da,u8 status,u8 dialogToken)396 static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
397 {
398 	struct xmit_frame			*pmgntframe;
399 	struct pkt_attrib			*pattrib;
400 	unsigned char					*pframe;
401 	struct rtw_ieee80211_hdr	*pwlanhdr;
402 	unsigned short				*fctrl;
403 	_adapter *padapter = pwdinfo->padapter;
404 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
405 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
406 	unsigned char category = RTW_WLAN_CATEGORY_P2P;//P2P action frame
407 	u32	p2poui = cpu_to_be32(P2POUI);
408 	u8	oui_subtype = P2P_PRESENCE_RESPONSE;
409 	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
410 	u8 noa_attr_content[32] = { 0x00 };
411 	u32 p2pielen = 0;
412 
413 	DBG_871X("[%s]\n", __FUNCTION__);
414 
415 	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
416 	{
417 		return;
418 	}
419 
420 	//update attribute
421 	pattrib = &pmgntframe->attrib;
422 	update_mgntframe_attrib(padapter, pattrib);
423 
424 	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
425 
426 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
427 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
428 
429 	fctrl = &(pwlanhdr->frame_ctl);
430 	*(fctrl) = 0;
431 
432 	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
433 	_rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
434 	_rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
435 
436 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
437 	pmlmeext->mgnt_seq++;
438 	SetFrameSubType(pframe, WIFI_ACTION);
439 
440 	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
441 	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
442 
443 	//Build P2P action frame header
444 	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
445 	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
446 	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
447 	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
448 
449 
450 	//Add P2P IE header
451 	//	P2P OUI
452 	p2pielen = 0;
453 	p2pie[ p2pielen++ ] = 0x50;
454 	p2pie[ p2pielen++ ] = 0x6F;
455 	p2pie[ p2pielen++ ] = 0x9A;
456 	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
457 
458 	//Add Status attribute in P2P IE
459 	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
460 
461 	//Add NoA attribute in P2P IE
462 	noa_attr_content[0] = 0x1;//index
463 	noa_attr_content[1] = 0x0;//CTWindow and OppPS Parameters
464 
465 	//todo: Notice of Absence Descriptor(s)
466 
467 	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
468 
469 
470 
471 	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &(pattrib->pktlen));
472 
473 
474 	pattrib->last_txcmdsz = pattrib->pktlen;
475 
476 	dump_mgntframe(padapter, pmgntframe);
477 
478 }
479 
build_beacon_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)480 u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
481 {
482 	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
483 	u16 capability=0;
484 	u32 len=0, p2pielen = 0;
485 
486 
487 	//	P2P OUI
488 	p2pielen = 0;
489 	p2pie[ p2pielen++ ] = 0x50;
490 	p2pie[ p2pielen++ ] = 0x6F;
491 	p2pie[ p2pielen++ ] = 0x9A;
492 	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
493 
494 
495 	//	According to the P2P Specification, the beacon frame should contain 3 P2P attributes
496 	//	1. P2P Capability
497 	//	2. P2P Device ID
498 	//	3. Notice of Absence ( NOA )
499 
500 	//	P2P Capability ATTR
501 	//	Type:
502 	//	Length:
503 	//	Value:
504 	//	Device Capability Bitmap, 1 byte
505 	//	Be able to participate in additional P2P Groups and
506 	//	support the P2P Invitation Procedure
507 	//	Group Capability Bitmap, 1 byte
508 	capability = P2P_DEVCAP_INVITATION_PROC|P2P_DEVCAP_CLIENT_DISCOVERABILITY;
509 	capability |=  ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
510 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
511 		capability |= (P2P_GRPCAP_GROUP_FORMATION<<8);
512 
513 	capability = cpu_to_le16(capability);
514 
515 	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8*)&capability);
516 
517 
518 	// P2P Device ID ATTR
519 	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
520 
521 
522 	// Notice of Absence ATTR
523 	//	Type:
524 	//	Length:
525 	//	Value:
526 
527 	//go_add_noa_attr(pwdinfo);
528 
529 
530 	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
531 
532 
533 	return len;
534 
535 }
536 
537 #ifdef CONFIG_WFD
build_beacon_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)538 u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
539 {
540 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
541 	u16 val16=0;
542 	u32 len=0, wfdielen = 0;
543 	_adapter *padapter = pwdinfo->padapter;
544 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
545 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
546 
547 	//	WFD OUI
548 	wfdielen = 0;
549 	wfdie[ wfdielen++ ] = 0x50;
550 	wfdie[ wfdielen++ ] = 0x6F;
551 	wfdie[ wfdielen++ ] = 0x9A;
552 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
553 
554 	//	Commented by Albert 20110812
555 	//	According to the WFD Specification, the beacon frame should contain 4 WFD attributes
556 	//	1. WFD Device Information
557 	//	2. Associated BSSID
558 	//	3. Coupled Sink Information
559 
560 
561 	//	WFD Device Information ATTR
562 	//	Type:
563 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
564 
565 	//	Length:
566 	//	Note: In the WFD specification, the size of length field is 2.
567 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
568 	wfdielen += 2;
569 
570 	//	Value1:
571 	//	WFD device information
572 
573 	if ( P2P_ROLE_GO == pwdinfo->role )
574 	{
575 		if ( is_any_client_associated( pwdinfo->padapter ) )
576 		{
577 			//	WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery)
578 			val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD;
579 			RTW_PUT_BE16(wfdie + wfdielen, val16);
580 		}
581 		else
582 		{
583 			//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery)
584 			val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
585 			RTW_PUT_BE16(wfdie + wfdielen, val16);
586 		}
587 
588 	}
589 	else
590 	{
591 		//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
592 		val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
593 		RTW_PUT_BE16(wfdie + wfdielen, val16);
594 	}
595 
596 	wfdielen += 2;
597 
598 	//	Value2:
599 	//	Session Management Control Port
600 	//	Default TCP port for RTSP messages is 554
601 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
602 	wfdielen += 2;
603 
604 	//	Value3:
605 	//	WFD Device Maximum Throughput
606 	//	300Mbps is the maximum throughput
607 	RTW_PUT_BE16(wfdie + wfdielen, 300);
608 	wfdielen += 2;
609 
610 	//	Associated BSSID ATTR
611 	//	Type:
612 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
613 
614 	//	Length:
615 	//	Note: In the WFD specification, the size of length field is 2.
616 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
617 	wfdielen += 2;
618 
619 	//	Value:
620 	//	Associated BSSID
621 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
622 	{
623 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
624 	}
625 	else
626 	{
627 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
628 	}
629 
630 	wfdielen += ETH_ALEN;
631 
632 	//	Coupled Sink Information ATTR
633 	//	Type:
634 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
635 
636 	//	Length:
637 	//	Note: In the WFD specification, the size of length field is 2.
638 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
639 	wfdielen += 2;
640 
641 	//	Value:
642 	//	Coupled Sink Status bitmap
643 	//	Not coupled/available for Coupling
644 	wfdie[ wfdielen++ ] = 0;
645 	//  MAC Addr.
646 	wfdie[ wfdielen++ ] = 0;
647 	wfdie[ wfdielen++ ] = 0;
648 	wfdie[ wfdielen++ ] = 0;
649 	wfdie[ wfdielen++ ] = 0;
650 	wfdie[ wfdielen++ ] = 0;
651 	wfdie[ wfdielen++ ] = 0;
652 
653 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
654 
655 	return len;
656 
657 }
658 
build_probe_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)659 u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
660 {
661 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
662 	u16 val16=0;
663 	u32 len=0, wfdielen = 0;
664 	_adapter *padapter = pwdinfo->padapter;
665 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
666 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
667 
668 	//	WFD OUI
669 	wfdielen = 0;
670 	wfdie[ wfdielen++ ] = 0x50;
671 	wfdie[ wfdielen++ ] = 0x6F;
672 	wfdie[ wfdielen++ ] = 0x9A;
673 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
674 
675 	//	Commented by Albert 20110812
676 	//	According to the WFD Specification, the probe request frame should contain 4 WFD attributes
677 	//	1. WFD Device Information
678 	//	2. Associated BSSID
679 	//	3. Coupled Sink Information
680 
681 
682 	//	WFD Device Information ATTR
683 	//	Type:
684 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
685 
686 	//	Length:
687 	//	Note: In the WFD specification, the size of length field is 2.
688 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
689 	wfdielen += 2;
690 
691 	//	Value1:
692 	//	WFD device information
693 
694 	if ( 1 == pwdinfo->wfd_tdls_enable )
695 	{
696 		//	WFD primary sink + available for WFD session + WiFi TDLS mode + WSC ( WFD Service Discovery )
697 		val16 = pwfd_info->wfd_device_type |
698 						WFD_DEVINFO_SESSION_AVAIL |
699 						WFD_DEVINFO_WSD |
700 						WFD_DEVINFO_PC_TDLS;
701 		RTW_PUT_BE16(wfdie + wfdielen, val16 );
702 	}
703 	else
704 	{
705 		//	WFD primary sink + available for WFD session + WiFi Direct mode + WSC ( WFD Service Discovery )
706 		val16 = pwfd_info->wfd_device_type |
707 						WFD_DEVINFO_SESSION_AVAIL |
708 						WFD_DEVINFO_WSD;
709 		RTW_PUT_BE16(wfdie + wfdielen, val16 );
710 	}
711 
712 	wfdielen += 2;
713 
714 	//	Value2:
715 	//	Session Management Control Port
716 	//	Default TCP port for RTSP messages is 554
717 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
718 	wfdielen += 2;
719 
720 	//	Value3:
721 	//	WFD Device Maximum Throughput
722 	//	300Mbps is the maximum throughput
723 	RTW_PUT_BE16(wfdie + wfdielen, 300);
724 	wfdielen += 2;
725 
726 	//	Associated BSSID ATTR
727 	//	Type:
728 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
729 
730 	//	Length:
731 	//	Note: In the WFD specification, the size of length field is 2.
732 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
733 	wfdielen += 2;
734 
735 	//	Value:
736 	//	Associated BSSID
737 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
738 	{
739 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
740 	}
741 	else
742 	{
743 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
744 	}
745 
746 	wfdielen += ETH_ALEN;
747 
748 	//	Coupled Sink Information ATTR
749 	//	Type:
750 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
751 
752 	//	Length:
753 	//	Note: In the WFD specification, the size of length field is 2.
754 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
755 	wfdielen += 2;
756 
757 	//	Value:
758 	//	Coupled Sink Status bitmap
759 	//	Not coupled/available for Coupling
760 	wfdie[ wfdielen++ ] = 0;
761 	//  MAC Addr.
762 	wfdie[ wfdielen++ ] = 0;
763 	wfdie[ wfdielen++ ] = 0;
764 	wfdie[ wfdielen++ ] = 0;
765 	wfdie[ wfdielen++ ] = 0;
766 	wfdie[ wfdielen++ ] = 0;
767 	wfdie[ wfdielen++ ] = 0;
768 
769 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
770 
771 	return len;
772 
773 }
774 
build_probe_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf,u8 tunneled)775 u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunneled)
776 {
777 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
778 	u32 len=0, wfdielen = 0;
779 	_adapter *padapter = pwdinfo->padapter;
780 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
781 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
782 
783 	//	WFD OUI
784 	wfdielen = 0;
785 	wfdie[ wfdielen++ ] = 0x50;
786 	wfdie[ wfdielen++ ] = 0x6F;
787 	wfdie[ wfdielen++ ] = 0x9A;
788 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
789 
790 	//	Commented by Albert 20110812
791 	//	According to the WFD Specification, the probe response frame should contain 4 WFD attributes
792 	//	1. WFD Device Information
793 	//	2. Associated BSSID
794 	//	3. Coupled Sink Information
795 	//	4. WFD Session Information
796 
797 
798 	//	WFD Device Information ATTR
799 	//	Type:
800 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
801 
802 	//	Length:
803 	//	Note: In the WFD specification, the size of length field is 2.
804 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
805 	wfdielen += 2;
806 
807 	//	Value1:
808 	//	WFD device information
809 	//	WFD primary sink + available for WFD session + WiFi Direct mode
810 
811 	if (  _TRUE == pwdinfo->session_available )
812 	{
813 		if ( P2P_ROLE_GO == pwdinfo->role )
814 		{
815 			if ( is_any_client_associated( pwdinfo->padapter ) )
816 			{
817 				if ( pwdinfo->wfd_tdls_enable )
818 				{
819 					//	TDLS mode + WSD ( WFD Service Discovery )
820 					RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
821 				}
822 				else
823 				{
824 					//	WiFi Direct mode + WSD ( WFD Service Discovery )
825 					RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
826 				}
827 			}
828 			else
829 			{
830 				if ( pwdinfo->wfd_tdls_enable )
831 				{
832 					//	available for WFD session + TDLS mode + WSD ( WFD Service Discovery )
833 					RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
834 				}
835 				else
836 				{
837 					//	available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
838 					RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
839 				}
840 			}
841 		}
842 		else
843 		{
844 			if ( pwdinfo->wfd_tdls_enable )
845 			{
846 				//	available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
847 				RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
848 			}
849 			else
850 			{
851 
852 				//	available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
853 				RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
854 			}
855 		}
856 	}
857 	else
858 	{
859 		if ( pwdinfo->wfd_tdls_enable )
860 		{
861 			RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD |WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
862 		}
863 		else
864 		{
865 			RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
866 		}
867 
868 	}
869 
870 	wfdielen += 2;
871 
872 	//	Value2:
873 	//	Session Management Control Port
874 	//	Default TCP port for RTSP messages is 554
875 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
876 	wfdielen += 2;
877 
878 	//	Value3:
879 	//	WFD Device Maximum Throughput
880 	//	300Mbps is the maximum throughput
881 	RTW_PUT_BE16(wfdie + wfdielen, 300);
882 	wfdielen += 2;
883 
884 	//	Associated BSSID ATTR
885 	//	Type:
886 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
887 
888 	//	Length:
889 	//	Note: In the WFD specification, the size of length field is 2.
890 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
891 	wfdielen += 2;
892 
893 	//	Value:
894 	//	Associated BSSID
895 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
896 	{
897 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
898 	}
899 	else
900 	{
901 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
902 	}
903 
904 	wfdielen += ETH_ALEN;
905 
906 	//	Coupled Sink Information ATTR
907 	//	Type:
908 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
909 
910 	//	Length:
911 	//	Note: In the WFD specification, the size of length field is 2.
912 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
913 	wfdielen += 2;
914 
915 	//	Value:
916 	//	Coupled Sink Status bitmap
917 	//	Not coupled/available for Coupling
918 	wfdie[ wfdielen++ ] = 0;
919 	//  MAC Addr.
920 	wfdie[ wfdielen++ ] = 0;
921 	wfdie[ wfdielen++ ] = 0;
922 	wfdie[ wfdielen++ ] = 0;
923 	wfdie[ wfdielen++ ] = 0;
924 	wfdie[ wfdielen++ ] = 0;
925 	wfdie[ wfdielen++ ] = 0;
926 
927 	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
928 	{
929 		//	WFD Session Information ATTR
930 		//	Type:
931 		wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
932 
933 		//	Length:
934 		//	Note: In the WFD specification, the size of length field is 2.
935 		RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
936 		wfdielen += 2;
937 
938 		//	Todo: to add the list of WFD device info descriptor in WFD group.
939 
940 	}
941 #ifdef CONFIG_CONCURRENT_MODE
942 #ifdef CONFIG_TDLS
943 	if ( ( tunneled == 0 ) && ( padapter->pbuddy_adapter->wdinfo.wfd_tdls_enable == 1 ) )
944 	{
945 		//	Alternative MAC Address ATTR
946 		//	Type:
947 		wfdie[ wfdielen++ ] = WFD_ATTR_ALTER_MAC;
948 
949 		//	Length:
950 		//	Note: In the WFD specification, the size of length field is 2.
951 		RTW_PUT_BE16(wfdie + wfdielen,  ETH_ALEN );
952 		wfdielen += 2;
953 
954 		//	Value:
955 		//	Alternative MAC Address
956 		_rtw_memcpy(wfdie + wfdielen, adapter_mac_addr(padapter->pbuddy_adapter), ETH_ALEN);
957 		//	This mac address is used to make the WFD session when TDLS is enable.
958 
959 		wfdielen += ETH_ALEN;
960 	}
961 #endif // CONFIG_TDLS
962 #endif // CONFIG_CONCURRENT_MODE
963 
964 	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
965 
966 	return len;
967 
968 }
969 
build_assoc_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)970 u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
971 {
972 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
973 	u16 val16=0;
974 	u32 len=0, wfdielen = 0;
975 	_adapter 					*padapter = NULL;
976 	struct mlme_priv			*pmlmepriv = NULL;
977 	struct wifi_display_info		*pwfd_info = NULL;
978 
979 	//	WFD OUI
980 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
981 	{
982 		return 0;
983 	}
984 
985 	padapter = pwdinfo->padapter;
986 	pmlmepriv = &padapter->mlmepriv;
987 	pwfd_info = padapter->wdinfo.wfd_info;
988 
989 	wfdielen = 0;
990 	wfdie[ wfdielen++ ] = 0x50;
991 	wfdie[ wfdielen++ ] = 0x6F;
992 	wfdie[ wfdielen++ ] = 0x9A;
993 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
994 
995 	//	Commented by Albert 20110812
996 	//	According to the WFD Specification, the probe request frame should contain 4 WFD attributes
997 	//	1. WFD Device Information
998 	//	2. Associated BSSID
999 	//	3. Coupled Sink Information
1000 
1001 
1002 	//	WFD Device Information ATTR
1003 	//	Type:
1004 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1005 
1006 	//	Length:
1007 	//	Note: In the WFD specification, the size of length field is 2.
1008 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1009 	wfdielen += 2;
1010 
1011 	//	Value1:
1012 	//	WFD device information
1013 	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
1014 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1015 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1016 	wfdielen += 2;
1017 
1018 	//	Value2:
1019 	//	Session Management Control Port
1020 	//	Default TCP port for RTSP messages is 554
1021 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
1022 	wfdielen += 2;
1023 
1024 	//	Value3:
1025 	//	WFD Device Maximum Throughput
1026 	//	300Mbps is the maximum throughput
1027 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1028 	wfdielen += 2;
1029 
1030 	//	Associated BSSID ATTR
1031 	//	Type:
1032 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1033 
1034 	//	Length:
1035 	//	Note: In the WFD specification, the size of length field is 2.
1036 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1037 	wfdielen += 2;
1038 
1039 	//	Value:
1040 	//	Associated BSSID
1041 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
1042 	{
1043 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
1044 	}
1045 	else
1046 	{
1047 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
1048 	}
1049 
1050 	wfdielen += ETH_ALEN;
1051 
1052 	//	Coupled Sink Information ATTR
1053 	//	Type:
1054 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1055 
1056 	//	Length:
1057 	//	Note: In the WFD specification, the size of length field is 2.
1058 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1059 	wfdielen += 2;
1060 
1061 	//	Value:
1062 	//	Coupled Sink Status bitmap
1063 	//	Not coupled/available for Coupling
1064 	wfdie[ wfdielen++ ] = 0;
1065 	//  MAC Addr.
1066 	wfdie[ wfdielen++ ] = 0;
1067 	wfdie[ wfdielen++ ] = 0;
1068 	wfdie[ wfdielen++ ] = 0;
1069 	wfdie[ wfdielen++ ] = 0;
1070 	wfdie[ wfdielen++ ] = 0;
1071 	wfdie[ wfdielen++ ] = 0;
1072 
1073 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1074 
1075 	return len;
1076 
1077 }
1078 
build_assoc_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1079 u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1080 {
1081 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1082 	u32 len=0, wfdielen = 0;
1083 	u16 val16=0;
1084 	_adapter *padapter = pwdinfo->padapter;
1085 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1086 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
1087 
1088 	//	WFD OUI
1089 	wfdielen = 0;
1090 	wfdie[ wfdielen++ ] = 0x50;
1091 	wfdie[ wfdielen++ ] = 0x6F;
1092 	wfdie[ wfdielen++ ] = 0x9A;
1093 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
1094 
1095 	//	Commented by Albert 20110812
1096 	//	According to the WFD Specification, the probe request frame should contain 4 WFD attributes
1097 	//	1. WFD Device Information
1098 	//	2. Associated BSSID
1099 	//	3. Coupled Sink Information
1100 
1101 
1102 	//	WFD Device Information ATTR
1103 	//	Type:
1104 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1105 
1106 	//	Length:
1107 	//	Note: In the WFD specification, the size of length field is 2.
1108 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1109 	wfdielen += 2;
1110 
1111 	//	Value1:
1112 	//	WFD device information
1113 	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
1114 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1115 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1116 	wfdielen += 2;
1117 
1118 	//	Value2:
1119 	//	Session Management Control Port
1120 	//	Default TCP port for RTSP messages is 554
1121 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
1122 	wfdielen += 2;
1123 
1124 	//	Value3:
1125 	//	WFD Device Maximum Throughput
1126 	//	300Mbps is the maximum throughput
1127 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1128 	wfdielen += 2;
1129 
1130 	//	Associated BSSID ATTR
1131 	//	Type:
1132 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1133 
1134 	//	Length:
1135 	//	Note: In the WFD specification, the size of length field is 2.
1136 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1137 	wfdielen += 2;
1138 
1139 	//	Value:
1140 	//	Associated BSSID
1141 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
1142 	{
1143 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
1144 	}
1145 	else
1146 	{
1147 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
1148 	}
1149 
1150 	wfdielen += ETH_ALEN;
1151 
1152 	//	Coupled Sink Information ATTR
1153 	//	Type:
1154 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1155 
1156 	//	Length:
1157 	//	Note: In the WFD specification, the size of length field is 2.
1158 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1159 	wfdielen += 2;
1160 
1161 	//	Value:
1162 	//	Coupled Sink Status bitmap
1163 	//	Not coupled/available for Coupling
1164 	wfdie[ wfdielen++ ] = 0;
1165 	//  MAC Addr.
1166 	wfdie[ wfdielen++ ] = 0;
1167 	wfdie[ wfdielen++ ] = 0;
1168 	wfdie[ wfdielen++ ] = 0;
1169 	wfdie[ wfdielen++ ] = 0;
1170 	wfdie[ wfdielen++ ] = 0;
1171 	wfdie[ wfdielen++ ] = 0;
1172 
1173 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1174 
1175 	return len;
1176 
1177 }
1178 
build_nego_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1179 u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1180 {
1181 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1182 	u32 len=0, wfdielen = 0;
1183 	u16 val16=0;
1184 	_adapter *padapter = pwdinfo->padapter;
1185 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1186 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
1187 
1188 	//	WFD OUI
1189 	wfdielen = 0;
1190 	wfdie[ wfdielen++ ] = 0x50;
1191 	wfdie[ wfdielen++ ] = 0x6F;
1192 	wfdie[ wfdielen++ ] = 0x9A;
1193 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
1194 
1195 	//	Commented by Albert 20110825
1196 	//	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
1197 	//	1. WFD Device Information
1198 	//	2. Associated BSSID ( Optional )
1199 	//	3. Local IP Adress ( Optional )
1200 
1201 
1202 	//	WFD Device Information ATTR
1203 	//	Type:
1204 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1205 
1206 	//	Length:
1207 	//	Note: In the WFD specification, the size of length field is 2.
1208 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1209 	wfdielen += 2;
1210 
1211 	//	Value1:
1212 	//	WFD device information
1213 	//	WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available
1214 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
1215 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1216 	wfdielen += 2;
1217 
1218 	//	Value2:
1219 	//	Session Management Control Port
1220 	//	Default TCP port for RTSP messages is 554
1221 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
1222 	wfdielen += 2;
1223 
1224 	//	Value3:
1225 	//	WFD Device Maximum Throughput
1226 	//	300Mbps is the maximum throughput
1227 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1228 	wfdielen += 2;
1229 
1230 	//	Associated BSSID ATTR
1231 	//	Type:
1232 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1233 
1234 	//	Length:
1235 	//	Note: In the WFD specification, the size of length field is 2.
1236 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1237 	wfdielen += 2;
1238 
1239 	//	Value:
1240 	//	Associated BSSID
1241 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
1242 	{
1243 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
1244 	}
1245 	else
1246 	{
1247 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
1248 	}
1249 
1250 	wfdielen += ETH_ALEN;
1251 
1252 	//	Coupled Sink Information ATTR
1253 	//	Type:
1254 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1255 
1256 	//	Length:
1257 	//	Note: In the WFD specification, the size of length field is 2.
1258 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1259 	wfdielen += 2;
1260 
1261 	//	Value:
1262 	//	Coupled Sink Status bitmap
1263 	//	Not coupled/available for Coupling
1264 	wfdie[ wfdielen++ ] = 0;
1265 	//  MAC Addr.
1266 	wfdie[ wfdielen++ ] = 0;
1267 	wfdie[ wfdielen++ ] = 0;
1268 	wfdie[ wfdielen++ ] = 0;
1269 	wfdie[ wfdielen++ ] = 0;
1270 	wfdie[ wfdielen++ ] = 0;
1271 	wfdie[ wfdielen++ ] = 0;
1272 
1273 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1274 
1275 	return len;
1276 
1277 }
1278 
build_nego_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1279 u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1280 {
1281 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1282 	u32 len=0, wfdielen = 0;
1283 	u16 val16=0;
1284 	_adapter *padapter = pwdinfo->padapter;
1285 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1286 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
1287 
1288 	//	WFD OUI
1289 	wfdielen = 0;
1290 	wfdie[ wfdielen++ ] = 0x50;
1291 	wfdie[ wfdielen++ ] = 0x6F;
1292 	wfdie[ wfdielen++ ] = 0x9A;
1293 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
1294 
1295 	//	Commented by Albert 20110825
1296 	//	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
1297 	//	1. WFD Device Information
1298 	//	2. Associated BSSID ( Optional )
1299 	//	3. Local IP Adress ( Optional )
1300 
1301 
1302 	//	WFD Device Information ATTR
1303 	//	Type:
1304 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1305 
1306 	//	Length:
1307 	//	Note: In the WFD specification, the size of length field is 2.
1308 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1309 	wfdielen += 2;
1310 
1311 	//	Value1:
1312 	//	WFD device information
1313 	//	WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available
1314 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
1315 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1316 	wfdielen += 2;
1317 
1318 	//	Value2:
1319 	//	Session Management Control Port
1320 	//	Default TCP port for RTSP messages is 554
1321 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
1322 	wfdielen += 2;
1323 
1324 	//	Value3:
1325 	//	WFD Device Maximum Throughput
1326 	//	300Mbps is the maximum throughput
1327 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1328 	wfdielen += 2;
1329 
1330 	//	Associated BSSID ATTR
1331 	//	Type:
1332 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1333 
1334 	//	Length:
1335 	//	Note: In the WFD specification, the size of length field is 2.
1336 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1337 	wfdielen += 2;
1338 
1339 	//	Value:
1340 	//	Associated BSSID
1341 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
1342 	{
1343 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
1344 	}
1345 	else
1346 	{
1347 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
1348 	}
1349 
1350 	wfdielen += ETH_ALEN;
1351 
1352 	//	Coupled Sink Information ATTR
1353 	//	Type:
1354 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1355 
1356 	//	Length:
1357 	//	Note: In the WFD specification, the size of length field is 2.
1358 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1359 	wfdielen += 2;
1360 
1361 	//	Value:
1362 	//	Coupled Sink Status bitmap
1363 	//	Not coupled/available for Coupling
1364 	wfdie[ wfdielen++ ] = 0;
1365 	//  MAC Addr.
1366 	wfdie[ wfdielen++ ] = 0;
1367 	wfdie[ wfdielen++ ] = 0;
1368 	wfdie[ wfdielen++ ] = 0;
1369 	wfdie[ wfdielen++ ] = 0;
1370 	wfdie[ wfdielen++ ] = 0;
1371 	wfdie[ wfdielen++ ] = 0;
1372 
1373 
1374 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1375 
1376 	return len;
1377 
1378 }
1379 
build_nego_confirm_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1380 u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1381 {
1382 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1383 	u32 len=0, wfdielen = 0;
1384 	u16 val16=0;
1385 	_adapter *padapter = pwdinfo->padapter;
1386 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1387 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
1388 
1389 	//	WFD OUI
1390 	wfdielen = 0;
1391 	wfdie[ wfdielen++ ] = 0x50;
1392 	wfdie[ wfdielen++ ] = 0x6F;
1393 	wfdie[ wfdielen++ ] = 0x9A;
1394 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
1395 
1396 	//	Commented by Albert 20110825
1397 	//	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
1398 	//	1. WFD Device Information
1399 	//	2. Associated BSSID ( Optional )
1400 	//	3. Local IP Adress ( Optional )
1401 
1402 
1403 	//	WFD Device Information ATTR
1404 	//	Type:
1405 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1406 
1407 	//	Length:
1408 	//	Note: In the WFD specification, the size of length field is 2.
1409 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1410 	wfdielen += 2;
1411 
1412 	//	Value1:
1413 	//	WFD device information
1414 	//	WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available
1415 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
1416 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1417 	wfdielen += 2;
1418 
1419 	//	Value2:
1420 	//	Session Management Control Port
1421 	//	Default TCP port for RTSP messages is 554
1422 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
1423 	wfdielen += 2;
1424 
1425 	//	Value3:
1426 	//	WFD Device Maximum Throughput
1427 	//	300Mbps is the maximum throughput
1428 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1429 	wfdielen += 2;
1430 
1431 	//	Associated BSSID ATTR
1432 	//	Type:
1433 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1434 
1435 	//	Length:
1436 	//	Note: In the WFD specification, the size of length field is 2.
1437 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1438 	wfdielen += 2;
1439 
1440 	//	Value:
1441 	//	Associated BSSID
1442 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
1443 	{
1444 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
1445 	}
1446 	else
1447 	{
1448 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
1449 	}
1450 
1451 	wfdielen += ETH_ALEN;
1452 
1453 	//	Coupled Sink Information ATTR
1454 	//	Type:
1455 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1456 
1457 	//	Length:
1458 	//	Note: In the WFD specification, the size of length field is 2.
1459 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1460 	wfdielen += 2;
1461 
1462 	//	Value:
1463 	//	Coupled Sink Status bitmap
1464 	//	Not coupled/available for Coupling
1465 	wfdie[ wfdielen++ ] = 0;
1466 	//  MAC Addr.
1467 	wfdie[ wfdielen++ ] = 0;
1468 	wfdie[ wfdielen++ ] = 0;
1469 	wfdie[ wfdielen++ ] = 0;
1470 	wfdie[ wfdielen++ ] = 0;
1471 	wfdie[ wfdielen++ ] = 0;
1472 	wfdie[ wfdielen++ ] = 0;
1473 
1474 
1475 	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1476 
1477 	return len;
1478 
1479 }
1480 
build_invitation_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1481 u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1482 {
1483 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1484 	u32 len=0, wfdielen = 0;
1485 	u16 val16=0;
1486 	_adapter *padapter = pwdinfo->padapter;
1487 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1488 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
1489 
1490 	//	WFD OUI
1491 	wfdielen = 0;
1492 	wfdie[ wfdielen++ ] = 0x50;
1493 	wfdie[ wfdielen++ ] = 0x6F;
1494 	wfdie[ wfdielen++ ] = 0x9A;
1495 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
1496 
1497 	//	Commented by Albert 20110825
1498 	//	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes
1499 	//	1. WFD Device Information
1500 	//	2. Associated BSSID ( Optional )
1501 	//	3. Local IP Adress ( Optional )
1502 
1503 
1504 	//	WFD Device Information ATTR
1505 	//	Type:
1506 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1507 
1508 	//	Length:
1509 	//	Note: In the WFD specification, the size of length field is 2.
1510 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1511 	wfdielen += 2;
1512 
1513 	//	Value1:
1514 	//	WFD device information
1515 	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
1516 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1517 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1518 	wfdielen += 2;
1519 
1520 	//	Value2:
1521 	//	Session Management Control Port
1522 	//	Default TCP port for RTSP messages is 554
1523 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
1524 	wfdielen += 2;
1525 
1526 	//	Value3:
1527 	//	WFD Device Maximum Throughput
1528 	//	300Mbps is the maximum throughput
1529 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1530 	wfdielen += 2;
1531 
1532 	//	Associated BSSID ATTR
1533 	//	Type:
1534 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1535 
1536 	//	Length:
1537 	//	Note: In the WFD specification, the size of length field is 2.
1538 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1539 	wfdielen += 2;
1540 
1541 	//	Value:
1542 	//	Associated BSSID
1543 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
1544 	{
1545 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
1546 	}
1547 	else
1548 	{
1549 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
1550 	}
1551 
1552 	wfdielen += ETH_ALEN;
1553 
1554 	//	Coupled Sink Information ATTR
1555 	//	Type:
1556 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1557 
1558 	//	Length:
1559 	//	Note: In the WFD specification, the size of length field is 2.
1560 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1561 	wfdielen += 2;
1562 
1563 	//	Value:
1564 	//	Coupled Sink Status bitmap
1565 	//	Not coupled/available for Coupling
1566 	wfdie[ wfdielen++ ] = 0;
1567 	//  MAC Addr.
1568 	wfdie[ wfdielen++ ] = 0;
1569 	wfdie[ wfdielen++ ] = 0;
1570 	wfdie[ wfdielen++ ] = 0;
1571 	wfdie[ wfdielen++ ] = 0;
1572 	wfdie[ wfdielen++ ] = 0;
1573 	wfdie[ wfdielen++ ] = 0;
1574 
1575 	if ( P2P_ROLE_GO == pwdinfo->role )
1576 	{
1577 		//	WFD Session Information ATTR
1578 		//	Type:
1579 		wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
1580 
1581 		//	Length:
1582 		//	Note: In the WFD specification, the size of length field is 2.
1583 		RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
1584 		wfdielen += 2;
1585 
1586 		//	Todo: to add the list of WFD device info descriptor in WFD group.
1587 
1588 	}
1589 
1590 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1591 
1592 	return len;
1593 
1594 }
1595 
build_invitation_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1596 u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1597 {
1598 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1599 	u16 val16=0;
1600 	u32 len=0, wfdielen = 0;
1601 	_adapter *padapter = pwdinfo->padapter;
1602 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1603 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
1604 
1605 	//	WFD OUI
1606 	wfdielen = 0;
1607 	wfdie[ wfdielen++ ] = 0x50;
1608 	wfdie[ wfdielen++ ] = 0x6F;
1609 	wfdie[ wfdielen++ ] = 0x9A;
1610 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
1611 
1612 	//	Commented by Albert 20110825
1613 	//	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes
1614 	//	1. WFD Device Information
1615 	//	2. Associated BSSID ( Optional )
1616 	//	3. Local IP Adress ( Optional )
1617 
1618 
1619 	//	WFD Device Information ATTR
1620 	//	Type:
1621 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1622 
1623 	//	Length:
1624 	//	Note: In the WFD specification, the size of length field is 2.
1625 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1626 	wfdielen += 2;
1627 
1628 	//	Value1:
1629 	//	WFD device information
1630 	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
1631 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1632 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1633 	wfdielen += 2;
1634 
1635 	//	Value2:
1636 	//	Session Management Control Port
1637 	//	Default TCP port for RTSP messages is 554
1638 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
1639 	wfdielen += 2;
1640 
1641 	//	Value3:
1642 	//	WFD Device Maximum Throughput
1643 	//	300Mbps is the maximum throughput
1644 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1645 	wfdielen += 2;
1646 
1647 	//	Associated BSSID ATTR
1648 	//	Type:
1649 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1650 
1651 	//	Length:
1652 	//	Note: In the WFD specification, the size of length field is 2.
1653 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1654 	wfdielen += 2;
1655 
1656 	//	Value:
1657 	//	Associated BSSID
1658 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
1659 	{
1660 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
1661 	}
1662 	else
1663 	{
1664 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
1665 	}
1666 
1667 	wfdielen += ETH_ALEN;
1668 
1669 	//	Coupled Sink Information ATTR
1670 	//	Type:
1671 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1672 
1673 	//	Length:
1674 	//	Note: In the WFD specification, the size of length field is 2.
1675 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1676 	wfdielen += 2;
1677 
1678 	//	Value:
1679 	//	Coupled Sink Status bitmap
1680 	//	Not coupled/available for Coupling
1681 	wfdie[ wfdielen++ ] = 0;
1682 	//  MAC Addr.
1683 	wfdie[ wfdielen++ ] = 0;
1684 	wfdie[ wfdielen++ ] = 0;
1685 	wfdie[ wfdielen++ ] = 0;
1686 	wfdie[ wfdielen++ ] = 0;
1687 	wfdie[ wfdielen++ ] = 0;
1688 	wfdie[ wfdielen++ ] = 0;
1689 
1690 	if ( P2P_ROLE_GO == pwdinfo->role )
1691 	{
1692 		//	WFD Session Information ATTR
1693 		//	Type:
1694 		wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
1695 
1696 		//	Length:
1697 		//	Note: In the WFD specification, the size of length field is 2.
1698 		RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
1699 		wfdielen += 2;
1700 
1701 		//	Todo: to add the list of WFD device info descriptor in WFD group.
1702 
1703 	}
1704 
1705 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1706 
1707 	return len;
1708 
1709 }
1710 
build_provdisc_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1711 u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1712 {
1713 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1714 	u32 len=0, wfdielen = 0;
1715 	u16 val16=0;
1716 	_adapter *padapter = pwdinfo->padapter;
1717 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1718 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
1719 
1720 	//	WFD OUI
1721 	wfdielen = 0;
1722 	wfdie[ wfdielen++ ] = 0x50;
1723 	wfdie[ wfdielen++ ] = 0x6F;
1724 	wfdie[ wfdielen++ ] = 0x9A;
1725 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
1726 
1727 	//	Commented by Albert 20110825
1728 	//	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes
1729 	//	1. WFD Device Information
1730 	//	2. Associated BSSID ( Optional )
1731 	//	3. Local IP Adress ( Optional )
1732 
1733 
1734 	//	WFD Device Information ATTR
1735 	//	Type:
1736 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1737 
1738 	//	Length:
1739 	//	Note: In the WFD specification, the size of length field is 2.
1740 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1741 	wfdielen += 2;
1742 
1743 	//	Value1:
1744 	//	WFD device information
1745 	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
1746 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1747 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1748 	wfdielen += 2;
1749 
1750 	//	Value2:
1751 	//	Session Management Control Port
1752 	//	Default TCP port for RTSP messages is 554
1753 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
1754 	wfdielen += 2;
1755 
1756 	//	Value3:
1757 	//	WFD Device Maximum Throughput
1758 	//	300Mbps is the maximum throughput
1759 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1760 	wfdielen += 2;
1761 
1762 	//	Associated BSSID ATTR
1763 	//	Type:
1764 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1765 
1766 	//	Length:
1767 	//	Note: In the WFD specification, the size of length field is 2.
1768 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1769 	wfdielen += 2;
1770 
1771 	//	Value:
1772 	//	Associated BSSID
1773 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
1774 	{
1775 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
1776 	}
1777 	else
1778 	{
1779 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
1780 	}
1781 
1782 	wfdielen += ETH_ALEN;
1783 
1784 	//	Coupled Sink Information ATTR
1785 	//	Type:
1786 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1787 
1788 	//	Length:
1789 	//	Note: In the WFD specification, the size of length field is 2.
1790 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1791 	wfdielen += 2;
1792 
1793 	//	Value:
1794 	//	Coupled Sink Status bitmap
1795 	//	Not coupled/available for Coupling
1796 	wfdie[ wfdielen++ ] = 0;
1797 	//  MAC Addr.
1798 	wfdie[ wfdielen++ ] = 0;
1799 	wfdie[ wfdielen++ ] = 0;
1800 	wfdie[ wfdielen++ ] = 0;
1801 	wfdie[ wfdielen++ ] = 0;
1802 	wfdie[ wfdielen++ ] = 0;
1803 	wfdie[ wfdielen++ ] = 0;
1804 
1805 
1806 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1807 
1808 	return len;
1809 
1810 }
1811 
build_provdisc_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1812 u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1813 {
1814 	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1815 	u32 len=0, wfdielen = 0;
1816 	u16 val16=0;
1817 	_adapter *padapter = pwdinfo->padapter;
1818 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1819 	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
1820 
1821 	//	WFD OUI
1822 	wfdielen = 0;
1823 	wfdie[ wfdielen++ ] = 0x50;
1824 	wfdie[ wfdielen++ ] = 0x6F;
1825 	wfdie[ wfdielen++ ] = 0x9A;
1826 	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
1827 
1828 	//	Commented by Albert 20110825
1829 	//	According to the WFD Specification, the provision discovery response frame should contain 3 WFD attributes
1830 	//	1. WFD Device Information
1831 	//	2. Associated BSSID ( Optional )
1832 	//	3. Local IP Adress ( Optional )
1833 
1834 
1835 	//	WFD Device Information ATTR
1836 	//	Type:
1837 	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1838 
1839 	//	Length:
1840 	//	Note: In the WFD specification, the size of length field is 2.
1841 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1842 	wfdielen += 2;
1843 
1844 	//	Value1:
1845 	//	WFD device information
1846 	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
1847 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1848 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1849 	wfdielen += 2;
1850 
1851 	//	Value2:
1852 	//	Session Management Control Port
1853 	//	Default TCP port for RTSP messages is 554
1854 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
1855 	wfdielen += 2;
1856 
1857 	//	Value3:
1858 	//	WFD Device Maximum Throughput
1859 	//	300Mbps is the maximum throughput
1860 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1861 	wfdielen += 2;
1862 
1863 	//	Associated BSSID ATTR
1864 	//	Type:
1865 	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1866 
1867 	//	Length:
1868 	//	Note: In the WFD specification, the size of length field is 2.
1869 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1870 	wfdielen += 2;
1871 
1872 	//	Value:
1873 	//	Associated BSSID
1874 	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
1875 	{
1876 		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
1877 	}
1878 	else
1879 	{
1880 		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
1881 	}
1882 
1883 	wfdielen += ETH_ALEN;
1884 
1885 	//	Coupled Sink Information ATTR
1886 	//	Type:
1887 	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1888 
1889 	//	Length:
1890 	//	Note: In the WFD specification, the size of length field is 2.
1891 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1892 	wfdielen += 2;
1893 
1894 	//	Value:
1895 	//	Coupled Sink Status bitmap
1896 	//	Not coupled/available for Coupling
1897 	wfdie[ wfdielen++ ] = 0;
1898 	//  MAC Addr.
1899 	wfdie[ wfdielen++ ] = 0;
1900 	wfdie[ wfdielen++ ] = 0;
1901 	wfdie[ wfdielen++ ] = 0;
1902 	wfdie[ wfdielen++ ] = 0;
1903 	wfdie[ wfdielen++ ] = 0;
1904 	wfdie[ wfdielen++ ] = 0;
1905 
1906 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1907 
1908 	return len;
1909 
1910 }
1911 
1912 
1913 #endif //CONFIG_WFD
1914 
build_probe_resp_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1915 u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1916 {
1917 	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
1918 	u32 len=0, p2pielen = 0;
1919 #ifdef CONFIG_INTEL_WIDI
1920 	struct mlme_priv *pmlmepriv = &(pwdinfo->padapter->mlmepriv);
1921 	u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 };
1922 	u8 widi_version = 0, i = 0;
1923 
1924 	if( _rtw_memcmp( pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN ) == _FALSE )
1925 	{
1926 		widi_version = 35;
1927 	}
1928 	else if( pmlmepriv->num_p2p_sdt != 0 )
1929 	{
1930 		widi_version = 40;
1931 	}
1932 #endif //CONFIG_INTEL_WIDI
1933 
1934 	//	P2P OUI
1935 	p2pielen = 0;
1936 	p2pie[ p2pielen++ ] = 0x50;
1937 	p2pie[ p2pielen++ ] = 0x6F;
1938 	p2pie[ p2pielen++ ] = 0x9A;
1939 	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
1940 
1941 	//	Commented by Albert 20100907
1942 	//	According to the P2P Specification, the probe response frame should contain 5 P2P attributes
1943 	//	1. P2P Capability
1944 	//	2. Extended Listen Timing
1945 	//	3. Notice of Absence ( NOA )	( Only GO needs this )
1946 	//	4. Device Info
1947 	//	5. Group Info	( Only GO need this )
1948 
1949 	//	P2P Capability ATTR
1950 	//	Type:
1951 	p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
1952 
1953 	//	Length:
1954 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
1955 	RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
1956 	p2pielen += 2;
1957 
1958 	//	Value:
1959 	//	Device Capability Bitmap, 1 byte
1960 	p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
1961 
1962 	//	Group Capability Bitmap, 1 byte
1963 	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1964 	{
1965 		p2pie[ p2pielen ] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
1966 
1967 		if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
1968 			p2pie[ p2pielen ] |= P2P_GRPCAP_GROUP_FORMATION;
1969 
1970 		p2pielen++;
1971 	}
1972 	else if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) )
1973 	{
1974 		//	Group Capability Bitmap, 1 byte
1975 		if ( pwdinfo->persistent_supported )
1976 			p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
1977 		else
1978 			p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
1979 	}
1980 
1981 	//	Extended Listen Timing ATTR
1982 	//	Type:
1983 	p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
1984 
1985 	//	Length:
1986 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
1987 	RTW_PUT_LE16(p2pie + p2pielen, 0x0004);
1988 	p2pielen += 2;
1989 
1990 	//	Value:
1991 	//	Availability Period
1992 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
1993 	RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
1994 	p2pielen += 2;
1995 
1996 	//	Availability Interval
1997 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
1998 	RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
1999 	p2pielen += 2;
2000 
2001 
2002 	// Notice of Absence ATTR
2003 	//	Type:
2004 	//	Length:
2005 	//	Value:
2006 	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2007 	{
2008 		//go_add_noa_attr(pwdinfo);
2009 	}
2010 
2011 	//	Device Info ATTR
2012 	//	Type:
2013 	p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
2014 
2015 	//	Length:
2016 	//	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes)
2017 	//	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
2018 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
2019 #ifdef CONFIG_INTEL_WIDI
2020 	if( widi_version == 35 )
2021 	{
2022 		RTW_PUT_LE16(p2pie + p2pielen, 21 + 8 + pwdinfo->device_name_len);
2023 	}
2024 	else if( widi_version == 40 )
2025 	{
2026 		RTW_PUT_LE16(p2pie + p2pielen, 21 + 8 * pmlmepriv->num_p2p_sdt + pwdinfo->device_name_len);
2027 	}
2028 	else
2029 #endif //CONFIG_INTEL_WIDI
2030 	RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
2031 	p2pielen += 2;
2032 
2033 	//	Value:
2034 	//	P2P Device Address
2035 	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );
2036 	p2pielen += ETH_ALEN;
2037 
2038 	//	Config Method
2039 	//	This field should be big endian. Noted by P2P specification.
2040 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
2041 	RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm);
2042 	p2pielen += 2;
2043 
2044 #ifdef CONFIG_INTEL_WIDI
2045 	if( widi_version == 40 )
2046 	{
2047 		//	Primary Device Type
2048 		//	Category ID
2049 		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
2050 		RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_pdt_cid );
2051 		p2pielen += 2;
2052 
2053 		//	OUI
2054 		//*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
2055 		RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
2056 		p2pielen += 4;
2057 
2058 		//	Sub Category ID
2059 		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
2060 		RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_pdt_scid);
2061 		p2pielen += 2;
2062 	}
2063 	else
2064 #endif //CONFIG_INTEL_WIDI
2065 	{
2066 		//	Primary Device Type
2067 		//	Category ID
2068 		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
2069 		RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
2070 		p2pielen += 2;
2071 
2072 		//	OUI
2073 		//*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
2074 		RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
2075 		p2pielen += 4;
2076 
2077 		//	Sub Category ID
2078 		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
2079 		RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
2080 		p2pielen += 2;
2081 	}
2082 
2083 	//	Number of Secondary Device Types
2084 #ifdef CONFIG_INTEL_WIDI
2085 	if( widi_version == 35 )
2086 	{
2087 		p2pie[ p2pielen++ ] = 0x01;
2088 
2089 		RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_DISPLAYS);
2090 		p2pielen += 2;
2091 
2092 		RTW_PUT_BE32(p2pie + p2pielen, INTEL_DEV_TYPE_OUI);
2093 		p2pielen += 4;
2094 
2095 		RTW_PUT_BE16(p2pie + p2pielen, P2P_SCID_WIDI_CONSUMER_SINK);
2096 		p2pielen += 2;
2097 	}
2098 	else if( widi_version == 40 )
2099 	{
2100 		p2pie[ p2pielen++ ] = pmlmepriv->num_p2p_sdt;
2101 		for( ; i < pmlmepriv->num_p2p_sdt; i++ )
2102 		{
2103 			RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_sdt_cid[i]);
2104 			p2pielen += 2;
2105 
2106 			RTW_PUT_BE32(p2pie + p2pielen, INTEL_DEV_TYPE_OUI);
2107 			p2pielen += 4;
2108 
2109 			RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_sdt_scid[i]);
2110 			p2pielen += 2;
2111 		}
2112 	}
2113 	else
2114 #endif //CONFIG_INTEL_WIDI
2115 	p2pie[ p2pielen++ ] = 0x00;	//	No Secondary Device Type List
2116 
2117 	//	Device Name
2118 	//	Type:
2119 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
2120 	RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
2121 	p2pielen += 2;
2122 
2123 	//	Length:
2124 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
2125 	RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
2126 	p2pielen += 2;
2127 
2128 	//	Value:
2129 	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
2130 	p2pielen += pwdinfo->device_name_len;
2131 
2132 	// Group Info ATTR
2133 	//	Type:
2134 	//	Length:
2135 	//	Value:
2136 	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2137 	{
2138 		p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
2139 	}
2140 
2141 
2142 	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2143 
2144 
2145 	return len;
2146 
2147 }
2148 
build_prov_disc_request_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pbuf,u8 * pssid,u8 ussidlen,u8 * pdev_raddr)2149 u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8* pssid, u8 ussidlen, u8* pdev_raddr )
2150 {
2151 	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
2152 	u32 len=0, p2pielen = 0;
2153 
2154 	//	P2P OUI
2155 	p2pielen = 0;
2156 	p2pie[ p2pielen++ ] = 0x50;
2157 	p2pie[ p2pielen++ ] = 0x6F;
2158 	p2pie[ p2pielen++ ] = 0x9A;
2159 	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
2160 
2161 	//	Commented by Albert 20110301
2162 	//	According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes
2163 	//	1. P2P Capability
2164 	//	2. Device Info
2165 	//	3. Group ID ( When joining an operating P2P Group )
2166 
2167 	//	P2P Capability ATTR
2168 	//	Type:
2169 	p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
2170 
2171 	//	Length:
2172 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
2173 	RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
2174 	p2pielen += 2;
2175 
2176 	//	Value:
2177 	//	Device Capability Bitmap, 1 byte
2178 	p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
2179 
2180 	//	Group Capability Bitmap, 1 byte
2181 	if ( pwdinfo->persistent_supported )
2182 		p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
2183 	else
2184 		p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
2185 
2186 
2187 	//	Device Info ATTR
2188 	//	Type:
2189 	p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
2190 
2191 	//	Length:
2192 	//	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes)
2193 	//	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
2194 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
2195 	RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
2196 	p2pielen += 2;
2197 
2198 	//	Value:
2199 	//	P2P Device Address
2200 	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );
2201 	p2pielen += ETH_ALEN;
2202 
2203 	//	Config Method
2204 	//	This field should be big endian. Noted by P2P specification.
2205 	if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC )
2206 	{
2207 		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_PBC );
2208 		RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC);
2209 	}
2210 	else
2211 	{
2212 		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY );
2213 		RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY);
2214 	}
2215 
2216 	p2pielen += 2;
2217 
2218 	//	Primary Device Type
2219 	//	Category ID
2220 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
2221 	RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
2222 	p2pielen += 2;
2223 
2224 	//	OUI
2225 	//*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
2226 	RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
2227 	p2pielen += 4;
2228 
2229 	//	Sub Category ID
2230 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
2231 	RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
2232 	p2pielen += 2;
2233 
2234 	//	Number of Secondary Device Types
2235 	p2pie[ p2pielen++ ] = 0x00;	//	No Secondary Device Type List
2236 
2237 	//	Device Name
2238 	//	Type:
2239 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
2240 	RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
2241 	p2pielen += 2;
2242 
2243 	//	Length:
2244 	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
2245 	RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
2246 	p2pielen += 2;
2247 
2248 	//	Value:
2249 	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
2250 	p2pielen += pwdinfo->device_name_len;
2251 
2252 	if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
2253 	{
2254 		//	Added by Albert 2011/05/19
2255 		//	In this case, the pdev_raddr is the device address of the group owner.
2256 
2257 		//	P2P Group ID ATTR
2258 		//	Type:
2259 		p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
2260 
2261 		//	Length:
2262 		//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + ussidlen );
2263 		RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen);
2264 		p2pielen += 2;
2265 
2266 		//	Value:
2267 		_rtw_memcpy( p2pie + p2pielen, pdev_raddr, ETH_ALEN );
2268 		p2pielen += ETH_ALEN;
2269 
2270 		_rtw_memcpy( p2pie + p2pielen, pssid, ussidlen );
2271 		p2pielen += ussidlen;
2272 
2273 	}
2274 
2275 	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2276 
2277 
2278 	return len;
2279 
2280 }
2281 
2282 
build_assoc_resp_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pbuf,u8 status_code)2283 u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
2284 {
2285 	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
2286 	u32 len=0, p2pielen = 0;
2287 
2288 	//	P2P OUI
2289 	p2pielen = 0;
2290 	p2pie[ p2pielen++ ] = 0x50;
2291 	p2pie[ p2pielen++ ] = 0x6F;
2292 	p2pie[ p2pielen++ ] = 0x9A;
2293 	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
2294 
2295 	// According to the P2P Specification, the Association response frame should contain 2 P2P attributes
2296 	//	1. Status
2297 	//	2. Extended Listen Timing (optional)
2298 
2299 
2300 	//	Status ATTR
2301 	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
2302 
2303 
2304 	// Extended Listen Timing ATTR
2305 	//	Type:
2306 	//	Length:
2307 	//	Value:
2308 
2309 
2310 	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2311 
2312 	return len;
2313 
2314 }
2315 
build_deauth_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)2316 u32 build_deauth_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
2317 {
2318 	u32 len=0;
2319 
2320 	return len;
2321 }
2322 
process_probe_req_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2323 u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2324 {
2325 	u8 *p;
2326 	u32 ret=_FALSE;
2327 	u8 *p2pie;
2328 	u32	p2pielen = 0;
2329 	int ssid_len=0, rate_cnt = 0;
2330 
2331 	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
2332 			len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
2333 
2334 	if ( rate_cnt <= 4 )
2335 	{
2336 		int i, g_rate =0;
2337 
2338 		for( i = 0; i < rate_cnt; i++ )
2339 		{
2340 			if ( ( ( *( p + 2 + i ) & 0xff ) != 0x02 ) &&
2341 				( ( *( p + 2 + i ) & 0xff ) != 0x04 ) &&
2342 				( ( *( p + 2 + i ) & 0xff ) != 0x0B ) &&
2343 				( ( *( p + 2 + i ) & 0xff ) != 0x16 ) )
2344 			{
2345 				g_rate = 1;
2346 			}
2347 		}
2348 
2349 		if ( g_rate == 0 )
2350 		{
2351 			//	There is no OFDM rate included in SupportedRates IE of this probe request frame
2352 			//	The driver should response this probe request.
2353 			return ret;
2354 		}
2355 	}
2356 	else
2357 	{
2358 		//	rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4.
2359 		//	We should proceed the following check for this probe request.
2360 	}
2361 
2362 	//	Added comments by Albert 20100906
2363 	//	There are several items we should check here.
2364 	//	1. This probe request frame must contain the P2P IE. (Done)
2365 	//	2. This probe request frame must contain the wildcard SSID. (Done)
2366 	//	3. Wildcard BSSID. (Todo)
2367 	//	4. Destination Address. ( Done in mgt_dispatcher function )
2368 	//	5. Requested Device Type in WSC IE. (Todo)
2369 	//	6. Device ID attribute in P2P IE. (Todo)
2370 
2371 	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
2372 			len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
2373 
2374 	ssid_len &= 0xff;	//	Just last 1 byte is valid for ssid len of the probe request
2375 	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2376 	{
2377 		if((p2pie=rtw_get_p2p_ie( pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_ , len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_ , NULL, &p2pielen)))
2378 		{
2379 			if ( (p != NULL) && _rtw_memcmp( ( void * ) ( p+2 ), ( void * ) pwdinfo->p2p_wildcard_ssid , 7 ))
2380 			{
2381 				//todo:
2382 				//Check Requested Device Type attributes in WSC IE.
2383 				//Check Device ID attribute in P2P IE
2384 
2385 				ret = _TRUE;
2386 			}
2387 			else if ( (p != NULL) && ( ssid_len == 0 ) )
2388 			{
2389 				ret = _TRUE;
2390 			}
2391 		}
2392 		else
2393 		{
2394 			//non -p2p device
2395 		}
2396 
2397 	}
2398 
2399 
2400 	return ret;
2401 
2402 }
2403 
process_assoc_req_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pframe,uint len,struct sta_info * psta)2404 u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
2405 {
2406 	u8 status_code = P2P_STATUS_SUCCESS;
2407 	u8 *pbuf, *pattr_content=NULL;
2408 	u32 attr_contentlen = 0;
2409 	u16 cap_attr=0;
2410 	unsigned short	frame_type, ie_offset=0;
2411 	u8 * ies;
2412 	u32 ies_len;
2413 	u8 * p2p_ie;
2414 	u32	p2p_ielen = 0;
2415 
2416 	if(!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2417 		return P2P_STATUS_FAIL_REQUEST_UNABLE;
2418 
2419 	frame_type = GetFrameSubType(pframe);
2420 	if (frame_type == WIFI_ASSOCREQ)
2421 	{
2422 		ie_offset = _ASOCREQ_IE_OFFSET_;
2423 	}
2424 	else // WIFI_REASSOCREQ
2425 	{
2426 		ie_offset = _REASOCREQ_IE_OFFSET_;
2427 	}
2428 
2429 	ies = pframe + WLAN_HDR_A3_LEN + ie_offset;
2430 	ies_len = len - WLAN_HDR_A3_LEN - ie_offset;
2431 
2432 	p2p_ie = rtw_get_p2p_ie(ies , ies_len , NULL, &p2p_ielen);
2433 
2434 	if ( !p2p_ie )
2435 	{
2436 		DBG_8192C( "[%s] P2P IE not Found!!\n", __FUNCTION__ );
2437 		status_code =  P2P_STATUS_FAIL_INVALID_PARAM;
2438 	}
2439 	else
2440 	{
2441 		DBG_8192C( "[%s] P2P IE Found!!\n", __FUNCTION__ );
2442 	}
2443 
2444 	while ( p2p_ie )
2445 	{
2446 		//Check P2P Capability ATTR
2447 		if( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*) &attr_contentlen) )
2448 		{
2449 			DBG_8192C( "[%s] Got P2P Capability Attr!!\n", __FUNCTION__ );
2450 			cap_attr = le16_to_cpu(cap_attr);
2451 			psta->dev_cap = cap_attr&0xff;
2452 		}
2453 
2454 		//Check Extended Listen Timing ATTR
2455 
2456 
2457 		//Check P2P Device Info ATTR
2458 		if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint*)&attr_contentlen))
2459 		{
2460 			DBG_8192C( "[%s] Got P2P DEVICE INFO Attr!!\n", __FUNCTION__ );
2461 			pattr_content = pbuf = rtw_zmalloc(attr_contentlen);
2462 			if(pattr_content)
2463 			{
2464 				u8 num_of_secdev_type;
2465 				u16 dev_name_len;
2466 
2467 
2468 				rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO , pattr_content, (uint*)&attr_contentlen);
2469 
2470 				_rtw_memcpy(psta->dev_addr, 	pattr_content, ETH_ALEN);//P2P Device Address
2471 
2472 				pattr_content += ETH_ALEN;
2473 
2474 				_rtw_memcpy(&psta->config_methods, pattr_content, 2);//Config Methods
2475 				psta->config_methods = be16_to_cpu(psta->config_methods);
2476 
2477 				pattr_content += 2;
2478 
2479 				_rtw_memcpy(psta->primary_dev_type, pattr_content, 8);
2480 
2481 				pattr_content += 8;
2482 
2483 				num_of_secdev_type = *pattr_content;
2484 				pattr_content += 1;
2485 
2486 				if(num_of_secdev_type==0)
2487 				{
2488 					psta->num_of_secdev_type = 0;
2489 				}
2490 				else
2491 				{
2492 					u32 len;
2493 
2494 					psta->num_of_secdev_type = num_of_secdev_type;
2495 
2496 					len = (sizeof(psta->secdev_types_list)<(num_of_secdev_type*8)) ? (sizeof(psta->secdev_types_list)) : (num_of_secdev_type*8);
2497 
2498 					_rtw_memcpy(psta->secdev_types_list, pattr_content, len);
2499 
2500 					pattr_content += (num_of_secdev_type*8);
2501 				}
2502 
2503 
2504 				//dev_name_len = attr_contentlen - ETH_ALEN - 2 - 8 - 1 - (num_of_secdev_type*8);
2505 				psta->dev_name_len=0;
2506 				if(WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(u16*)pattr_content))
2507 				{
2508 					dev_name_len = be16_to_cpu(*(u16*)(pattr_content+2));
2509 
2510 					psta->dev_name_len = (sizeof(psta->dev_name)<dev_name_len) ? sizeof(psta->dev_name):dev_name_len;
2511 
2512 					_rtw_memcpy(psta->dev_name, pattr_content+4, psta->dev_name_len);
2513 				}
2514 
2515 				rtw_mfree(pbuf, attr_contentlen);
2516 
2517 			}
2518 
2519 		}
2520 
2521 		//Get the next P2P IE
2522 		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2523 
2524 	}
2525 
2526 	return status_code;
2527 
2528 }
2529 
process_p2p_devdisc_req(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2530 u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2531 {
2532 	u8 *frame_body;
2533 	u8 status, dialogToken;
2534 	struct sta_info *psta = NULL;
2535 	_adapter *padapter = pwdinfo->padapter;
2536 	struct sta_priv *pstapriv = &padapter->stapriv;
2537 	u8 *p2p_ie;
2538 	u32	p2p_ielen = 0;
2539 
2540 	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2541 
2542 	dialogToken = frame_body[7];
2543 	status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
2544 
2545 	if ( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)) )
2546 	{
2547 		u8 groupid[ 38 ] = { 0x00 };
2548 		u8 dev_addr[ETH_ALEN] = { 0x00 };
2549 		u32	attr_contentlen = 0;
2550 
2551 		if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen))
2552 		{
2553 			if(_rtw_memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
2554 				_rtw_memcmp(pwdinfo->p2p_group_ssid, groupid+ETH_ALEN, pwdinfo->p2p_group_ssid_len))
2555 			{
2556 				attr_contentlen=0;
2557 				if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen))
2558 				{
2559 					_irqL irqL;
2560 					_list	*phead, *plist;
2561 
2562 					_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2563 					phead = &pstapriv->asoc_list;
2564 					plist = get_next(phead);
2565 
2566 					//look up sta asoc_queue
2567 					while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
2568 					{
2569 						psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
2570 
2571 						plist = get_next(plist);
2572 
2573 						if(psta->is_p2p_device && (psta->dev_cap&P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
2574 							_rtw_memcmp(psta->dev_addr, dev_addr, ETH_ALEN))
2575 						{
2576 
2577 							//_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2578 							//issue GO Discoverability Request
2579 							issue_group_disc_req(pwdinfo, psta->hwaddr);
2580 							//_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2581 
2582 							status = P2P_STATUS_SUCCESS;
2583 
2584 							break;
2585 						}
2586 						else
2587 						{
2588 							status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2589 						}
2590 
2591 					}
2592 					_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2593 
2594 				}
2595 				else
2596 				{
2597 					status = P2P_STATUS_FAIL_INVALID_PARAM;
2598 				}
2599 
2600 			}
2601 			else
2602 			{
2603 				status = P2P_STATUS_FAIL_INVALID_PARAM;
2604 			}
2605 
2606 		}
2607 
2608 	}
2609 
2610 
2611 	//issue Device Discoverability Response
2612 	issue_p2p_devdisc_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
2613 
2614 
2615 	return (status==P2P_STATUS_SUCCESS) ? _TRUE:_FALSE;
2616 
2617 }
2618 
process_p2p_devdisc_resp(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2619 u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2620 {
2621 	return _TRUE;
2622 }
2623 
process_p2p_provdisc_req(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2624 u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo,  u8 *pframe, uint len )
2625 {
2626 	u8 *frame_body;
2627 	u8 *wpsie;
2628 	uint	wps_ielen = 0, attr_contentlen = 0;
2629 	u16	uconfig_method = 0;
2630 
2631 
2632 	frame_body = (pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2633 
2634 	if ( (wpsie=rtw_get_wps_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen)) )
2635 	{
2636 		if ( rtw_get_wps_attr_content( wpsie, wps_ielen, WPS_ATTR_CONF_METHOD , ( u8* ) &uconfig_method, &attr_contentlen) )
2637 		{
2638 			uconfig_method = be16_to_cpu( uconfig_method );
2639 			switch( uconfig_method )
2640 			{
2641 				case WPS_CM_DISPLYA:
2642 				{
2643 					_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3 );
2644 					break;
2645 				}
2646 				case WPS_CM_LABEL:
2647 				{
2648 					_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "lab", 3 );
2649 					break;
2650 				}
2651 				case WPS_CM_PUSH_BUTTON:
2652 				{
2653 					_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3 );
2654 					break;
2655 				}
2656 				case WPS_CM_KEYPAD:
2657 				{
2658 					_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3 );
2659 					break;
2660 				}
2661 			}
2662 			issue_p2p_provision_resp( pwdinfo, GetAddr2Ptr(pframe), frame_body, uconfig_method);
2663 		}
2664 	}
2665 	DBG_871X( "[%s] config method = %s\n", __FUNCTION__, pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req );
2666 	return _TRUE;
2667 
2668 }
2669 
process_p2p_provdisc_resp(struct wifidirect_info * pwdinfo,u8 * pframe)2670 u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo,  u8 *pframe)
2671 {
2672 
2673 	return _TRUE;
2674 }
2675 
rtw_p2p_get_peer_ch_list(struct wifidirect_info * pwdinfo,u8 * ch_content,u8 ch_cnt,u8 * peer_ch_list)2676 u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
2677 {
2678 	u8 i = 0, j = 0;
2679 	u8 temp = 0;
2680 	u8 ch_no = 0;
2681 	ch_content += 3;
2682 	ch_cnt -= 3;
2683 
2684 	while( ch_cnt > 0)
2685 	{
2686 		ch_content += 1;
2687 		ch_cnt -= 1;
2688 		temp = *ch_content;
2689 		for( i = 0 ; i < temp ; i++, j++ )
2690 		{
2691 			peer_ch_list[j] = *( ch_content + 1 + i );
2692 		}
2693 		ch_content += (temp + 1);
2694 		ch_cnt -= (temp + 1);
2695 		ch_no += temp ;
2696 	}
2697 
2698 	return ch_no;
2699 }
2700 
rtw_p2p_check_peer_oper_ch(struct mlme_ext_priv * pmlmeext,u8 ch)2701 u8 rtw_p2p_check_peer_oper_ch(struct mlme_ext_priv *pmlmeext, u8 ch)
2702 {
2703 	u8 i = 0;
2704 
2705 	for( i = 0; i < pmlmeext->max_chan_nums; i++ )
2706 	{
2707 		if ( pmlmeext->channel_set[ i ].ChannelNum == ch )
2708 		{
2709 			return _SUCCESS;
2710 		}
2711 	}
2712 
2713 	return _FAIL;
2714 }
2715 
rtw_p2p_ch_inclusion(struct mlme_ext_priv * pmlmeext,u8 * peer_ch_list,u8 peer_ch_num,u8 * ch_list_inclusioned)2716 u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
2717 {
2718 	int	i = 0, j = 0, temp = 0;
2719 	u8 ch_no = 0;
2720 
2721 	for( i = 0; i < peer_ch_num; i++ )
2722 	{
2723 		for( j = temp; j < pmlmeext->max_chan_nums; j++ )
2724 		{
2725 			if( *( peer_ch_list + i ) == pmlmeext->channel_set[ j ].ChannelNum )
2726 			{
2727 				ch_list_inclusioned[ ch_no++ ] = *( peer_ch_list + i );
2728 				temp = j;
2729 				break;
2730 			}
2731 		}
2732 	}
2733 
2734 	return ch_no;
2735 }
2736 
process_p2p_group_negotation_req(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2737 u8 process_p2p_group_negotation_req( struct wifidirect_info *pwdinfo, u8 *pframe, uint len )
2738 {
2739 	_adapter *padapter = pwdinfo->padapter;
2740 	u8	result = P2P_STATUS_SUCCESS;
2741 	u32	p2p_ielen = 0, wps_ielen = 0;
2742 	u8 * ies;
2743 	u32 ies_len;
2744 	u8 *p2p_ie;
2745 	u8 *wpsie;
2746 	u16		wps_devicepassword_id = 0x0000;
2747 	uint	wps_devicepassword_id_len = 0;
2748 #ifdef CONFIG_WFD
2749 	u8	wfd_ie[ 128 ] = { 0x00 };
2750 	u32	wfd_ielen = 0;
2751 #ifdef CONFIG_TDLS
2752 	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
2753 #endif // CONFIG_TDLS
2754 #endif // CONFIG_WFD
2755 #ifdef CONFIG_CONCURRENT_MODE
2756 	_adapter				*pbuddy_adapter = pwdinfo->padapter->pbuddy_adapter;
2757 	struct wifidirect_info	*pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
2758 	struct mlme_priv		*pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
2759 	struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
2760 #endif
2761 
2762 	if ( (wpsie=rtw_get_wps_ie( pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen)) )
2763 	{
2764 		//	Commented by Kurt 20120113
2765 		//	If some device wants to do p2p handshake without sending prov_disc_req
2766 		//	We have to get peer_req_cm from here.
2767 		if(_rtw_memcmp( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3) )
2768 		{
2769 			rtw_get_wps_attr_content( wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
2770 			wps_devicepassword_id = be16_to_cpu( wps_devicepassword_id );
2771 
2772 			if ( wps_devicepassword_id == WPS_DPID_USER_SPEC )
2773 			{
2774 				_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3 );
2775 			}
2776 			else if ( wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC )
2777 			{
2778 				_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3 );
2779 			}
2780 			else
2781 			{
2782 				_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3 );
2783 			}
2784 		}
2785 	}
2786 	else
2787 	{
2788 		DBG_871X( "[%s] WPS IE not Found!!\n", __FUNCTION__ );
2789 		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2790 		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2791 		return( result );
2792 	}
2793 
2794 	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2795 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2796 
2797 	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
2798 
2799 	if ( !p2p_ie )
2800 	{
2801 		DBG_871X( "[%s] P2P IE not Found!!\n", __FUNCTION__ );
2802 		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2803 		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2804 	}
2805 
2806 	while ( p2p_ie )
2807 	{
2808 		u8	attr_content = 0x00;
2809 		u32	attr_contentlen = 0;
2810 		u8	ch_content[100] = { 0x00 };
2811 		uint	ch_cnt = 0;
2812 		u8	peer_ch_list[100] = { 0x00 };
2813 		u8	peer_ch_num = 0;
2814 		u8	ch_list_inclusioned[100] = { 0x00 };
2815 		u8	ch_num_inclusioned = 0;
2816 		u16	cap_attr;
2817 		u8 listen_ch_attr[5] = { 0x00 };
2818 
2819 		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
2820 
2821 		//Check P2P Capability ATTR
2822 		if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen) )
2823 		{
2824 			cap_attr = le16_to_cpu(cap_attr);
2825 
2826 #if defined(CONFIG_WFD) && defined(CONFIG_TDLS)
2827 			if(!(cap_attr & P2P_GRPCAP_INTRABSS) )
2828 				ptdlsinfo->ap_prohibited = _TRUE;
2829 #endif //defined(CONFIG_WFD) && defined(CONFIG_TDLS)
2830 		}
2831 
2832 		if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen) )
2833 		{
2834 			DBG_871X( "[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01 );
2835 			pwdinfo->peer_intent = attr_content;	//	include both intent and tie breaker values.
2836 
2837 			if ( pwdinfo->intent == ( pwdinfo->peer_intent >> 1 ) )
2838 			{
2839 				//	Try to match the tie breaker value
2840 				if ( pwdinfo->intent == P2P_MAX_INTENT )
2841 				{
2842 					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2843 					result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2844 				}
2845 				else
2846 				{
2847 					if ( attr_content & 0x01 )
2848 					{
2849 						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2850 					}
2851 					else
2852 					{
2853 						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2854 					}
2855 				}
2856 			}
2857 			else if ( pwdinfo->intent > ( pwdinfo->peer_intent >> 1 ) )
2858 			{
2859 				rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2860 			}
2861 			else
2862 			{
2863 				rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2864 			}
2865 
2866 			if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2867 			{
2868 				//	Store the group id information.
2869 				_rtw_memcpy( pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN );
2870 				_rtw_memcpy( pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
2871 			}
2872 		}
2873 
2874 		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, (u8 *)listen_ch_attr, (uint *) &attr_contentlen) && attr_contentlen == 5)
2875 			pwdinfo->nego_req_info.peer_ch = listen_ch_attr[4];
2876 
2877 		DBG_871X(FUNC_ADPT_FMT" listen channel :%u\n", FUNC_ADPT_ARG(padapter), pwdinfo->nego_req_info.peer_ch);
2878 
2879 		attr_contentlen = 0;
2880 		if ( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen ) )
2881 		{
2882 			if ( attr_contentlen != ETH_ALEN )
2883 			{
2884 				_rtw_memset( pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN );
2885 			}
2886 		}
2887 
2888 		if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt) )
2889 		{
2890 			peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
2891 			ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2892 
2893 			if( ch_num_inclusioned == 0)
2894 			{
2895 				DBG_871X( "[%s] No common channel in channel list!\n", __FUNCTION__ );
2896 				result = P2P_STATUS_FAIL_NO_COMMON_CH;
2897 				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2898 				break;
2899 			}
2900 
2901 			if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2902 			{
2903 				if ( !rtw_p2p_is_channel_list_ok( pwdinfo->operating_channel,
2904 												ch_list_inclusioned, ch_num_inclusioned) )
2905 				{
2906 #ifdef CONFIG_CONCURRENT_MODE
2907 					if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
2908 					{
2909 						DBG_871X( "[%s] desired channel NOT Found!\n", __FUNCTION__ );
2910 						result = P2P_STATUS_FAIL_NO_COMMON_CH;
2911 						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2912 						break;
2913 					}
2914 					else
2915 #endif //CONFIG_CONCURRENT_MODE
2916 					{
2917 						u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2918 						attr_contentlen = 0;
2919 
2920 						if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) )
2921 						{
2922 							peer_operating_ch = operatingch_info[4];
2923 						}
2924 
2925 						if ( rtw_p2p_is_channel_list_ok( peer_operating_ch,
2926 														ch_list_inclusioned, ch_num_inclusioned) )
2927 						{
2928 							/**
2929 							 *	Change our operating channel as peer's for compatibility.
2930 							 */
2931 							pwdinfo->operating_channel = peer_operating_ch;
2932 							DBG_871X( "[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);
2933 						}
2934 						else
2935 						{
2936 							// Take first channel of ch_list_inclusioned as operating channel
2937 							pwdinfo->operating_channel = ch_list_inclusioned[0];
2938 							DBG_871X( "[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);
2939 						}
2940 					}
2941 
2942 				}
2943 			}
2944 		}
2945 
2946 		//Get the next P2P IE
2947 		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2948 	}
2949 
2950 	if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) {
2951 		result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2952 		rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
2953 		return result;
2954 	}
2955 
2956 #ifdef CONFIG_WFD
2957 	//	Added by Albert 20110823
2958 	//	Try to get the TCP port information when receiving the negotiation request.
2959 	if ( rtw_get_wfd_ie( pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wfd_ie, &wfd_ielen ) )
2960 	{
2961 		u8	attr_content[ 10 ] = { 0x00 };
2962 		u32	attr_contentlen = 0;
2963 
2964 		DBG_871X( "[%s] WFD IE Found!!\n", __FUNCTION__ );
2965 		rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
2966 		if ( attr_contentlen )
2967 		{
2968 			pwdinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );
2969 			DBG_871X( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_rtsp_ctrlport );
2970 		}
2971 	}
2972 #endif // CONFIG_WFD
2973 
2974 	return( result );
2975 }
2976 
process_p2p_group_negotation_resp(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2977 u8 process_p2p_group_negotation_resp( struct wifidirect_info *pwdinfo, u8 *pframe, uint len )
2978 {
2979 	_adapter *padapter = pwdinfo->padapter;
2980 	u8	result = P2P_STATUS_SUCCESS;
2981 	u32	p2p_ielen, wps_ielen;
2982 	u8 * ies;
2983 	u32 ies_len;
2984 	u8 * p2p_ie;
2985 #ifdef CONFIG_WFD
2986 	u8	wfd_ie[ 128 ] = { 0x00 };
2987 	u32	wfd_ielen = 0;
2988 #ifdef CONFIG_TDLS
2989 	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
2990 #endif // CONFIG_TDLS
2991 #endif // CONFIG_WFD
2992 
2993 	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2994 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2995 
2996 	//	Be able to know which one is the P2P GO and which one is P2P client.
2997 
2998 	if ( rtw_get_wps_ie( ies, ies_len, NULL, &wps_ielen) )
2999 	{
3000 
3001 	}
3002 	else
3003 	{
3004 		DBG_871X( "[%s] WPS IE not Found!!\n", __FUNCTION__ );
3005 		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
3006 		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
3007 	}
3008 
3009 	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
3010 	if ( !p2p_ie )
3011 	{
3012 		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3013 		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
3014 		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
3015 	}
3016 	else
3017 	{
3018 
3019 		u8	attr_content = 0x00;
3020 		u32	attr_contentlen = 0;
3021 		u8	operatingch_info[5] = { 0x00 };
3022 		uint	ch_cnt = 0;
3023 		u8	ch_content[100] = { 0x00 };
3024 		u8	groupid[ 38 ];
3025 		u16	cap_attr;
3026 		u8	peer_ch_list[100] = { 0x00 };
3027 		u8	peer_ch_num = 0;
3028 		u8	ch_list_inclusioned[100] = { 0x00 };
3029 		u8	ch_num_inclusioned = 0;
3030 
3031 		while ( p2p_ie )	//	Found the P2P IE.
3032 		{
3033 
3034 			//Check P2P Capability ATTR
3035 			if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen) )
3036 			{
3037 				cap_attr = le16_to_cpu(cap_attr);
3038 #ifdef CONFIG_TDLS
3039 				if(!(cap_attr & P2P_GRPCAP_INTRABSS) )
3040 					ptdlsinfo->ap_prohibited = _TRUE;
3041 #endif // CONFIG_TDLS
3042 			}
3043 
3044 			rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
3045 			if ( attr_contentlen == 1 )
3046 			{
3047 				DBG_871X( "[%s] Status = %d\n", __FUNCTION__, attr_content );
3048 				if ( attr_content == P2P_STATUS_SUCCESS )
3049 				{
3050 					//	Do nothing.
3051 				}
3052 				else
3053 				{
3054 					if ( P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content ) {
3055 						rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
3056 					} else {
3057 						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
3058 					}
3059 					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3060 					result = attr_content;
3061 					break;
3062 				}
3063 			}
3064 
3065 			//	Try to get the peer's interface address
3066 			attr_contentlen = 0;
3067 			if ( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen ) )
3068 			{
3069 				if ( attr_contentlen != ETH_ALEN )
3070 				{
3071 					_rtw_memset( pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN );
3072 				}
3073 			}
3074 
3075 			//	Try to get the peer's intent and tie breaker value.
3076 			attr_content = 0x00;
3077 			attr_contentlen = 0;
3078 			if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen) )
3079 			{
3080 				DBG_871X( "[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01 );
3081 				pwdinfo->peer_intent = attr_content;	//	include both intent and tie breaker values.
3082 
3083 				if ( pwdinfo->intent == ( pwdinfo->peer_intent >> 1 ) )
3084 				{
3085 					//	Try to match the tie breaker value
3086 					if ( pwdinfo->intent == P2P_MAX_INTENT )
3087 					{
3088 						rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3089 						result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
3090 						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
3091 					}
3092 					else
3093 					{
3094 						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3095 						rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3096 						if ( attr_content & 0x01 )
3097 						{
3098 							rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3099 						}
3100 						else
3101 						{
3102 							rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3103 						}
3104 					}
3105 				}
3106 				else if ( pwdinfo->intent > ( pwdinfo->peer_intent >> 1 ) )
3107 				{
3108 					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3109 					rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3110 					rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3111 				}
3112 				else
3113 				{
3114 					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3115 					rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3116 					rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3117 				}
3118 
3119 				if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
3120 				{
3121 					//	Store the group id information.
3122 					_rtw_memcpy( pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN );
3123 					_rtw_memcpy( pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
3124 
3125 				}
3126 			}
3127 
3128 			//	Try to get the operation channel information
3129 
3130 			attr_contentlen = 0;
3131 			if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
3132 			{
3133 				DBG_871X( "[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4] );
3134 				pwdinfo->peer_operating_ch = operatingch_info[4];
3135 			}
3136 
3137 			//	Try to get the channel list information
3138 			if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len ) )
3139 			{
3140 				DBG_871X( "[%s] channel list attribute found, len = %d\n", __FUNCTION__,  pwdinfo->channel_list_attr_len );
3141 
3142 				peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
3143 				ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
3144 
3145 				if( ch_num_inclusioned == 0)
3146 				{
3147 					DBG_871X( "[%s] No common channel in channel list!\n", __FUNCTION__ );
3148 					result = P2P_STATUS_FAIL_NO_COMMON_CH;
3149 					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
3150 					break;
3151 				}
3152 
3153 				if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
3154 				{
3155 					if ( !rtw_p2p_is_channel_list_ok( pwdinfo->operating_channel,
3156 													ch_list_inclusioned, ch_num_inclusioned) )
3157 					{
3158 #ifdef CONFIG_CONCURRENT_MODE
3159 						if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3160 						{
3161 							DBG_871X( "[%s] desired channel NOT Found!\n", __FUNCTION__ );
3162 							result = P2P_STATUS_FAIL_NO_COMMON_CH;
3163 							rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
3164 							break;
3165 						}
3166 						else
3167 #endif //CONFIG_CONCURRENT_MODE
3168 						{
3169 							u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
3170 							attr_contentlen = 0;
3171 
3172 							if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) )
3173 							{
3174 								peer_operating_ch = operatingch_info[4];
3175 							}
3176 
3177 							if ( rtw_p2p_is_channel_list_ok( peer_operating_ch,
3178 															ch_list_inclusioned, ch_num_inclusioned) )
3179 							{
3180 								/**
3181 								 *	Change our operating channel as peer's for compatibility.
3182 								 */
3183 								pwdinfo->operating_channel = peer_operating_ch;
3184 								DBG_871X( "[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);
3185 							}
3186 							else
3187 							{
3188 								// Take first channel of ch_list_inclusioned as operating channel
3189 								pwdinfo->operating_channel = ch_list_inclusioned[0];
3190 								DBG_871X( "[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);
3191 							}
3192 						}
3193 
3194 					}
3195 				}
3196 
3197 			}
3198 			else
3199 			{
3200 				DBG_871X( "[%s] channel list attribute not found!\n", __FUNCTION__);
3201 			}
3202 
3203 			//	Try to get the group id information if peer is GO
3204 			attr_contentlen = 0;
3205 			_rtw_memset( groupid, 0x00, 38 );
3206 			if ( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen) )
3207 			{
3208 				_rtw_memcpy( pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN );
3209 				_rtw_memcpy( pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN );
3210 			}
3211 
3212 			//Get the next P2P IE
3213 			p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3214 		}
3215 
3216 	}
3217 
3218 #ifdef CONFIG_WFD
3219 	//	Added by Albert 20111122
3220 	//	Try to get the TCP port information when receiving the negotiation response.
3221 	if ( rtw_get_wfd_ie( pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wfd_ie, &wfd_ielen ) )
3222 	{
3223 		u8	attr_content[ 10 ] = { 0x00 };
3224 		u32	attr_contentlen = 0;
3225 
3226 		DBG_8192C( "[%s] WFD IE Found!!\n", __FUNCTION__ );
3227 		rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
3228 		if ( attr_contentlen )
3229 		{
3230 			pwdinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );
3231 			DBG_8192C( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_rtsp_ctrlport );
3232 		}
3233 	}
3234 #endif // CONFIG_WFD
3235 
3236 	return( result );
3237 
3238 }
3239 
process_p2p_group_negotation_confirm(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)3240 u8 process_p2p_group_negotation_confirm( struct wifidirect_info *pwdinfo, u8 *pframe, uint len )
3241 {
3242 	u8 * ies;
3243 	u32 ies_len;
3244 	u8 * p2p_ie;
3245 	u32	p2p_ielen = 0;
3246 	u8	result = P2P_STATUS_SUCCESS;
3247 	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
3248 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3249 
3250 	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
3251 	while ( p2p_ie )	//	Found the P2P IE.
3252 	{
3253 		u8	attr_content = 0x00, operatingch_info[5] = { 0x00 };
3254 		u8	groupid[ 38 ] = { 0x00 };
3255 		u32	attr_contentlen = 0;
3256 
3257 		pwdinfo->negotiation_dialog_token = 1;
3258 		rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
3259 		if ( attr_contentlen == 1 )
3260 		{
3261 			DBG_871X( "[%s] Status = %d\n", __FUNCTION__, attr_content );
3262 			result = attr_content;
3263 
3264 			if ( attr_content == P2P_STATUS_SUCCESS )
3265 			{
3266 				u8	bcancelled = 0;
3267 
3268 				_cancel_timer( &pwdinfo->restore_p2p_state_timer, &bcancelled );
3269 
3270 				//	Commented by Albert 20100911
3271 				//	Todo: Need to handle the case which both Intents are the same.
3272 				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3273 				rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3274 				if ( ( pwdinfo->intent ) > ( pwdinfo->peer_intent >> 1 ) )
3275 				{
3276 					rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3277 				}
3278 				else if ( ( pwdinfo->intent ) < ( pwdinfo->peer_intent >> 1 ) )
3279 				{
3280 					rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3281 				}
3282 				else
3283 				{
3284 					//	Have to compare the Tie Breaker
3285 					if ( pwdinfo->peer_intent & 0x01 )
3286 					{
3287 						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3288 					}
3289 					else
3290 					{
3291 						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3292 					}
3293 				}
3294 
3295 #ifdef CONFIG_CONCURRENT_MODE
3296 				if ( check_buddy_fwstate(pwdinfo->padapter , _FW_LINKED ) )
3297 				{
3298 					//	Switch back to the AP channel soon.
3299 					_set_timer( &pwdinfo->ap_p2p_switch_timer, 100 );
3300 				}
3301 #endif
3302 			}
3303 			else
3304 			{
3305 				rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3306 				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
3307 				break;
3308 			}
3309 		}
3310 
3311 		//	Try to get the group id information
3312 		attr_contentlen = 0;
3313 		_rtw_memset( groupid, 0x00, 38 );
3314 		if ( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen) )
3315 		{
3316 			DBG_871X( "[%s] Ssid = %s, ssidlen = %zu\n", __FUNCTION__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]) );
3317 			_rtw_memcpy( pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN );
3318 			_rtw_memcpy( pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN );
3319 		}
3320 
3321 		attr_contentlen = 0;
3322 		if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) )
3323 		{
3324 			DBG_871X( "[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4] );
3325 			pwdinfo->peer_operating_ch = operatingch_info[4];
3326 		}
3327 
3328 		//Get the next P2P IE
3329 		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3330 
3331 	}
3332 
3333 	return( result );
3334 }
3335 
process_p2p_presence_req(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)3336 u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
3337 {
3338 	u8 *frame_body;
3339 	u8 dialogToken=0;
3340 	u8 status = P2P_STATUS_SUCCESS;
3341 
3342 	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
3343 
3344 	dialogToken = frame_body[6];
3345 
3346 	//todo: check NoA attribute
3347 
3348 	issue_p2p_presence_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
3349 
3350 	return _TRUE;
3351 }
3352 
find_phase_handler(_adapter * padapter)3353 void find_phase_handler( _adapter*	padapter )
3354 {
3355 	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
3356 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
3357 	NDIS_802_11_SSID 	ssid;
3358 	_irqL				irqL;
3359 	u8					_status = 0;
3360 
3361 _func_enter_;
3362 
3363 	_rtw_memset((unsigned char*)&ssid, 0, sizeof(NDIS_802_11_SSID));
3364 	_rtw_memcpy(ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN );
3365 	ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
3366 
3367 	rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
3368 
3369 	_enter_critical_bh(&pmlmepriv->lock, &irqL);
3370 	_status = rtw_sitesurvey_cmd(padapter, &ssid, 1, NULL, 0);
3371 	_exit_critical_bh(&pmlmepriv->lock, &irqL);
3372 
3373 
3374 _func_exit_;
3375 }
3376 
3377 void p2p_concurrent_handler(  _adapter* padapter );
3378 
restore_p2p_state_handler(_adapter * padapter)3379 void restore_p2p_state_handler( _adapter*	padapter )
3380 {
3381 	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
3382 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
3383 
3384 _func_enter_;
3385 
3386 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3387 	{
3388 		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3389 	}
3390 
3391 #ifdef CONFIG_CONCURRENT_MODE
3392 	if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3393 	{
3394 		_adapter				*pbuddy_adapter = padapter->pbuddy_adapter;
3395 		struct mlme_priv		*pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
3396 		struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3397 
3398 		if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP))
3399 		{
3400 			set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
3401 
3402 			issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500);
3403 		}
3404 	}
3405 #endif
3406 
3407 	rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3408 
3409 	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
3410 	{
3411 #ifdef CONFIG_CONCURRENT_MODE
3412 		p2p_concurrent_handler( padapter );
3413 #else
3414 		//	In the P2P client mode, the driver should not switch back to its listen channel
3415 		//	because this P2P client should stay at the operating channel of P2P GO.
3416 		set_channel_bwmode( padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3417 #endif
3418 	}
3419 _func_exit_;
3420 }
3421 
pre_tx_invitereq_handler(_adapter * padapter)3422 void pre_tx_invitereq_handler( _adapter*	padapter )
3423 {
3424 	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
3425 	u8	val8 = 1;
3426 _func_enter_;
3427 
3428 	set_channel_bwmode(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3429 	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3430 	issue_probereq_p2p(padapter, NULL);
3431 	_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
3432 
3433 _func_exit_;
3434 }
3435 
pre_tx_provdisc_handler(_adapter * padapter)3436 void pre_tx_provdisc_handler( _adapter*	padapter )
3437 {
3438 	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
3439 	u8	val8 = 1;
3440 _func_enter_;
3441 
3442 	set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3443 	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3444 	issue_probereq_p2p(padapter, NULL);
3445 	_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
3446 
3447 _func_exit_;
3448 }
3449 
pre_tx_negoreq_handler(_adapter * padapter)3450 void pre_tx_negoreq_handler( _adapter*	padapter )
3451 {
3452 	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
3453 	u8	val8 = 1;
3454 _func_enter_;
3455 
3456 	set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3457 	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3458 	issue_probereq_p2p(padapter, NULL);
3459 	_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
3460 
3461 _func_exit_;
3462 }
3463 
3464 #ifdef CONFIG_CONCURRENT_MODE
p2p_concurrent_handler(_adapter * padapter)3465 void p2p_concurrent_handler( _adapter*	padapter )
3466 {
3467 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
3468 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
3469 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
3470 	//_adapter				*pbuddy_adapter = padapter->pbuddy_adapter;
3471 	//struct wifidirect_info	*pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
3472 	//struct mlme_priv		*pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
3473 	//struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3474 	u8					val8;
3475 _func_enter_;
3476 
3477 	if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
3478 	{
3479 		PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
3480 		struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3481 
3482 		pwdinfo->operating_channel = pbuddy_mlmeext->cur_channel;
3483 
3484 		if( pwdinfo->driver_interface == DRIVER_CFG80211 )
3485 		{
3486 			DBG_871X("%s, switch ch back to buddy's cur_channel=%d\n", __func__, pbuddy_mlmeext->cur_channel);
3487 
3488 			set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
3489 
3490 			if (check_buddy_fwstate(padapter, WIFI_FW_STATION_STATE))
3491 				issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500);
3492 		}
3493 		else if( pwdinfo->driver_interface == DRIVER_WEXT )
3494 		{
3495 			if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
3496 			{
3497 				//	Now, the driver stays on the AP's channel.
3498 				//	If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel.
3499 				if ( pwdinfo->ext_listen_period > 0 )
3500 				{
3501 					DBG_8192C( "[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period );
3502 
3503 					if ( pbuddy_mlmeext->cur_channel != pwdinfo->listen_channel )
3504 					{
3505 						//	Will switch to listen channel so that need to send the NULL data with PW bit to AP.
3506 						issue_nulldata(pbuddy_adapter, NULL, 1, 3, 500);
3507 						set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3508 					}
3509 
3510 					rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3511 					if(!check_buddy_mlmeinfo_state(padapter, WIFI_FW_AP_STATE) &&
3512 					((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE))
3513 					{
3514 						val8 = 1;
3515 						rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3516 					}
3517 					//	Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not.
3518 					_set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period );
3519 				}
3520 			}
3521 			else if ( rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) ||
3522 					rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) ||
3523 					( rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE ) ||
3524 					rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ) )
3525 			{
3526 				//	Now, the driver is in the listen state of P2P mode.
3527 				DBG_8192C( "[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval );
3528 
3529 				//	Commented by Albert 2012/11/01
3530 				//	If the AP's channel is the same as the listen channel, we should still be in the listen state
3531 				//	Other P2P device is still able to find this device out even this device is in the AP's channel.
3532 				//	So, configure this device to be able to receive the probe request frame and set it to listen state.
3533 				if ( pbuddy_mlmeext->cur_channel != pwdinfo->listen_channel )
3534 				{
3535 					set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
3536 					if (!check_buddy_mlmeinfo_state(padapter, WIFI_FW_AP_STATE) && ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE))
3537 					{
3538 						val8 = 0;
3539 						rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3540 					}
3541 					rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
3542 					issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500);
3543 				}
3544 
3545 				//	Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not.
3546 				_set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval );
3547 			}
3548 			else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
3549 			{
3550 				//	The driver had finished the P2P handshake successfully.
3551 				val8 = 0;
3552 				rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3553 				set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
3554 				issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500);
3555 			}
3556 			else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
3557 			{
3558 				val8 = 1;
3559 				set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3560 				rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3561 				issue_probereq_p2p(padapter, NULL);
3562 				_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
3563 			}
3564 			else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE)
3565 			{
3566 				val8 = 1;
3567 				set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3568 				rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3569 				issue_probereq_p2p(padapter, NULL);
3570 				_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
3571 			}
3572 			else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ ) && pwdinfo->invitereq_info.benable == _TRUE)
3573 			{
3574 				/*
3575 				val8 = 1;
3576 			set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3577 				rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3578 				issue_probereq_p2p(padapter, NULL);
3579 				_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
3580 				*/
3581 			}
3582 		}
3583 	}
3584 	else
3585 	{
3586 		set_channel_bwmode( padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3587 	}
3588 
3589 _func_exit_;
3590 }
3591 #endif
3592 
3593 #ifdef CONFIG_IOCTL_CFG80211
ro_ch_handler(_adapter * padapter)3594 static void ro_ch_handler(_adapter *padapter)
3595 {
3596 	struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
3597 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3598 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3599 	u8 ch, bw, offset;
3600 _func_enter_;
3601 
3602 	if (rtw_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) {
3603 		if (0)
3604 			DBG_871X(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
3605 				FUNC_ADPT_ARG(padapter), ch, bw, offset);
3606 	}
3607 	else if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->listen_channel) {
3608 		ch = pwdinfo->listen_channel;
3609 		bw = CHANNEL_WIDTH_20;
3610 		offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3611 		if (0)
3612 			DBG_871X(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n",
3613 				FUNC_ADPT_ARG(padapter), ch, bw, offset);
3614 	}
3615 	else {
3616 		ch = pcfg80211_wdinfo->restore_channel;
3617 		bw = CHANNEL_WIDTH_20;
3618 		offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3619 		if (0)
3620 			DBG_871X(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n",
3621 				FUNC_ADPT_ARG(padapter), ch, bw, offset);
3622 	}
3623 
3624 	set_channel_bwmode(padapter, ch, offset, bw);
3625 
3626 	rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3627 #ifdef CONFIG_DEBUG_CFG80211
3628 	DBG_871X("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
3629 #endif
3630 
3631 	pcfg80211_wdinfo->is_ro_ch = _FALSE;
3632 	pcfg80211_wdinfo->last_ro_ch_time = rtw_get_current_time();
3633 
3634 	DBG_871X("cfg80211_remain_on_channel_expired cookie:0x%llx, ch=%d, bw=%d, offset=%d\n"
3635 		, pcfg80211_wdinfo->remain_on_ch_cookie
3636 		, rtw_get_oper_ch(padapter), rtw_get_oper_bw(padapter), rtw_get_oper_choffset(padapter));
3637 
3638 	rtw_cfg80211_remain_on_channel_expired(padapter,
3639 		pcfg80211_wdinfo->remain_on_ch_cookie,
3640 		&pcfg80211_wdinfo->remain_on_ch_channel,
3641 		pcfg80211_wdinfo->remain_on_ch_type, GFP_KERNEL);
3642 
3643 _func_exit_;
3644 }
3645 
ro_ch_timer_process(void * FunctionContext)3646 static void ro_ch_timer_process (void *FunctionContext)
3647 {
3648 	_adapter *adapter = (_adapter *)FunctionContext;
3649 	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
3650 
3651 	//printk("%s \n", __FUNCTION__);
3652 
3653 #ifdef	CONFIG_CONCURRENT_MODE
3654 	ATOMIC_SET(&pwdev_priv->ro_ch_to, 1);
3655 #endif
3656 
3657 	p2p_protocol_wk_cmd( adapter, P2P_RO_CH_WK);
3658 }
3659 
rtw_change_p2pie_op_ch(_adapter * padapter,const u8 * frame_body,u32 len,u8 ch)3660 static void rtw_change_p2pie_op_ch(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
3661 {
3662 	u8 *ies, *p2p_ie;
3663 	u32 ies_len, p2p_ielen;
3664 	PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
3665 	struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3666 
3667 	ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3668 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3669 
3670 	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
3671 
3672 	while ( p2p_ie ) {
3673 		u32	attr_contentlen = 0;
3674 		u8 *pattr = NULL;
3675 
3676 		//Check P2P_ATTR_OPERATING_CH
3677 		attr_contentlen = 0;
3678 		pattr = NULL;
3679 		if((pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint*)&attr_contentlen))!=NULL)
3680 		{
3681 			*(pattr+4) = ch;
3682 		}
3683 
3684 		//Get the next P2P IE
3685 		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3686 	}
3687 }
3688 
rtw_change_p2pie_ch_list(_adapter * padapter,const u8 * frame_body,u32 len,u8 ch)3689 static void rtw_change_p2pie_ch_list(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
3690 {
3691 	u8 *ies, *p2p_ie;
3692 	u32 ies_len, p2p_ielen;
3693 	PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
3694 	struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3695 
3696 	ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3697 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3698 
3699 	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
3700 
3701 	while (p2p_ie) {
3702 		u32	attr_contentlen = 0;
3703 		u8 *pattr = NULL;
3704 
3705 		//Check P2P_ATTR_CH_LIST
3706 		if ((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint*)&attr_contentlen))!=NULL) {
3707 			int i;
3708 			u32 num_of_ch;
3709 			u8 *pattr_temp = pattr + 3 ;
3710 
3711 			attr_contentlen -= 3;
3712 
3713 			while (attr_contentlen>0) {
3714 				num_of_ch = *(pattr_temp+1);
3715 
3716 				for(i=0; i<num_of_ch; i++)
3717 					*(pattr_temp+2+i) = ch;
3718 
3719 				pattr_temp += (2+num_of_ch);
3720 				attr_contentlen -= (2+num_of_ch);
3721 			}
3722 		}
3723 
3724 		//Get the next P2P IE
3725 		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3726 	}
3727 }
3728 
rtw_chk_p2pie_ch_list_with_buddy(_adapter * padapter,const u8 * frame_body,u32 len)3729 static bool rtw_chk_p2pie_ch_list_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
3730 {
3731 	bool fit = _FALSE;
3732 #ifdef CONFIG_CONCURRENT_MODE
3733 	u8 *ies, *p2p_ie;
3734 	u32 ies_len, p2p_ielen;
3735 	PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
3736 	struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3737 	u8 buddy_ch = pbuddy_mlmeext->cur_channel;
3738 
3739 	ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3740 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3741 
3742 	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
3743 
3744 	while (p2p_ie) {
3745 		u32	attr_contentlen = 0;
3746 		u8 *pattr = NULL;
3747 
3748 		//Check P2P_ATTR_CH_LIST
3749 		if ((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint*)&attr_contentlen))!=NULL) {
3750 			int i;
3751 			u32 num_of_ch;
3752 			u8 *pattr_temp = pattr + 3 ;
3753 
3754 			attr_contentlen -= 3;
3755 
3756 			while (attr_contentlen>0) {
3757 				num_of_ch = *(pattr_temp+1);
3758 
3759 				for(i=0; i<num_of_ch; i++) {
3760 					if (*(pattr_temp+2+i) == buddy_ch) {
3761 						DBG_871X(FUNC_ADPT_FMT" ch_list fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), buddy_ch);
3762 						fit = _TRUE;
3763 						break;
3764 					}
3765 				}
3766 
3767 				pattr_temp += (2+num_of_ch);
3768 				attr_contentlen -= (2+num_of_ch);
3769 			}
3770 		}
3771 
3772 		//Get the next P2P IE
3773 		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3774 	}
3775 #endif
3776 	return fit;
3777 }
3778 
rtw_chk_p2pie_op_ch_with_buddy(_adapter * padapter,const u8 * frame_body,u32 len)3779 static bool rtw_chk_p2pie_op_ch_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
3780 {
3781 	bool fit = _FALSE;
3782 #ifdef CONFIG_CONCURRENT_MODE
3783 	u8 *ies, *p2p_ie;
3784 	u32 ies_len, p2p_ielen;
3785 	PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
3786 	struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3787 	u8 buddy_ch = pbuddy_mlmeext->cur_channel;
3788 
3789 	ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3790 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3791 
3792 	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
3793 
3794 	while (p2p_ie) {
3795 		u32	attr_contentlen = 0;
3796 		u8 *pattr = NULL;
3797 
3798 		//Check P2P_ATTR_OPERATING_CH
3799 		attr_contentlen = 0;
3800 		pattr = NULL;
3801 		if((pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint*)&attr_contentlen))!=NULL) {
3802 			if (*(pattr+4) == buddy_ch) {
3803 				DBG_871X(FUNC_ADPT_FMT" op_ch fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), buddy_ch);
3804 				fit = _TRUE;
3805 				break;
3806 			}
3807 		}
3808 
3809 		//Get the next P2P IE
3810 		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3811 	}
3812 #endif
3813 	return fit;
3814 }
3815 
rtw_cfg80211_adjust_p2pie_channel(_adapter * padapter,const u8 * frame_body,u32 len)3816 static void rtw_cfg80211_adjust_p2pie_channel(_adapter *padapter, const u8 *frame_body, u32 len)
3817 {
3818 #ifdef CONFIG_CONCURRENT_MODE
3819 	u8 *ies, *p2p_ie;
3820 	u32 ies_len, p2p_ielen;
3821 	PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
3822 	struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
3823 
3824 	ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3825 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3826 
3827 	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
3828 
3829 	while ( p2p_ie )
3830 	{
3831 		u32	attr_contentlen = 0;
3832 		u8 *pattr = NULL;
3833 
3834 		//Check P2P_ATTR_CH_LIST
3835 		if((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint*)&attr_contentlen))!=NULL)
3836 		{
3837 			int i;
3838 			u32 num_of_ch;
3839 			u8 *pattr_temp = pattr + 3 ;
3840 
3841 			attr_contentlen -= 3;
3842 
3843 			while(attr_contentlen>0)
3844 			{
3845 				num_of_ch = *(pattr_temp+1);
3846 
3847 				for(i=0; i<num_of_ch; i++)
3848 					*(pattr_temp+2+i) = pbuddy_mlmeext->cur_channel;//forcing to the same channel
3849 
3850 				pattr_temp += (2+num_of_ch);
3851 				attr_contentlen -= (2+num_of_ch);
3852 			}
3853 		}
3854 
3855 		//Check P2P_ATTR_OPERATING_CH
3856 		attr_contentlen = 0;
3857 		pattr = NULL;
3858 		if((pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint*)&attr_contentlen))!=NULL)
3859 		{
3860 			*(pattr+4) = pbuddy_mlmeext->cur_channel;//forcing to the same channel
3861 		}
3862 
3863 		//Get the next P2P IE
3864 		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3865 
3866 	}
3867 
3868 #endif
3869 }
3870 
3871 #ifdef CONFIG_WFD
rtw_append_wfd_ie(_adapter * padapter,u8 * buf,u32 * len)3872 void rtw_append_wfd_ie(_adapter *padapter, u8 *buf, u32* len)
3873 {
3874 	unsigned char	*frame_body;
3875 	u8 category, action, OUI_Subtype, dialogToken=0;
3876 	u32	wfdielen = 0;
3877 	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
3878 
3879 	frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));
3880 	category = frame_body[0];
3881 
3882 	if(category == RTW_WLAN_CATEGORY_PUBLIC)
3883 	{
3884 		action = frame_body[1];
3885 		if (action == ACT_PUBLIC_VENDOR
3886 			&& _rtw_memcmp(frame_body+2, P2P_OUI, 4) == _TRUE
3887 		)
3888 		{
3889 			OUI_Subtype = frame_body[6];
3890 			dialogToken = frame_body[7];
3891 			switch( OUI_Subtype )//OUI Subtype
3892 			{
3893 				case P2P_GO_NEGO_REQ:
3894 				{
3895 					wfdielen = build_nego_req_wfd_ie( &padapter->wdinfo, buf + ( *len ) );
3896 					(*len) += wfdielen;
3897 					break;
3898 				}
3899 				case P2P_GO_NEGO_RESP:
3900 				{
3901 					wfdielen = build_nego_resp_wfd_ie( &padapter->wdinfo, buf + ( *len ) );
3902 					(*len) += wfdielen;
3903 					break;
3904 				}
3905 				case P2P_GO_NEGO_CONF:
3906 				{
3907 					wfdielen = build_nego_confirm_wfd_ie( &padapter->wdinfo, buf + ( *len ) );
3908 					(*len) += wfdielen;
3909 					break;
3910 				}
3911 				case P2P_INVIT_REQ:
3912 				{
3913 					wfdielen = build_invitation_req_wfd_ie( &padapter->wdinfo, buf + ( *len ) );
3914 					(*len) += wfdielen;
3915 					break;
3916 				}
3917 				case P2P_INVIT_RESP:
3918 				{
3919 					wfdielen = build_invitation_resp_wfd_ie( &padapter->wdinfo, buf + ( *len ) );
3920 					(*len) += wfdielen;
3921 					break;
3922 				}
3923 				case P2P_DEVDISC_REQ:
3924 					break;
3925 				case P2P_DEVDISC_RESP:
3926 
3927 					break;
3928 				case P2P_PROVISION_DISC_REQ:
3929 				{
3930 					wfdielen = build_provdisc_req_wfd_ie( &padapter->wdinfo, buf + ( *len ) );
3931 					(*len) += wfdielen;
3932 					break;
3933 				}
3934 				case P2P_PROVISION_DISC_RESP:
3935 				{
3936 					wfdielen = build_provdisc_resp_wfd_ie( &padapter->wdinfo, buf + ( *len ) );
3937 					(*len) += wfdielen;
3938 					break;
3939 				}
3940 				default:
3941 
3942 					break;
3943 			}
3944 
3945 		}
3946 
3947 	}
3948 	else if(category == RTW_WLAN_CATEGORY_P2P)
3949 	{
3950 		OUI_Subtype = frame_body[5];
3951 		dialogToken = frame_body[6];
3952 
3953 #ifdef CONFIG_DEBUG_CFG80211
3954 		DBG_871X("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
3955 					cpu_to_be32( *( ( u32* ) ( frame_body + 1 ) ) ), OUI_Subtype, dialogToken);
3956 #endif
3957 
3958 		switch(OUI_Subtype)
3959 		{
3960 			case P2P_NOTICE_OF_ABSENCE:
3961 
3962 				break;
3963 			case P2P_PRESENCE_REQUEST:
3964 
3965 				break;
3966 			case P2P_PRESENCE_RESPONSE:
3967 
3968 				break;
3969 			case P2P_GO_DISC_REQUEST:
3970 
3971 				break;
3972 			default:
3973 
3974 				break;
3975 		}
3976 
3977 	}
3978 	else
3979 	{
3980 		DBG_871X("%s, action frame category=%d\n", __func__, category);
3981 		//is_p2p_frame = (-1);
3982 	}
3983 
3984 	return;
3985 }
3986 #endif
3987 
dump_p2p_attr_ch_list(u8 * p2p_ie,uint p2p_ielen,u8 * buf,u32 buf_len)3988 u8 *dump_p2p_attr_ch_list(u8 *p2p_ie, uint p2p_ielen, u8 *buf, u32 buf_len)
3989 {
3990 	uint attr_contentlen = 0;
3991 	u8 *pattr = NULL;
3992 	int w_sz = 0;
3993 	u8 ch_cnt = 0;
3994 	u8 ch_list[40];
3995 	bool continuous = _FALSE;
3996 
3997 	if ((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, &attr_contentlen))!=NULL) {
3998 		int i, j;
3999 		u32 num_of_ch;
4000 		u8 *pattr_temp = pattr + 3 ;
4001 
4002 		attr_contentlen -= 3;
4003 
4004 		_rtw_memset(ch_list, 0, 40);
4005 
4006 		while (attr_contentlen>0) {
4007 			num_of_ch = *(pattr_temp+1);
4008 
4009 			for(i=0; i<num_of_ch; i++) {
4010 				for (j=0;j<ch_cnt;j++) {
4011 					if (ch_list[j] == *(pattr_temp+2+i))
4012 						break;
4013 				}
4014 				if (j>=ch_cnt)
4015 					ch_list[ch_cnt++] = *(pattr_temp+2+i);
4016 
4017 			}
4018 
4019 			pattr_temp += (2+num_of_ch);
4020 			attr_contentlen -= (2+num_of_ch);
4021 		}
4022 
4023 		for (j=0;j<ch_cnt;j++) {
4024 			if (j == 0) {
4025 				w_sz += snprintf(buf+w_sz, buf_len-w_sz, "%u", ch_list[j]);
4026 			} else if (ch_list[j] - ch_list[j-1] != 1) {
4027 				w_sz += snprintf(buf+w_sz, buf_len-w_sz, ", %u", ch_list[j]);
4028 			} else if (j != ch_cnt-1 && ch_list[j+1] - ch_list[j] == 1) {
4029 				/* empty */
4030 			} else {
4031 				w_sz += snprintf(buf+w_sz, buf_len-w_sz, "-%u", ch_list[j]);
4032 			}
4033 		}
4034 	}
4035 	return buf;
4036 }
4037 
4038 /*
4039  * return _TRUE if requester is GO, _FALSE if responder is GO
4040  */
rtw_p2p_nego_intent_compare(u8 req,u8 resp)4041 bool rtw_p2p_nego_intent_compare(u8 req, u8 resp)
4042 {
4043 	if (req>>1 == resp >>1)
4044 		return  req&0x01 ? _TRUE : _FALSE;
4045 	else if (req>>1 > resp>>1)
4046 		return _TRUE;
4047 	else
4048 		return _FALSE;
4049 }
4050 
rtw_p2p_check_frames(_adapter * padapter,const u8 * buf,u32 len,u8 tx)4051 int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx)
4052 {
4053 	int is_p2p_frame = (-1);
4054 	unsigned char	*frame_body;
4055 	u8 category, action, OUI_Subtype, dialogToken=0;
4056 	u8 *p2p_ie = NULL;
4057 	uint p2p_ielen = 0;
4058 	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
4059 	int status = -1;
4060 	u8 ch_list_buf[128] = {'\0'};
4061 	int op_ch = -1;
4062 	int listen_ch = -1;
4063 	u8 intent = 0;
4064 
4065 	frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));
4066 	category = frame_body[0];
4067 	//just for check
4068 	if(category == RTW_WLAN_CATEGORY_PUBLIC)
4069 	{
4070 		action = frame_body[1];
4071 		if (action == ACT_PUBLIC_VENDOR
4072 			&& _rtw_memcmp(frame_body+2, P2P_OUI, 4) == _TRUE
4073 		)
4074 		{
4075 			OUI_Subtype = frame_body[6];
4076 			dialogToken = frame_body[7];
4077 			is_p2p_frame = OUI_Subtype;
4078 			#ifdef CONFIG_DEBUG_CFG80211
4079 			DBG_871X("ACTION_CATEGORY_PUBLIC: ACT_PUBLIC_VENDOR, OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
4080 				cpu_to_be32( *( ( u32* ) ( frame_body + 2 ) ) ), OUI_Subtype, dialogToken);
4081 			#endif
4082 
4083 			p2p_ie = rtw_get_p2p_ie(
4084 				(u8 *)buf+sizeof(struct rtw_ieee80211_hdr_3addr)+_PUBLIC_ACTION_IE_OFFSET_,
4085 				len-sizeof(struct rtw_ieee80211_hdr_3addr)-_PUBLIC_ACTION_IE_OFFSET_,
4086 				NULL, &p2p_ielen);
4087 
4088 			switch( OUI_Subtype )//OUI Subtype
4089 			{
4090 				u8 *cont;
4091 				uint cont_len;
4092 				case P2P_GO_NEGO_REQ:
4093 				{
4094 					struct rtw_wdev_nego_info* nego_info = &pwdev_priv->nego_info;
4095 
4096 					if (tx) {
4097 						#ifdef CONFIG_DRV_ISSUE_PROV_REQ // IOT FOR S2
4098 						if(pwdev_priv->provdisc_req_issued == _FALSE)
4099 							rtw_cfg80211_issue_p2p_provision_request(padapter, buf, len);
4100 						#endif //CONFIG_DRV_ISSUE_PROV_REQ
4101 
4102 						//pwdev_priv->provdisc_req_issued = _FALSE;
4103 
4104 						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4105 						if(check_buddy_fwstate(padapter, _FW_LINKED))
4106 							rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr));
4107 						#endif
4108 					}
4109 
4110 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
4111 						op_ch = *(cont+4);
4112 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, NULL, &cont_len)))
4113 						listen_ch = *(cont+4);
4114 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len)))
4115 						intent = *cont;
4116 
4117 					if (nego_info->token != dialogToken)
4118 						rtw_wdev_nego_info_init(nego_info);
4119 
4120 					_rtw_memcpy(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN);
4121 					nego_info->active = tx ? 1 : 0;
4122 					nego_info->token = dialogToken;
4123 					nego_info->req_op_ch = op_ch;
4124 					nego_info->req_listen_ch = listen_ch;
4125 					nego_info->req_intent = intent;
4126 					nego_info->state = 0;
4127 
4128 					dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4129 					DBG_871X("RTW_%s:P2P_GO_NEGO_REQ, dialogToken=%d, intent:%u%s, listen_ch:%d, op_ch:%d, ch_list:%s\n",
4130 							(tx==_TRUE)?"Tx":"Rx", dialogToken, (intent>>1), intent&0x1 ? "+" : "-", listen_ch, op_ch, ch_list_buf);
4131 
4132 					if (!tx) {
4133 						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4134 						if(check_buddy_fwstate(padapter, _FW_LINKED)
4135 							&& rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE)
4136 						{
4137 							DBG_871X(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
4138 							rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0);
4139 						}
4140 						#endif
4141 					}
4142 
4143 					break;
4144 				}
4145 				case P2P_GO_NEGO_RESP:
4146 				{
4147 					struct rtw_wdev_nego_info* nego_info = &pwdev_priv->nego_info;
4148 
4149 					if (tx) {
4150 						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4151 						if(check_buddy_fwstate(padapter, _FW_LINKED))
4152 							rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr));
4153 						#endif
4154 					}
4155 
4156 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
4157 						op_ch = *(cont+4);
4158 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len)))
4159 						intent = *cont;
4160 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len)))
4161 						status = *cont;
4162 
4163 					if (nego_info->token == dialogToken && nego_info->state == 0
4164 						&& _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE
4165 					) {
4166 						nego_info->status = (status==-1) ? 0xff : status;
4167 						nego_info->rsp_op_ch= op_ch;
4168 						nego_info->rsp_intent = intent;
4169 						nego_info->state = 1;
4170 						if (status != 0)
4171 							nego_info->token = 0; /* init */
4172 					}
4173 
4174 					dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4175 					DBG_871X("RTW_%s:P2P_GO_NEGO_RESP, dialogToken=%d, intent:%u%s, status:%d, op_ch:%d, ch_list:%s\n",
4176 							(tx==_TRUE)?"Tx":"Rx", dialogToken, (intent>>1), intent&0x1 ? "+" : "-", status, op_ch, ch_list_buf);
4177 
4178 					if (!tx) {
4179 						pwdev_priv->provdisc_req_issued = _FALSE;
4180 						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4181 						if(check_buddy_fwstate(padapter, _FW_LINKED)
4182 							&& rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE)
4183 						{
4184 							DBG_871X(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
4185 							rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0);
4186 						}
4187 						#endif
4188 					}
4189 
4190 					break;
4191 				}
4192 				case P2P_GO_NEGO_CONF:
4193 				{
4194 					struct rtw_wdev_nego_info* nego_info = &pwdev_priv->nego_info;
4195 					bool is_go = _FALSE;
4196 
4197 					if (tx) {
4198 						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4199 						if(check_buddy_fwstate(padapter, _FW_LINKED))
4200 							rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr));
4201 						#endif
4202 					}
4203 
4204 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
4205 						op_ch = *(cont+4);
4206 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len)))
4207 						status = *cont;
4208 
4209 					if (nego_info->token == dialogToken && nego_info->state == 1
4210 						&& _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE
4211 					) {
4212 						nego_info->status = (status==-1) ? 0xff : status;
4213 						nego_info->conf_op_ch = (op_ch==-1) ? 0 : op_ch;
4214 						nego_info->state = 2;
4215 
4216 						if (status == 0) {
4217 							if (rtw_p2p_nego_intent_compare(nego_info->req_intent, nego_info->rsp_intent) ^ !tx)
4218 								is_go = _TRUE;
4219 						}
4220 
4221 						nego_info->token = 0; /* init */
4222 					}
4223 
4224 					dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4225 					DBG_871X("RTW_%s:P2P_GO_NEGO_CONF, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n",
4226 						(tx==_TRUE)?"Tx":"Rx", dialogToken, status, op_ch, ch_list_buf);
4227 
4228 					if (!tx) {
4229 					}
4230 
4231 					break;
4232 				}
4233 				case P2P_INVIT_REQ:
4234 				{
4235 					struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
4236 					int flags = -1;
4237 
4238 					if (tx) {
4239 						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4240 						if(check_buddy_fwstate(padapter, _FW_LINKED))
4241 							rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr));
4242 						#endif
4243 					}
4244 
4245 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len)))
4246 						flags = *cont;
4247 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
4248 						op_ch = *(cont+4);
4249 
4250 					if (invit_info->token != dialogToken)
4251 						rtw_wdev_invit_info_init(invit_info);
4252 
4253 					_rtw_memcpy(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN);
4254 					invit_info->active = tx ? 1 : 0;
4255 					invit_info->token = dialogToken;
4256 					invit_info->flags = (flags==-1) ? 0x0 : flags;
4257 					invit_info->req_op_ch= op_ch;
4258 					invit_info->state = 0;
4259 
4260 					dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4261 					DBG_871X("RTW_%s:P2P_INVIT_REQ, dialogToken=%d, flags:0x%02x, op_ch:%d, ch_list:%s\n",
4262 							(tx==_TRUE)?"Tx":"Rx", dialogToken, flags, op_ch, ch_list_buf);
4263 
4264 					if (!tx) {
4265 						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4266 						if(check_buddy_fwstate(padapter, _FW_LINKED)) {
4267 							if (op_ch != -1 && rtw_chk_p2pie_op_ch_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
4268 								DBG_871X(FUNC_ADPT_FMT" op_ch:%u has no intersect with buddy\n", FUNC_ADPT_ARG(padapter), op_ch);
4269 								rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0);
4270 							} else if (rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
4271 								DBG_871X(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
4272 								rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0);
4273 							}
4274 						}
4275 						#endif
4276 					}
4277 
4278 					break;
4279 				}
4280 				case P2P_INVIT_RESP:
4281 				{
4282 					struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
4283 
4284 					if (tx) {
4285 						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4286 						if(check_buddy_fwstate(padapter, _FW_LINKED))
4287 							rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr));
4288 						#endif
4289 					}
4290 
4291 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len)))
4292 					{
4293 #ifdef CONFIG_P2P_INVITE_IOT
4294 						if(tx && *cont==7)
4295 						{
4296 							DBG_871X("TX_P2P_INVITE_RESP, status is no common channel, change to unknown group\n");
4297 							*cont = 8; //unknow group status
4298 						}
4299 #endif //CONFIG_P2P_INVITE_IOT
4300 						status = *cont;
4301 					}
4302 					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
4303 						op_ch = *(cont+4);
4304 
4305 					if (invit_info->token == dialogToken && invit_info->state == 0
4306 						&& _rtw_memcmp(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE
4307 					) {
4308 						invit_info->status = (status==-1) ? 0xff : status;
4309 						invit_info->rsp_op_ch= op_ch;
4310 						invit_info->state = 1;
4311 						invit_info->token = 0; /* init */
4312 					}
4313 
4314 					dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4315 					DBG_871X("RTW_%s:P2P_INVIT_RESP, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n",
4316 							(tx==_TRUE)?"Tx":"Rx", dialogToken, status, op_ch, ch_list_buf);
4317 
4318 					if (!tx) {
4319 					}
4320 
4321 					break;
4322 				}
4323 				case P2P_DEVDISC_REQ:
4324 					DBG_871X("RTW_%s:P2P_DEVDISC_REQ, dialogToken=%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken);
4325 					break;
4326 				case P2P_DEVDISC_RESP:
4327 					cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
4328 					DBG_871X("RTW_%s:P2P_DEVDISC_RESP, dialogToken=%d, status:%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken, cont?*cont:-1);
4329 					break;
4330 				case P2P_PROVISION_DISC_REQ:
4331 				{
4332 					size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);
4333 					u8 *p2p_ie;
4334 					uint p2p_ielen = 0;
4335 					uint contentlen = 0;
4336 
4337 					DBG_871X("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken=%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken);
4338 
4339 					//if(tx)
4340 					{
4341 						pwdev_priv->provdisc_req_issued = _FALSE;
4342 
4343 						if( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)))
4344 						{
4345 
4346 							if(rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, NULL, &contentlen))
4347 							{
4348 								pwdev_priv->provdisc_req_issued = _FALSE;//case: p2p_client join p2p GO
4349 							}
4350 							else
4351 							{
4352 								#ifdef CONFIG_DEBUG_CFG80211
4353 								DBG_871X("provdisc_req_issued is _TRUE\n");
4354 								#endif //CONFIG_DEBUG_CFG80211
4355 								pwdev_priv->provdisc_req_issued = _TRUE;//case: p2p_devices connection before Nego req.
4356 							}
4357 
4358 						}
4359 					}
4360 				}
4361 					break;
4362 				case P2P_PROVISION_DISC_RESP:
4363 					DBG_871X("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken=%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken);
4364 					break;
4365 				default:
4366 					DBG_871X("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx==_TRUE)?"Tx":"Rx", OUI_Subtype, dialogToken);
4367 					break;
4368 			}
4369 
4370 		}
4371 
4372 	}
4373 	else if(category == RTW_WLAN_CATEGORY_P2P)
4374 	{
4375 		OUI_Subtype = frame_body[5];
4376 		dialogToken = frame_body[6];
4377 
4378 		#ifdef CONFIG_DEBUG_CFG80211
4379 		DBG_871X("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
4380 			cpu_to_be32( *( ( u32* ) ( frame_body + 1 ) ) ), OUI_Subtype, dialogToken);
4381 		#endif
4382 
4383 		is_p2p_frame = OUI_Subtype;
4384 
4385 		switch(OUI_Subtype)
4386 		{
4387 			case P2P_NOTICE_OF_ABSENCE:
4388 				DBG_871X("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken=%d\n", (tx==_TRUE)?"TX":"RX", dialogToken);
4389 				break;
4390 			case P2P_PRESENCE_REQUEST:
4391 				DBG_871X("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken=%d\n", (tx==_TRUE)?"TX":"RX", dialogToken);
4392 				break;
4393 			case P2P_PRESENCE_RESPONSE:
4394 				DBG_871X("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken=%d\n", (tx==_TRUE)?"TX":"RX", dialogToken);
4395 				break;
4396 			case P2P_GO_DISC_REQUEST:
4397 				DBG_871X("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken=%d\n", (tx==_TRUE)?"TX":"RX", dialogToken);
4398 				break;
4399 			default:
4400 				DBG_871X("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx==_TRUE)?"TX":"RX", OUI_Subtype, dialogToken);
4401 				break;
4402 		}
4403 
4404 	}
4405 	else
4406 	{
4407 		DBG_871X("RTW_%s:action frame category=%d\n", (tx==_TRUE)?"TX":"RX", category);
4408 	}
4409 
4410 	return is_p2p_frame;
4411 }
4412 
rtw_init_cfg80211_wifidirect_info(_adapter * padapter)4413 void rtw_init_cfg80211_wifidirect_info( _adapter*	padapter)
4414 {
4415 	struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
4416 
4417 	_rtw_memset(pcfg80211_wdinfo, 0x00, sizeof(struct cfg80211_wifidirect_info) );
4418 
4419 	_init_timer( &pcfg80211_wdinfo->remain_on_ch_timer, padapter->pnetdev, ro_ch_timer_process, padapter );
4420 }
4421 #endif //CONFIG_IOCTL_CFG80211
4422 
p2p_protocol_wk_hdl(_adapter * padapter,int intCmdType)4423 void p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType)
4424 {
4425 	struct wifidirect_info	*pwdinfo= &(padapter->wdinfo);
4426 
4427 _func_enter_;
4428 
4429 	switch(intCmdType)
4430 	{
4431 		case P2P_FIND_PHASE_WK:
4432 		{
4433 			find_phase_handler( padapter );
4434 			break;
4435 		}
4436 		case P2P_RESTORE_STATE_WK:
4437 		{
4438 			restore_p2p_state_handler( padapter );
4439 			break;
4440 		}
4441 		case P2P_PRE_TX_PROVDISC_PROCESS_WK:
4442 		{
4443 #ifdef CONFIG_CONCURRENT_MODE
4444 			if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4445 			{
4446 				p2p_concurrent_handler( padapter );
4447 			}
4448 			else
4449 			{
4450 				pre_tx_provdisc_handler( padapter );
4451 			}
4452 #else
4453 			pre_tx_provdisc_handler( padapter );
4454 #endif
4455 			break;
4456 		}
4457 		case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
4458 		{
4459 #ifdef CONFIG_CONCURRENT_MODE
4460 			if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4461 			{
4462 				p2p_concurrent_handler( padapter );
4463 			}
4464 			else
4465 			{
4466 				pre_tx_invitereq_handler( padapter );
4467 			}
4468 #else
4469 			pre_tx_invitereq_handler( padapter );
4470 #endif
4471 			break;
4472 		}
4473 		case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
4474 		{
4475 #ifdef CONFIG_CONCURRENT_MODE
4476 			if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
4477 			{
4478 				p2p_concurrent_handler( padapter );
4479 			}
4480 			else
4481 			{
4482 				pre_tx_negoreq_handler( padapter );
4483 			}
4484 #else
4485 			pre_tx_negoreq_handler( padapter );
4486 #endif
4487 			break;
4488 		}
4489 #ifdef CONFIG_P2P
4490 #ifdef CONFIG_CONCURRENT_MODE
4491 		case P2P_AP_P2P_CH_SWITCH_PROCESS_WK:
4492 		{
4493 			p2p_concurrent_handler( padapter );
4494 			break;
4495 		}
4496 #endif
4497 #endif
4498 #ifdef CONFIG_IOCTL_CFG80211
4499 		case P2P_RO_CH_WK:
4500 		{
4501 			ro_ch_handler( padapter );
4502 			break;
4503 		}
4504 #endif //CONFIG_IOCTL_CFG80211
4505 
4506 	}
4507 
4508 _func_exit_;
4509 }
4510 
process_p2p_cross_connect_ie(PADAPTER padapter,u8 * IEs,u32 IELength)4511 int process_p2p_cross_connect_ie(PADAPTER padapter, u8 *IEs, u32 IELength)
4512 {
4513 	int ret = _TRUE;
4514 	u8 * ies;
4515 	u32 ies_len;
4516 	u8 * p2p_ie;
4517 	u32	p2p_ielen = 0;
4518 	u8	p2p_attr[MAX_P2P_IE_LEN] = { 0x00 };// NoA length should be n*(13) + 2
4519 	u32	attr_contentlen = 0;
4520 
4521 	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo );
4522 
4523 _func_enter_;
4524 
4525 	if(IELength <= _BEACON_IE_OFFSET_)
4526 		return ret;
4527 
4528 	ies = IEs + _BEACON_IE_OFFSET_;
4529 	ies_len = IELength - _BEACON_IE_OFFSET_;
4530 
4531 	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen);
4532 
4533 	while(p2p_ie)
4534 	{
4535 		// Get P2P Manageability IE.
4536 		if(rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_MANAGEABILITY, p2p_attr, &attr_contentlen))
4537 		{
4538 			if ((p2p_attr[0]&(BIT(0)|BIT(1))) == 0x01) {
4539 				ret = _FALSE;
4540 			}
4541 			break;
4542 		}
4543 		//Get the next P2P IE
4544 		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
4545 	}
4546 
4547 _func_exit_;
4548 	return ret;
4549 }
4550 
4551 #ifdef CONFIG_P2P_PS
process_p2p_ps_ie(PADAPTER padapter,u8 * IEs,u32 IELength)4552 void process_p2p_ps_ie(PADAPTER padapter, u8 *IEs, u32 IELength)
4553 {
4554 	u8 * ies;
4555 	u32 ies_len;
4556 	u8 * p2p_ie;
4557 	u32	p2p_ielen = 0;
4558 	u8	noa_attr[MAX_P2P_IE_LEN] = { 0x00 };// NoA length should be n*(13) + 2
4559 	u32	attr_contentlen = 0;
4560 
4561 	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo );
4562 	u8	find_p2p = _FALSE, find_p2p_ps = _FALSE;
4563 	u8	noa_offset, noa_num, noa_index;
4564 
4565 _func_enter_;
4566 
4567 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4568 	{
4569 		return;
4570 	}
4571 #ifdef CONFIG_CONCURRENT_MODE
4572 	if(padapter->iface_type != IFACE_PORT0)
4573 		return;
4574 #endif
4575 	if(IELength <= _BEACON_IE_OFFSET_)
4576 		return;
4577 
4578 	ies = IEs + _BEACON_IE_OFFSET_;
4579 	ies_len = IELength - _BEACON_IE_OFFSET_;
4580 
4581 	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen);
4582 
4583 	while(p2p_ie)
4584 	{
4585 		find_p2p = _TRUE;
4586 		// Get Notice of Absence IE.
4587 		if(rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen))
4588 		{
4589 			find_p2p_ps = _TRUE;
4590 			noa_index = noa_attr[0];
4591 
4592 			if( (pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
4593 				(noa_index != pwdinfo->noa_index) )// if index change, driver should reconfigure related setting.
4594 			{
4595 				pwdinfo->noa_index = noa_index;
4596 				pwdinfo->opp_ps = noa_attr[1] >> 7;
4597 				pwdinfo->ctwindow = noa_attr[1] & 0x7F;
4598 
4599 				noa_offset = 2;
4600 				noa_num = 0;
4601 				// NoA length should be n*(13) + 2
4602 				if(attr_contentlen > 2)
4603 				{
4604 					while(noa_offset < attr_contentlen)
4605 					{
4606 						//_rtw_memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1);
4607 						pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
4608 						noa_offset += 1;
4609 
4610 						_rtw_memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
4611 						noa_offset += 4;
4612 
4613 						_rtw_memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
4614 						noa_offset += 4;
4615 
4616 						_rtw_memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
4617 						noa_offset += 4;
4618 
4619 						noa_num++;
4620 					}
4621 				}
4622 				pwdinfo->noa_num = noa_num;
4623 
4624 				if( pwdinfo->opp_ps == 1 )
4625 				{
4626 					pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
4627 					// driver should wait LPS for entering CTWindow
4628 					if(adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
4629 					{
4630 						p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
4631 					}
4632 				}
4633 				else if( pwdinfo->noa_num > 0 )
4634 				{
4635 					pwdinfo->p2p_ps_mode = P2P_PS_NOA;
4636 					p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
4637 				}
4638 				else if( pwdinfo->p2p_ps_mode > P2P_PS_NONE)
4639 				{
4640 					p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
4641 				}
4642 			}
4643 
4644 			break; // find target, just break.
4645 		}
4646 
4647 		//Get the next P2P IE
4648 		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
4649 
4650 	}
4651 
4652 	if(find_p2p == _TRUE)
4653 	{
4654 		if( (pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == _FALSE) )
4655 		{
4656 			p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
4657 		}
4658 	}
4659 
4660 _func_exit_;
4661 }
4662 
p2p_ps_wk_hdl(_adapter * padapter,u8 p2p_ps_state)4663 void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state)
4664 {
4665 	struct pwrctrl_priv		*pwrpriv = adapter_to_pwrctl(padapter);
4666 	struct wifidirect_info	*pwdinfo= &(padapter->wdinfo);
4667 
4668 _func_enter_;
4669 
4670 	// Pre action for p2p state
4671 	switch(p2p_ps_state)
4672 	{
4673 		case P2P_PS_DISABLE:
4674 			pwdinfo->p2p_ps_state = p2p_ps_state;
4675 
4676 			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4677 
4678 			pwdinfo->noa_index = 0;
4679 			pwdinfo->ctwindow = 0;
4680 			pwdinfo->opp_ps = 0;
4681 			pwdinfo->noa_num = 0;
4682 			pwdinfo->p2p_ps_mode = P2P_PS_NONE;
4683 			if(pwrpriv->bFwCurrentInPSMode == _TRUE)
4684 			{
4685 				if(pwrpriv->smart_ps == 0)
4686 				{
4687 					pwrpriv->smart_ps = 2;
4688 					rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));
4689 				}
4690 			}
4691 			break;
4692 		case P2P_PS_ENABLE:
4693 			if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
4694 				pwdinfo->p2p_ps_state = p2p_ps_state;
4695 
4696 				if( pwdinfo->ctwindow > 0 )
4697 				{
4698 					if(pwrpriv->smart_ps != 0)
4699 					{
4700 						pwrpriv->smart_ps = 0;
4701 						DBG_871X("%s(): Enter CTW, change SmartPS\n", __FUNCTION__);
4702 						rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));
4703 					}
4704 				}
4705 				rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4706 			}
4707 			break;
4708 		case P2P_PS_SCAN:
4709 		case P2P_PS_SCAN_DONE:
4710 		case P2P_PS_ALLSTASLEEP:
4711 			if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
4712 				pwdinfo->p2p_ps_state = p2p_ps_state;
4713 				rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4714 			}
4715 			break;
4716 		default:
4717 			break;
4718 	}
4719 
4720 _func_exit_;
4721 }
4722 
p2p_ps_wk_cmd(_adapter * padapter,u8 p2p_ps_state,u8 enqueue)4723 u8 p2p_ps_wk_cmd(_adapter*padapter, u8 p2p_ps_state, u8 enqueue)
4724 {
4725 	struct cmd_obj	*ph2c;
4726 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
4727 	struct wifidirect_info	*pwdinfo= &(padapter->wdinfo);
4728 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
4729 	u8	res = _SUCCESS;
4730 
4731 _func_enter_;
4732 
4733 	if ( rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
4734 #ifdef CONFIG_CONCURRENT_MODE
4735 		|| (padapter->iface_type != IFACE_PORT0)
4736 #endif
4737 		)
4738 	{
4739 		return res;
4740 	}
4741 
4742 	if(enqueue)
4743 	{
4744 		ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
4745 		if(ph2c==NULL){
4746 			res= _FAIL;
4747 			goto exit;
4748 		}
4749 
4750 		pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4751 		if(pdrvextra_cmd_parm==NULL){
4752 			rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
4753 			res= _FAIL;
4754 			goto exit;
4755 		}
4756 
4757 		pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
4758 		pdrvextra_cmd_parm->type = p2p_ps_state;
4759 		pdrvextra_cmd_parm->size = 0;
4760 		pdrvextra_cmd_parm->pbuf = NULL;
4761 
4762 		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
4763 
4764 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4765 	}
4766 	else
4767 	{
4768 		p2p_ps_wk_hdl(padapter, p2p_ps_state);
4769 	}
4770 
4771 exit:
4772 
4773 _func_exit_;
4774 
4775 	return res;
4776 
4777 }
4778 #endif // CONFIG_P2P_PS
4779 
reset_ch_sitesurvey_timer_process(void * FunctionContext)4780 static void reset_ch_sitesurvey_timer_process (void *FunctionContext)
4781 {
4782 	_adapter *adapter = (_adapter *)FunctionContext;
4783 	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
4784 
4785 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4786 		return;
4787 
4788 	DBG_871X( "[%s] In\n", __FUNCTION__ );
4789 	//	Reset the operation channel information
4790 	pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
4791 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
4792 	pwdinfo->rx_invitereq_info.operation_ch[1] = 0;
4793 	pwdinfo->rx_invitereq_info.operation_ch[2] = 0;
4794 	pwdinfo->rx_invitereq_info.operation_ch[3] = 0;
4795 #endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
4796 	pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
4797 }
4798 
reset_ch_sitesurvey_timer_process2(void * FunctionContext)4799 static void reset_ch_sitesurvey_timer_process2 (void *FunctionContext)
4800 {
4801 	_adapter *adapter = (_adapter *)FunctionContext;
4802 	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
4803 
4804 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4805 		return;
4806 
4807 	DBG_871X( "[%s] In\n", __FUNCTION__ );
4808 	//	Reset the operation channel information
4809 	pwdinfo->p2p_info.operation_ch[0] = 0;
4810 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
4811 	pwdinfo->p2p_info.operation_ch[1] = 0;
4812 	pwdinfo->p2p_info.operation_ch[2] = 0;
4813 	pwdinfo->p2p_info.operation_ch[3] = 0;
4814 #endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
4815 	pwdinfo->p2p_info.scan_op_ch_only = 0;
4816 }
4817 
restore_p2p_state_timer_process(void * FunctionContext)4818 static void restore_p2p_state_timer_process (void *FunctionContext)
4819 {
4820 	_adapter *adapter = (_adapter *)FunctionContext;
4821 	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
4822 
4823 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4824 		return;
4825 
4826 	p2p_protocol_wk_cmd( adapter, P2P_RESTORE_STATE_WK );
4827 }
4828 
pre_tx_scan_timer_process(void * FunctionContext)4829 static void pre_tx_scan_timer_process (void *FunctionContext)
4830 {
4831 	_adapter 							*adapter = (_adapter *) FunctionContext;
4832 	struct	wifidirect_info				*pwdinfo = &adapter->wdinfo;
4833 	_irqL							irqL;
4834 	struct mlme_priv					*pmlmepriv = &adapter->mlmepriv;
4835 	u8								_status = 0;
4836 
4837 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4838 		return;
4839 
4840 	_enter_critical_bh(&pmlmepriv->lock, &irqL);
4841 
4842 
4843 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
4844 	{
4845 		if ( _TRUE == pwdinfo->tx_prov_disc_info.benable )	//	the provision discovery request frame is trigger to send or not
4846 		{
4847 			p2p_protocol_wk_cmd( adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK );
4848 			//issue_probereq_p2p(adapter, NULL);
4849 			//_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
4850 		}
4851 	}
4852 	else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
4853 	{
4854 		if ( _TRUE == pwdinfo->nego_req_info.benable )
4855 		{
4856 			p2p_protocol_wk_cmd( adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK );
4857 		}
4858 	}
4859 	else if ( rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ ) )
4860 	{
4861 		if ( _TRUE == pwdinfo->invitereq_info.benable )
4862 		{
4863 			p2p_protocol_wk_cmd( adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK );
4864 		}
4865 	}
4866 	else
4867 	{
4868 		DBG_8192C( "[%s] p2p_state is %d, ignore!!\n", __FUNCTION__, rtw_p2p_state(pwdinfo) );
4869 	}
4870 
4871 	_exit_critical_bh(&pmlmepriv->lock, &irqL);
4872 }
4873 
find_phase_timer_process(void * FunctionContext)4874 static void find_phase_timer_process (void *FunctionContext)
4875 {
4876 	_adapter *adapter = (_adapter *)FunctionContext;
4877 	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
4878 
4879 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4880 		return;
4881 
4882 	adapter->wdinfo.find_phase_state_exchange_cnt++;
4883 
4884 	p2p_protocol_wk_cmd( adapter, P2P_FIND_PHASE_WK );
4885 }
4886 
4887 #ifdef CONFIG_CONCURRENT_MODE
ap_p2p_switch_timer_process(void * FunctionContext)4888 void ap_p2p_switch_timer_process (void *FunctionContext)
4889 {
4890 	_adapter *adapter = (_adapter *)FunctionContext;
4891 	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
4892 #ifdef CONFIG_IOCTL_CFG80211
4893 	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
4894 #endif
4895 
4896 	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4897 		return;
4898 
4899 #ifdef CONFIG_IOCTL_CFG80211
4900 	ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
4901 #endif
4902 
4903 	p2p_protocol_wk_cmd( adapter, P2P_AP_P2P_CH_SWITCH_PROCESS_WK );
4904 }
4905 #endif
4906 
reset_global_wifidirect_info(_adapter * padapter)4907 void reset_global_wifidirect_info( _adapter* padapter )
4908 {
4909 	struct wifidirect_info	*pwdinfo;
4910 
4911 	pwdinfo = &padapter->wdinfo;
4912 	pwdinfo->persistent_supported = 0;
4913 	pwdinfo->session_available = _TRUE;
4914 	pwdinfo->wfd_tdls_enable = 0;
4915 	pwdinfo->wfd_tdls_weaksec = _TRUE;
4916 }
4917 
4918 #ifdef CONFIG_WFD
rtw_init_wifi_display_info(_adapter * padapter)4919 int rtw_init_wifi_display_info(_adapter* padapter)
4920 {
4921 	int	res = _SUCCESS;
4922 	struct wifi_display_info *pwfd_info = &padapter->wfd_info;
4923 
4924 	// Used in P2P and TDLS
4925 	pwfd_info->rtsp_ctrlport = 554;
4926 	pwfd_info->peer_rtsp_ctrlport = 0;	//	Reset to 0
4927 	pwfd_info->wfd_enable = _FALSE;
4928 	pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
4929 	pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
4930 
4931 	// Used in P2P
4932 	pwfd_info->peer_session_avail = _TRUE;
4933 	pwfd_info->wfd_pc = _FALSE;
4934 
4935 	// Used in TDLS
4936 	_rtw_memset( pwfd_info->ip_address, 0x00, 4 );
4937 	_rtw_memset( pwfd_info->peer_ip_address, 0x00, 4 );
4938 	return res;
4939 
4940 }
4941 #endif //CONFIG_WFD
4942 
rtw_init_wifidirect_timers(_adapter * padapter)4943 void rtw_init_wifidirect_timers(_adapter* padapter)
4944 {
4945 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4946 
4947 	_init_timer( &pwdinfo->find_phase_timer, padapter->pnetdev, find_phase_timer_process, padapter );
4948 	_init_timer( &pwdinfo->restore_p2p_state_timer, padapter->pnetdev, restore_p2p_state_timer_process, padapter );
4949 	_init_timer( &pwdinfo->pre_tx_scan_timer, padapter->pnetdev, pre_tx_scan_timer_process, padapter );
4950 	_init_timer( &pwdinfo->reset_ch_sitesurvey, padapter->pnetdev, reset_ch_sitesurvey_timer_process, padapter );
4951 	_init_timer( &pwdinfo->reset_ch_sitesurvey2, padapter->pnetdev, reset_ch_sitesurvey_timer_process2, padapter );
4952 #ifdef CONFIG_CONCURRENT_MODE
4953 	_init_timer( &pwdinfo->ap_p2p_switch_timer, padapter->pnetdev, ap_p2p_switch_timer_process, padapter );
4954 #endif
4955 }
4956 
rtw_init_wifidirect_addrs(_adapter * padapter,u8 * dev_addr,u8 * iface_addr)4957 void rtw_init_wifidirect_addrs(_adapter* padapter, u8 *dev_addr, u8 *iface_addr)
4958 {
4959 #ifdef CONFIG_P2P
4960 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4961 
4962 	/*init device&interface address */
4963 	if (dev_addr) {
4964 		_rtw_memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
4965 	}
4966 	if (iface_addr) {
4967 		_rtw_memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
4968 	}
4969 #endif
4970 }
4971 
init_wifidirect_info(_adapter * padapter,enum P2P_ROLE role)4972 void init_wifidirect_info( _adapter* padapter, enum P2P_ROLE role)
4973 {
4974 	struct wifidirect_info	*pwdinfo;
4975 #ifdef CONFIG_WFD
4976 	struct wifi_display_info	*pwfd_info = &padapter->wfd_info;
4977 #endif
4978 #ifdef CONFIG_CONCURRENT_MODE
4979 	_adapter				*pbuddy_adapter = padapter->pbuddy_adapter;
4980 	struct wifidirect_info	*pbuddy_wdinfo = NULL;
4981 	struct mlme_priv		*pbuddy_mlmepriv = NULL;
4982 	struct mlme_ext_priv	*pbuddy_mlmeext = NULL;
4983 #endif
4984 
4985 	pwdinfo = &padapter->wdinfo;
4986 
4987 	pwdinfo->padapter = padapter;
4988 
4989 	//	1, 6, 11 are the social channel defined in the WiFi Direct specification.
4990 	pwdinfo->social_chan[0] = 1;
4991 	pwdinfo->social_chan[1] = 6;
4992 	pwdinfo->social_chan[2] = 11;
4993 	pwdinfo->social_chan[3] = 0;	//	channel 0 for scanning ending in site survey function.
4994 
4995 #ifdef CONFIG_CONCURRENT_MODE
4996 	if (pbuddy_adapter) {
4997 		pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
4998 		pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
4999 		pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
5000 	}
5001 
5002 	if ( ( check_buddy_fwstate(padapter, _FW_LINKED ) == _TRUE ) &&
5003 	      ( ( pbuddy_mlmeext->cur_channel == 1) || ( pbuddy_mlmeext->cur_channel == 6 ) || ( pbuddy_mlmeext->cur_channel == 11 ) )
5004 	   )
5005 	{
5006 		//	Use the AP's channel as the listen channel
5007 		//	This will avoid the channel switch between AP's channel and listen channel.
5008 		pwdinfo->listen_channel = pbuddy_mlmeext->cur_channel;
5009 	}
5010 	else
5011 #endif //CONFIG_CONCURRENT_MODE
5012 	{
5013 		//	Use the channel 11 as the listen channel
5014 		pwdinfo->listen_channel = 11;
5015 	}
5016 
5017 	if (role == P2P_ROLE_DEVICE)
5018 	{
5019 		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
5020 		#ifdef CONFIG_CONCURRENT_MODE
5021 		if ( check_buddy_fwstate(padapter, _FW_LINKED ) == _TRUE )
5022 		{
5023 			rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
5024 		}
5025 		else
5026 		#endif
5027 		{
5028 			rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
5029 		}
5030 		pwdinfo->intent = 1;
5031 		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
5032 	}
5033 	else if (role == P2P_ROLE_CLIENT)
5034 	{
5035 		rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
5036 		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
5037 		pwdinfo->intent = 1;
5038 		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
5039 	}
5040 	else if (role == P2P_ROLE_GO)
5041 	{
5042 		rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
5043 		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
5044 		pwdinfo->intent = 15;
5045 		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
5046 	}
5047 
5048 //	Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 )
5049 	pwdinfo->support_rate[0] = 0x8c;	//	6(B)
5050 	pwdinfo->support_rate[1] = 0x92;	//	9(B)
5051 	pwdinfo->support_rate[2] = 0x18;	//	12
5052 	pwdinfo->support_rate[3] = 0x24;	//	18
5053 	pwdinfo->support_rate[4] = 0x30;	//	24
5054 	pwdinfo->support_rate[5] = 0x48;	//	36
5055 	pwdinfo->support_rate[6] = 0x60;	//	48
5056 	pwdinfo->support_rate[7] = 0x6c;	//	54
5057 
5058 	_rtw_memcpy( ( void* ) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7 );
5059 
5060 	_rtw_memset( pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN );
5061 	pwdinfo->device_name_len = 0;
5062 
5063 	_rtw_memset( &pwdinfo->invitereq_info, 0x00, sizeof( struct tx_invite_req_info ) );
5064 	pwdinfo->invitereq_info.token = 3;	//	Token used for P2P invitation request frame.
5065 
5066 	_rtw_memset( &pwdinfo->inviteresp_info, 0x00, sizeof( struct tx_invite_resp_info ) );
5067 	pwdinfo->inviteresp_info.token = 0;
5068 
5069 	pwdinfo->profileindex = 0;
5070 	_rtw_memset( &pwdinfo->profileinfo[ 0 ], 0x00, sizeof( struct profile_info ) * P2P_MAX_PERSISTENT_GROUP_NUM );
5071 
5072 	rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
5073 
5074 	pwdinfo->listen_dwell = ( u8 ) (( rtw_get_current_time() % 3 ) + 1);
5075 	//DBG_8192C( "[%s] listen_dwell time is %d00ms\n", __FUNCTION__, pwdinfo->listen_dwell );
5076 
5077 	_rtw_memset( &pwdinfo->tx_prov_disc_info, 0x00, sizeof( struct tx_provdisc_req_info ) );
5078 	pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
5079 
5080 	_rtw_memset( &pwdinfo->nego_req_info, 0x00, sizeof( struct tx_nego_req_info ) );
5081 
5082 	pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
5083 	pwdinfo->negotiation_dialog_token = 1;
5084 
5085 	_rtw_memset( pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN );
5086 	pwdinfo->nego_ssidlen = 0;
5087 
5088 	pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
5089 #ifdef CONFIG_WFD
5090 	pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY  | WPS_CONFIG_METHOD_PBC;
5091 	pwdinfo->wfd_info = pwfd_info;
5092 #else
5093 	pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
5094 #endif //CONFIG_WFD
5095 	pwdinfo->channel_list_attr_len = 0;
5096 	_rtw_memset( pwdinfo->channel_list_attr, 0x00, 100 );
5097 
5098 	_rtw_memset( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4 );
5099 	_rtw_memset( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3 );
5100 	_rtw_memset( &pwdinfo->groupid_info, 0x00, sizeof( struct group_id_info ) );
5101 #ifdef CONFIG_CONCURRENT_MODE
5102 #ifdef CONFIG_IOCTL_CFG80211
5103 	pwdinfo->ext_listen_interval = 1000; //The interval to be available with legacy AP during p2p0-find/scan
5104 	pwdinfo->ext_listen_period = 3000; //The time period to be available for P2P during nego
5105 #else //!CONFIG_IOCTL_CFG80211
5106 	//pwdinfo->ext_listen_interval = 3000;
5107 	//pwdinfo->ext_listen_period = 400;
5108 	pwdinfo->ext_listen_interval = 1000;
5109 	pwdinfo->ext_listen_period = 1000;
5110 #endif //!CONFIG_IOCTL_CFG80211
5111 #endif
5112 
5113 // Commented by Kurt 20130319
5114 // For WiDi purpose: Use CFG80211 interface but controled WFD/RDS frame by driver itself.
5115 #ifdef CONFIG_IOCTL_CFG80211
5116 	pwdinfo->driver_interface = DRIVER_CFG80211;
5117 #else
5118 	pwdinfo->driver_interface = DRIVER_WEXT;
5119 #endif //CONFIG_IOCTL_CFG80211
5120 
5121 	pwdinfo->wfd_tdls_enable = 0;
5122 	_rtw_memset( pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN );
5123 	_rtw_memset( pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN );
5124 
5125 	pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
5126 	pwdinfo->rx_invitereq_info.operation_ch[1] = 0;	//	Used to indicate the scan end in site survey function
5127 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5128 	pwdinfo->rx_invitereq_info.operation_ch[2] = 0;
5129 	pwdinfo->rx_invitereq_info.operation_ch[3] = 0;
5130 	pwdinfo->rx_invitereq_info.operation_ch[4] = 0;
5131 #endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
5132 	pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
5133 	pwdinfo->p2p_info.operation_ch[0] = 0;
5134 	pwdinfo->p2p_info.operation_ch[1] = 0;			//	Used to indicate the scan end in site survey function
5135 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5136 	pwdinfo->p2p_info.operation_ch[2] = 0;
5137 	pwdinfo->p2p_info.operation_ch[3] = 0;
5138 	pwdinfo->p2p_info.operation_ch[4] = 0;
5139 #endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
5140 	pwdinfo->p2p_info.scan_op_ch_only = 0;
5141 }
5142 
5143 #ifdef CONFIG_DBG_P2P
5144 
5145 /**
5146  * rtw_p2p_role_txt - Get the p2p role name as a text string
5147  * @role: P2P role
5148  * Returns: The state name as a printable text string
5149  */
rtw_p2p_role_txt(enum P2P_ROLE role)5150 const char * rtw_p2p_role_txt(enum P2P_ROLE role)
5151 {
5152 	switch (role) {
5153 	case P2P_ROLE_DISABLE:
5154 		return "P2P_ROLE_DISABLE";
5155 	case P2P_ROLE_DEVICE:
5156 		return "P2P_ROLE_DEVICE";
5157 	case P2P_ROLE_CLIENT:
5158 		return "P2P_ROLE_CLIENT";
5159 	case P2P_ROLE_GO:
5160 		return "P2P_ROLE_GO";
5161 	default:
5162 		return "UNKNOWN";
5163 	}
5164 }
5165 
5166 /**
5167  * rtw_p2p_state_txt - Get the p2p state name as a text string
5168  * @state: P2P state
5169  * Returns: The state name as a printable text string
5170  */
rtw_p2p_state_txt(enum P2P_STATE state)5171 const char * rtw_p2p_state_txt(enum P2P_STATE state)
5172 {
5173 	switch (state) {
5174 	case P2P_STATE_NONE:
5175 		return "P2P_STATE_NONE";
5176 	case P2P_STATE_IDLE:
5177 		return "P2P_STATE_IDLE";
5178 	case P2P_STATE_LISTEN:
5179 		return "P2P_STATE_LISTEN";
5180 	case P2P_STATE_SCAN:
5181 		return "P2P_STATE_SCAN";
5182 	case P2P_STATE_FIND_PHASE_LISTEN:
5183 		return "P2P_STATE_FIND_PHASE_LISTEN";
5184 	case P2P_STATE_FIND_PHASE_SEARCH:
5185 		return "P2P_STATE_FIND_PHASE_SEARCH";
5186 	case P2P_STATE_TX_PROVISION_DIS_REQ:
5187 		return "P2P_STATE_TX_PROVISION_DIS_REQ";
5188 	case P2P_STATE_RX_PROVISION_DIS_RSP:
5189 		return "P2P_STATE_RX_PROVISION_DIS_RSP";
5190 	case P2P_STATE_RX_PROVISION_DIS_REQ:
5191 		return "P2P_STATE_RX_PROVISION_DIS_REQ";
5192 	case P2P_STATE_GONEGO_ING:
5193 		return "P2P_STATE_GONEGO_ING";
5194 	case P2P_STATE_GONEGO_OK:
5195 		return "P2P_STATE_GONEGO_OK";
5196 	case P2P_STATE_GONEGO_FAIL:
5197 		return "P2P_STATE_GONEGO_FAIL";
5198 	case P2P_STATE_RECV_INVITE_REQ_MATCH:
5199 		return "P2P_STATE_RECV_INVITE_REQ_MATCH";
5200 	case P2P_STATE_PROVISIONING_ING:
5201 		return "P2P_STATE_PROVISIONING_ING";
5202 	case P2P_STATE_PROVISIONING_DONE:
5203 		return "P2P_STATE_PROVISIONING_DONE";
5204 	case P2P_STATE_TX_INVITE_REQ:
5205 		return "P2P_STATE_TX_INVITE_REQ";
5206 	case P2P_STATE_RX_INVITE_RESP_OK:
5207 		return "P2P_STATE_RX_INVITE_RESP_OK";
5208 	case P2P_STATE_RECV_INVITE_REQ_DISMATCH:
5209 		return "P2P_STATE_RECV_INVITE_REQ_DISMATCH";
5210 	case P2P_STATE_RECV_INVITE_REQ_GO:
5211 		return "P2P_STATE_RECV_INVITE_REQ_GO";
5212 	case P2P_STATE_RECV_INVITE_REQ_JOIN:
5213 		return "P2P_STATE_RECV_INVITE_REQ_JOIN";
5214 	case P2P_STATE_RX_INVITE_RESP_FAIL:
5215 		return "P2P_STATE_RX_INVITE_RESP_FAIL";
5216 	case P2P_STATE_RX_INFOR_NOREADY:
5217 		return "P2P_STATE_RX_INFOR_NOREADY";
5218 	case P2P_STATE_TX_INFOR_NOREADY:
5219 		return "P2P_STATE_TX_INFOR_NOREADY";
5220 	default:
5221 		return "UNKNOWN";
5222 	}
5223 }
5224 
dbg_rtw_p2p_set_state(struct wifidirect_info * wdinfo,enum P2P_STATE state,const char * caller,int line)5225 void dbg_rtw_p2p_set_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)
5226 {
5227 	if(!_rtw_p2p_chk_state(wdinfo, state)) {
5228 		enum P2P_STATE old_state = _rtw_p2p_state(wdinfo);
5229 		_rtw_p2p_set_state(wdinfo, state);
5230 		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_state from %s to %s\n", caller, line
5231 			, rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))
5232 		);
5233 	} else {
5234 		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_state to same state %s\n", caller, line
5235 			, rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))
5236 		);
5237 	}
5238 }
dbg_rtw_p2p_set_pre_state(struct wifidirect_info * wdinfo,enum P2P_STATE state,const char * caller,int line)5239 void dbg_rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)
5240 {
5241 	if(_rtw_p2p_pre_state(wdinfo) != state) {
5242 		enum P2P_STATE old_state = _rtw_p2p_pre_state(wdinfo);
5243 		_rtw_p2p_set_pre_state(wdinfo, state);
5244 		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_pre_state from %s to %s\n", caller, line
5245 			, rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))
5246 		);
5247 	} else {
5248 		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_pre_state to same state %s\n", caller, line
5249 			, rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))
5250 		);
5251 	}
5252 }
5253 #if 0
5254 void dbg_rtw_p2p_restore_state(struct wifidirect_info *wdinfo, const char *caller, int line)
5255 {
5256 	if(wdinfo->pre_p2p_state != -1) {
5257 		DBG_871X("[CONFIG_DBG_P2P]%s:%d restore from %s to %s\n", caller, line
5258 			, p2p_state_str[wdinfo->p2p_state], p2p_state_str[wdinfo->pre_p2p_state]
5259 		);
5260 		_rtw_p2p_restore_state(wdinfo);
5261 	} else {
5262 		DBG_871X("[CONFIG_DBG_P2P]%s:%d restore no pre state, cur state %s\n", caller, line
5263 			, p2p_state_str[wdinfo->p2p_state]
5264 		);
5265 	}
5266 }
5267 #endif
dbg_rtw_p2p_set_role(struct wifidirect_info * wdinfo,enum P2P_ROLE role,const char * caller,int line)5268 void dbg_rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role, const char *caller, int line)
5269 {
5270 	if(wdinfo->role != role) {
5271 		enum P2P_ROLE old_role = wdinfo->role;
5272 		_rtw_p2p_set_role(wdinfo, role);
5273 		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_role from %s to %s\n", caller, line
5274 			, rtw_p2p_role_txt(old_role), rtw_p2p_role_txt(wdinfo->role)
5275 		);
5276 	} else {
5277 		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_role to same role %s\n", caller, line
5278 			, rtw_p2p_role_txt(wdinfo->role)
5279 		);
5280 	}
5281 }
5282 #endif //CONFIG_DBG_P2P
5283 
5284 
rtw_p2p_enable(_adapter * padapter,enum P2P_ROLE role)5285 int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role)
5286 {
5287 	int ret = _SUCCESS;
5288 	struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
5289 
5290 	if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT|| role == P2P_ROLE_GO)
5291 	{
5292 		u8 channel, ch_offset;
5293 		u16 bwmode;
5294 
5295 #ifdef CONFIG_CONCURRENT_MODE
5296 		_adapter				*pbuddy_adapter = padapter->pbuddy_adapter;
5297 		struct wifidirect_info	*pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
5298 		//	Commented by Albert 2011/12/30
5299 		//	The driver just supports 1 P2P group operation.
5300 		//	So, this function will do nothing if the buddy adapter had enabled the P2P function.
5301 		if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
5302 		{
5303 			//	The buddy adapter had enabled the P2P function.
5304 			return ret;
5305 		}
5306 #endif //CONFIG_CONCURRENT_MODE
5307 
5308 		//leave IPS/Autosuspend
5309 		if (_FAIL == rtw_pwr_wakeup(padapter)) {
5310 			ret = _FAIL;
5311 			goto exit;
5312 		}
5313 
5314 		//	Added by Albert 2011/03/22
5315 		//	In the P2P mode, the driver should not support the b mode.
5316 		//	So, the Tx packet shouldn't use the CCK rate
5317 		update_tx_basic_rate(padapter, WIRELESS_11AGN);
5318 
5319 		//Enable P2P function
5320 		init_wifidirect_info(padapter, role);
5321 
5322 		rtw_hal_set_odm_var(padapter,HAL_ODM_P2P_STATE,NULL,_TRUE);
5323 		#ifdef CONFIG_WFD
5324 		rtw_hal_set_odm_var(padapter,HAL_ODM_WIFI_DISPLAY_STATE,NULL,_TRUE);
5325 		#endif
5326 
5327 	}
5328 	else if (role == P2P_ROLE_DISABLE)
5329 	{
5330 #ifdef CONFIG_INTEL_WIDI
5331 		if( padapter->mlmepriv.p2p_reject_disable == _TRUE )
5332 			return ret;
5333 #endif //CONFIG_INTEL_WIDI
5334 
5335 #ifdef CONFIG_IOCTL_CFG80211
5336 		if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
5337 			adapter_wdev_data(padapter)->p2p_enabled = _FALSE;
5338 #endif //CONFIG_IOCTL_CFG80211
5339 
5340 
5341 		//Disable P2P function
5342 		if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
5343 		{
5344 			_cancel_timer_ex( &pwdinfo->find_phase_timer );
5345 			_cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5346 			_cancel_timer_ex( &pwdinfo->pre_tx_scan_timer);
5347 			_cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey);
5348 			_cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey2);
5349 			reset_ch_sitesurvey_timer_process( padapter );
5350 			reset_ch_sitesurvey_timer_process2( padapter );
5351 			#ifdef CONFIG_CONCURRENT_MODE
5352 			_cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer);
5353 			#endif
5354 			rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
5355 			rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_NONE);
5356 			rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
5357 			_rtw_memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
5358 
5359 			/* Remove profiles in wifidirect_info structure. */
5360 			_rtw_memset( &pwdinfo->profileinfo[ 0 ], 0x00, sizeof( struct profile_info ) * P2P_MAX_PERSISTENT_GROUP_NUM );
5361 			pwdinfo->profileindex = 0;
5362 		}
5363 
5364 		rtw_hal_set_odm_var(padapter,HAL_ODM_P2P_STATE,NULL,_FALSE);
5365 		#ifdef CONFIG_WFD
5366 		rtw_hal_set_odm_var(padapter,HAL_ODM_WIFI_DISPLAY_STATE,NULL,_FALSE);
5367 		#endif
5368 
5369 		if (_FAIL == rtw_pwr_wakeup(padapter)) {
5370 			ret = _FAIL;
5371 			goto exit;
5372 		}
5373 
5374 		//Restore to initial setting.
5375 		update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
5376 
5377 #ifdef CONFIG_INTEL_WIDI
5378 		rtw_reset_widi_info(padapter);
5379 #endif //CONFIG_INTEL_WIDI
5380 
5381 		//For WiDi purpose.
5382 #ifdef CONFIG_IOCTL_CFG80211
5383 		pwdinfo->driver_interface = DRIVER_CFG80211;
5384 #else
5385 		pwdinfo->driver_interface = DRIVER_WEXT;
5386 #endif //CONFIG_IOCTL_CFG80211
5387 
5388 	}
5389 
5390 exit:
5391 	return ret;
5392 }
5393 
5394 #endif //CONFIG_P2P
5395 
5396