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