xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/core/rtw_p2p.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2019 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _RTW_P2P_C_
16 
17 #include <drv_types.h>
18 
19 #ifdef CONFIG_P2P
20 
21 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37))
22 	#error "Linux kernel version is too old to enable CONFIG_P2P"
23 #endif
24 #ifndef CONFIG_IOCTL_CFG80211
25 	#error "Enable CONFIG_P2P without CONFIG_IOCTL_CFG80211"
26 #endif
27 
is_any_client_associated(_adapter * padapter)28 int is_any_client_associated(_adapter *padapter)
29 {
30 	return padapter->stapriv.asoc_list_cnt ? _TRUE : _FALSE;
31 }
32 
33 #ifdef CONFIG_WFD
build_beacon_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)34 u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
35 {
36 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
37 	u16 val16 = 0;
38 	u32 len = 0, wfdielen = 0;
39 	_adapter *padapter = pwdinfo->padapter;
40 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
41 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
42 
43 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
44 		goto exit;
45 
46 	/*	WFD OUI */
47 	wfdielen = 0;
48 	wfdie[wfdielen++] = 0x50;
49 	wfdie[wfdielen++] = 0x6F;
50 	wfdie[wfdielen++] = 0x9A;
51 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
52 
53 	/*	Commented by Albert 20110812 */
54 	/*	According to the WFD Specification, the beacon frame should contain 4 WFD attributes */
55 	/*	1. WFD Device Information */
56 	/*	2. Associated BSSID */
57 	/*	3. Coupled Sink Information */
58 
59 
60 	/*	WFD Device Information ATTR */
61 	/*	Type: */
62 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
63 
64 	/*	Length: */
65 	/*	Note: In the WFD specification, the size of length field is 2. */
66 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
67 	wfdielen += 2;
68 
69 	/*	Value1: */
70 	/*	WFD device information */
71 
72 	if (P2P_ROLE_GO == pwdinfo->role) {
73 		if (is_any_client_associated(pwdinfo->padapter)) {
74 			/*	WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) */
75 			val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD;
76 			RTW_PUT_BE16(wfdie + wfdielen, val16);
77 		} else {
78 			/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
79 			val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
80 			RTW_PUT_BE16(wfdie + wfdielen, val16);
81 		}
82 
83 	} else {
84 		/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
85 		val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
86 		RTW_PUT_BE16(wfdie + wfdielen, val16);
87 	}
88 
89 	wfdielen += 2;
90 
91 	/*	Value2: */
92 	/*	Session Management Control Port */
93 	/*	Default TCP port for RTSP messages is 554 */
94 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
95 	wfdielen += 2;
96 
97 	/*	Value3: */
98 	/*	WFD Device Maximum Throughput */
99 	/*	300Mbps is the maximum throughput */
100 	RTW_PUT_BE16(wfdie + wfdielen, 300);
101 	wfdielen += 2;
102 
103 	/*	Associated BSSID ATTR */
104 	/*	Type: */
105 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
106 
107 	/*	Length: */
108 	/*	Note: In the WFD specification, the size of length field is 2. */
109 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
110 	wfdielen += 2;
111 
112 	/*	Value: */
113 	/*	Associated BSSID */
114 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
115 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
116 	else
117 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
118 
119 	wfdielen += ETH_ALEN;
120 
121 	/*	Coupled Sink Information ATTR */
122 	/*	Type: */
123 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
124 
125 	/*	Length: */
126 	/*	Note: In the WFD specification, the size of length field is 2. */
127 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
128 	wfdielen += 2;
129 
130 	/*	Value: */
131 	/*	Coupled Sink Status bitmap */
132 	/*	Not coupled/available for Coupling */
133 	wfdie[wfdielen++] = 0;
134 	/* MAC Addr. */
135 	wfdie[wfdielen++] = 0;
136 	wfdie[wfdielen++] = 0;
137 	wfdie[wfdielen++] = 0;
138 	wfdie[wfdielen++] = 0;
139 	wfdie[wfdielen++] = 0;
140 	wfdie[wfdielen++] = 0;
141 
142 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
143 
144 exit:
145 	return len;
146 }
147 
build_probe_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)148 u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
149 {
150 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
151 	u16 val16 = 0;
152 	u32 len = 0, wfdielen = 0;
153 	_adapter *padapter = pwdinfo->padapter;
154 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
155 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
156 
157 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
158 		goto exit;
159 
160 	/*	WFD OUI */
161 	wfdielen = 0;
162 	wfdie[wfdielen++] = 0x50;
163 	wfdie[wfdielen++] = 0x6F;
164 	wfdie[wfdielen++] = 0x9A;
165 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
166 
167 	/*	Commented by Albert 20110812 */
168 	/*	According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
169 	/*	1. WFD Device Information */
170 	/*	2. Associated BSSID */
171 	/*	3. Coupled Sink Information */
172 
173 
174 	/*	WFD Device Information ATTR */
175 	/*	Type: */
176 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
177 
178 	/*	Length: */
179 	/*	Note: In the WFD specification, the size of length field is 2. */
180 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
181 	wfdielen += 2;
182 
183 	/*	Value1: */
184 	/*	WFD device information */
185 
186 	if (1 == pwdinfo->wfd_tdls_enable) {
187 		/*	WFD primary sink + available for WFD session + WiFi TDLS mode + WSC ( WFD Service Discovery )	 */
188 		val16 = pwfd_info->wfd_device_type |
189 			WFD_DEVINFO_SESSION_AVAIL |
190 			WFD_DEVINFO_WSD |
191 			WFD_DEVINFO_PC_TDLS;
192 		RTW_PUT_BE16(wfdie + wfdielen, val16);
193 	} else {
194 		/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSC ( WFD Service Discovery )	 */
195 		val16 = pwfd_info->wfd_device_type |
196 			WFD_DEVINFO_SESSION_AVAIL |
197 			WFD_DEVINFO_WSD;
198 		RTW_PUT_BE16(wfdie + wfdielen, val16);
199 	}
200 
201 	wfdielen += 2;
202 
203 	/*	Value2: */
204 	/*	Session Management Control Port */
205 	/*	Default TCP port for RTSP messages is 554 */
206 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
207 	wfdielen += 2;
208 
209 	/*	Value3: */
210 	/*	WFD Device Maximum Throughput */
211 	/*	300Mbps is the maximum throughput */
212 	RTW_PUT_BE16(wfdie + wfdielen, 300);
213 	wfdielen += 2;
214 
215 	/*	Associated BSSID ATTR */
216 	/*	Type: */
217 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
218 
219 	/*	Length: */
220 	/*	Note: In the WFD specification, the size of length field is 2. */
221 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
222 	wfdielen += 2;
223 
224 	/*	Value: */
225 	/*	Associated BSSID */
226 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
227 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
228 	else
229 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
230 
231 	wfdielen += ETH_ALEN;
232 
233 	/*	Coupled Sink Information ATTR */
234 	/*	Type: */
235 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
236 
237 	/*	Length: */
238 	/*	Note: In the WFD specification, the size of length field is 2. */
239 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
240 	wfdielen += 2;
241 
242 	/*	Value: */
243 	/*	Coupled Sink Status bitmap */
244 	/*	Not coupled/available for Coupling */
245 	wfdie[wfdielen++] = 0;
246 	/* MAC Addr. */
247 	wfdie[wfdielen++] = 0;
248 	wfdie[wfdielen++] = 0;
249 	wfdie[wfdielen++] = 0;
250 	wfdie[wfdielen++] = 0;
251 	wfdie[wfdielen++] = 0;
252 	wfdie[wfdielen++] = 0;
253 
254 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
255 
256 exit:
257 	return len;
258 }
259 
build_probe_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf,u8 tunneled)260 u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunneled)
261 {
262 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
263 	u32 len = 0, wfdielen = 0;
264 	_adapter *padapter = pwdinfo->padapter;
265 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
266 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
267 	u16 v16 = 0;
268 
269 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
270 		goto exit;
271 
272 	/*	WFD OUI */
273 	wfdielen = 0;
274 	wfdie[wfdielen++] = 0x50;
275 	wfdie[wfdielen++] = 0x6F;
276 	wfdie[wfdielen++] = 0x9A;
277 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
278 
279 	/*	Commented by Albert 20110812 */
280 	/*	According to the WFD Specification, the probe response frame should contain 4 WFD attributes */
281 	/*	1. WFD Device Information */
282 	/*	2. Associated BSSID */
283 	/*	3. Coupled Sink Information */
284 	/*	4. WFD Session Information */
285 
286 
287 	/*	WFD Device Information ATTR */
288 	/*	Type: */
289 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
290 
291 	/*	Length: */
292 	/*	Note: In the WFD specification, the size of length field is 2. */
293 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
294 	wfdielen += 2;
295 
296 	/*	Value1: */
297 	/*	WFD device information */
298 	/*	WFD primary sink + available for WFD session + WiFi Direct mode */
299 
300 	if (P2P_ROLE_GO == pwdinfo->role) {
301 		if (is_any_client_associated(pwdinfo->padapter)) {
302 			if (pwdinfo->wfd_tdls_enable) {
303 				/*	TDLS mode + WSD ( WFD Service Discovery ) */
304 				v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;
305 				RTW_PUT_BE16(wfdie + wfdielen, v16);
306 			} else {
307 				/*	WiFi Direct mode + WSD ( WFD Service Discovery ) */
308 				v16 =  pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;
309 				RTW_PUT_BE16(wfdie + wfdielen, v16);
310 			}
311 		} else {
312 			if (pwdinfo->wfd_tdls_enable) {
313 				/*	available for WFD session + TDLS mode + WSD ( WFD Service Discovery ) */
314 				v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;
315 				RTW_PUT_BE16(wfdie + wfdielen, v16);
316 			} else {
317 				/*	available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
318 				v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;
319 				RTW_PUT_BE16(wfdie + wfdielen, v16);
320 			}
321 		}
322 	} else {
323 		if (pwdinfo->wfd_tdls_enable) {
324 			/*	available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
325 			v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;
326 			RTW_PUT_BE16(wfdie + wfdielen, v16);
327 		} else {
328 			/*	available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
329 			v16 =  pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;
330 			RTW_PUT_BE16(wfdie + wfdielen, v16);
331 		}
332 	}
333 
334 	wfdielen += 2;
335 
336 	/*	Value2: */
337 	/*	Session Management Control Port */
338 	/*	Default TCP port for RTSP messages is 554 */
339 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
340 	wfdielen += 2;
341 
342 	/*	Value3: */
343 	/*	WFD Device Maximum Throughput */
344 	/*	300Mbps is the maximum throughput */
345 	RTW_PUT_BE16(wfdie + wfdielen, 300);
346 	wfdielen += 2;
347 
348 	/*	Associated BSSID ATTR */
349 	/*	Type: */
350 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
351 
352 	/*	Length: */
353 	/*	Note: In the WFD specification, the size of length field is 2. */
354 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
355 	wfdielen += 2;
356 
357 	/*	Value: */
358 	/*	Associated BSSID */
359 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
360 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
361 	else
362 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
363 
364 	wfdielen += ETH_ALEN;
365 
366 	/*	Coupled Sink Information ATTR */
367 	/*	Type: */
368 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
369 
370 	/*	Length: */
371 	/*	Note: In the WFD specification, the size of length field is 2. */
372 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
373 	wfdielen += 2;
374 
375 	/*	Value: */
376 	/*	Coupled Sink Status bitmap */
377 	/*	Not coupled/available for Coupling */
378 	wfdie[wfdielen++] = 0;
379 	/* MAC Addr. */
380 	wfdie[wfdielen++] = 0;
381 	wfdie[wfdielen++] = 0;
382 	wfdie[wfdielen++] = 0;
383 	wfdie[wfdielen++] = 0;
384 	wfdie[wfdielen++] = 0;
385 	wfdie[wfdielen++] = 0;
386 
387 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
388 		/*	WFD Session Information ATTR */
389 		/*	Type: */
390 		wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;
391 
392 		/*	Length: */
393 		/*	Note: In the WFD specification, the size of length field is 2. */
394 		RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
395 		wfdielen += 2;
396 
397 		/*	Todo: to add the list of WFD device info descriptor in WFD group. */
398 
399 	}
400 #ifdef CONFIG_CONCURRENT_MODE
401 #ifdef CONFIG_TDLS
402 	{
403 		int i;
404 		_adapter *iface = NULL;
405 		struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
406 
407 		for (i = 0; i < dvobj->iface_nums; i++) {
408 			iface = dvobj->padapters[i];
409 			if ((iface) && rtw_is_adapter_up(iface)) {
410 				if (iface == padapter)
411 					continue;
412 
413 				if ((tunneled == 0) && (iface->wdinfo.wfd_tdls_enable == 1)) {
414 					/*	Alternative MAC Address ATTR
415 						Type:					*/
416 					wfdie[wfdielen++] = WFD_ATTR_ALTER_MAC;
417 
418 					/*	Length:
419 						Note: In the WFD specification, the size of length field is 2.*/
420 					RTW_PUT_BE16(wfdie + wfdielen,  ETH_ALEN);
421 					wfdielen += 2;
422 
423 					/*	Value:
424 						Alternative MAC Address*/
425 					_rtw_memcpy(wfdie + wfdielen, adapter_mac_addr(iface), ETH_ALEN);
426 					wfdielen += ETH_ALEN;
427 				}
428 			}
429 		}
430 	}
431 
432 #endif /* CONFIG_TDLS*/
433 #endif /* CONFIG_CONCURRENT_MODE */
434 
435 	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
436 
437 exit:
438 	return len;
439 }
440 
build_assoc_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)441 u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
442 {
443 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
444 	u16 val16 = 0;
445 	u32 len = 0, wfdielen = 0;
446 	_adapter			*padapter = NULL;
447 	struct mlme_priv			*pmlmepriv = NULL;
448 	struct wifi_display_info		*pwfd_info = NULL;
449 
450 	padapter = pwdinfo->padapter;
451 	pmlmepriv = &padapter->mlmepriv;
452 	pwfd_info = padapter->wdinfo.wfd_info;
453 
454 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
455 		goto exit;
456 
457 	/* Only P2P GC need to include the WFD IE in the association request */
458 	if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
459 		goto exit;
460 
461 	/* WFD OUI */
462 	wfdielen = 0;
463 	wfdie[wfdielen++] = 0x50;
464 	wfdie[wfdielen++] = 0x6F;
465 	wfdie[wfdielen++] = 0x9A;
466 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
467 
468 	/*	Commented by Albert 20110812 */
469 	/*	According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
470 	/*	1. WFD Device Information */
471 	/*	2. Associated BSSID */
472 	/*	3. Coupled Sink Information */
473 
474 
475 	/*	WFD Device Information ATTR */
476 	/*	Type: */
477 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
478 
479 	/*	Length: */
480 	/*	Note: In the WFD specification, the size of length field is 2. */
481 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
482 	wfdielen += 2;
483 
484 	/*	Value1: */
485 	/*	WFD device information */
486 	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
487 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
488 	RTW_PUT_BE16(wfdie + wfdielen, val16);
489 	wfdielen += 2;
490 
491 	/*	Value2: */
492 	/*	Session Management Control Port */
493 	/*	Default TCP port for RTSP messages is 554 */
494 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
495 	wfdielen += 2;
496 
497 	/*	Value3: */
498 	/*	WFD Device Maximum Throughput */
499 	/*	300Mbps is the maximum throughput */
500 	RTW_PUT_BE16(wfdie + wfdielen, 300);
501 	wfdielen += 2;
502 
503 	/*	Associated BSSID ATTR */
504 	/*	Type: */
505 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
506 
507 	/*	Length: */
508 	/*	Note: In the WFD specification, the size of length field is 2. */
509 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
510 	wfdielen += 2;
511 
512 	/*	Value: */
513 	/*	Associated BSSID */
514 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
515 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
516 	else
517 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
518 
519 	wfdielen += ETH_ALEN;
520 
521 	/*	Coupled Sink Information ATTR */
522 	/*	Type: */
523 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
524 
525 	/*	Length: */
526 	/*	Note: In the WFD specification, the size of length field is 2. */
527 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
528 	wfdielen += 2;
529 
530 	/*	Value: */
531 	/*	Coupled Sink Status bitmap */
532 	/*	Not coupled/available for Coupling */
533 	wfdie[wfdielen++] = 0;
534 	/* MAC Addr. */
535 	wfdie[wfdielen++] = 0;
536 	wfdie[wfdielen++] = 0;
537 	wfdie[wfdielen++] = 0;
538 	wfdie[wfdielen++] = 0;
539 	wfdie[wfdielen++] = 0;
540 	wfdie[wfdielen++] = 0;
541 
542 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
543 
544 exit:
545 	return len;
546 }
547 
build_assoc_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)548 u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
549 {
550 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
551 	u32 len = 0, wfdielen = 0;
552 	u16 val16 = 0;
553 	_adapter *padapter = pwdinfo->padapter;
554 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
555 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
556 
557 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
558 		goto exit;
559 
560 	/*	WFD OUI */
561 	wfdielen = 0;
562 	wfdie[wfdielen++] = 0x50;
563 	wfdie[wfdielen++] = 0x6F;
564 	wfdie[wfdielen++] = 0x9A;
565 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
566 
567 	/*	Commented by Albert 20110812 */
568 	/*	According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
569 	/*	1. WFD Device Information */
570 	/*	2. Associated BSSID */
571 	/*	3. Coupled Sink Information */
572 
573 
574 	/*	WFD Device Information ATTR */
575 	/*	Type: */
576 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
577 
578 	/*	Length: */
579 	/*	Note: In the WFD specification, the size of length field is 2. */
580 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
581 	wfdielen += 2;
582 
583 	/*	Value1: */
584 	/*	WFD device information */
585 	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
586 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
587 	RTW_PUT_BE16(wfdie + wfdielen, val16);
588 	wfdielen += 2;
589 
590 	/*	Value2: */
591 	/*	Session Management Control Port */
592 	/*	Default TCP port for RTSP messages is 554 */
593 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
594 	wfdielen += 2;
595 
596 	/*	Value3: */
597 	/*	WFD Device Maximum Throughput */
598 	/*	300Mbps is the maximum throughput */
599 	RTW_PUT_BE16(wfdie + wfdielen, 300);
600 	wfdielen += 2;
601 
602 	/*	Associated BSSID ATTR */
603 	/*	Type: */
604 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
605 
606 	/*	Length: */
607 	/*	Note: In the WFD specification, the size of length field is 2. */
608 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
609 	wfdielen += 2;
610 
611 	/*	Value: */
612 	/*	Associated BSSID */
613 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
614 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
615 	else
616 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
617 
618 	wfdielen += ETH_ALEN;
619 
620 	/*	Coupled Sink Information ATTR */
621 	/*	Type: */
622 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
623 
624 	/*	Length: */
625 	/*	Note: In the WFD specification, the size of length field is 2. */
626 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
627 	wfdielen += 2;
628 
629 	/*	Value: */
630 	/*	Coupled Sink Status bitmap */
631 	/*	Not coupled/available for Coupling */
632 	wfdie[wfdielen++] = 0;
633 	/* MAC Addr. */
634 	wfdie[wfdielen++] = 0;
635 	wfdie[wfdielen++] = 0;
636 	wfdie[wfdielen++] = 0;
637 	wfdie[wfdielen++] = 0;
638 	wfdie[wfdielen++] = 0;
639 	wfdie[wfdielen++] = 0;
640 
641 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
642 
643 exit:
644 	return len;
645 }
646 
build_nego_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)647 u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
648 {
649 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
650 	u32 len = 0, wfdielen = 0;
651 	u16 val16 = 0;
652 	_adapter *padapter = pwdinfo->padapter;
653 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
654 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
655 
656 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
657 		goto exit;
658 
659 	/*	WFD OUI */
660 	wfdielen = 0;
661 	wfdie[wfdielen++] = 0x50;
662 	wfdie[wfdielen++] = 0x6F;
663 	wfdie[wfdielen++] = 0x9A;
664 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
665 
666 	/*	Commented by Albert 20110825 */
667 	/*	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
668 	/*	1. WFD Device Information */
669 	/*	2. Associated BSSID ( Optional ) */
670 	/*	3. Local IP Adress ( Optional ) */
671 
672 
673 	/*	WFD Device Information ATTR */
674 	/*	Type: */
675 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
676 
677 	/*	Length: */
678 	/*	Note: In the WFD specification, the size of length field is 2. */
679 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
680 	wfdielen += 2;
681 
682 	/*	Value1: */
683 	/*	WFD device information */
684 	/*	WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */
685 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
686 	RTW_PUT_BE16(wfdie + wfdielen, val16);
687 	wfdielen += 2;
688 
689 	/*	Value2: */
690 	/*	Session Management Control Port */
691 	/*	Default TCP port for RTSP messages is 554 */
692 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
693 	wfdielen += 2;
694 
695 	/*	Value3: */
696 	/*	WFD Device Maximum Throughput */
697 	/*	300Mbps is the maximum throughput */
698 	RTW_PUT_BE16(wfdie + wfdielen, 300);
699 	wfdielen += 2;
700 
701 	/*	Associated BSSID ATTR */
702 	/*	Type: */
703 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
704 
705 	/*	Length: */
706 	/*	Note: In the WFD specification, the size of length field is 2. */
707 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
708 	wfdielen += 2;
709 
710 	/*	Value: */
711 	/*	Associated BSSID */
712 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
713 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
714 	else
715 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
716 
717 	wfdielen += ETH_ALEN;
718 
719 	/*	Coupled Sink Information ATTR */
720 	/*	Type: */
721 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
722 
723 	/*	Length: */
724 	/*	Note: In the WFD specification, the size of length field is 2. */
725 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
726 	wfdielen += 2;
727 
728 	/*	Value: */
729 	/*	Coupled Sink Status bitmap */
730 	/*	Not coupled/available for Coupling */
731 	wfdie[wfdielen++] = 0;
732 	/* MAC Addr. */
733 	wfdie[wfdielen++] = 0;
734 	wfdie[wfdielen++] = 0;
735 	wfdie[wfdielen++] = 0;
736 	wfdie[wfdielen++] = 0;
737 	wfdie[wfdielen++] = 0;
738 	wfdie[wfdielen++] = 0;
739 
740 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
741 
742 exit:
743 	return len;
744 }
745 
build_nego_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)746 u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
747 {
748 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
749 	u32 len = 0, wfdielen = 0;
750 	u16 val16 = 0;
751 	_adapter *padapter = pwdinfo->padapter;
752 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
753 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
754 
755 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
756 		goto exit;
757 
758 	/*	WFD OUI */
759 	wfdielen = 0;
760 	wfdie[wfdielen++] = 0x50;
761 	wfdie[wfdielen++] = 0x6F;
762 	wfdie[wfdielen++] = 0x9A;
763 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
764 
765 	/*	Commented by Albert 20110825 */
766 	/*	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
767 	/*	1. WFD Device Information */
768 	/*	2. Associated BSSID ( Optional ) */
769 	/*	3. Local IP Adress ( Optional ) */
770 
771 
772 	/*	WFD Device Information ATTR */
773 	/*	Type: */
774 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
775 
776 	/*	Length: */
777 	/*	Note: In the WFD specification, the size of length field is 2. */
778 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
779 	wfdielen += 2;
780 
781 	/*	Value1: */
782 	/*	WFD device information */
783 	/*	WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */
784 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
785 	RTW_PUT_BE16(wfdie + wfdielen, val16);
786 	wfdielen += 2;
787 
788 	/*	Value2: */
789 	/*	Session Management Control Port */
790 	/*	Default TCP port for RTSP messages is 554 */
791 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
792 	wfdielen += 2;
793 
794 	/*	Value3: */
795 	/*	WFD Device Maximum Throughput */
796 	/*	300Mbps is the maximum throughput */
797 	RTW_PUT_BE16(wfdie + wfdielen, 300);
798 	wfdielen += 2;
799 
800 	/*	Associated BSSID ATTR */
801 	/*	Type: */
802 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
803 
804 	/*	Length: */
805 	/*	Note: In the WFD specification, the size of length field is 2. */
806 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
807 	wfdielen += 2;
808 
809 	/*	Value: */
810 	/*	Associated BSSID */
811 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
812 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
813 	else
814 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
815 
816 	wfdielen += ETH_ALEN;
817 
818 	/*	Coupled Sink Information ATTR */
819 	/*	Type: */
820 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
821 
822 	/*	Length: */
823 	/*	Note: In the WFD specification, the size of length field is 2. */
824 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
825 	wfdielen += 2;
826 
827 	/*	Value: */
828 	/*	Coupled Sink Status bitmap */
829 	/*	Not coupled/available for Coupling */
830 	wfdie[wfdielen++] = 0;
831 	/* MAC Addr. */
832 	wfdie[wfdielen++] = 0;
833 	wfdie[wfdielen++] = 0;
834 	wfdie[wfdielen++] = 0;
835 	wfdie[wfdielen++] = 0;
836 	wfdie[wfdielen++] = 0;
837 	wfdie[wfdielen++] = 0;
838 
839 
840 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
841 
842 exit:
843 	return len;
844 }
845 
build_nego_confirm_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)846 u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
847 {
848 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
849 	u32 len = 0, wfdielen = 0;
850 	u16 val16 = 0;
851 	_adapter *padapter = pwdinfo->padapter;
852 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
853 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
854 
855 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
856 		goto exit;
857 
858 	/*	WFD OUI */
859 	wfdielen = 0;
860 	wfdie[wfdielen++] = 0x50;
861 	wfdie[wfdielen++] = 0x6F;
862 	wfdie[wfdielen++] = 0x9A;
863 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
864 
865 	/*	Commented by Albert 20110825 */
866 	/*	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
867 	/*	1. WFD Device Information */
868 	/*	2. Associated BSSID ( Optional ) */
869 	/*	3. Local IP Adress ( Optional ) */
870 
871 
872 	/*	WFD Device Information ATTR */
873 	/*	Type: */
874 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
875 
876 	/*	Length: */
877 	/*	Note: In the WFD specification, the size of length field is 2. */
878 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
879 	wfdielen += 2;
880 
881 	/*	Value1: */
882 	/*	WFD device information */
883 	/*	WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */
884 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
885 	RTW_PUT_BE16(wfdie + wfdielen, val16);
886 	wfdielen += 2;
887 
888 	/*	Value2: */
889 	/*	Session Management Control Port */
890 	/*	Default TCP port for RTSP messages is 554 */
891 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
892 	wfdielen += 2;
893 
894 	/*	Value3: */
895 	/*	WFD Device Maximum Throughput */
896 	/*	300Mbps is the maximum throughput */
897 	RTW_PUT_BE16(wfdie + wfdielen, 300);
898 	wfdielen += 2;
899 
900 	/*	Associated BSSID ATTR */
901 	/*	Type: */
902 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
903 
904 	/*	Length: */
905 	/*	Note: In the WFD specification, the size of length field is 2. */
906 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
907 	wfdielen += 2;
908 
909 	/*	Value: */
910 	/*	Associated BSSID */
911 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
912 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
913 	else
914 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
915 
916 	wfdielen += ETH_ALEN;
917 
918 	/*	Coupled Sink Information ATTR */
919 	/*	Type: */
920 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
921 
922 	/*	Length: */
923 	/*	Note: In the WFD specification, the size of length field is 2. */
924 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
925 	wfdielen += 2;
926 
927 	/*	Value: */
928 	/*	Coupled Sink Status bitmap */
929 	/*	Not coupled/available for Coupling */
930 	wfdie[wfdielen++] = 0;
931 	/* MAC Addr. */
932 	wfdie[wfdielen++] = 0;
933 	wfdie[wfdielen++] = 0;
934 	wfdie[wfdielen++] = 0;
935 	wfdie[wfdielen++] = 0;
936 	wfdie[wfdielen++] = 0;
937 	wfdie[wfdielen++] = 0;
938 
939 
940 	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
941 
942 exit:
943 	return len;
944 }
945 
build_invitation_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)946 u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
947 {
948 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
949 	u32 len = 0, wfdielen = 0;
950 	u16 val16 = 0;
951 	_adapter *padapter = pwdinfo->padapter;
952 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
953 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
954 
955 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
956 		goto exit;
957 
958 	/*	WFD OUI */
959 	wfdielen = 0;
960 	wfdie[wfdielen++] = 0x50;
961 	wfdie[wfdielen++] = 0x6F;
962 	wfdie[wfdielen++] = 0x9A;
963 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
964 
965 	/*	Commented by Albert 20110825 */
966 	/*	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
967 	/*	1. WFD Device Information */
968 	/*	2. Associated BSSID ( Optional ) */
969 	/*	3. Local IP Adress ( Optional ) */
970 
971 
972 	/*	WFD Device Information ATTR */
973 	/*	Type: */
974 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
975 
976 	/*	Length: */
977 	/*	Note: In the WFD specification, the size of length field is 2. */
978 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
979 	wfdielen += 2;
980 
981 	/*	Value1: */
982 	/*	WFD device information */
983 	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
984 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
985 	RTW_PUT_BE16(wfdie + wfdielen, val16);
986 	wfdielen += 2;
987 
988 	/*	Value2: */
989 	/*	Session Management Control Port */
990 	/*	Default TCP port for RTSP messages is 554 */
991 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
992 	wfdielen += 2;
993 
994 	/*	Value3: */
995 	/*	WFD Device Maximum Throughput */
996 	/*	300Mbps is the maximum throughput */
997 	RTW_PUT_BE16(wfdie + wfdielen, 300);
998 	wfdielen += 2;
999 
1000 	/*	Associated BSSID ATTR */
1001 	/*	Type: */
1002 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1003 
1004 	/*	Length: */
1005 	/*	Note: In the WFD specification, the size of length field is 2. */
1006 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1007 	wfdielen += 2;
1008 
1009 	/*	Value: */
1010 	/*	Associated BSSID */
1011 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1012 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1013 	else
1014 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1015 
1016 	wfdielen += ETH_ALEN;
1017 
1018 	/*	Coupled Sink Information ATTR */
1019 	/*	Type: */
1020 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1021 
1022 	/*	Length: */
1023 	/*	Note: In the WFD specification, the size of length field is 2. */
1024 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1025 	wfdielen += 2;
1026 
1027 	/*	Value: */
1028 	/*	Coupled Sink Status bitmap */
1029 	/*	Not coupled/available for Coupling */
1030 	wfdie[wfdielen++] = 0;
1031 	/* MAC Addr. */
1032 	wfdie[wfdielen++] = 0;
1033 	wfdie[wfdielen++] = 0;
1034 	wfdie[wfdielen++] = 0;
1035 	wfdie[wfdielen++] = 0;
1036 	wfdie[wfdielen++] = 0;
1037 	wfdie[wfdielen++] = 0;
1038 
1039 	if (P2P_ROLE_GO == pwdinfo->role) {
1040 		/*	WFD Session Information ATTR */
1041 		/*	Type: */
1042 		wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;
1043 
1044 		/*	Length: */
1045 		/*	Note: In the WFD specification, the size of length field is 2. */
1046 		RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
1047 		wfdielen += 2;
1048 
1049 		/*	Todo: to add the list of WFD device info descriptor in WFD group. */
1050 
1051 	}
1052 
1053 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1054 
1055 exit:
1056 	return len;
1057 }
1058 
build_invitation_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1059 u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1060 {
1061 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1062 	u16 val16 = 0;
1063 	u32 len = 0, wfdielen = 0;
1064 	_adapter *padapter = pwdinfo->padapter;
1065 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1066 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
1067 
1068 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
1069 		goto exit;
1070 
1071 	/*	WFD OUI */
1072 	wfdielen = 0;
1073 	wfdie[wfdielen++] = 0x50;
1074 	wfdie[wfdielen++] = 0x6F;
1075 	wfdie[wfdielen++] = 0x9A;
1076 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
1077 
1078 	/*	Commented by Albert 20110825 */
1079 	/*	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1080 	/*	1. WFD Device Information */
1081 	/*	2. Associated BSSID ( Optional ) */
1082 	/*	3. Local IP Adress ( Optional ) */
1083 
1084 
1085 	/*	WFD Device Information ATTR */
1086 	/*	Type: */
1087 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1088 
1089 	/*	Length: */
1090 	/*	Note: In the WFD specification, the size of length field is 2. */
1091 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1092 	wfdielen += 2;
1093 
1094 	/*	Value1: */
1095 	/*	WFD device information */
1096 	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1097 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1098 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1099 	wfdielen += 2;
1100 
1101 	/*	Value2: */
1102 	/*	Session Management Control Port */
1103 	/*	Default TCP port for RTSP messages is 554 */
1104 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1105 	wfdielen += 2;
1106 
1107 	/*	Value3: */
1108 	/*	WFD Device Maximum Throughput */
1109 	/*	300Mbps is the maximum throughput */
1110 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1111 	wfdielen += 2;
1112 
1113 	/*	Associated BSSID ATTR */
1114 	/*	Type: */
1115 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1116 
1117 	/*	Length: */
1118 	/*	Note: In the WFD specification, the size of length field is 2. */
1119 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1120 	wfdielen += 2;
1121 
1122 	/*	Value: */
1123 	/*	Associated BSSID */
1124 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1125 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1126 	else
1127 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1128 
1129 	wfdielen += ETH_ALEN;
1130 
1131 	/*	Coupled Sink Information ATTR */
1132 	/*	Type: */
1133 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1134 
1135 	/*	Length: */
1136 	/*	Note: In the WFD specification, the size of length field is 2. */
1137 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1138 	wfdielen += 2;
1139 
1140 	/*	Value: */
1141 	/*	Coupled Sink Status bitmap */
1142 	/*	Not coupled/available for Coupling */
1143 	wfdie[wfdielen++] = 0;
1144 	/* MAC Addr. */
1145 	wfdie[wfdielen++] = 0;
1146 	wfdie[wfdielen++] = 0;
1147 	wfdie[wfdielen++] = 0;
1148 	wfdie[wfdielen++] = 0;
1149 	wfdie[wfdielen++] = 0;
1150 	wfdie[wfdielen++] = 0;
1151 
1152 	if (P2P_ROLE_GO == pwdinfo->role) {
1153 		/*	WFD Session Information ATTR */
1154 		/*	Type: */
1155 		wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;
1156 
1157 		/*	Length: */
1158 		/*	Note: In the WFD specification, the size of length field is 2. */
1159 		RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
1160 		wfdielen += 2;
1161 
1162 		/*	Todo: to add the list of WFD device info descriptor in WFD group. */
1163 
1164 	}
1165 
1166 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1167 
1168 exit:
1169 	return len;
1170 }
1171 
build_provdisc_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1172 u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1173 {
1174 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1175 	u32 len = 0, wfdielen = 0;
1176 	u16 val16 = 0;
1177 	_adapter *padapter = pwdinfo->padapter;
1178 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1179 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
1180 
1181 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
1182 		goto exit;
1183 
1184 	/*	WFD OUI */
1185 	wfdielen = 0;
1186 	wfdie[wfdielen++] = 0x50;
1187 	wfdie[wfdielen++] = 0x6F;
1188 	wfdie[wfdielen++] = 0x9A;
1189 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
1190 
1191 	/*	Commented by Albert 20110825 */
1192 	/*	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1193 	/*	1. WFD Device Information */
1194 	/*	2. Associated BSSID ( Optional ) */
1195 	/*	3. Local IP Adress ( Optional ) */
1196 
1197 
1198 	/*	WFD Device Information ATTR */
1199 	/*	Type: */
1200 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1201 
1202 	/*	Length: */
1203 	/*	Note: In the WFD specification, the size of length field is 2. */
1204 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1205 	wfdielen += 2;
1206 
1207 	/*	Value1: */
1208 	/*	WFD device information */
1209 	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1210 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1211 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1212 	wfdielen += 2;
1213 
1214 	/*	Value2: */
1215 	/*	Session Management Control Port */
1216 	/*	Default TCP port for RTSP messages is 554 */
1217 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1218 	wfdielen += 2;
1219 
1220 	/*	Value3: */
1221 	/*	WFD Device Maximum Throughput */
1222 	/*	300Mbps is the maximum throughput */
1223 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1224 	wfdielen += 2;
1225 
1226 	/*	Associated BSSID ATTR */
1227 	/*	Type: */
1228 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1229 
1230 	/*	Length: */
1231 	/*	Note: In the WFD specification, the size of length field is 2. */
1232 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1233 	wfdielen += 2;
1234 
1235 	/*	Value: */
1236 	/*	Associated BSSID */
1237 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1238 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1239 	else
1240 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1241 
1242 	wfdielen += ETH_ALEN;
1243 
1244 	/*	Coupled Sink Information ATTR */
1245 	/*	Type: */
1246 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1247 
1248 	/*	Length: */
1249 	/*	Note: In the WFD specification, the size of length field is 2. */
1250 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1251 	wfdielen += 2;
1252 
1253 	/*	Value: */
1254 	/*	Coupled Sink Status bitmap */
1255 	/*	Not coupled/available for Coupling */
1256 	wfdie[wfdielen++] = 0;
1257 	/* MAC Addr. */
1258 	wfdie[wfdielen++] = 0;
1259 	wfdie[wfdielen++] = 0;
1260 	wfdie[wfdielen++] = 0;
1261 	wfdie[wfdielen++] = 0;
1262 	wfdie[wfdielen++] = 0;
1263 	wfdie[wfdielen++] = 0;
1264 
1265 
1266 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1267 
1268 exit:
1269 	return len;
1270 }
1271 
build_provdisc_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1272 u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1273 {
1274 	u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1275 	u32 len = 0, wfdielen = 0;
1276 	u16 val16 = 0;
1277 	_adapter *padapter = pwdinfo->padapter;
1278 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1279 	struct wifi_display_info	*pwfd_info = padapter->wdinfo.wfd_info;
1280 
1281 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
1282 		goto exit;
1283 
1284 	/*	WFD OUI */
1285 	wfdielen = 0;
1286 	wfdie[wfdielen++] = 0x50;
1287 	wfdie[wfdielen++] = 0x6F;
1288 	wfdie[wfdielen++] = 0x9A;
1289 	wfdie[wfdielen++] = 0x0A;	/*	WFA WFD v1.0 */
1290 
1291 	/*	Commented by Albert 20110825 */
1292 	/*	According to the WFD Specification, the provision discovery response frame should contain 3 WFD attributes */
1293 	/*	1. WFD Device Information */
1294 	/*	2. Associated BSSID ( Optional ) */
1295 	/*	3. Local IP Adress ( Optional ) */
1296 
1297 
1298 	/*	WFD Device Information ATTR */
1299 	/*	Type: */
1300 	wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1301 
1302 	/*	Length: */
1303 	/*	Note: In the WFD specification, the size of length field is 2. */
1304 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1305 	wfdielen += 2;
1306 
1307 	/*	Value1: */
1308 	/*	WFD device information */
1309 	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1310 	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1311 	RTW_PUT_BE16(wfdie + wfdielen, val16);
1312 	wfdielen += 2;
1313 
1314 	/*	Value2: */
1315 	/*	Session Management Control Port */
1316 	/*	Default TCP port for RTSP messages is 554 */
1317 	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1318 	wfdielen += 2;
1319 
1320 	/*	Value3: */
1321 	/*	WFD Device Maximum Throughput */
1322 	/*	300Mbps is the maximum throughput */
1323 	RTW_PUT_BE16(wfdie + wfdielen, 300);
1324 	wfdielen += 2;
1325 
1326 	/*	Associated BSSID ATTR */
1327 	/*	Type: */
1328 	wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1329 
1330 	/*	Length: */
1331 	/*	Note: In the WFD specification, the size of length field is 2. */
1332 	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1333 	wfdielen += 2;
1334 
1335 	/*	Value: */
1336 	/*	Associated BSSID */
1337 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1338 		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1339 	else
1340 		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1341 
1342 	wfdielen += ETH_ALEN;
1343 
1344 	/*	Coupled Sink Information ATTR */
1345 	/*	Type: */
1346 	wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1347 
1348 	/*	Length: */
1349 	/*	Note: In the WFD specification, the size of length field is 2. */
1350 	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1351 	wfdielen += 2;
1352 
1353 	/*	Value: */
1354 	/*	Coupled Sink Status bitmap */
1355 	/*	Not coupled/available for Coupling */
1356 	wfdie[wfdielen++] = 0;
1357 	/* MAC Addr. */
1358 	wfdie[wfdielen++] = 0;
1359 	wfdie[wfdielen++] = 0;
1360 	wfdie[wfdielen++] = 0;
1361 	wfdie[wfdielen++] = 0;
1362 	wfdie[wfdielen++] = 0;
1363 	wfdie[wfdielen++] = 0;
1364 
1365 	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1366 
1367 exit:
1368 	return len;
1369 }
1370 #endif /* CONFIG_WFD */
1371 
process_probe_req_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)1372 u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
1373 {
1374 	u8 *p;
1375 	u32 ret = _FALSE;
1376 	u8 *p2pie;
1377 	u32	p2pielen = 0;
1378 	int ssid_len = 0, rate_cnt = 0;
1379 
1380 	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
1381 		       len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
1382 
1383 	if (rate_cnt <= 4) {
1384 		int i, g_rate = 0;
1385 
1386 		for (i = 0; i < rate_cnt; i++) {
1387 			if (((*(p + 2 + i) & 0xff) != 0x02) &&
1388 			    ((*(p + 2 + i) & 0xff) != 0x04) &&
1389 			    ((*(p + 2 + i) & 0xff) != 0x0B) &&
1390 			    ((*(p + 2 + i) & 0xff) != 0x16))
1391 				g_rate = 1;
1392 		}
1393 
1394 		if (g_rate == 0) {
1395 			/*	There is no OFDM rate included in SupportedRates IE of this probe request frame */
1396 			/*	The driver should response this probe request. */
1397 			return ret;
1398 		}
1399 	} else {
1400 		/*	rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */
1401 		/*	We should proceed the following check for this probe request. */
1402 	}
1403 
1404 	/*	Added comments by Albert 20100906 */
1405 	/*	There are several items we should check here. */
1406 	/*	1. This probe request frame must contain the P2P IE. (Done) */
1407 	/*	2. This probe request frame must contain the wildcard SSID. (Done) */
1408 	/*	3. Wildcard BSSID. (Todo) */
1409 	/*	4. Destination Address. ( Done in mgt_dispatcher function ) */
1410 	/*	5. Requested Device Type in WSC IE. (Todo) */
1411 	/*	6. Device ID attribute in P2P IE. (Todo) */
1412 
1413 	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
1414 		       len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
1415 
1416 	ssid_len &= 0xff;	/*	Just last 1 byte is valid for ssid len of the probe request */
1417 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1418 		p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_ , len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_ , NULL, &p2pielen);
1419 		if (p2pie) {
1420 			if ((p != NULL) && _rtw_memcmp((void *)(p + 2), (void *) pwdinfo->p2p_wildcard_ssid , 7)) {
1421 				/* todo: */
1422 				/* Check Requested Device Type attributes in WSC IE. */
1423 				/* Check Device ID attribute in P2P IE */
1424 
1425 				ret = _TRUE;
1426 			} else if ((p != NULL) && (ssid_len == 0))
1427 				ret = _TRUE;
1428 		} else {
1429 			/* non -p2p device */
1430 		}
1431 
1432 	}
1433 
1434 
1435 	return ret;
1436 
1437 }
1438 
process_assoc_req_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pframe,uint len,struct sta_info * psta)1439 u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
1440 {
1441 	u8 status_code = P2P_STATUS_SUCCESS;
1442 	u8 *pbuf, *pattr_content = NULL;
1443 	u32 attr_contentlen = 0;
1444 	u16 cap_attr = 0;
1445 	unsigned short	frame_type, ie_offset = 0;
1446 	u8 *ies;
1447 	u32 ies_len;
1448 	u8 *p2p_ie;
1449 	u32	p2p_ielen = 0;
1450 
1451 	if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1452 		return P2P_STATUS_FAIL_REQUEST_UNABLE;
1453 
1454 	frame_type = get_frame_sub_type(pframe);
1455 	if (frame_type == WIFI_ASSOCREQ)
1456 		ie_offset = _ASOCREQ_IE_OFFSET_;
1457 	else /* WIFI_REASSOCREQ */
1458 		ie_offset = _REASOCREQ_IE_OFFSET_;
1459 
1460 	ies = pframe + WLAN_HDR_A3_LEN + ie_offset;
1461 	ies_len = len - WLAN_HDR_A3_LEN - ie_offset;
1462 
1463 	p2p_ie = rtw_get_p2p_ie(ies , ies_len , NULL, &p2p_ielen);
1464 
1465 	if (!p2p_ie) {
1466 		RTW_INFO("[%s] P2P IE not Found!!\n", __FUNCTION__);
1467 		status_code =  P2P_STATUS_FAIL_INVALID_PARAM;
1468 	} else
1469 		RTW_INFO("[%s] P2P IE Found!!\n", __FUNCTION__);
1470 
1471 	while (p2p_ie) {
1472 		/* Check P2P Capability ATTR */
1473 		attr_contentlen = sizeof(cap_attr);
1474 		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *) &attr_contentlen)) {
1475 			RTW_INFO("[%s] Got P2P Capability Attr!!\n", __FUNCTION__);
1476 			cap_attr = le16_to_cpu(cap_attr);
1477 			psta->dev_cap = cap_attr & 0xff;
1478 		}
1479 
1480 		/* Check Extended Listen Timing ATTR */
1481 
1482 
1483 		/* Check P2P Device Info ATTR */
1484 		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint *)&attr_contentlen)) {
1485 			RTW_INFO("[%s] Got P2P DEVICE INFO Attr!!\n", __FUNCTION__);
1486 			pattr_content = pbuf = rtw_zmalloc(attr_contentlen);
1487 			if (pattr_content) {
1488 				u8 num_of_secdev_type;
1489 				u16 dev_name_len;
1490 
1491 
1492 				rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO , pattr_content, (uint *)&attr_contentlen);
1493 
1494 				_rtw_memcpy(psta->dev_addr, 	pattr_content, ETH_ALEN);/* P2P Device Address */
1495 
1496 				pattr_content += ETH_ALEN;
1497 
1498 				_rtw_memcpy(&psta->config_methods, pattr_content, 2);/* Config Methods */
1499 				psta->config_methods = be16_to_cpu(psta->config_methods);
1500 
1501 				pattr_content += 2;
1502 
1503 				_rtw_memcpy(psta->primary_dev_type, pattr_content, 8);
1504 
1505 				pattr_content += 8;
1506 
1507 				num_of_secdev_type = *pattr_content;
1508 				pattr_content += 1;
1509 
1510 				if (num_of_secdev_type == 0)
1511 					psta->num_of_secdev_type = 0;
1512 				else {
1513 					u32 len;
1514 
1515 					psta->num_of_secdev_type = num_of_secdev_type;
1516 
1517 					len = (sizeof(psta->secdev_types_list) < (num_of_secdev_type * 8)) ? (sizeof(psta->secdev_types_list)) : (num_of_secdev_type * 8);
1518 
1519 					_rtw_memcpy(psta->secdev_types_list, pattr_content, len);
1520 
1521 					pattr_content += (num_of_secdev_type * 8);
1522 				}
1523 
1524 
1525 				/* dev_name_len = attr_contentlen - ETH_ALEN - 2 - 8 - 1 - (num_of_secdev_type*8); */
1526 				psta->dev_name_len = 0;
1527 				if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(u16 *)pattr_content)) {
1528 					dev_name_len = be16_to_cpu(*(u16 *)(pattr_content + 2));
1529 
1530 					psta->dev_name_len = (sizeof(psta->dev_name) < dev_name_len) ? sizeof(psta->dev_name) : dev_name_len;
1531 
1532 					_rtw_memcpy(psta->dev_name, pattr_content + 4, psta->dev_name_len);
1533 				}
1534 
1535 				rtw_mfree(pbuf, attr_contentlen);
1536 
1537 			}
1538 
1539 		}
1540 
1541 		/* Get the next P2P IE */
1542 		p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
1543 
1544 	}
1545 
1546 	return status_code;
1547 
1548 }
1549 
1550 #ifdef CONFIG_IOCTL_CFG80211
1551 #if 0
1552 static void rtw_change_p2pie_op_ch(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
1553 {
1554 	u8 *ies, *p2p_ie;
1555 	u32 ies_len, p2p_ielen;
1556 
1557 	ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
1558 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
1559 
1560 	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
1561 
1562 	while (p2p_ie) {
1563 		u32	attr_contentlen = 0;
1564 		u8 *pattr = NULL;
1565 
1566 		/* Check P2P_ATTR_OPERATING_CH */
1567 		attr_contentlen = 0;
1568 		pattr = NULL;
1569 		pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
1570 		if (pattr != NULL)
1571 			*(pattr + 4) = ch;
1572 
1573 		/* Get the next P2P IE */
1574 		p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
1575 	}
1576 }
1577 #endif
1578 
1579 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
rtw_change_p2pie_ch_list(_adapter * padapter,const u8 * frame_body,u32 len,u8 ch)1580 static void rtw_change_p2pie_ch_list(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
1581 {
1582 	u8 *ies, *p2p_ie;
1583 	u32 ies_len, p2p_ielen;
1584 
1585 	ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
1586 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
1587 
1588 	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
1589 
1590 	while (p2p_ie) {
1591 		u32	attr_contentlen = 0;
1592 		u8 *pattr = NULL;
1593 
1594 		/* Check P2P_ATTR_CH_LIST */
1595 		pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
1596 		if (pattr != NULL) {
1597 			int i;
1598 			u32 num_of_ch;
1599 			u8 *pattr_temp = pattr + 3 ;
1600 
1601 			attr_contentlen -= 3;
1602 
1603 			while (attr_contentlen > 0) {
1604 				num_of_ch = *(pattr_temp + 1);
1605 
1606 				for (i = 0; i < num_of_ch; i++)
1607 					*(pattr_temp + 2 + i) = ch;
1608 
1609 				pattr_temp += (2 + num_of_ch);
1610 				attr_contentlen -= (2 + num_of_ch);
1611 			}
1612 		}
1613 
1614 		/* Get the next P2P IE */
1615 		p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
1616 	}
1617 }
1618 #endif
1619 
1620 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
rtw_chk_p2pie_ch_list_with_buddy(_adapter * padapter,const u8 * frame_body,u32 len)1621 static bool rtw_chk_p2pie_ch_list_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
1622 {
1623 	bool fit = _FALSE;
1624 	u8 *ies, *p2p_ie;
1625 	u32 ies_len, p2p_ielen;
1626 	u8 union_ch = rtw_mi_get_union_chan(padapter);
1627 
1628 	ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
1629 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
1630 
1631 	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
1632 
1633 	while (p2p_ie) {
1634 		u32	attr_contentlen = 0;
1635 		u8 *pattr = NULL;
1636 
1637 		/* Check P2P_ATTR_CH_LIST */
1638 		pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
1639 		if (pattr != NULL) {
1640 			int i;
1641 			u32 num_of_ch;
1642 			u8 *pattr_temp = pattr + 3 ;
1643 
1644 			attr_contentlen -= 3;
1645 
1646 			while (attr_contentlen > 0) {
1647 				num_of_ch = *(pattr_temp + 1);
1648 
1649 				for (i = 0; i < num_of_ch; i++) {
1650 					if (*(pattr_temp + 2 + i) == union_ch) {
1651 						RTW_INFO(FUNC_ADPT_FMT" ch_list fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), union_ch);
1652 						fit = _TRUE;
1653 						break;
1654 					}
1655 				}
1656 
1657 				pattr_temp += (2 + num_of_ch);
1658 				attr_contentlen -= (2 + num_of_ch);
1659 			}
1660 		}
1661 
1662 		/* Get the next P2P IE */
1663 		p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
1664 	}
1665 
1666 	return fit;
1667 }
1668 
1669 #if defined(CONFIG_P2P_INVITE_IOT)
rtw_chk_p2pie_op_ch_with_buddy(_adapter * padapter,const u8 * frame_body,u32 len)1670 static bool rtw_chk_p2pie_op_ch_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
1671 {
1672 	bool fit = _FALSE;
1673 	u8 *ies, *p2p_ie;
1674 	u32 ies_len, p2p_ielen;
1675 	u8 union_ch = rtw_mi_get_union_chan(padapter);
1676 
1677 	ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
1678 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
1679 
1680 	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
1681 
1682 	while (p2p_ie) {
1683 		u32	attr_contentlen = 0;
1684 		u8 *pattr = NULL;
1685 
1686 		/* Check P2P_ATTR_OPERATING_CH */
1687 		attr_contentlen = 0;
1688 		pattr = NULL;
1689 		pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
1690 		if (pattr != NULL) {
1691 			if (*(pattr + 4) == union_ch) {
1692 				RTW_INFO(FUNC_ADPT_FMT" op_ch fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), union_ch);
1693 				fit = _TRUE;
1694 				break;
1695 			}
1696 		}
1697 
1698 		/* Get the next P2P IE */
1699 		p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
1700 	}
1701 
1702 	return fit;
1703 }
1704 #endif
1705 
rtw_cfg80211_adjust_p2pie_channel(_adapter * padapter,const u8 * frame_body,u32 len)1706 static void rtw_cfg80211_adjust_p2pie_channel(_adapter *padapter, const u8 *frame_body, u32 len)
1707 {
1708 	u8 *ies, *p2p_ie;
1709 	u32 ies_len, p2p_ielen;
1710 	u8 union_ch = rtw_mi_get_union_chan(padapter);
1711 
1712 	ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
1713 	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
1714 
1715 	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
1716 
1717 	while (p2p_ie) {
1718 		u32	attr_contentlen = 0;
1719 		u8 *pattr = NULL;
1720 
1721 		/* Check P2P_ATTR_CH_LIST */
1722 		pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
1723 		if (pattr != NULL) {
1724 			int i;
1725 			u32 num_of_ch;
1726 			u8 *pattr_temp = pattr + 3 ;
1727 
1728 			attr_contentlen -= 3;
1729 
1730 			while (attr_contentlen > 0) {
1731 				num_of_ch = *(pattr_temp + 1);
1732 
1733 				for (i = 0; i < num_of_ch; i++) {
1734 					if (*(pattr_temp + 2 + i) && *(pattr_temp + 2 + i) != union_ch) {
1735 						RTW_ERR("replace ch_list:%u with:%u\n", *(pattr_temp + 2 + i), union_ch);
1736 						*(pattr_temp + 2 + i) = union_ch; /*forcing to the same channel*/
1737 					}
1738 				}
1739 
1740 				pattr_temp += (2 + num_of_ch);
1741 				attr_contentlen -= (2 + num_of_ch);
1742 			}
1743 		}
1744 
1745 		/* Check P2P_ATTR_OPERATING_CH */
1746 		attr_contentlen = 0;
1747 		pattr = NULL;
1748 		pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
1749 		if (pattr != NULL) {
1750 			if (*(pattr + 4) && *(pattr + 4) != union_ch) {
1751 				RTW_ERR("replace op_ch:%u with:%u\n", *(pattr + 4), union_ch);
1752 				*(pattr + 4) = union_ch; /*forcing to the same channel	*/
1753 			}
1754 		}
1755 
1756 		/* Get the next P2P IE */
1757 		p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
1758 
1759 	}
1760 
1761 }
1762 #endif
1763 
1764 #ifdef CONFIG_WFD
rtw_xframe_build_wfd_ie(struct xmit_frame * xframe)1765 u32 rtw_xframe_build_wfd_ie(struct xmit_frame *xframe)
1766 {
1767 	_adapter *adapter = xframe->padapter;
1768 	struct wifidirect_info *wdinfo = &adapter->wdinfo;
1769 	u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
1770 	u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
1771 	u8 *frame_tail = frame + xframe->attrib.pktlen;
1772 	u8 category, action, OUI_Subtype, dialogToken = 0;
1773 	u32	wfdielen = 0;
1774 
1775 	category = frame_body[0];
1776 	if (category == RTW_WLAN_CATEGORY_PUBLIC) {
1777 		action = frame_body[1];
1778 		if (action == ACT_PUBLIC_VENDOR
1779 		    && _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
1780 		   ) {
1781 			OUI_Subtype = frame_body[6];
1782 			dialogToken = frame_body[7];
1783 
1784 			switch (OUI_Subtype) {
1785 			case P2P_GO_NEGO_REQ:
1786 				wfdielen = build_nego_req_wfd_ie(wdinfo, frame_tail);
1787 				break;
1788 			case P2P_GO_NEGO_RESP:
1789 				wfdielen = build_nego_resp_wfd_ie(wdinfo, frame_tail);
1790 				break;
1791 			case P2P_GO_NEGO_CONF:
1792 				wfdielen = build_nego_confirm_wfd_ie(wdinfo, frame_tail);
1793 				break;
1794 			case P2P_INVIT_REQ:
1795 				wfdielen = build_invitation_req_wfd_ie(wdinfo, frame_tail);
1796 				break;
1797 			case P2P_INVIT_RESP:
1798 				wfdielen = build_invitation_resp_wfd_ie(wdinfo, frame_tail);
1799 				break;
1800 			case P2P_PROVISION_DISC_REQ:
1801 				wfdielen = build_provdisc_req_wfd_ie(wdinfo, frame_tail);
1802 				break;
1803 			case P2P_PROVISION_DISC_RESP:
1804 				wfdielen = build_provdisc_resp_wfd_ie(wdinfo, frame_tail);
1805 				break;
1806 			case P2P_DEVDISC_REQ:
1807 			case P2P_DEVDISC_RESP:
1808 			default:
1809 				break;
1810 			}
1811 
1812 		}
1813 	} else if (category == RTW_WLAN_CATEGORY_P2P) {
1814 		OUI_Subtype = frame_body[5];
1815 		dialogToken = frame_body[6];
1816 
1817 #ifdef CONFIG_DEBUG_CFG80211
1818 		RTW_INFO("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n"
1819 			, cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);
1820 #endif
1821 
1822 		switch (OUI_Subtype) {
1823 		case P2P_NOTICE_OF_ABSENCE:
1824 			break;
1825 		case P2P_PRESENCE_REQUEST:
1826 			break;
1827 		case P2P_PRESENCE_RESPONSE:
1828 			break;
1829 		case P2P_GO_DISC_REQUEST:
1830 			break;
1831 		default:
1832 			break;
1833 		}
1834 	} else
1835 		RTW_INFO("%s, action frame category=%d\n", __func__, category);
1836 
1837 	xframe->attrib.pktlen += wfdielen;
1838 
1839 	return wfdielen;
1840 }
1841 #endif /* CONFIG_WFD */
1842 
rtw_xframe_del_wfd_ie(struct xmit_frame * xframe)1843 bool rtw_xframe_del_wfd_ie(struct xmit_frame *xframe)
1844 {
1845 #define DBG_XFRAME_DEL_WFD_IE 0
1846 	u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
1847 	u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
1848 	u8 *frame_tail = frame + xframe->attrib.pktlen;
1849 	u8 category, action, OUI_Subtype;
1850 	u8 *ies = NULL;
1851 	uint ies_len_ori = 0;
1852 	uint ies_len = 0;
1853 
1854 	category = frame_body[0];
1855 	if (category == RTW_WLAN_CATEGORY_PUBLIC) {
1856 		action = frame_body[1];
1857 		if (action == ACT_PUBLIC_VENDOR
1858 		    && _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
1859 		   ) {
1860 			OUI_Subtype = frame_body[6];
1861 
1862 			switch (OUI_Subtype) {
1863 			case P2P_GO_NEGO_REQ:
1864 			case P2P_GO_NEGO_RESP:
1865 			case P2P_GO_NEGO_CONF:
1866 			case P2P_INVIT_REQ:
1867 			case P2P_INVIT_RESP:
1868 			case P2P_PROVISION_DISC_REQ:
1869 			case P2P_PROVISION_DISC_RESP:
1870 				ies = frame_body + 8;
1871 				ies_len_ori = frame_tail - (frame_body + 8);
1872 				break;
1873 			}
1874 		}
1875 	}
1876 
1877 	if (ies && ies_len_ori) {
1878 		ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_XFRAME_DEL_WFD_IE ? __func__ : NULL);
1879 		xframe->attrib.pktlen -= (ies_len_ori - ies_len);
1880 	}
1881 
1882 	return ies_len_ori != ies_len;
1883 }
1884 
1885 /*
1886 * rtw_xframe_chk_wfd_ie -
1887 *
1888 */
rtw_xframe_chk_wfd_ie(struct xmit_frame * xframe)1889 void rtw_xframe_chk_wfd_ie(struct xmit_frame *xframe)
1890 {
1891 	_adapter *adapter = xframe->padapter;
1892 #ifdef CONFIG_IOCTL_CFG80211
1893 	struct wifidirect_info *wdinfo = &adapter->wdinfo;
1894 #endif
1895 	u8 build = 0;
1896 	u8 del = 0;
1897 
1898 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(adapter), WL_FUNC_MIRACAST))
1899 		del = 1;
1900 
1901 #ifdef CONFIG_IOCTL_CFG80211
1902 	if (wdinfo->wfd_info->wfd_enable == _TRUE)
1903 #endif
1904 		del = build = 1;
1905 
1906 	if (del)
1907 		rtw_xframe_del_wfd_ie(xframe);
1908 
1909 #ifdef CONFIG_WFD
1910 	if (build)
1911 		rtw_xframe_build_wfd_ie(xframe);
1912 #endif
1913 }
1914 
dump_p2p_attr_ch_list(u8 * p2p_ie,uint p2p_ielen,u8 * buf,u32 buf_len)1915 u8 *dump_p2p_attr_ch_list(u8 *p2p_ie, uint p2p_ielen, u8 *buf, u32 buf_len)
1916 {
1917 	uint attr_contentlen = 0;
1918 	u8 *pattr = NULL;
1919 	int w_sz = 0;
1920 	u8 ch_cnt = 0;
1921 	u8 ch_list[40];
1922 
1923 	pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, &attr_contentlen);
1924 	if (pattr != NULL) {
1925 		int i, j;
1926 		u32 num_of_ch;
1927 		u8 *pattr_temp = pattr + 3 ;
1928 
1929 		attr_contentlen -= 3;
1930 
1931 		_rtw_memset(ch_list, 0, 40);
1932 
1933 		while (attr_contentlen > 0) {
1934 			num_of_ch = *(pattr_temp + 1);
1935 
1936 			for (i = 0; i < num_of_ch; i++) {
1937 				for (j = 0; j < ch_cnt; j++) {
1938 					if (ch_list[j] == *(pattr_temp + 2 + i))
1939 						break;
1940 				}
1941 				if (j >= ch_cnt)
1942 					ch_list[ch_cnt++] = *(pattr_temp + 2 + i);
1943 
1944 			}
1945 
1946 			pattr_temp += (2 + num_of_ch);
1947 			attr_contentlen -= (2 + num_of_ch);
1948 		}
1949 
1950 		for (j = 0; j < ch_cnt; j++) {
1951 			if (j == 0)
1952 				w_sz += snprintf(buf + w_sz, buf_len - w_sz, "%u", ch_list[j]);
1953 			else if (ch_list[j] - ch_list[j - 1] != 1)
1954 				w_sz += snprintf(buf + w_sz, buf_len - w_sz, ", %u", ch_list[j]);
1955 			else if (j != ch_cnt - 1 && ch_list[j + 1] - ch_list[j] == 1) {
1956 				/* empty */
1957 			} else
1958 				w_sz += snprintf(buf + w_sz, buf_len - w_sz, "-%u", ch_list[j]);
1959 		}
1960 	}
1961 	return buf;
1962 }
1963 
1964 /*
1965  * return _TRUE if requester is GO, _FALSE if responder is GO
1966  */
rtw_p2p_nego_intent_compare(u8 req,u8 resp)1967 bool rtw_p2p_nego_intent_compare(u8 req, u8 resp)
1968 {
1969 	if (req >> 1 == resp >> 1)
1970 		return  req & 0x01 ? _TRUE : _FALSE;
1971 	else if (req >> 1 > resp >> 1)
1972 		return _TRUE;
1973 	else
1974 		return _FALSE;
1975 }
1976 
rtw_p2p_check_frames(_adapter * padapter,const u8 * buf,u32 len,u8 tx)1977 int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx)
1978 {
1979 	int is_p2p_frame = (-1);
1980 	unsigned char	*frame_body;
1981 	u8 category, action, OUI_Subtype, dialogToken = 0;
1982 	u8 *p2p_ie = NULL;
1983 	uint p2p_ielen = 0;
1984 	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
1985 	int status = -1;
1986 	u8 ch_list_buf[128] = {'\0'};
1987 	int op_ch = -1;
1988 	int listen_ch = -1;
1989 	u8 intent = 0;
1990 	u8 *iaddr = NULL;
1991 	u8 *gbssid = NULL;
1992 
1993 	frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));
1994 	category = frame_body[0];
1995 	/* just for check */
1996 	if (category == RTW_WLAN_CATEGORY_PUBLIC) {
1997 		action = frame_body[1];
1998 		if (action == ACT_PUBLIC_VENDOR
1999 			&& _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
2000 		) {
2001 			OUI_Subtype = frame_body[6];
2002 			dialogToken = frame_body[7];
2003 			is_p2p_frame = OUI_Subtype;
2004 
2005 			#ifdef CONFIG_DEBUG_CFG80211
2006 			RTW_INFO("ACTION_CATEGORY_PUBLIC: ACT_PUBLIC_VENDOR, OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
2007 				cpu_to_be32(*((u32 *)(frame_body + 2))), OUI_Subtype, dialogToken);
2008 			#endif
2009 
2010 			p2p_ie = rtw_get_p2p_ie(
2011 				(u8 *)buf + sizeof(struct rtw_ieee80211_hdr_3addr) + _PUBLIC_ACTION_IE_OFFSET_
2012 				, len - sizeof(struct rtw_ieee80211_hdr_3addr) - _PUBLIC_ACTION_IE_OFFSET_
2013 				, NULL, &p2p_ielen);
2014 
2015 			switch (OUI_Subtype) { /* OUI Subtype */
2016 				u8 *cont;
2017 				uint cont_len;
2018 			case P2P_GO_NEGO_REQ: {
2019 				struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
2020 
2021 				if (tx) {
2022 					#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
2023 					if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
2024 						rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
2025 					#endif
2026 				}
2027 
2028 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
2029 				if (cont)
2030 					op_ch = *(cont + 4);
2031 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, NULL, &cont_len);
2032 				if (cont)
2033 					listen_ch = *(cont + 4);
2034 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len);
2035 				if (cont)
2036 					intent = *cont;
2037 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, NULL, &cont_len);
2038 				if (cont && cont_len == 6)
2039 					iaddr = cont;
2040 
2041 				if (nego_info->token != dialogToken)
2042 					rtw_wdev_nego_info_init(nego_info);
2043 
2044 				_rtw_memcpy(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN);
2045 				if (iaddr)
2046 					_rtw_memcpy(tx ? nego_info->iface_addr : nego_info->peer_iface_addr, iaddr, ETH_ALEN);
2047 				nego_info->active = tx ? 1 : 0;
2048 				nego_info->token = dialogToken;
2049 				nego_info->req_op_ch = op_ch;
2050 				nego_info->req_listen_ch = listen_ch;
2051 				nego_info->req_intent = intent;
2052 				nego_info->state = 0;
2053 
2054 				dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
2055 				RTW_INFO("RTW_%s:P2P_GO_NEGO_REQ, dialogToken=%d, intent:%u%s, listen_ch:%d, op_ch:%d, ch_list:%s"
2056 					, (tx == _TRUE) ? "Tx" : "Rx" , dialogToken , (intent >> 1) , intent & 0x1 ? "+" : "-" , listen_ch , op_ch , ch_list_buf);
2057 				if (iaddr)
2058 					_RTW_INFO(", iaddr:"MAC_FMT, MAC_ARG(iaddr));
2059 				_RTW_INFO("\n");
2060 
2061 				if (!tx) {
2062 					#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
2063 					if (rtw_mi_check_status(padapter, MI_LINKED)
2064 					    && rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE
2065 					    && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2066 						RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
2067 						rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
2068 					}
2069 					#endif
2070 				}
2071 
2072 				break;
2073 			}
2074 			case P2P_GO_NEGO_RESP: {
2075 				struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
2076 
2077 				if (tx) {
2078 					#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
2079 					if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
2080 						rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
2081 					#endif
2082 				}
2083 
2084 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
2085 				if (cont)
2086 					op_ch = *(cont + 4);
2087 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len);
2088 				if (cont)
2089 					intent = *cont;
2090 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
2091 				if (cont)
2092 					status = *cont;
2093 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, NULL, &cont_len);
2094 				if (cont && cont_len == 6)
2095 					iaddr = cont;
2096 
2097 				if (nego_info->token == dialogToken && nego_info->state == 0
2098 					&& _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE
2099 				) {
2100 					if (iaddr)
2101 						_rtw_memcpy(tx ? nego_info->iface_addr : nego_info->peer_iface_addr, iaddr, ETH_ALEN);
2102 					nego_info->status = (status == -1) ? 0xff : status;
2103 					nego_info->rsp_op_ch = op_ch;
2104 					nego_info->rsp_intent = intent;
2105 					nego_info->state = 1;
2106 					if (status != 0)
2107 						nego_info->token = 0; /* init */
2108 				}
2109 
2110 				dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
2111 				RTW_INFO("RTW_%s:P2P_GO_NEGO_RESP, dialogToken=%d, intent:%u%s, status:%d, op_ch:%d, ch_list:%s"
2112 					, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, (intent >> 1), intent & 0x1 ? "+" : "-", status, op_ch, ch_list_buf);
2113 				if (iaddr)
2114 					_RTW_INFO(", iaddr:"MAC_FMT, MAC_ARG(iaddr));
2115 				_RTW_INFO("\n");
2116 
2117 				if (!tx) {
2118 					#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
2119 					if (rtw_mi_check_status(padapter, MI_LINKED)
2120 					    && rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE
2121 					    && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2122 						RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
2123 						rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
2124 					}
2125 					#endif
2126 				}
2127 
2128 				break;
2129 			}
2130 			case P2P_GO_NEGO_CONF: {
2131 				struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
2132 				bool is_go = _FALSE;
2133 
2134 				if (tx) {
2135 					#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
2136 					if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
2137 						rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
2138 					#endif
2139 				}
2140 
2141 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
2142 				if (cont)
2143 					op_ch = *(cont + 4);
2144 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
2145 				if (cont)
2146 					status = *cont;
2147 
2148 				if (nego_info->token == dialogToken && nego_info->state == 1
2149 				    && _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE
2150 				   ) {
2151 					nego_info->status = (status == -1) ? 0xff : status;
2152 					nego_info->conf_op_ch = (op_ch == -1) ? 0 : op_ch;
2153 					nego_info->state = 2;
2154 
2155 					if (status == 0) {
2156 						if (rtw_p2p_nego_intent_compare(nego_info->req_intent, nego_info->rsp_intent) ^ !tx)
2157 							is_go = _TRUE;
2158 					}
2159 
2160 					nego_info->token = 0; /* init */
2161 				}
2162 
2163 				dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
2164 				RTW_INFO("RTW_%s:P2P_GO_NEGO_CONF, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n"
2165 					, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, status, op_ch, ch_list_buf);
2166 
2167 				if (!tx) {
2168 				}
2169 
2170 				break;
2171 			}
2172 			case P2P_INVIT_REQ: {
2173 				struct rtw_wdev_invit_info *invit_info = &pwdev_priv->invit_info;
2174 				int flags = -1;
2175 
2176 				if (tx) {
2177 					#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
2178 					if (rtw_mi_check_status(padapter, MI_LINKED)
2179 					    && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
2180 						rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
2181 					#endif
2182 				}
2183 
2184 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len);
2185 				if (cont)
2186 					flags = *cont;
2187 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
2188 				if (cont)
2189 					op_ch = *(cont + 4);
2190 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, NULL, &cont_len);
2191 				if (cont && cont_len == 6)
2192 					gbssid = cont;
2193 
2194 				if (invit_info->token != dialogToken)
2195 					rtw_wdev_invit_info_init(invit_info);
2196 
2197 				_rtw_memcpy(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN);
2198 				if (gbssid)
2199 					_rtw_memcpy(invit_info->group_bssid, gbssid, ETH_ALEN);
2200 				invit_info->active = tx ? 1 : 0;
2201 				invit_info->token = dialogToken;
2202 				invit_info->flags = (flags == -1) ? 0x0 : flags;
2203 				invit_info->req_op_ch = op_ch;
2204 				invit_info->state = 0;
2205 
2206 				dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
2207 				RTW_INFO("RTW_%s:P2P_INVIT_REQ, dialogToken=%d, flags:0x%02x, op_ch:%d, ch_list:%s"
2208 					, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, flags, op_ch, ch_list_buf);
2209 				if (gbssid)
2210 					_RTW_INFO(", gbssid:"MAC_FMT, MAC_ARG(gbssid));
2211 				_RTW_INFO("\n");
2212 
2213 				if (!tx) {
2214 					#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
2215 					if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2216 						#if defined(CONFIG_P2P_INVITE_IOT)
2217 						if (op_ch != -1 && rtw_chk_p2pie_op_ch_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
2218 							RTW_INFO(FUNC_ADPT_FMT" op_ch:%u has no intersect with buddy\n", FUNC_ADPT_ARG(padapter), op_ch);
2219 							rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
2220 						} else
2221 						#endif
2222 						if (rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
2223 							RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
2224 							rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
2225 						}
2226 					}
2227 					#endif
2228 				}
2229 
2230 				break;
2231 			}
2232 			case P2P_INVIT_RESP: {
2233 				struct rtw_wdev_invit_info *invit_info = &pwdev_priv->invit_info;
2234 
2235 				if (tx) {
2236 					#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
2237 					if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
2238 						rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
2239 					#endif
2240 				}
2241 
2242 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
2243 				if (cont) {
2244 					#ifdef CONFIG_P2P_INVITE_IOT
2245 					if (tx && *cont == 7) {
2246 						RTW_INFO("TX_P2P_INVITE_RESP, status is no common channel, change to unknown group\n");
2247 						*cont = 8; /* unknow group status */
2248 					}
2249 					#endif /* CONFIG_P2P_INVITE_IOT */
2250 					status = *cont;
2251 				}
2252 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
2253 				if (cont)
2254 					op_ch = *(cont + 4);
2255 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, NULL, &cont_len);
2256 				if (cont && cont_len == 6)
2257 					gbssid = cont;
2258 
2259 				if (invit_info->token == dialogToken && invit_info->state == 0
2260 				    && _rtw_memcmp(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE
2261 				   ) {
2262 					invit_info->status = (status == -1) ? 0xff : status;
2263 					invit_info->rsp_op_ch = op_ch;
2264 					invit_info->state = 1;
2265 					invit_info->token = 0; /* init */
2266 				}
2267 
2268 				dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
2269 				RTW_INFO("RTW_%s:P2P_INVIT_RESP, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s"
2270 					, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, status, op_ch, ch_list_buf);
2271 				if (gbssid)
2272 					_RTW_INFO(", gbssid:"MAC_FMT, MAC_ARG(gbssid));
2273 				_RTW_INFO("\n");
2274 
2275 				if (!tx) {
2276 				}
2277 
2278 				break;
2279 			}
2280 			case P2P_DEVDISC_REQ:
2281 				RTW_INFO("RTW_%s:P2P_DEVDISC_REQ, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
2282 				break;
2283 			case P2P_DEVDISC_RESP:
2284 				cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
2285 				RTW_INFO("RTW_%s:P2P_DEVDISC_RESP, dialogToken=%d, status:%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken, cont ? *cont : -1);
2286 				break;
2287 			case P2P_PROVISION_DISC_REQ:
2288 				RTW_INFO("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
2289 				break;
2290 			case P2P_PROVISION_DISC_RESP:
2291 				RTW_INFO("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
2292 				break;
2293 			default:
2294 				RTW_INFO("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", OUI_Subtype, dialogToken);
2295 				break;
2296 			}
2297 
2298 		}
2299 
2300 	} else if (category == RTW_WLAN_CATEGORY_P2P) {
2301 		OUI_Subtype = frame_body[5];
2302 		dialogToken = frame_body[6];
2303 
2304 		#ifdef CONFIG_DEBUG_CFG80211
2305 		RTW_INFO("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
2306 			cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);
2307 		#endif
2308 
2309 		is_p2p_frame = OUI_Subtype;
2310 
2311 		switch (OUI_Subtype) {
2312 		case P2P_NOTICE_OF_ABSENCE:
2313 			RTW_INFO("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
2314 			break;
2315 		case P2P_PRESENCE_REQUEST:
2316 			RTW_INFO("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
2317 			break;
2318 		case P2P_PRESENCE_RESPONSE:
2319 			RTW_INFO("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
2320 			break;
2321 		case P2P_GO_DISC_REQUEST:
2322 			RTW_INFO("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
2323 			break;
2324 		default:
2325 			RTW_INFO("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", OUI_Subtype, dialogToken);
2326 			break;
2327 		}
2328 
2329 	}
2330 
2331 	return is_p2p_frame;
2332 }
2333 #endif /* CONFIG_IOCTL_CFG80211	 */
2334 
process_p2p_cross_connect_ie(_adapter * padapter,u8 * IEs,u32 IELength)2335 int process_p2p_cross_connect_ie(_adapter *padapter, u8 *IEs, u32 IELength)
2336 {
2337 	int ret = _TRUE;
2338 	u8 *ies;
2339 	u32 ies_len;
2340 	u8 *p2p_ie;
2341 	u32	p2p_ielen = 0;
2342 	u8	p2p_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */
2343 	u32	attr_contentlen = 0;
2344 
2345 
2346 
2347 	if (IELength <= _BEACON_IE_OFFSET_)
2348 		return ret;
2349 
2350 	ies = IEs + _BEACON_IE_OFFSET_;
2351 	ies_len = IELength - _BEACON_IE_OFFSET_;
2352 
2353 	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2354 
2355 	while (p2p_ie) {
2356 		/* Get P2P Manageability IE. */
2357 		attr_contentlen = sizeof(p2p_attr);
2358 		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_MANAGEABILITY, p2p_attr, &attr_contentlen)) {
2359 			if ((p2p_attr[0] & (BIT(0) | BIT(1))) == 0x01)
2360 				ret = _FALSE;
2361 			break;
2362 		}
2363 		/* Get the next P2P IE */
2364 		p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2365 	}
2366 
2367 	return ret;
2368 }
2369 
2370 #ifdef CONFIG_P2P_PS
process_p2p_ps_ie(_adapter * padapter,u8 * IEs,u32 IELength)2371 void process_p2p_ps_ie(_adapter *padapter, u8 *IEs, u32 IELength)
2372 {
2373 	u8 *ies;
2374 	u32 ies_len;
2375 	u8 *p2p_ie;
2376 	u32	p2p_ielen = 0;
2377 	u8 *noa_attr; /* NoA length should be n*(13) + 2 */
2378 	u32	attr_contentlen = 0;
2379 
2380 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
2381 	u8	find_p2p = _FALSE, find_p2p_ps = _FALSE;
2382 	u8	noa_offset, noa_num, noa_index;
2383 
2384 
2385 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DISABLE) ||
2386 	    rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
2387 		return;
2388 
2389 	if (IELength <= _BEACON_IE_OFFSET_)
2390 		return;
2391 
2392 	ies = IEs + _BEACON_IE_OFFSET_;
2393 	ies_len = IELength - _BEACON_IE_OFFSET_;
2394 
2395 	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2396 
2397 	while (p2p_ie) {
2398 		find_p2p = _TRUE;
2399 		/* Get Notice of Absence IE. */
2400 		noa_attr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, NULL, &attr_contentlen);
2401 		if (noa_attr) {
2402 			find_p2p_ps = _TRUE;
2403 			noa_index = noa_attr[0];
2404 
2405 			if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
2406 			    (noa_index != pwdinfo->noa_index)) { /* if index change, driver should reconfigure related setting. */
2407 				pwdinfo->noa_index = noa_index;
2408 				pwdinfo->opp_ps = noa_attr[1] >> 7;
2409 				if (pwdinfo->opp_ps != 1)
2410 					pwdinfo->ctwindow = 0;
2411 				else
2412 					pwdinfo->ctwindow = noa_attr[1] & 0x7F;
2413 				noa_offset = 2;
2414 				noa_num = 0;
2415 				/* NoA length should be n*(13) + 2 */
2416 				if (attr_contentlen > 2 && (attr_contentlen - 2) % 13 == 0) {
2417 					while (noa_offset < attr_contentlen && noa_num < P2P_MAX_NOA_NUM) {
2418 						/* _rtw_memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
2419 						pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
2420 						noa_offset += 1;
2421 
2422 						_rtw_memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
2423 						noa_offset += 4;
2424 
2425 						_rtw_memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
2426 						noa_offset += 4;
2427 
2428 						_rtw_memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
2429 						noa_offset += 4;
2430 
2431 						noa_num++;
2432 					}
2433 				}
2434 				pwdinfo->noa_num = noa_num;
2435 
2436 				if (pwdinfo->opp_ps == 1) {
2437 					pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
2438 					/* driver should wait LPS for entering CTWindow */
2439 					if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
2440 						p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
2441 				} else if (pwdinfo->noa_num > 0) {
2442 					pwdinfo->p2p_ps_mode = P2P_PS_NOA;
2443 					p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
2444 				} else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)
2445 					p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
2446 			}
2447 
2448 			break; /* find target, just break. */
2449 		}
2450 
2451 		/* Get the next P2P IE */
2452 		p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2453 
2454 	}
2455 
2456 	if (find_p2p == _TRUE) {
2457 		if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == _FALSE))
2458 			p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
2459 	}
2460 
2461 }
2462 
p2p_ps_wk_hdl(_adapter * padapter,u8 p2p_ps_state)2463 void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state)
2464 {
2465 	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
2466 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2467 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2468 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2469 	int i;
2470 
2471 	/* Pre action for p2p state */
2472 	switch (p2p_ps_state) {
2473 	case P2P_PS_DISABLE:
2474 		RTW_INFO("%s, P2P PS disabled\n", __func__);
2475 
2476 		rtw_phl_p2pps_noa_disable_all(GET_PHL_INFO(dvobj),
2477 					      padapter->phl_role);
2478 		pwdinfo->p2p_ps_mode = P2P_PS_NONE;
2479 		pwdinfo->p2p_ps_state = p2p_ps_state;
2480 		pwdinfo->noa_index = 0;
2481 		pwdinfo->ctwindow = 0;
2482 		pwdinfo->opp_ps = 0;
2483 		pwdinfo->noa_num = 0;
2484 		for (i = 0; i < P2P_MAX_NOA_NUM; i++) {
2485 			pwdinfo->noa_count[i] = 0;
2486 			pwdinfo->noa_duration[i] = 0;
2487 			pwdinfo->noa_interval[i] = 0;
2488 			pwdinfo->noa_start_time[i] = 0;
2489 		}
2490 
2491 		break;
2492 	case P2P_PS_ENABLE:
2493 		if (pwdinfo->p2p_ps_mode <= P2P_PS_NONE)
2494 			return;
2495 
2496 		RTW_INFO("%s, P2P PS enabled\n", __func__);
2497 
2498 		/* Disable all NoA desc before update NoA desc */
2499 		rtw_phl_p2pps_noa_disable_all(GET_PHL_INFO(dvobj),
2500 					      padapter->phl_role);
2501 
2502 		for (i = 0; i < pwdinfo->noa_num; i++) {
2503 			struct rtw_phl_noa_desc desc = {0};
2504 			enum rtw_phl_status phl_sts;
2505 
2506 			desc.enable = _TRUE;
2507 			/* config NOA start time */
2508 			desc.start_t_h = (u32)(pmlmeext->TSFValue >> 32);
2509 			desc.start_t_l = pwdinfo->noa_start_time[i];
2510 			/* config NOA duration */
2511 			desc.duration = pwdinfo->noa_duration[i];
2512 			/* config NOA interval */
2513 			desc.interval = pwdinfo->noa_interval[i];
2514 			/* config NOA count */
2515 			desc.count = pwdinfo->noa_count[i];
2516 			desc.w_role = padapter->phl_role;
2517 			if (pwdinfo->noa_count[i] == 255)
2518 				desc.tag = P2PPS_TRIG_GC_255;
2519 			else
2520 				desc.tag = P2PPS_TRIG_GC;
2521 
2522 			RTW_INFO("[NoA Desc]- entry: %d\n", i);
2523 			RTW_INFO("[NoA Desc]- duration: %u\n", desc.duration);
2524 			RTW_INFO("[NoA Desc]- interval: %u\n", desc.interval);
2525 			RTW_INFO("[NoA Desc]- high_start_time: %u\n",
2526 				 desc.start_t_h);
2527 			RTW_INFO("[NoA Desc]- low_start_time: %u\n",
2528 				 desc.start_t_l);
2529 			RTW_INFO("[NoA Desc]- count: %u\n",desc.count);
2530 
2531 			phl_sts = rtw_phl_p2pps_noa_update(GET_PHL_INFO(dvobj),
2532 							   &desc);
2533 			if (phl_sts != RTW_PHL_STATUS_SUCCESS)
2534 				RTW_ERR("rtw_phl_p2pps_noa_update failed\n");
2535 		}
2536 
2537 		break;
2538 	case P2P_PS_SCAN:
2539 	case P2P_PS_SCAN_DONE:
2540 	case P2P_PS_ALLSTASLEEP:
2541 		if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
2542 			pwdinfo->p2p_ps_state = p2p_ps_state;
2543 			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
2544 		}
2545 		break;
2546 	default:
2547 		break;
2548 	}
2549 }
2550 
p2p_ps_wk_cmd(_adapter * padapter,u8 p2p_ps_state,u8 enqueue)2551 u8 p2p_ps_wk_cmd(_adapter *padapter, u8 p2p_ps_state, u8 enqueue)
2552 {
2553 	struct cmd_obj	*cmd;
2554 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
2555 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
2556 	struct cmd_priv	*pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
2557 	u8 res = _SUCCESS;
2558 
2559 
2560 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DISABLE) ||
2561 	    rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
2562 		return res;
2563 
2564 	if (enqueue) {
2565 		cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2566 		if (cmd == NULL) {
2567 			res = _FAIL;
2568 			goto exit;
2569 		}
2570 		cmd->padapter = padapter;
2571 
2572 		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2573 		if (pdrvextra_cmd_parm == NULL) {
2574 			rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
2575 			res = _FAIL;
2576 			goto exit;
2577 		}
2578 
2579 		pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
2580 		pdrvextra_cmd_parm->type = p2p_ps_state;
2581 		pdrvextra_cmd_parm->size = 0;
2582 		pdrvextra_cmd_parm->pbuf = NULL;
2583 
2584 		init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
2585 
2586 		res = rtw_enqueue_cmd(pcmdpriv, cmd);
2587 	} else
2588 		p2p_ps_wk_hdl(padapter, p2p_ps_state);
2589 exit:
2590 	return res;
2591 }
2592 #endif /* CONFIG_P2P_PS */
2593 
reset_global_wifidirect_info(_adapter * padapter)2594 void reset_global_wifidirect_info(_adapter *padapter)
2595 {
2596 	struct wifidirect_info	*pwdinfo;
2597 
2598 	pwdinfo = &padapter->wdinfo;
2599 	rtw_tdls_wfd_enable(padapter, 0);
2600 	pwdinfo->wfd_tdls_weaksec = _TRUE;
2601 }
2602 
2603 #ifdef CONFIG_WFD
rtw_init_wifi_display_info(_adapter * padapter)2604 int rtw_init_wifi_display_info(_adapter *padapter)
2605 {
2606 	int	res = _SUCCESS;
2607 	struct wifi_display_info *pwfd_info = &padapter->wfd_info;
2608 
2609 	/* Used in P2P and TDLS */
2610 	pwfd_info->init_rtsp_ctrlport = 554;
2611 #ifdef CONFIG_IOCTL_CFG80211
2612 	pwfd_info->rtsp_ctrlport = 0;
2613 #else
2614 	pwfd_info->rtsp_ctrlport = pwfd_info->init_rtsp_ctrlport; /* set non-zero value for legacy wfd */
2615 #endif
2616 	pwfd_info->tdls_rtsp_ctrlport = 0;
2617 	pwfd_info->peer_rtsp_ctrlport = 0;	/*	Reset to 0 */
2618 	pwfd_info->wfd_enable = _FALSE;
2619 	pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
2620 	pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
2621 
2622 	/* Used in P2P */
2623 	pwfd_info->peer_session_avail = _TRUE;
2624 	pwfd_info->wfd_pc = _FALSE;
2625 
2626 	/* Used in TDLS */
2627 	_rtw_memset(pwfd_info->ip_address, 0x00, 4);
2628 	_rtw_memset(pwfd_info->peer_ip_address, 0x00, 4);
2629 	return res;
2630 
2631 }
2632 
rtw_wfd_enable(_adapter * adapter,bool on)2633 inline void rtw_wfd_enable(_adapter *adapter, bool on)
2634 {
2635 	struct wifi_display_info *wfdinfo = &adapter->wfd_info;
2636 
2637 	if (on) {
2638 		wfdinfo->rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;
2639 		wfdinfo->wfd_enable = _TRUE;
2640 
2641 	} else {
2642 		wfdinfo->wfd_enable = _FALSE;
2643 		wfdinfo->rtsp_ctrlport = 0;
2644 	}
2645 }
2646 
rtw_wfd_set_ctrl_port(_adapter * adapter,u16 port)2647 inline void rtw_wfd_set_ctrl_port(_adapter *adapter, u16 port)
2648 {
2649 	struct wifi_display_info *wfdinfo = &adapter->wfd_info;
2650 
2651 	wfdinfo->init_rtsp_ctrlport = port;
2652 	if (wfdinfo->wfd_enable == _TRUE)
2653 		wfdinfo->rtsp_ctrlport = port;
2654 	if (adapter->wdinfo.wfd_tdls_enable == 1)
2655 		wfdinfo->tdls_rtsp_ctrlport = port;
2656 }
2657 
rtw_tdls_wfd_enable(_adapter * adapter,bool on)2658 inline void rtw_tdls_wfd_enable(_adapter *adapter, bool on)
2659 {
2660 	struct wifi_display_info *wfdinfo = &adapter->wfd_info;
2661 
2662 	if (on) {
2663 		wfdinfo->tdls_rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;
2664 		adapter->wdinfo.wfd_tdls_enable = 1;
2665 
2666 	} else {
2667 		adapter->wdinfo.wfd_tdls_enable = 0;
2668 		wfdinfo->tdls_rtsp_ctrlport = 0;
2669 	}
2670 }
2671 
rtw_append_beacon_wfd_ie(_adapter * adapter,u8 * pbuf)2672 u32 rtw_append_beacon_wfd_ie(_adapter *adapter, u8 *pbuf)
2673 {
2674 	struct wifidirect_info *wdinfo = &adapter->wdinfo;
2675 	struct mlme_priv *mlme = &adapter->mlmepriv;
2676 	u8 build_ie_by_self = 0;
2677 	u32 len = 0;
2678 
2679 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(adapter), WL_FUNC_MIRACAST))
2680 		goto exit;
2681 
2682 #ifdef CONFIG_IOCTL_CFG80211
2683 	if (_TRUE == wdinfo->wfd_info->wfd_enable)
2684 #endif
2685 		build_ie_by_self = 1;
2686 
2687 	if (build_ie_by_self)
2688 		len = build_beacon_wfd_ie(wdinfo, pbuf);
2689 #ifdef CONFIG_IOCTL_CFG80211
2690 	else if (mlme->wfd_beacon_ie && mlme->wfd_beacon_ie_len > 0) {
2691 		len = mlme->wfd_beacon_ie_len;
2692 		_rtw_memcpy(pbuf, mlme->wfd_beacon_ie, len);
2693 	}
2694 #endif
2695 
2696 exit:
2697 	return len;
2698 }
2699 
rtw_append_probe_req_wfd_ie(_adapter * adapter,u8 * pbuf)2700 u32 rtw_append_probe_req_wfd_ie(_adapter *adapter, u8 *pbuf)
2701 {
2702 	struct wifidirect_info *wdinfo = &adapter->wdinfo;
2703 	struct mlme_priv *mlme = &adapter->mlmepriv;
2704 	u8 build_ie_by_self = 0;
2705 	u32 len = 0;
2706 
2707 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(adapter), WL_FUNC_MIRACAST))
2708 		goto exit;
2709 
2710 #ifdef CONFIG_IOCTL_CFG80211
2711 	if (_TRUE == wdinfo->wfd_info->wfd_enable)
2712 #endif
2713 		build_ie_by_self = 1;
2714 
2715 	if (build_ie_by_self)
2716 		len = build_probe_req_wfd_ie(wdinfo, pbuf);
2717 #ifdef CONFIG_IOCTL_CFG80211
2718 	else if (mlme->wfd_probe_req_ie && mlme->wfd_probe_req_ie_len > 0) {
2719 		len = mlme->wfd_probe_req_ie_len;
2720 		_rtw_memcpy(pbuf, mlme->wfd_probe_req_ie, len);
2721 	}
2722 #endif
2723 
2724 exit:
2725 	return len;
2726 }
2727 
rtw_append_probe_resp_wfd_ie(_adapter * adapter,u8 * pbuf)2728 u32 rtw_append_probe_resp_wfd_ie(_adapter *adapter, u8 *pbuf)
2729 {
2730 	struct wifidirect_info *wdinfo = &adapter->wdinfo;
2731 	struct mlme_priv *mlme = &adapter->mlmepriv;
2732 	u8 build_ie_by_self = 0;
2733 	u32 len = 0;
2734 
2735 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(adapter), WL_FUNC_MIRACAST))
2736 		goto exit;
2737 
2738 #ifdef CONFIG_IOCTL_CFG80211
2739 	if (_TRUE == wdinfo->wfd_info->wfd_enable)
2740 #endif
2741 		build_ie_by_self = 1;
2742 
2743 	if (build_ie_by_self)
2744 		len = build_probe_resp_wfd_ie(wdinfo, pbuf, 0);
2745 #ifdef CONFIG_IOCTL_CFG80211
2746 	else if (mlme->wfd_probe_resp_ie && mlme->wfd_probe_resp_ie_len > 0) {
2747 		len = mlme->wfd_probe_resp_ie_len;
2748 		_rtw_memcpy(pbuf, mlme->wfd_probe_resp_ie, len);
2749 	}
2750 #endif
2751 
2752 exit:
2753 	return len;
2754 }
2755 
rtw_append_assoc_req_wfd_ie(_adapter * adapter,u8 * pbuf)2756 u32 rtw_append_assoc_req_wfd_ie(_adapter *adapter, u8 *pbuf)
2757 {
2758 	struct wifidirect_info *wdinfo = &adapter->wdinfo;
2759 	struct mlme_priv *mlme = &adapter->mlmepriv;
2760 	u8 build_ie_by_self = 0;
2761 	u32 len = 0;
2762 
2763 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(adapter), WL_FUNC_MIRACAST))
2764 		goto exit;
2765 
2766 #ifdef CONFIG_IOCTL_CFG80211
2767 	if (_TRUE == wdinfo->wfd_info->wfd_enable)
2768 #endif
2769 		build_ie_by_self = 1;
2770 
2771 	if (build_ie_by_self)
2772 		len = build_assoc_req_wfd_ie(wdinfo, pbuf);
2773 #ifdef CONFIG_IOCTL_CFG80211
2774 	else if (mlme->wfd_assoc_req_ie && mlme->wfd_assoc_req_ie_len > 0) {
2775 		len = mlme->wfd_assoc_req_ie_len;
2776 		_rtw_memcpy(pbuf, mlme->wfd_assoc_req_ie, len);
2777 	}
2778 #endif
2779 
2780 exit:
2781 	return len;
2782 }
2783 
rtw_append_assoc_resp_wfd_ie(_adapter * adapter,u8 * pbuf)2784 u32 rtw_append_assoc_resp_wfd_ie(_adapter *adapter, u8 *pbuf)
2785 {
2786 	struct wifidirect_info *wdinfo = &adapter->wdinfo;
2787 	struct mlme_priv *mlme = &adapter->mlmepriv;
2788 	u8 build_ie_by_self = 0;
2789 	u32 len = 0;
2790 
2791 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(adapter), WL_FUNC_MIRACAST))
2792 		goto exit;
2793 
2794 #ifdef CONFIG_IOCTL_CFG80211
2795 	if (_TRUE == wdinfo->wfd_info->wfd_enable)
2796 #endif
2797 		build_ie_by_self = 1;
2798 
2799 	if (build_ie_by_self)
2800 		len = build_assoc_resp_wfd_ie(wdinfo, pbuf);
2801 #ifdef CONFIG_IOCTL_CFG80211
2802 	else if (mlme->wfd_assoc_resp_ie && mlme->wfd_assoc_resp_ie_len > 0) {
2803 		len = mlme->wfd_assoc_resp_ie_len;
2804 		_rtw_memcpy(pbuf, mlme->wfd_assoc_resp_ie, len);
2805 	}
2806 #endif
2807 
2808 exit:
2809 	return len;
2810 }
2811 
2812 #endif /* CONFIG_WFD */
2813 
init_wifidirect_info(_adapter * padapter,enum P2P_ROLE role)2814 void init_wifidirect_info(_adapter *padapter, enum P2P_ROLE role)
2815 {
2816 	struct wifidirect_info	*pwdinfo;
2817 #ifdef CONFIG_WFD
2818 	struct wifi_display_info	*pwfd_info = &padapter->wfd_info;
2819 #endif
2820 	pwdinfo = &padapter->wdinfo;
2821 
2822 	pwdinfo->padapter = padapter;
2823 
2824 	if (role == P2P_ROLE_DEVICE)
2825 		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2826 	else if (role == P2P_ROLE_CLIENT)
2827 		rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2828 	else if (role == P2P_ROLE_GO)
2829 		rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2830 
2831 	/*	Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 )	 */
2832 	pwdinfo->support_rate[0] = 0x8c;	/*	6(B) */
2833 	pwdinfo->support_rate[1] = 0x92;	/*	9(B) */
2834 	pwdinfo->support_rate[2] = 0x18;	/*	12 */
2835 	pwdinfo->support_rate[3] = 0x24;	/*	18 */
2836 	pwdinfo->support_rate[4] = 0x30;	/*	24 */
2837 	pwdinfo->support_rate[5] = 0x48;	/*	36 */
2838 	pwdinfo->support_rate[6] = 0x60;	/*	48 */
2839 	pwdinfo->support_rate[7] = 0x6c;	/*	54 */
2840 
2841 	_rtw_memcpy((void *) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
2842 
2843 #ifdef CONFIG_WFD
2844 	pwdinfo->wfd_info = pwfd_info;
2845 #endif /* CONFIG_WFD */
2846 
2847 	pwdinfo->wfd_tdls_enable = 0;
2848 }
2849 
_rtw_p2p_set_role(struct wifidirect_info * wdinfo,enum P2P_ROLE role)2850 void _rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role)
2851 {
2852 	if (wdinfo->role != role) {
2853 		wdinfo->role = role;
2854 		rtw_mi_update_iface_status(&(wdinfo->padapter->mlmepriv), 0);
2855 	}
2856 }
2857 
2858 #ifdef CONFIG_DBG_P2P
2859 
2860 /**
2861  * rtw_p2p_role_txt - Get the p2p role name as a text string
2862  * @role: P2P role
2863  * Returns: The state name as a printable text string
2864  */
rtw_p2p_role_txt(enum P2P_ROLE role)2865 const char *rtw_p2p_role_txt(enum P2P_ROLE role)
2866 {
2867 	switch (role) {
2868 	case P2P_ROLE_DISABLE:
2869 		return "P2P_ROLE_DISABLE";
2870 	case P2P_ROLE_DEVICE:
2871 		return "P2P_ROLE_DEVICE";
2872 	case P2P_ROLE_CLIENT:
2873 		return "P2P_ROLE_CLIENT";
2874 	case P2P_ROLE_GO:
2875 		return "P2P_ROLE_GO";
2876 	default:
2877 		return "UNKNOWN";
2878 	}
2879 }
2880 
2881 /**
2882  * rtw_p2p_state_txt - Get the p2p state name as a text string
2883  * @state: P2P state
2884  * Returns: The state name as a printable text string
2885  */
rtw_p2p_state_txt(enum P2P_STATE state)2886 const char *rtw_p2p_state_txt(enum P2P_STATE state)
2887 {
2888 	switch (state) {
2889 	case P2P_STATE_NONE:
2890 		return "P2P_STATE_NONE";
2891 	case P2P_STATE_IDLE:
2892 		return "P2P_STATE_IDLE";
2893 	case P2P_STATE_LISTEN:
2894 		return "P2P_STATE_LISTEN";
2895 	case P2P_STATE_FIND_PHASE_SEARCH:
2896 		return "P2P_STATE_FIND_PHASE_SEARCH";
2897 	case P2P_STATE_GONEGO_OK:
2898 		return "P2P_STATE_GONEGO_OK";
2899 	default:
2900 		return "UNKNOWN";
2901 	}
2902 }
2903 
2904 #if 0
2905 void dbg_rtw_p2p_restore_state(struct wifidirect_info *wdinfo, const char *caller, int line)
2906 {
2907 	if (wdinfo->pre_p2p_state != -1) {
2908 		RTW_INFO("[CONFIG_DBG_P2P]%s:%d restore from %s to %s\n", caller, line
2909 			, p2p_state_str[wdinfo->p2p_state], p2p_state_str[wdinfo->pre_p2p_state]
2910 			);
2911 		_rtw_p2p_restore_state(wdinfo);
2912 	} else {
2913 		RTW_INFO("[CONFIG_DBG_P2P]%s:%d restore no pre state, cur state %s\n", caller, line
2914 			 , p2p_state_str[wdinfo->p2p_state]
2915 			);
2916 	}
2917 }
2918 #endif
dbg_rtw_p2p_set_role(struct wifidirect_info * wdinfo,enum P2P_ROLE role,const char * caller,int line)2919 void dbg_rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role, const char *caller, int line)
2920 {
2921 	if (wdinfo->role != role) {
2922 		enum P2P_ROLE old_role = wdinfo->role;
2923 		_rtw_p2p_set_role(wdinfo, role);
2924 		RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_role from %s to %s\n", caller, line
2925 			, rtw_p2p_role_txt(old_role), rtw_p2p_role_txt(wdinfo->role)
2926 			);
2927 	} else {
2928 		RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_role to same role %s\n", caller, line
2929 			 , rtw_p2p_role_txt(wdinfo->role)
2930 			);
2931 	}
2932 }
2933 #endif /* CONFIG_DBG_P2P */
2934 
2935 
rtw_p2p_enable(_adapter * padapter,enum P2P_ROLE role)2936 int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role)
2937 {
2938 	int ret = _SUCCESS;
2939 	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2940 
2941 	if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT || role == P2P_ROLE_GO) {
2942 #ifndef RTW_USE_CFG80211_REPORT_PROBE_REQ
2943 #if defined(CONFIG_CONCURRENT_MODE) && !RTW_P2P_GROUP_INTERFACE
2944 		/*	Commented by Albert 2011/12/30 */
2945 		/*	The driver just supports 1 P2P group operation. */
2946 		/*	So, this function will do nothing if the buddy adapter had enabled the P2P function. */
2947 		/*if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
2948 			return ret;*/
2949 		/* Only selected interface can be P2P interface */
2950 		if (padapter->iface_id != padapter->registrypriv.sel_p2p_iface) {
2951 			RTW_ERR("%s, iface_id:%d is not P2P interface!\n", __func__, padapter->iface_id);
2952 			ret = _FAIL;
2953 			return ret;
2954 		}
2955 #endif
2956 #endif
2957 		/* leave IPS/Autosuspend */
2958 		if (_FAIL == rtw_pwr_wakeup(padapter)) {
2959 			ret = _FAIL;
2960 			goto exit;
2961 		}
2962 
2963 		/* The P2P device does not need to remove the CCK rate of the
2964 		 * adapter as it can act as an STA.
2965 		 */
2966 		if (role != P2P_ROLE_DEVICE)
2967 			update_tx_basic_rate(padapter, WLAN_MD_11AGN);
2968 
2969 		/* Enable P2P function */
2970 		init_wifidirect_info(padapter, role);
2971 
2972 		#ifdef CONFIG_IOCTL_CFG80211
2973 		adapter_wdev_data(padapter)->p2p_enabled = _TRUE;
2974 		#endif
2975 
2976 #if 0
2977 		rtw_hal_set_phydm_var(padapter, HAL_PHYDM_P2P_STATE, NULL, _TRUE);
2978 #ifdef CONFIG_WFD
2979 		if (rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
2980 			rtw_hal_set_phydm_var(padapter, HAL_PHYDM_WIFI_DISPLAY_STATE, NULL, _TRUE);
2981 #endif
2982 #endif
2983 	} else if (role == P2P_ROLE_DISABLE) {
2984 
2985 		#ifdef CONFIG_IOCTL_CFG80211
2986 		adapter_wdev_data(padapter)->p2p_enabled = _FALSE;
2987 		#endif
2988 
2989 		pwdinfo->listen_channel = 0;
2990 
2991 		/* Disable P2P function */
2992 		if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DISABLE))
2993 			rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
2994 		else
2995 			RTW_ERR("%s, disable P2P when p2p role is P2P_ROLE_DISABLE!\n", __func__);
2996 
2997 #if 0
2998 		rtw_hal_set_phydm_var(padapter, HAL_PHYDM_P2P_STATE, NULL, _FALSE);
2999 #ifdef CONFIG_WFD
3000 		if (rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_MIRACAST))
3001 			rtw_hal_set_phydm_var(padapter, HAL_PHYDM_WIFI_DISPLAY_STATE, NULL, _FALSE);
3002 #endif
3003 #endif
3004 		if (_FAIL == rtw_pwr_wakeup(padapter)) {
3005 			ret = _FAIL;
3006 			goto exit;
3007 		}
3008 
3009 		/* Restore to initial setting. */
3010 		update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
3011 	}
3012 
3013 exit:
3014 	return ret;
3015 }
3016 
3017 #endif /* CONFIG_P2P */