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