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 CONFIG_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 */