1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
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
19 ******************************************************************************/
22 #include <drv_types.h>
26 int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8 *ch_list, u8 ch_cnt)
30 for (i = 0; i < ch_cnt; i++) {
31 if (ch_list[i] == desired_ch) {
39 int is_any_client_associated(_adapter *padapter)
41 return padapter->stapriv.asoc_list_cnt ? _TRUE : _FALSE;
44 static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
50 u8 tmplen, *pdata_attr, *pstart, *pcur;
51 struct sta_info *psta = NULL;
52 _adapter *padapter = pwdinfo->padapter;
53 struct sta_priv *pstapriv = &padapter->stapriv;
55 RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
57 pdata_attr = rtw_zmalloc(MAX_P2P_IE_LEN);
59 if (NULL == pdata_attr) {
60 RTW_INFO("%s pdata_attr malloc failed\n", __FUNCTION__);
67 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
68 phead = &pstapriv->asoc_list;
69 plist = get_next(phead);
71 /* look up sta asoc_queue */
72 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
73 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
75 plist = get_next(plist);
78 if (psta->is_p2p_device) {
83 /* P2P device address */
84 _rtw_memcpy(pcur, psta->dev_addr, ETH_ALEN);
87 /* P2P interface address */
88 _rtw_memcpy(pcur, psta->hwaddr, ETH_ALEN);
91 *pcur = psta->dev_cap;
94 /* *(u16*)(pcur) = cpu_to_be16(psta->config_methods); */
95 RTW_PUT_BE16(pcur, psta->config_methods);
98 _rtw_memcpy(pcur, psta->primary_dev_type, 8);
101 *pcur = psta->num_of_secdev_type;
104 _rtw_memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type * 8);
105 pcur += psta->num_of_secdev_type * 8;
107 if (psta->dev_name_len > 0) {
108 /* *(u16*)(pcur) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); */
109 RTW_PUT_BE16(pcur, WPS_ATTR_DEVICE_NAME);
112 /* *(u16*)(pcur) = cpu_to_be16( psta->dev_name_len ); */
113 RTW_PUT_BE16(pcur, psta->dev_name_len);
116 _rtw_memcpy(pcur, psta->dev_name, psta->dev_name_len);
117 pcur += psta->dev_name_len;
121 tmplen = (u8)(pcur - pstart);
123 *pstart = (tmplen - 1);
127 /* pstart += tmplen; */
134 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
137 len = rtw_set_p2p_attr_content(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
139 rtw_mfree(pdata_attr, MAX_P2P_IE_LEN);
146 static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
148 struct xmit_frame *pmgntframe;
149 struct pkt_attrib *pattrib;
150 unsigned char *pframe;
151 struct rtw_ieee80211_hdr *pwlanhdr;
152 unsigned short *fctrl;
153 _adapter *padapter = pwdinfo->padapter;
154 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
155 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
156 unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */
157 u32 p2poui = cpu_to_be32(P2POUI);
158 u8 oui_subtype = P2P_GO_DISC_REQUEST;
161 RTW_INFO("[%s]\n", __FUNCTION__);
163 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
164 if (pmgntframe == NULL)
167 /* update attribute */
168 pattrib = &pmgntframe->attrib;
169 update_mgntframe_attrib(padapter, pattrib);
171 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
173 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
174 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
176 fctrl = &(pwlanhdr->frame_ctl);
179 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
180 _rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
181 _rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
183 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
184 pmlmeext->mgnt_seq++;
185 SetFrameSubType(pframe, WIFI_ACTION);
187 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
188 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
190 /* Build P2P action frame header */
191 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
192 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
193 pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
194 pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
196 /* there is no IE in this P2P action frame */
198 pattrib->last_txcmdsz = pattrib->pktlen;
200 dump_mgntframe(padapter, pmgntframe);
204 static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
206 struct xmit_frame *pmgntframe;
207 struct pkt_attrib *pattrib;
208 unsigned char *pframe;
209 struct rtw_ieee80211_hdr *pwlanhdr;
210 unsigned short *fctrl;
211 _adapter *padapter = pwdinfo->padapter;
212 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
213 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
214 unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
215 u8 action = P2P_PUB_ACTION_ACTION;
216 u32 p2poui = cpu_to_be32(P2POUI);
217 u8 oui_subtype = P2P_DEVDISC_RESP;
218 u8 p2pie[8] = { 0x00 };
221 RTW_INFO("[%s]\n", __FUNCTION__);
223 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
224 if (pmgntframe == NULL)
227 /* update attribute */
228 pattrib = &pmgntframe->attrib;
229 update_mgntframe_attrib(padapter, pattrib);
231 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
233 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
234 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
236 fctrl = &(pwlanhdr->frame_ctl);
239 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
240 _rtw_memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
241 _rtw_memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
243 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
244 pmlmeext->mgnt_seq++;
245 SetFrameSubType(pframe, WIFI_ACTION);
247 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
248 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
250 /* Build P2P public action frame header */
251 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
252 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
253 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
254 pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
255 pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
261 p2pie[p2pielen++] = 0x50;
262 p2pie[p2pielen++] = 0x6F;
263 p2pie[p2pielen++] = 0x9A;
264 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
266 /* P2P_ATTR_STATUS */
267 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
269 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
271 pattrib->last_txcmdsz = pattrib->pktlen;
273 dump_mgntframe(padapter, pmgntframe);
277 static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8 *raddr, u8 *frame_body, u16 config_method)
279 _adapter *padapter = pwdinfo->padapter;
280 unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
281 u8 action = P2P_PUB_ACTION_ACTION;
282 u8 dialogToken = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */
283 u32 p2poui = cpu_to_be32(P2POUI);
284 u8 oui_subtype = P2P_PROVISION_DISC_RESP;
285 u8 wpsie[100] = { 0x00 };
291 struct xmit_frame *pmgntframe;
292 struct pkt_attrib *pattrib;
293 unsigned char *pframe;
294 struct rtw_ieee80211_hdr *pwlanhdr;
295 unsigned short *fctrl;
296 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
297 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
298 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
301 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
302 if (pmgntframe == NULL)
305 /* update attribute */
306 pattrib = &pmgntframe->attrib;
307 update_mgntframe_attrib(padapter, pattrib);
309 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
311 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
312 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
314 fctrl = &(pwlanhdr->frame_ctl);
317 _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
318 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
319 _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
321 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
322 pmlmeext->mgnt_seq++;
323 SetFrameSubType(pframe, WIFI_ACTION);
325 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
326 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
328 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
329 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
330 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
331 pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
332 pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
336 /* *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI ); */
337 RTW_PUT_BE32(wpsie, WPSOUI);
343 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
347 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
351 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
356 /* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD ); */
357 RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD);
361 /* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 ); */
362 RTW_PUT_BE16(wpsie + wpsielen, 0x0002);
366 /* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( config_method ); */
367 RTW_PUT_BE16(wpsie + wpsielen, config_method);
370 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
373 wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe);
375 pattrib->pktlen += wfdielen;
378 pattrib->last_txcmdsz = pattrib->pktlen;
380 dump_mgntframe(padapter, pmgntframe);
386 static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
388 struct xmit_frame *pmgntframe;
389 struct pkt_attrib *pattrib;
390 unsigned char *pframe;
391 struct rtw_ieee80211_hdr *pwlanhdr;
392 unsigned short *fctrl;
393 _adapter *padapter = pwdinfo->padapter;
394 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
395 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
396 unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */
397 u32 p2poui = cpu_to_be32(P2POUI);
398 u8 oui_subtype = P2P_PRESENCE_RESPONSE;
399 u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
400 u8 noa_attr_content[32] = { 0x00 };
403 RTW_INFO("[%s]\n", __FUNCTION__);
405 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
406 if (pmgntframe == NULL)
409 /* update attribute */
410 pattrib = &pmgntframe->attrib;
411 update_mgntframe_attrib(padapter, pattrib);
413 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
415 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
416 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
418 fctrl = &(pwlanhdr->frame_ctl);
421 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
422 _rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
423 _rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
425 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
426 pmlmeext->mgnt_seq++;
427 SetFrameSubType(pframe, WIFI_ACTION);
429 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
430 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
432 /* Build P2P action frame header */
433 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
434 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
435 pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
436 pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
439 /* Add P2P IE header */
442 p2pie[p2pielen++] = 0x50;
443 p2pie[p2pielen++] = 0x6F;
444 p2pie[p2pielen++] = 0x9A;
445 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
447 /* Add Status attribute in P2P IE */
448 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
450 /* Add NoA attribute in P2P IE */
451 noa_attr_content[0] = 0x1;/* index */
452 noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */
454 /* todo: Notice of Absence Descriptor(s) */
456 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
460 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &(pattrib->pktlen));
463 pattrib->last_txcmdsz = pattrib->pktlen;
465 dump_mgntframe(padapter, pmgntframe);
469 u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
471 u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
473 u32 len = 0, p2pielen = 0;
478 p2pie[p2pielen++] = 0x50;
479 p2pie[p2pielen++] = 0x6F;
480 p2pie[p2pielen++] = 0x9A;
481 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
484 /* According to the P2P Specification, the beacon frame should contain 3 P2P attributes */
485 /* 1. P2P Capability */
486 /* 2. P2P Device ID */
487 /* 3. Notice of Absence ( NOA ) */
489 /* P2P Capability ATTR */
493 /* Device Capability Bitmap, 1 byte */
494 /* Be able to participate in additional P2P Groups and */
495 /* support the P2P Invitation Procedure */
496 /* Group Capability Bitmap, 1 byte */
497 capability = P2P_DEVCAP_INVITATION_PROC | P2P_DEVCAP_CLIENT_DISCOVERABILITY;
498 capability |= ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
499 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
500 capability |= (P2P_GRPCAP_GROUP_FORMATION << 8);
502 capability = cpu_to_le16(capability);
504 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8 *)&capability);
507 /* P2P Device ID ATTR */
508 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
511 /* Notice of Absence ATTR */
516 /* go_add_noa_attr(pwdinfo); */
519 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
527 u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
529 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
531 u32 len = 0, wfdielen = 0;
532 _adapter *padapter = pwdinfo->padapter;
533 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
534 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
536 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
541 wfdie[wfdielen++] = 0x50;
542 wfdie[wfdielen++] = 0x6F;
543 wfdie[wfdielen++] = 0x9A;
544 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
546 /* Commented by Albert 20110812 */
547 /* According to the WFD Specification, the beacon frame should contain 4 WFD attributes */
548 /* 1. WFD Device Information */
549 /* 2. Associated BSSID */
550 /* 3. Coupled Sink Information */
553 /* WFD Device Information ATTR */
555 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
558 /* Note: In the WFD specification, the size of length field is 2. */
559 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
563 /* WFD device information */
565 if (P2P_ROLE_GO == pwdinfo->role) {
566 if (is_any_client_associated(pwdinfo->padapter)) {
567 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) */
568 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD;
569 RTW_PUT_BE16(wfdie + wfdielen, val16);
571 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
572 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
573 RTW_PUT_BE16(wfdie + wfdielen, val16);
577 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
578 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
579 RTW_PUT_BE16(wfdie + wfdielen, val16);
585 /* Session Management Control Port */
586 /* Default TCP port for RTSP messages is 554 */
587 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
591 /* WFD Device Maximum Throughput */
592 /* 300Mbps is the maximum throughput */
593 RTW_PUT_BE16(wfdie + wfdielen, 300);
596 /* Associated BSSID ATTR */
598 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
601 /* Note: In the WFD specification, the size of length field is 2. */
602 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
606 /* Associated BSSID */
607 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
608 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
610 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
612 wfdielen += ETH_ALEN;
614 /* Coupled Sink Information ATTR */
616 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
619 /* Note: In the WFD specification, the size of length field is 2. */
620 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
624 /* Coupled Sink Status bitmap */
625 /* Not coupled/available for Coupling */
626 wfdie[wfdielen++] = 0;
628 wfdie[wfdielen++] = 0;
629 wfdie[wfdielen++] = 0;
630 wfdie[wfdielen++] = 0;
631 wfdie[wfdielen++] = 0;
632 wfdie[wfdielen++] = 0;
633 wfdie[wfdielen++] = 0;
635 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
641 u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
643 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
645 u32 len = 0, wfdielen = 0;
646 _adapter *padapter = pwdinfo->padapter;
647 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
648 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
650 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
655 wfdie[wfdielen++] = 0x50;
656 wfdie[wfdielen++] = 0x6F;
657 wfdie[wfdielen++] = 0x9A;
658 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
660 /* Commented by Albert 20110812 */
661 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
662 /* 1. WFD Device Information */
663 /* 2. Associated BSSID */
664 /* 3. Coupled Sink Information */
667 /* WFD Device Information ATTR */
669 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
672 /* Note: In the WFD specification, the size of length field is 2. */
673 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
677 /* WFD device information */
679 if (1 == pwdinfo->wfd_tdls_enable) {
680 /* WFD primary sink + available for WFD session + WiFi TDLS mode + WSC ( WFD Service Discovery ) */
681 val16 = pwfd_info->wfd_device_type |
682 WFD_DEVINFO_SESSION_AVAIL |
685 RTW_PUT_BE16(wfdie + wfdielen, val16);
687 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSC ( WFD Service Discovery ) */
688 val16 = pwfd_info->wfd_device_type |
689 WFD_DEVINFO_SESSION_AVAIL |
691 RTW_PUT_BE16(wfdie + wfdielen, val16);
697 /* Session Management Control Port */
698 /* Default TCP port for RTSP messages is 554 */
699 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
703 /* WFD Device Maximum Throughput */
704 /* 300Mbps is the maximum throughput */
705 RTW_PUT_BE16(wfdie + wfdielen, 300);
708 /* Associated BSSID ATTR */
710 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
713 /* Note: In the WFD specification, the size of length field is 2. */
714 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
718 /* Associated BSSID */
719 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
720 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
722 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
724 wfdielen += ETH_ALEN;
726 /* Coupled Sink Information ATTR */
728 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
731 /* Note: In the WFD specification, the size of length field is 2. */
732 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
736 /* Coupled Sink Status bitmap */
737 /* Not coupled/available for Coupling */
738 wfdie[wfdielen++] = 0;
740 wfdie[wfdielen++] = 0;
741 wfdie[wfdielen++] = 0;
742 wfdie[wfdielen++] = 0;
743 wfdie[wfdielen++] = 0;
744 wfdie[wfdielen++] = 0;
745 wfdie[wfdielen++] = 0;
747 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
753 u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunneled)
755 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
756 u32 len = 0, wfdielen = 0;
757 _adapter *padapter = pwdinfo->padapter;
758 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
759 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
761 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
766 wfdie[wfdielen++] = 0x50;
767 wfdie[wfdielen++] = 0x6F;
768 wfdie[wfdielen++] = 0x9A;
769 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
771 /* Commented by Albert 20110812 */
772 /* According to the WFD Specification, the probe response frame should contain 4 WFD attributes */
773 /* 1. WFD Device Information */
774 /* 2. Associated BSSID */
775 /* 3. Coupled Sink Information */
776 /* 4. WFD Session Information */
779 /* WFD Device Information ATTR */
781 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
784 /* Note: In the WFD specification, the size of length field is 2. */
785 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
789 /* WFD device information */
790 /* WFD primary sink + available for WFD session + WiFi Direct mode */
792 if (_TRUE == pwdinfo->session_available) {
793 if (P2P_ROLE_GO == pwdinfo->role) {
794 if (is_any_client_associated(pwdinfo->padapter)) {
795 if (pwdinfo->wfd_tdls_enable) {
796 /* TDLS mode + WSD ( WFD Service Discovery ) */
797 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
799 /* WiFi Direct mode + WSD ( WFD Service Discovery ) */
800 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
803 if (pwdinfo->wfd_tdls_enable) {
804 /* available for WFD session + TDLS mode + WSD ( WFD Service Discovery ) */
805 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);
807 /* available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
808 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
812 if (pwdinfo->wfd_tdls_enable) {
813 /* available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
814 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);
817 /* available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
818 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
822 if (pwdinfo->wfd_tdls_enable)
823 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
825 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
832 /* Session Management Control Port */
833 /* Default TCP port for RTSP messages is 554 */
834 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
838 /* WFD Device Maximum Throughput */
839 /* 300Mbps is the maximum throughput */
840 RTW_PUT_BE16(wfdie + wfdielen, 300);
843 /* Associated BSSID ATTR */
845 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
848 /* Note: In the WFD specification, the size of length field is 2. */
849 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
853 /* Associated BSSID */
854 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
855 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
857 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
859 wfdielen += ETH_ALEN;
861 /* Coupled Sink Information ATTR */
863 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
866 /* Note: In the WFD specification, the size of length field is 2. */
867 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
871 /* Coupled Sink Status bitmap */
872 /* Not coupled/available for Coupling */
873 wfdie[wfdielen++] = 0;
875 wfdie[wfdielen++] = 0;
876 wfdie[wfdielen++] = 0;
877 wfdie[wfdielen++] = 0;
878 wfdie[wfdielen++] = 0;
879 wfdie[wfdielen++] = 0;
880 wfdie[wfdielen++] = 0;
882 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
883 /* WFD Session Information ATTR */
885 wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;
888 /* Note: In the WFD specification, the size of length field is 2. */
889 RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
892 /* Todo: to add the list of WFD device info descriptor in WFD group. */
895 #ifdef CONFIG_CONCURRENT_MODE
899 _adapter *iface = NULL;
900 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
902 for (i = 0; i < dvobj->iface_nums; i++) {
903 iface = dvobj->padapters[i];
904 if ((iface) && rtw_is_adapter_up(iface)) {
905 if (iface == padapter)
908 if ((tunneled == 0) && (iface->wdinfo.wfd_tdls_enable == 1)) {
909 /* Alternative MAC Address ATTR
911 wfdie[wfdielen++] = WFD_ATTR_ALTER_MAC;
914 Note: In the WFD specification, the size of length field is 2.*/
915 RTW_PUT_BE16(wfdie + wfdielen, ETH_ALEN);
919 Alternative MAC Address*/
920 _rtw_memcpy(wfdie + wfdielen, adapter_mac_addr(iface), ETH_ALEN);
921 wfdielen += ETH_ALEN;
927 #endif /* CONFIG_TDLS*/
928 #endif /* CONFIG_CONCURRENT_MODE */
930 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
936 u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
938 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
940 u32 len = 0, wfdielen = 0;
941 _adapter *padapter = NULL;
942 struct mlme_priv *pmlmepriv = NULL;
943 struct wifi_display_info *pwfd_info = NULL;
945 padapter = pwdinfo->padapter;
946 pmlmepriv = &padapter->mlmepriv;
947 pwfd_info = padapter->wdinfo.wfd_info;
949 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
952 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
957 wfdie[wfdielen++] = 0x50;
958 wfdie[wfdielen++] = 0x6F;
959 wfdie[wfdielen++] = 0x9A;
960 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
962 /* Commented by Albert 20110812 */
963 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
964 /* 1. WFD Device Information */
965 /* 2. Associated BSSID */
966 /* 3. Coupled Sink Information */
969 /* WFD Device Information ATTR */
971 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
974 /* Note: In the WFD specification, the size of length field is 2. */
975 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
979 /* WFD device information */
980 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
981 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
982 RTW_PUT_BE16(wfdie + wfdielen, val16);
986 /* Session Management Control Port */
987 /* Default TCP port for RTSP messages is 554 */
988 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
992 /* WFD Device Maximum Throughput */
993 /* 300Mbps is the maximum throughput */
994 RTW_PUT_BE16(wfdie + wfdielen, 300);
997 /* Associated BSSID ATTR */
999 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1002 /* Note: In the WFD specification, the size of length field is 2. */
1003 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1007 /* Associated BSSID */
1008 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1009 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1011 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1013 wfdielen += ETH_ALEN;
1015 /* Coupled Sink Information ATTR */
1017 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1020 /* Note: In the WFD specification, the size of length field is 2. */
1021 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1025 /* Coupled Sink Status bitmap */
1026 /* Not coupled/available for Coupling */
1027 wfdie[wfdielen++] = 0;
1029 wfdie[wfdielen++] = 0;
1030 wfdie[wfdielen++] = 0;
1031 wfdie[wfdielen++] = 0;
1032 wfdie[wfdielen++] = 0;
1033 wfdie[wfdielen++] = 0;
1034 wfdie[wfdielen++] = 0;
1036 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1042 u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1044 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1045 u32 len = 0, wfdielen = 0;
1047 _adapter *padapter = pwdinfo->padapter;
1048 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1049 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1051 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1056 wfdie[wfdielen++] = 0x50;
1057 wfdie[wfdielen++] = 0x6F;
1058 wfdie[wfdielen++] = 0x9A;
1059 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1061 /* Commented by Albert 20110812 */
1062 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
1063 /* 1. WFD Device Information */
1064 /* 2. Associated BSSID */
1065 /* 3. Coupled Sink Information */
1068 /* WFD Device Information ATTR */
1070 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1073 /* Note: In the WFD specification, the size of length field is 2. */
1074 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1078 /* WFD device information */
1079 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1080 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1081 RTW_PUT_BE16(wfdie + wfdielen, val16);
1085 /* Session Management Control Port */
1086 /* Default TCP port for RTSP messages is 554 */
1087 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1091 /* WFD Device Maximum Throughput */
1092 /* 300Mbps is the maximum throughput */
1093 RTW_PUT_BE16(wfdie + wfdielen, 300);
1096 /* Associated BSSID ATTR */
1098 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1101 /* Note: In the WFD specification, the size of length field is 2. */
1102 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1106 /* Associated BSSID */
1107 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1108 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1110 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1112 wfdielen += ETH_ALEN;
1114 /* Coupled Sink Information ATTR */
1116 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1119 /* Note: In the WFD specification, the size of length field is 2. */
1120 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1124 /* Coupled Sink Status bitmap */
1125 /* Not coupled/available for Coupling */
1126 wfdie[wfdielen++] = 0;
1128 wfdie[wfdielen++] = 0;
1129 wfdie[wfdielen++] = 0;
1130 wfdie[wfdielen++] = 0;
1131 wfdie[wfdielen++] = 0;
1132 wfdie[wfdielen++] = 0;
1133 wfdie[wfdielen++] = 0;
1135 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1141 u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1143 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1144 u32 len = 0, wfdielen = 0;
1146 _adapter *padapter = pwdinfo->padapter;
1147 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1148 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1150 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1155 wfdie[wfdielen++] = 0x50;
1156 wfdie[wfdielen++] = 0x6F;
1157 wfdie[wfdielen++] = 0x9A;
1158 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1160 /* Commented by Albert 20110825 */
1161 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1162 /* 1. WFD Device Information */
1163 /* 2. Associated BSSID ( Optional ) */
1164 /* 3. Local IP Adress ( Optional ) */
1167 /* WFD Device Information ATTR */
1169 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1172 /* Note: In the WFD specification, the size of length field is 2. */
1173 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1177 /* WFD device information */
1178 /* WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */
1179 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
1180 RTW_PUT_BE16(wfdie + wfdielen, val16);
1184 /* Session Management Control Port */
1185 /* Default TCP port for RTSP messages is 554 */
1186 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1190 /* WFD Device Maximum Throughput */
1191 /* 300Mbps is the maximum throughput */
1192 RTW_PUT_BE16(wfdie + wfdielen, 300);
1195 /* Associated BSSID ATTR */
1197 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1200 /* Note: In the WFD specification, the size of length field is 2. */
1201 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1205 /* Associated BSSID */
1206 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1207 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1209 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1211 wfdielen += ETH_ALEN;
1213 /* Coupled Sink Information ATTR */
1215 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1218 /* Note: In the WFD specification, the size of length field is 2. */
1219 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1223 /* Coupled Sink Status bitmap */
1224 /* Not coupled/available for Coupling */
1225 wfdie[wfdielen++] = 0;
1227 wfdie[wfdielen++] = 0;
1228 wfdie[wfdielen++] = 0;
1229 wfdie[wfdielen++] = 0;
1230 wfdie[wfdielen++] = 0;
1231 wfdie[wfdielen++] = 0;
1232 wfdie[wfdielen++] = 0;
1234 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1240 u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1242 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1243 u32 len = 0, wfdielen = 0;
1245 _adapter *padapter = pwdinfo->padapter;
1246 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1247 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1249 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1254 wfdie[wfdielen++] = 0x50;
1255 wfdie[wfdielen++] = 0x6F;
1256 wfdie[wfdielen++] = 0x9A;
1257 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1259 /* Commented by Albert 20110825 */
1260 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1261 /* 1. WFD Device Information */
1262 /* 2. Associated BSSID ( Optional ) */
1263 /* 3. Local IP Adress ( Optional ) */
1266 /* WFD Device Information ATTR */
1268 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1271 /* Note: In the WFD specification, the size of length field is 2. */
1272 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1276 /* WFD device information */
1277 /* WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */
1278 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
1279 RTW_PUT_BE16(wfdie + wfdielen, val16);
1283 /* Session Management Control Port */
1284 /* Default TCP port for RTSP messages is 554 */
1285 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1289 /* WFD Device Maximum Throughput */
1290 /* 300Mbps is the maximum throughput */
1291 RTW_PUT_BE16(wfdie + wfdielen, 300);
1294 /* Associated BSSID ATTR */
1296 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1299 /* Note: In the WFD specification, the size of length field is 2. */
1300 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1304 /* Associated BSSID */
1305 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1306 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1308 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1310 wfdielen += ETH_ALEN;
1312 /* Coupled Sink Information ATTR */
1314 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1317 /* Note: In the WFD specification, the size of length field is 2. */
1318 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1322 /* Coupled Sink Status bitmap */
1323 /* Not coupled/available for Coupling */
1324 wfdie[wfdielen++] = 0;
1326 wfdie[wfdielen++] = 0;
1327 wfdie[wfdielen++] = 0;
1328 wfdie[wfdielen++] = 0;
1329 wfdie[wfdielen++] = 0;
1330 wfdie[wfdielen++] = 0;
1331 wfdie[wfdielen++] = 0;
1334 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1340 u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1342 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1343 u32 len = 0, wfdielen = 0;
1345 _adapter *padapter = pwdinfo->padapter;
1346 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1347 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1349 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1354 wfdie[wfdielen++] = 0x50;
1355 wfdie[wfdielen++] = 0x6F;
1356 wfdie[wfdielen++] = 0x9A;
1357 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1359 /* Commented by Albert 20110825 */
1360 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1361 /* 1. WFD Device Information */
1362 /* 2. Associated BSSID ( Optional ) */
1363 /* 3. Local IP Adress ( Optional ) */
1366 /* WFD Device Information ATTR */
1368 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1371 /* Note: In the WFD specification, the size of length field is 2. */
1372 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1376 /* WFD device information */
1377 /* WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */
1378 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
1379 RTW_PUT_BE16(wfdie + wfdielen, val16);
1383 /* Session Management Control Port */
1384 /* Default TCP port for RTSP messages is 554 */
1385 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1389 /* WFD Device Maximum Throughput */
1390 /* 300Mbps is the maximum throughput */
1391 RTW_PUT_BE16(wfdie + wfdielen, 300);
1394 /* Associated BSSID ATTR */
1396 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1399 /* Note: In the WFD specification, the size of length field is 2. */
1400 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1404 /* Associated BSSID */
1405 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1406 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1408 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1410 wfdielen += ETH_ALEN;
1412 /* Coupled Sink Information ATTR */
1414 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1417 /* Note: In the WFD specification, the size of length field is 2. */
1418 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1422 /* Coupled Sink Status bitmap */
1423 /* Not coupled/available for Coupling */
1424 wfdie[wfdielen++] = 0;
1426 wfdie[wfdielen++] = 0;
1427 wfdie[wfdielen++] = 0;
1428 wfdie[wfdielen++] = 0;
1429 wfdie[wfdielen++] = 0;
1430 wfdie[wfdielen++] = 0;
1431 wfdie[wfdielen++] = 0;
1434 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1440 u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1442 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1443 u32 len = 0, wfdielen = 0;
1445 _adapter *padapter = pwdinfo->padapter;
1446 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1447 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1449 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1454 wfdie[wfdielen++] = 0x50;
1455 wfdie[wfdielen++] = 0x6F;
1456 wfdie[wfdielen++] = 0x9A;
1457 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1459 /* Commented by Albert 20110825 */
1460 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1461 /* 1. WFD Device Information */
1462 /* 2. Associated BSSID ( Optional ) */
1463 /* 3. Local IP Adress ( Optional ) */
1466 /* WFD Device Information ATTR */
1468 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1471 /* Note: In the WFD specification, the size of length field is 2. */
1472 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1476 /* WFD device information */
1477 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1478 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1479 RTW_PUT_BE16(wfdie + wfdielen, val16);
1483 /* Session Management Control Port */
1484 /* Default TCP port for RTSP messages is 554 */
1485 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1489 /* WFD Device Maximum Throughput */
1490 /* 300Mbps is the maximum throughput */
1491 RTW_PUT_BE16(wfdie + wfdielen, 300);
1494 /* Associated BSSID ATTR */
1496 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1499 /* Note: In the WFD specification, the size of length field is 2. */
1500 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1504 /* Associated BSSID */
1505 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1506 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1508 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1510 wfdielen += ETH_ALEN;
1512 /* Coupled Sink Information ATTR */
1514 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1517 /* Note: In the WFD specification, the size of length field is 2. */
1518 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1522 /* Coupled Sink Status bitmap */
1523 /* Not coupled/available for Coupling */
1524 wfdie[wfdielen++] = 0;
1526 wfdie[wfdielen++] = 0;
1527 wfdie[wfdielen++] = 0;
1528 wfdie[wfdielen++] = 0;
1529 wfdie[wfdielen++] = 0;
1530 wfdie[wfdielen++] = 0;
1531 wfdie[wfdielen++] = 0;
1533 if (P2P_ROLE_GO == pwdinfo->role) {
1534 /* WFD Session Information ATTR */
1536 wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;
1539 /* Note: In the WFD specification, the size of length field is 2. */
1540 RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
1543 /* Todo: to add the list of WFD device info descriptor in WFD group. */
1547 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1553 u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1555 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1557 u32 len = 0, wfdielen = 0;
1558 _adapter *padapter = pwdinfo->padapter;
1559 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1560 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1562 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1567 wfdie[wfdielen++] = 0x50;
1568 wfdie[wfdielen++] = 0x6F;
1569 wfdie[wfdielen++] = 0x9A;
1570 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1572 /* Commented by Albert 20110825 */
1573 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1574 /* 1. WFD Device Information */
1575 /* 2. Associated BSSID ( Optional ) */
1576 /* 3. Local IP Adress ( Optional ) */
1579 /* WFD Device Information ATTR */
1581 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1584 /* Note: In the WFD specification, the size of length field is 2. */
1585 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1589 /* WFD device information */
1590 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1591 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1592 RTW_PUT_BE16(wfdie + wfdielen, val16);
1596 /* Session Management Control Port */
1597 /* Default TCP port for RTSP messages is 554 */
1598 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1602 /* WFD Device Maximum Throughput */
1603 /* 300Mbps is the maximum throughput */
1604 RTW_PUT_BE16(wfdie + wfdielen, 300);
1607 /* Associated BSSID ATTR */
1609 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1612 /* Note: In the WFD specification, the size of length field is 2. */
1613 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1617 /* Associated BSSID */
1618 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1619 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1621 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1623 wfdielen += ETH_ALEN;
1625 /* Coupled Sink Information ATTR */
1627 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1630 /* Note: In the WFD specification, the size of length field is 2. */
1631 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1635 /* Coupled Sink Status bitmap */
1636 /* Not coupled/available for Coupling */
1637 wfdie[wfdielen++] = 0;
1639 wfdie[wfdielen++] = 0;
1640 wfdie[wfdielen++] = 0;
1641 wfdie[wfdielen++] = 0;
1642 wfdie[wfdielen++] = 0;
1643 wfdie[wfdielen++] = 0;
1644 wfdie[wfdielen++] = 0;
1646 if (P2P_ROLE_GO == pwdinfo->role) {
1647 /* WFD Session Information ATTR */
1649 wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;
1652 /* Note: In the WFD specification, the size of length field is 2. */
1653 RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
1656 /* Todo: to add the list of WFD device info descriptor in WFD group. */
1660 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1666 u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1668 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1669 u32 len = 0, wfdielen = 0;
1671 _adapter *padapter = pwdinfo->padapter;
1672 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1673 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1675 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1680 wfdie[wfdielen++] = 0x50;
1681 wfdie[wfdielen++] = 0x6F;
1682 wfdie[wfdielen++] = 0x9A;
1683 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1685 /* Commented by Albert 20110825 */
1686 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1687 /* 1. WFD Device Information */
1688 /* 2. Associated BSSID ( Optional ) */
1689 /* 3. Local IP Adress ( Optional ) */
1692 /* WFD Device Information ATTR */
1694 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1697 /* Note: In the WFD specification, the size of length field is 2. */
1698 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1702 /* WFD device information */
1703 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1704 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1705 RTW_PUT_BE16(wfdie + wfdielen, val16);
1709 /* Session Management Control Port */
1710 /* Default TCP port for RTSP messages is 554 */
1711 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1715 /* WFD Device Maximum Throughput */
1716 /* 300Mbps is the maximum throughput */
1717 RTW_PUT_BE16(wfdie + wfdielen, 300);
1720 /* Associated BSSID ATTR */
1722 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1725 /* Note: In the WFD specification, the size of length field is 2. */
1726 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1730 /* Associated BSSID */
1731 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1732 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1734 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1736 wfdielen += ETH_ALEN;
1738 /* Coupled Sink Information ATTR */
1740 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1743 /* Note: In the WFD specification, the size of length field is 2. */
1744 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1748 /* Coupled Sink Status bitmap */
1749 /* Not coupled/available for Coupling */
1750 wfdie[wfdielen++] = 0;
1752 wfdie[wfdielen++] = 0;
1753 wfdie[wfdielen++] = 0;
1754 wfdie[wfdielen++] = 0;
1755 wfdie[wfdielen++] = 0;
1756 wfdie[wfdielen++] = 0;
1757 wfdie[wfdielen++] = 0;
1760 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1766 u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1768 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1769 u32 len = 0, wfdielen = 0;
1771 _adapter *padapter = pwdinfo->padapter;
1772 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1773 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1775 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1780 wfdie[wfdielen++] = 0x50;
1781 wfdie[wfdielen++] = 0x6F;
1782 wfdie[wfdielen++] = 0x9A;
1783 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1785 /* Commented by Albert 20110825 */
1786 /* According to the WFD Specification, the provision discovery response frame should contain 3 WFD attributes */
1787 /* 1. WFD Device Information */
1788 /* 2. Associated BSSID ( Optional ) */
1789 /* 3. Local IP Adress ( Optional ) */
1792 /* WFD Device Information ATTR */
1794 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1797 /* Note: In the WFD specification, the size of length field is 2. */
1798 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1802 /* WFD device information */
1803 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1804 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1805 RTW_PUT_BE16(wfdie + wfdielen, val16);
1809 /* Session Management Control Port */
1810 /* Default TCP port for RTSP messages is 554 */
1811 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1815 /* WFD Device Maximum Throughput */
1816 /* 300Mbps is the maximum throughput */
1817 RTW_PUT_BE16(wfdie + wfdielen, 300);
1820 /* Associated BSSID ATTR */
1822 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1825 /* Note: In the WFD specification, the size of length field is 2. */
1826 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1830 /* Associated BSSID */
1831 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1832 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1834 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1836 wfdielen += ETH_ALEN;
1838 /* Coupled Sink Information ATTR */
1840 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1843 /* Note: In the WFD specification, the size of length field is 2. */
1844 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1848 /* Coupled Sink Status bitmap */
1849 /* Not coupled/available for Coupling */
1850 wfdie[wfdielen++] = 0;
1852 wfdie[wfdielen++] = 0;
1853 wfdie[wfdielen++] = 0;
1854 wfdie[wfdielen++] = 0;
1855 wfdie[wfdielen++] = 0;
1856 wfdie[wfdielen++] = 0;
1857 wfdie[wfdielen++] = 0;
1859 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1864 #endif /* CONFIG_WFD */
1866 u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1868 u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
1869 u32 len = 0, p2pielen = 0;
1870 #ifdef CONFIG_INTEL_WIDI
1871 struct mlme_priv *pmlmepriv = &(pwdinfo->padapter->mlmepriv);
1872 u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 };
1873 u8 widi_version = 0, i = 0;
1875 if (_rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE)
1877 else if (pmlmepriv->num_p2p_sdt != 0)
1879 #endif /* CONFIG_INTEL_WIDI */
1883 p2pie[p2pielen++] = 0x50;
1884 p2pie[p2pielen++] = 0x6F;
1885 p2pie[p2pielen++] = 0x9A;
1886 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
1888 /* Commented by Albert 20100907 */
1889 /* According to the P2P Specification, the probe response frame should contain 5 P2P attributes */
1890 /* 1. P2P Capability */
1891 /* 2. Extended Listen Timing */
1892 /* 3. Notice of Absence ( NOA ) ( Only GO needs this ) */
1893 /* 4. Device Info */
1894 /* 5. Group Info ( Only GO need this ) */
1896 /* P2P Capability ATTR */
1898 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
1901 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); */
1902 RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
1906 /* Device Capability Bitmap, 1 byte */
1907 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
1909 /* Group Capability Bitmap, 1 byte */
1910 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1911 p2pie[p2pielen] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
1913 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
1914 p2pie[p2pielen] |= P2P_GRPCAP_GROUP_FORMATION;
1917 } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
1918 /* Group Capability Bitmap, 1 byte */
1919 if (pwdinfo->persistent_supported)
1920 p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
1922 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
1925 /* Extended Listen Timing ATTR */
1927 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
1930 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 ); */
1931 RTW_PUT_LE16(p2pie + p2pielen, 0x0004);
1935 /* Availability Period */
1936 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF ); */
1937 RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
1940 /* Availability Interval */
1941 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF ); */
1942 RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
1946 /* Notice of Absence ATTR */
1950 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1951 /* go_add_noa_attr(pwdinfo); */
1954 /* Device Info ATTR */
1956 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
1959 /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
1960 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
1961 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); */
1962 #ifdef CONFIG_INTEL_WIDI
1963 if (widi_version == 35)
1964 RTW_PUT_LE16(p2pie + p2pielen, 21 + 8 + pwdinfo->device_name_len);
1965 else if (widi_version == 40)
1966 RTW_PUT_LE16(p2pie + p2pielen, 21 + 8 * pmlmepriv->num_p2p_sdt + pwdinfo->device_name_len);
1968 #endif /* CONFIG_INTEL_WIDI */
1969 RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
1973 /* P2P Device Address */
1974 _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
1975 p2pielen += ETH_ALEN;
1978 /* This field should be big endian. Noted by P2P specification. */
1979 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm ); */
1980 RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm);
1983 #ifdef CONFIG_INTEL_WIDI
1984 if (widi_version == 40) {
1985 /* Primary Device Type */
1987 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA ); */
1988 RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_pdt_cid);
1992 /* *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); */
1993 RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
1996 /* Sub Category ID */
1997 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER ); */
1998 RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_pdt_scid);
2001 #endif /* CONFIG_INTEL_WIDI */
2003 /* Primary Device Type */
2005 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA ); */
2006 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
2010 /* *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); */
2011 RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
2014 /* Sub Category ID */
2015 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER ); */
2016 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
2020 /* Number of Secondary Device Types */
2021 #ifdef CONFIG_INTEL_WIDI
2022 if (widi_version == 35) {
2023 p2pie[p2pielen++] = 0x01;
2025 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_DISPLAYS);
2028 RTW_PUT_BE32(p2pie + p2pielen, INTEL_DEV_TYPE_OUI);
2031 RTW_PUT_BE16(p2pie + p2pielen, P2P_SCID_WIDI_CONSUMER_SINK);
2033 } else if (widi_version == 40) {
2034 p2pie[p2pielen++] = pmlmepriv->num_p2p_sdt;
2035 for (; i < pmlmepriv->num_p2p_sdt; i++) {
2036 RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_sdt_cid[i]);
2039 RTW_PUT_BE32(p2pie + p2pielen, INTEL_DEV_TYPE_OUI);
2042 RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_sdt_scid[i]);
2046 #endif /* CONFIG_INTEL_WIDI */
2047 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
2051 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); */
2052 RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
2056 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len ); */
2057 RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
2061 _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2062 p2pielen += pwdinfo->device_name_len;
2064 /* Group Info ATTR */
2068 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2069 p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
2072 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2079 u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
2081 u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
2082 u32 len = 0, p2pielen = 0;
2086 p2pie[p2pielen++] = 0x50;
2087 p2pie[p2pielen++] = 0x6F;
2088 p2pie[p2pielen++] = 0x9A;
2089 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2091 /* Commented by Albert 20110301 */
2092 /* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
2093 /* 1. P2P Capability */
2094 /* 2. Device Info */
2095 /* 3. Group ID ( When joining an operating P2P Group ) */
2097 /* P2P Capability ATTR */
2099 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2102 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); */
2103 RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
2107 /* Device Capability Bitmap, 1 byte */
2108 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2110 /* Group Capability Bitmap, 1 byte */
2111 if (pwdinfo->persistent_supported)
2112 p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
2114 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
2117 /* Device Info ATTR */
2119 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2122 /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2123 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2124 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); */
2125 RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
2129 /* P2P Device Address */
2130 _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
2131 p2pielen += ETH_ALEN;
2134 /* This field should be big endian. Noted by P2P specification. */
2135 if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC) {
2136 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_PBC ); */
2137 RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC);
2139 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY ); */
2140 RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY);
2145 /* Primary Device Type */
2147 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA ); */
2148 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
2152 /* *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); */
2153 RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
2156 /* Sub Category ID */
2157 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER ); */
2158 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
2161 /* Number of Secondary Device Types */
2162 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
2166 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); */
2167 RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
2171 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len ); */
2172 RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
2176 _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2177 p2pielen += pwdinfo->device_name_len;
2179 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2180 /* Added by Albert 2011/05/19 */
2181 /* In this case, the pdev_raddr is the device address of the group owner. */
2183 /* P2P Group ID ATTR */
2185 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2188 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + ussidlen ); */
2189 RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen);
2193 _rtw_memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN);
2194 p2pielen += ETH_ALEN;
2196 _rtw_memcpy(p2pie + p2pielen, pssid, ussidlen);
2197 p2pielen += ussidlen;
2201 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2209 u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
2211 u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
2212 u32 len = 0, p2pielen = 0;
2216 p2pie[p2pielen++] = 0x50;
2217 p2pie[p2pielen++] = 0x6F;
2218 p2pie[p2pielen++] = 0x9A;
2219 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2221 /* According to the P2P Specification, the Association response frame should contain 2 P2P attributes */
2223 /* 2. Extended Listen Timing (optional) */
2227 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
2230 /* Extended Listen Timing ATTR */
2236 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2242 u32 build_deauth_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
2249 u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2255 int ssid_len = 0, rate_cnt = 0;
2257 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
2258 len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
2260 if (rate_cnt <= 4) {
2263 for (i = 0; i < rate_cnt; i++) {
2264 if (((*(p + 2 + i) & 0xff) != 0x02) &&
2265 ((*(p + 2 + i) & 0xff) != 0x04) &&
2266 ((*(p + 2 + i) & 0xff) != 0x0B) &&
2267 ((*(p + 2 + i) & 0xff) != 0x16))
2272 /* There is no OFDM rate included in SupportedRates IE of this probe request frame */
2273 /* The driver should response this probe request. */
2277 /* rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */
2278 /* We should proceed the following check for this probe request. */
2281 /* Added comments by Albert 20100906 */
2282 /* There are several items we should check here. */
2283 /* 1. This probe request frame must contain the P2P IE. (Done) */
2284 /* 2. This probe request frame must contain the wildcard SSID. (Done) */
2285 /* 3. Wildcard BSSID. (Todo) */
2286 /* 4. Destination Address. ( Done in mgt_dispatcher function ) */
2287 /* 5. Requested Device Type in WSC IE. (Todo) */
2288 /* 6. Device ID attribute in P2P IE. (Todo) */
2290 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
2291 len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
2293 ssid_len &= 0xff; /* Just last 1 byte is valid for ssid len of the probe request */
2294 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2295 p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_ , len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_ , NULL, &p2pielen);
2297 if ((p != NULL) && _rtw_memcmp((void *)(p + 2), (void *) pwdinfo->p2p_wildcard_ssid , 7)) {
2299 /* Check Requested Device Type attributes in WSC IE. */
2300 /* Check Device ID attribute in P2P IE */
2303 } else if ((p != NULL) && (ssid_len == 0))
2306 /* non -p2p device */
2316 u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
2318 u8 status_code = P2P_STATUS_SUCCESS;
2319 u8 *pbuf, *pattr_content = NULL;
2320 u32 attr_contentlen = 0;
2322 unsigned short frame_type, ie_offset = 0;
2328 if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2329 return P2P_STATUS_FAIL_REQUEST_UNABLE;
2331 frame_type = GetFrameSubType(pframe);
2332 if (frame_type == WIFI_ASSOCREQ)
2333 ie_offset = _ASOCREQ_IE_OFFSET_;
2334 else /* WIFI_REASSOCREQ */
2335 ie_offset = _REASOCREQ_IE_OFFSET_;
2337 ies = pframe + WLAN_HDR_A3_LEN + ie_offset;
2338 ies_len = len - WLAN_HDR_A3_LEN - ie_offset;
2340 p2p_ie = rtw_get_p2p_ie(ies , ies_len , NULL, &p2p_ielen);
2343 RTW_INFO("[%s] P2P IE not Found!!\n", __FUNCTION__);
2344 status_code = P2P_STATUS_FAIL_INVALID_PARAM;
2346 RTW_INFO("[%s] P2P IE Found!!\n", __FUNCTION__);
2349 /* Check P2P Capability ATTR */
2350 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *) &attr_contentlen)) {
2351 RTW_INFO("[%s] Got P2P Capability Attr!!\n", __FUNCTION__);
2352 cap_attr = le16_to_cpu(cap_attr);
2353 psta->dev_cap = cap_attr & 0xff;
2356 /* Check Extended Listen Timing ATTR */
2359 /* Check P2P Device Info ATTR */
2360 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint *)&attr_contentlen)) {
2361 RTW_INFO("[%s] Got P2P DEVICE INFO Attr!!\n", __FUNCTION__);
2362 pattr_content = pbuf = rtw_zmalloc(attr_contentlen);
2363 if (pattr_content) {
2364 u8 num_of_secdev_type;
2368 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO , pattr_content, (uint *)&attr_contentlen);
2370 _rtw_memcpy(psta->dev_addr, pattr_content, ETH_ALEN);/* P2P Device Address */
2372 pattr_content += ETH_ALEN;
2374 _rtw_memcpy(&psta->config_methods, pattr_content, 2);/* Config Methods */
2375 psta->config_methods = be16_to_cpu(psta->config_methods);
2379 _rtw_memcpy(psta->primary_dev_type, pattr_content, 8);
2383 num_of_secdev_type = *pattr_content;
2386 if (num_of_secdev_type == 0)
2387 psta->num_of_secdev_type = 0;
2391 psta->num_of_secdev_type = num_of_secdev_type;
2393 len = (sizeof(psta->secdev_types_list) < (num_of_secdev_type * 8)) ? (sizeof(psta->secdev_types_list)) : (num_of_secdev_type * 8);
2395 _rtw_memcpy(psta->secdev_types_list, pattr_content, len);
2397 pattr_content += (num_of_secdev_type * 8);
2401 /* dev_name_len = attr_contentlen - ETH_ALEN - 2 - 8 - 1 - (num_of_secdev_type*8); */
2402 psta->dev_name_len = 0;
2403 if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(u16 *)pattr_content)) {
2404 dev_name_len = be16_to_cpu(*(u16 *)(pattr_content + 2));
2406 psta->dev_name_len = (sizeof(psta->dev_name) < dev_name_len) ? sizeof(psta->dev_name) : dev_name_len;
2408 _rtw_memcpy(psta->dev_name, pattr_content + 4, psta->dev_name_len);
2411 rtw_mfree(pbuf, attr_contentlen);
2417 /* Get the next P2P IE */
2418 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2426 u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2429 u8 status, dialogToken;
2430 struct sta_info *psta = NULL;
2431 _adapter *padapter = pwdinfo->padapter;
2432 struct sta_priv *pstapriv = &padapter->stapriv;
2436 frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2438 dialogToken = frame_body[7];
2439 status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
2441 p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
2443 u8 groupid[38] = { 0x00 };
2444 u8 dev_addr[ETH_ALEN] = { 0x00 };
2445 u32 attr_contentlen = 0;
2447 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
2448 if (_rtw_memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
2449 _rtw_memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN, pwdinfo->p2p_group_ssid_len)) {
2450 attr_contentlen = 0;
2451 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen)) {
2453 _list *phead, *plist;
2455 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2456 phead = &pstapriv->asoc_list;
2457 plist = get_next(phead);
2459 /* look up sta asoc_queue */
2460 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
2461 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
2463 plist = get_next(plist);
2465 if (psta->is_p2p_device && (psta->dev_cap & P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
2466 _rtw_memcmp(psta->dev_addr, dev_addr, ETH_ALEN)) {
2468 /* _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); */
2469 /* issue GO Discoverability Request */
2470 issue_group_disc_req(pwdinfo, psta->hwaddr);
2471 /* _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); */
2473 status = P2P_STATUS_SUCCESS;
2477 status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2480 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2483 status = P2P_STATUS_FAIL_INVALID_PARAM;
2486 status = P2P_STATUS_FAIL_INVALID_PARAM;
2493 /* issue Device Discoverability Response */
2494 issue_p2p_devdisc_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
2497 return (status == P2P_STATUS_SUCCESS) ? _TRUE : _FALSE;
2501 u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2506 u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2510 uint wps_ielen = 0, attr_contentlen = 0;
2511 u16 uconfig_method = 0;
2514 frame_body = (pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2516 wpsie = rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
2518 if (rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD , (u8 *) &uconfig_method, &attr_contentlen)) {
2519 uconfig_method = be16_to_cpu(uconfig_method);
2520 switch (uconfig_method) {
2521 case WPS_CM_DISPLYA: {
2522 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2525 case WPS_CM_LABEL: {
2526 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "lab", 3);
2529 case WPS_CM_PUSH_BUTTON: {
2530 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2533 case WPS_CM_KEYPAD: {
2534 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2538 issue_p2p_provision_resp(pwdinfo, GetAddr2Ptr(pframe), frame_body, uconfig_method);
2541 RTW_INFO("[%s] config method = %s\n", __FUNCTION__, pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
2546 u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe)
2552 u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
2560 while (ch_cnt > 0) {
2564 for (i = 0 ; i < temp ; i++, j++)
2565 peer_ch_list[j] = *(ch_content + 1 + i);
2566 ch_content += (temp + 1);
2567 ch_cnt -= (temp + 1);
2574 u8 rtw_p2p_check_peer_oper_ch(struct mlme_ext_priv *pmlmeext, u8 ch)
2578 for (i = 0; i < pmlmeext->max_chan_nums; i++) {
2579 if (pmlmeext->channel_set[i].ChannelNum == ch)
2586 u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
2588 int i = 0, j = 0, temp = 0;
2591 for (i = 0; i < peer_ch_num; i++) {
2592 for (j = temp; j < pmlmeext->max_chan_nums; j++) {
2593 if (*(peer_ch_list + i) == pmlmeext->channel_set[j].ChannelNum) {
2594 ch_list_inclusioned[ch_no++] = *(peer_ch_list + i);
2604 u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2606 _adapter *padapter = pwdinfo->padapter;
2607 u8 result = P2P_STATUS_SUCCESS;
2608 u32 p2p_ielen = 0, wps_ielen = 0;
2613 u16 wps_devicepassword_id = 0x0000;
2614 uint wps_devicepassword_id_len = 0;
2617 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
2618 #endif /* CONFIG_TDLS */
2619 #endif /* CONFIG_WFD */
2620 wpsie = rtw_get_wps_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
2622 /* Commented by Kurt 20120113 */
2623 /* If some device wants to do p2p handshake without sending prov_disc_req */
2624 /* We have to get peer_req_cm from here. */
2625 if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
2626 rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8 *) &wps_devicepassword_id, &wps_devicepassword_id_len);
2627 wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
2629 if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2630 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2631 else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2632 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2634 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2637 RTW_INFO("[%s] WPS IE not Found!!\n", __FUNCTION__);
2638 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2639 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2643 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2644 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2646 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2649 RTW_INFO("[%s] P2P IE not Found!!\n", __FUNCTION__);
2650 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2651 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2655 u8 attr_content = 0x00;
2656 u32 attr_contentlen = 0;
2657 u8 ch_content[100] = { 0x00 };
2659 u8 peer_ch_list[100] = { 0x00 };
2661 u8 ch_list_inclusioned[100] = { 0x00 };
2662 u8 ch_num_inclusioned = 0;
2664 u8 listen_ch_attr[5] = { 0x00 };
2666 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
2668 /* Check P2P Capability ATTR */
2669 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *)&attr_contentlen)) {
2670 cap_attr = le16_to_cpu(cap_attr);
2672 #if defined(CONFIG_WFD) && defined(CONFIG_TDLS)
2673 if (!(cap_attr & P2P_GRPCAP_INTRABSS))
2674 ptdlsinfo->ap_prohibited = _TRUE;
2675 #endif /* defined(CONFIG_WFD) && defined(CONFIG_TDLS) */
2678 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen)) {
2679 RTW_INFO("[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01);
2680 pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2682 if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
2683 /* Try to match the tie breaker value */
2684 if (pwdinfo->intent == P2P_MAX_INTENT) {
2685 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2686 result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2688 if (attr_content & 0x01)
2689 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2691 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2693 } else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
2694 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2696 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2698 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2699 /* Store the group id information. */
2700 _rtw_memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2701 _rtw_memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2705 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, (u8 *)listen_ch_attr, (uint *) &attr_contentlen) && attr_contentlen == 5)
2706 pwdinfo->nego_req_info.peer_ch = listen_ch_attr[4];
2708 RTW_INFO(FUNC_ADPT_FMT" listen channel :%u\n", FUNC_ADPT_ARG(padapter), pwdinfo->nego_req_info.peer_ch);
2710 attr_contentlen = 0;
2711 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
2712 if (attr_contentlen != ETH_ALEN)
2713 _rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2716 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt)) {
2717 peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
2718 ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2720 if (ch_num_inclusioned == 0) {
2721 RTW_INFO("[%s] No common channel in channel list!\n", __FUNCTION__);
2722 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2723 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2727 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2728 if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2729 ch_list_inclusioned, ch_num_inclusioned)) {
2730 #ifdef CONFIG_CONCURRENT_MODE
2731 if (rtw_mi_check_status(padapter, MI_LINKED)
2732 && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2733 RTW_INFO("[%s] desired channel NOT Found!\n", __FUNCTION__);
2734 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2735 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2738 #endif /* CONFIG_CONCURRENT_MODE */
2740 u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2741 attr_contentlen = 0;
2743 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2744 peer_operating_ch = operatingch_info[4];
2746 if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2747 ch_list_inclusioned, ch_num_inclusioned)) {
2749 * Change our operating channel as peer's for compatibility.
2751 pwdinfo->operating_channel = peer_operating_ch;
2752 RTW_INFO("[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);
2754 /* Take first channel of ch_list_inclusioned as operating channel */
2755 pwdinfo->operating_channel = ch_list_inclusioned[0];
2756 RTW_INFO("[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);
2764 /* Get the next P2P IE */
2765 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2768 if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) {
2769 result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2770 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
2775 rtw_process_wfd_ies(padapter, pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, __func__);
2781 u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2783 _adapter *padapter = pwdinfo->padapter;
2784 u8 result = P2P_STATUS_SUCCESS;
2785 u32 p2p_ielen, wps_ielen;
2791 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
2792 #endif /* CONFIG_TDLS */
2793 #endif /* CONFIG_WFD */
2795 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2796 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2798 /* Be able to know which one is the P2P GO and which one is P2P client. */
2800 if (rtw_get_wps_ie(ies, ies_len, NULL, &wps_ielen)) {
2803 RTW_INFO("[%s] WPS IE not Found!!\n", __FUNCTION__);
2804 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2805 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2808 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2810 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2811 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2812 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2815 u8 attr_content = 0x00;
2816 u32 attr_contentlen = 0;
2817 u8 operatingch_info[5] = { 0x00 };
2819 u8 ch_content[100] = { 0x00 };
2822 u8 peer_ch_list[100] = { 0x00 };
2824 u8 ch_list_inclusioned[100] = { 0x00 };
2825 u8 ch_num_inclusioned = 0;
2827 while (p2p_ie) { /* Found the P2P IE. */
2829 /* Check P2P Capability ATTR */
2830 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *)&attr_contentlen)) {
2831 cap_attr = le16_to_cpu(cap_attr);
2833 if (!(cap_attr & P2P_GRPCAP_INTRABSS))
2834 ptdlsinfo->ap_prohibited = _TRUE;
2835 #endif /* CONFIG_TDLS */
2838 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2839 if (attr_contentlen == 1) {
2840 RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content);
2841 if (attr_content == P2P_STATUS_SUCCESS) {
2844 if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content)
2845 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
2847 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2848 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2849 result = attr_content;
2854 /* Try to get the peer's interface address */
2855 attr_contentlen = 0;
2856 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
2857 if (attr_contentlen != ETH_ALEN)
2858 _rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2861 /* Try to get the peer's intent and tie breaker value. */
2862 attr_content = 0x00;
2863 attr_contentlen = 0;
2864 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen)) {
2865 RTW_INFO("[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01);
2866 pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2868 if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
2869 /* Try to match the tie breaker value */
2870 if (pwdinfo->intent == P2P_MAX_INTENT) {
2871 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2872 result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2873 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2875 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2876 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2877 if (attr_content & 0x01)
2878 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2880 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2882 } else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) {
2883 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2884 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2885 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2887 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2888 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2889 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2892 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2893 /* Store the group id information. */
2894 _rtw_memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2895 _rtw_memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2900 /* Try to get the operation channel information */
2902 attr_contentlen = 0;
2903 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
2904 RTW_INFO("[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4]);
2905 pwdinfo->peer_operating_ch = operatingch_info[4];
2908 /* Try to get the channel list information */
2909 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len)) {
2910 RTW_INFO("[%s] channel list attribute found, len = %d\n", __FUNCTION__, pwdinfo->channel_list_attr_len);
2912 peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
2913 ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2915 if (ch_num_inclusioned == 0) {
2916 RTW_INFO("[%s] No common channel in channel list!\n", __FUNCTION__);
2917 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2918 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2922 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2923 if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2924 ch_list_inclusioned, ch_num_inclusioned)) {
2925 #ifdef CONFIG_CONCURRENT_MODE
2926 if (rtw_mi_check_status(padapter, MI_LINKED)
2927 && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2928 RTW_INFO("[%s] desired channel NOT Found!\n", __FUNCTION__);
2929 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2930 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2933 #endif /* CONFIG_CONCURRENT_MODE */
2935 u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2936 attr_contentlen = 0;
2938 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2939 peer_operating_ch = operatingch_info[4];
2941 if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2942 ch_list_inclusioned, ch_num_inclusioned)) {
2944 * Change our operating channel as peer's for compatibility.
2946 pwdinfo->operating_channel = peer_operating_ch;
2947 RTW_INFO("[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);
2949 /* Take first channel of ch_list_inclusioned as operating channel */
2950 pwdinfo->operating_channel = ch_list_inclusioned[0];
2951 RTW_INFO("[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);
2959 RTW_INFO("[%s] channel list attribute not found!\n", __FUNCTION__);
2961 /* Try to get the group id information if peer is GO */
2962 attr_contentlen = 0;
2963 _rtw_memset(groupid, 0x00, 38);
2964 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
2965 _rtw_memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
2966 _rtw_memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
2969 /* Get the next P2P IE */
2970 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2976 rtw_process_wfd_ies(padapter, pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, __func__);
2983 u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2985 _adapter *padapter = pwdinfo->padapter;
2990 u8 result = P2P_STATUS_SUCCESS;
2991 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2992 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2994 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2995 while (p2p_ie) { /* Found the P2P IE. */
2996 u8 attr_content = 0x00, operatingch_info[5] = { 0x00 };
2997 u8 groupid[38] = { 0x00 };
2998 u32 attr_contentlen = 0;
3000 pwdinfo->negotiation_dialog_token = 1;
3001 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
3002 if (attr_contentlen == 1) {
3003 RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content);
3004 result = attr_content;
3006 if (attr_content == P2P_STATUS_SUCCESS) {
3009 _cancel_timer(&pwdinfo->restore_p2p_state_timer, &bcancelled);
3011 /* Commented by Albert 20100911 */
3012 /* Todo: Need to handle the case which both Intents are the same. */
3013 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3014 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3015 if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1))
3016 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3017 else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1))
3018 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3020 /* Have to compare the Tie Breaker */
3021 if (pwdinfo->peer_intent & 0x01)
3022 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3024 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3027 #ifdef CONFIG_CONCURRENT_MODE
3028 if (rtw_mi_check_status(padapter, MI_LINKED)
3029 && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
3030 /* Switch back to the AP channel soon. */
3031 _set_timer(&pwdinfo->ap_p2p_switch_timer, 100);
3035 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3036 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
3041 /* Try to get the group id information */
3042 attr_contentlen = 0;
3043 _rtw_memset(groupid, 0x00, 38);
3044 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
3045 RTW_INFO("[%s] Ssid = %s, ssidlen = %zu\n", __FUNCTION__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));
3046 _rtw_memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
3047 _rtw_memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
3050 attr_contentlen = 0;
3051 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
3052 RTW_INFO("[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4]);
3053 pwdinfo->peer_operating_ch = operatingch_info[4];
3056 /* Get the next P2P IE */
3057 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3064 u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
3068 u8 status = P2P_STATUS_SUCCESS;
3070 frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
3072 dialogToken = frame_body[6];
3074 /* todo: check NoA attribute */
3076 issue_p2p_presence_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
3081 void find_phase_handler(_adapter *padapter)
3083 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3084 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3085 NDIS_802_11_SSID ssid;
3090 _rtw_memset((unsigned char *)&ssid, 0, sizeof(NDIS_802_11_SSID));
3091 _rtw_memcpy(ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
3092 ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
3094 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
3096 _enter_critical_bh(&pmlmepriv->lock, &irqL);
3097 _status = rtw_sitesurvey_cmd(padapter, &ssid, 1, NULL, 0);
3098 _exit_critical_bh(&pmlmepriv->lock, &irqL);
3103 void p2p_concurrent_handler(_adapter *padapter);
3105 void restore_p2p_state_handler(_adapter *padapter)
3107 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3108 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3111 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3112 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3114 #ifdef CONFIG_CONCURRENT_MODE
3115 if (rtw_mi_check_status(padapter, MI_LINKED)) {
3116 u8 union_ch = rtw_mi_get_union_chan(padapter);
3117 u8 union_bw = rtw_mi_get_union_bw(padapter);
3118 u8 union_offset = rtw_mi_get_union_offset(padapter);
3120 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP)) {
3121 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
3122 rtw_mi_buddy_issue_nulldata(padapter, NULL, 0, 3, 500);
3127 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3129 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
3130 #ifdef CONFIG_CONCURRENT_MODE
3131 p2p_concurrent_handler(padapter);
3133 /* In the P2P client mode, the driver should not switch back to its listen channel */
3134 /* because this P2P client should stay at the operating channel of P2P GO. */
3135 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3140 void pre_tx_invitereq_handler(_adapter *padapter)
3142 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3145 set_channel_bwmode(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3146 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3147 issue_probereq_p2p(padapter, NULL);
3148 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3152 void pre_tx_provdisc_handler(_adapter *padapter)
3154 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3157 set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3158 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3159 issue_probereq_p2p(padapter, NULL);
3160 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3164 void pre_tx_negoreq_handler(_adapter *padapter)
3166 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3169 set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3170 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3171 issue_probereq_p2p(padapter , NULL);
3172 /* WIN Phone only accept unicast probe request when nego back */
3173 issue_probereq_p2p(padapter , pwdinfo->nego_req_info.peerDevAddr);
3174 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3178 #ifdef CONFIG_CONCURRENT_MODE
3179 void p2p_concurrent_handler(_adapter *padapter)
3181 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3182 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3183 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3186 if (rtw_mi_check_status(padapter, MI_LINKED)) {
3187 u8 union_ch = rtw_mi_get_union_chan(padapter);
3188 u8 union_bw = rtw_mi_get_union_bw(padapter);
3189 u8 union_offset = rtw_mi_get_union_offset(padapter);
3191 pwdinfo->operating_channel = union_ch;
3193 if (pwdinfo->driver_interface == DRIVER_CFG80211) {
3194 RTW_INFO("%s, switch ch back to union_ch=%d\n", __func__, union_ch);
3195 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
3197 rtw_mi_buddy_issue_nulldata(padapter, NULL, 0, 3, 500);
3199 } else if (pwdinfo->driver_interface == DRIVER_WEXT) {
3200 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
3201 /* Now, the driver stays on the AP's channel. */
3202 /* If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel. */
3203 if (pwdinfo->ext_listen_period > 0) {
3204 RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period);
3206 if (union_ch != pwdinfo->listen_channel) {
3207 /* Will switch to listen channel so that need to send the NULL data with PW bit to AP. */
3208 rtw_mi_buddy_issue_nulldata(padapter, NULL, 1, 3, 500);
3209 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3212 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3214 if (!rtw_mi_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) {
3216 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3218 /* Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not. */
3219 _set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period);
3221 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) ||
3222 rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) ||
3223 (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE) ||
3224 rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) {
3225 /* Now, the driver is in the listen state of P2P mode. */
3226 RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval);
3228 /* Commented by Albert 2012/11/01 */
3229 /* If the AP's channel is the same as the listen channel, we should still be in the listen state */
3230 /* Other P2P device is still able to find this device out even this device is in the AP's channel. */
3231 /* So, configure this device to be able to receive the probe request frame and set it to listen state. */
3232 if (union_ch != pwdinfo->listen_channel) {
3234 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
3235 if (!rtw_mi_check_status(padapter, MI_AP_MODE)) {
3237 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3239 rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
3240 rtw_mi_buddy_issue_nulldata(padapter, NULL, 0, 3, 500);
3243 /* Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not. */
3244 _set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval);
3245 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) {
3246 /* The driver had finished the P2P handshake successfully. */
3248 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3249 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
3250 rtw_mi_buddy_issue_nulldata(padapter, NULL, 0, 3, 500);
3251 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
3253 set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3254 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3255 issue_probereq_p2p(padapter, NULL);
3256 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3257 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE) {
3259 set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3260 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3261 issue_probereq_p2p(padapter, NULL);
3262 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3263 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ) && pwdinfo->invitereq_info.benable == _TRUE) {
3266 set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3267 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3268 issue_probereq_p2p(padapter, NULL);
3269 _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
3274 /* In p2p+softap. When in P2P_STATE_GONEGO_OK, not back to listen channel.*/
3275 if (!rtw_p2p_chk_state(pwdinfo , P2P_STATE_GONEGO_OK) || padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3276 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3278 RTW_INFO("%s, buddy not linked, go nego ok, not back to listen channel\n", __func__);
3284 #ifdef CONFIG_IOCTL_CFG80211
3285 static int ro_ch_handler(_adapter *adapter, u8 *buf)
3287 /* TODO: move remain on channel logical here */
3291 static int cancel_ro_ch_handler(_adapter *padapter, u8 *buf)
3293 int ret = H2C_SUCCESS;
3294 struct p2p_roch_parm *roch_parm = (struct p2p_roch_parm *)buf;
3295 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
3296 struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
3297 struct wireless_dev *wdev;
3298 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3301 _enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
3303 if (rtw_cfg80211_get_is_roch(padapter) != _TRUE)
3306 if (roch_parm->wdev && roch_parm->cookie) {
3307 if (pcfg80211_wdinfo->ro_ch_wdev != roch_parm->wdev) {
3308 RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"
3309 , FUNC_ADPT_ARG(padapter), pcfg80211_wdinfo->ro_ch_wdev, roch_parm->wdev);
3313 if (pcfg80211_wdinfo->remain_on_ch_cookie != roch_parm->cookie) {
3314 RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"
3315 , FUNC_ADPT_ARG(padapter), pcfg80211_wdinfo->remain_on_ch_cookie, roch_parm->cookie);
3320 if (rtw_mi_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) {
3322 RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
3323 FUNC_ADPT_ARG(padapter), ch, bw, offset);
3324 } else if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->listen_channel) {
3325 ch = pwdinfo->listen_channel;
3326 bw = CHANNEL_WIDTH_20;
3327 offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3329 RTW_INFO(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n",
3330 FUNC_ADPT_ARG(padapter), ch, bw, offset);
3332 ch = pcfg80211_wdinfo->restore_channel;
3333 bw = CHANNEL_WIDTH_20;
3334 offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3336 RTW_INFO(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n",
3337 FUNC_ADPT_ARG(padapter), ch, bw, offset);
3340 set_channel_bwmode(padapter, ch, offset, bw);
3342 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3343 #ifdef CONFIG_DEBUG_CFG80211
3344 RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
3347 wdev = pcfg80211_wdinfo->ro_ch_wdev;
3349 rtw_cfg80211_set_is_roch(padapter, _FALSE);
3350 pcfg80211_wdinfo->ro_ch_wdev = NULL;
3351 pcfg80211_wdinfo->last_ro_ch_time = rtw_get_current_time();
3353 rtw_cfg80211_remain_on_channel_expired(wdev
3354 , pcfg80211_wdinfo->remain_on_ch_cookie
3355 , &pcfg80211_wdinfo->remain_on_ch_channel
3356 , pcfg80211_wdinfo->remain_on_ch_type, GFP_KERNEL);
3358 RTW_INFO("cfg80211_remain_on_channel_expired cookie:0x%llx\n"
3359 , pcfg80211_wdinfo->remain_on_ch_cookie);
3361 #ifdef CONFIG_BT_COEXIST
3362 rtw_btcoex_ScanNotify(padapter, _FALSE);
3366 _exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
3371 static void ro_ch_timer_process(void *FunctionContext)
3373 _adapter *adapter = (_adapter *)FunctionContext;
3375 p2p_cancel_roch_cmd(adapter, 0, NULL, 0);
3378 static void rtw_change_p2pie_op_ch(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
3381 u32 ies_len, p2p_ielen;
3383 ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3384 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3386 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3389 u32 attr_contentlen = 0;
3392 /* Check P2P_ATTR_OPERATING_CH */
3393 attr_contentlen = 0;
3395 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
3399 /* Get the next P2P IE */
3400 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3404 static void rtw_change_p2pie_ch_list(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
3407 u32 ies_len, p2p_ielen;
3409 ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3410 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3412 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3415 u32 attr_contentlen = 0;
3418 /* Check P2P_ATTR_CH_LIST */
3419 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
3420 if (pattr != NULL) {
3423 u8 *pattr_temp = pattr + 3 ;
3425 attr_contentlen -= 3;
3427 while (attr_contentlen > 0) {
3428 num_of_ch = *(pattr_temp + 1);
3430 for (i = 0; i < num_of_ch; i++)
3431 *(pattr_temp + 2 + i) = ch;
3433 pattr_temp += (2 + num_of_ch);
3434 attr_contentlen -= (2 + num_of_ch);
3438 /* Get the next P2P IE */
3439 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3443 static bool rtw_chk_p2pie_ch_list_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
3446 #ifdef CONFIG_CONCURRENT_MODE
3448 u32 ies_len, p2p_ielen;
3449 u8 union_ch = rtw_mi_get_union_chan(padapter);
3451 ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3452 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3454 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3457 u32 attr_contentlen = 0;
3460 /* Check P2P_ATTR_CH_LIST */
3461 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
3462 if (pattr != NULL) {
3465 u8 *pattr_temp = pattr + 3 ;
3467 attr_contentlen -= 3;
3469 while (attr_contentlen > 0) {
3470 num_of_ch = *(pattr_temp + 1);
3472 for (i = 0; i < num_of_ch; i++) {
3473 if (*(pattr_temp + 2 + i) == union_ch) {
3474 RTW_INFO(FUNC_ADPT_FMT" ch_list fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), union_ch);
3480 pattr_temp += (2 + num_of_ch);
3481 attr_contentlen -= (2 + num_of_ch);
3485 /* Get the next P2P IE */
3486 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3492 static bool rtw_chk_p2pie_op_ch_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
3495 #ifdef CONFIG_CONCURRENT_MODE
3497 u32 ies_len, p2p_ielen;
3498 u8 union_ch = rtw_mi_get_union_chan(padapter);
3500 ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3501 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3503 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3506 u32 attr_contentlen = 0;
3509 /* Check P2P_ATTR_OPERATING_CH */
3510 attr_contentlen = 0;
3512 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
3513 if (pattr != NULL) {
3514 if (*(pattr + 4) == union_ch) {
3515 RTW_INFO(FUNC_ADPT_FMT" op_ch fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), union_ch);
3521 /* Get the next P2P IE */
3522 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3528 static void rtw_cfg80211_adjust_p2pie_channel(_adapter *padapter, const u8 *frame_body, u32 len)
3530 #ifdef CONFIG_CONCURRENT_MODE
3532 u32 ies_len, p2p_ielen;
3533 u8 union_ch = rtw_mi_get_union_chan(padapter);
3535 ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3536 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3538 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3541 u32 attr_contentlen = 0;
3544 /* Check P2P_ATTR_CH_LIST */
3545 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
3546 if (pattr != NULL) {
3549 u8 *pattr_temp = pattr + 3 ;
3551 attr_contentlen -= 3;
3553 while (attr_contentlen > 0) {
3554 num_of_ch = *(pattr_temp + 1);
3556 for (i = 0; i < num_of_ch; i++) {
3557 if (*(pattr_temp + 2 + i) && *(pattr_temp + 2 + i) != union_ch) {
3558 #ifdef RTW_SINGLE_WIPHY
3559 RTW_ERR("replace ch_list:%u with:%u\n", *(pattr_temp + 2 + i), union_ch);
3561 *(pattr_temp + 2 + i) = union_ch; /*forcing to the same channel*/
3565 pattr_temp += (2 + num_of_ch);
3566 attr_contentlen -= (2 + num_of_ch);
3570 /* Check P2P_ATTR_OPERATING_CH */
3571 attr_contentlen = 0;
3573 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
3574 if (pattr != NULL) {
3575 if (*(pattr + 4) && *(pattr + 4) != union_ch) {
3576 #ifdef RTW_SINGLE_WIPHY
3577 RTW_ERR("replace op_ch:%u with:%u\n", *(pattr + 4), union_ch);
3579 *(pattr + 4) = union_ch; /*forcing to the same channel */
3583 /* Get the next P2P IE */
3584 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3592 u32 rtw_xframe_build_wfd_ie(struct xmit_frame *xframe)
3594 _adapter *adapter = xframe->padapter;
3595 struct wifidirect_info *wdinfo = &adapter->wdinfo;
3596 u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
3597 u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
3598 u8 *frame_tail = frame + xframe->attrib.pktlen;
3599 u8 category, action, OUI_Subtype, dialogToken = 0;
3602 category = frame_body[0];
3603 if (category == RTW_WLAN_CATEGORY_PUBLIC) {
3604 action = frame_body[1];
3605 if (action == ACT_PUBLIC_VENDOR
3606 && _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
3608 OUI_Subtype = frame_body[6];
3609 dialogToken = frame_body[7];
3611 switch (OUI_Subtype) {
3612 case P2P_GO_NEGO_REQ:
3613 wfdielen = build_nego_req_wfd_ie(wdinfo, frame_tail);
3615 case P2P_GO_NEGO_RESP:
3616 wfdielen = build_nego_resp_wfd_ie(wdinfo, frame_tail);
3618 case P2P_GO_NEGO_CONF:
3619 wfdielen = build_nego_confirm_wfd_ie(wdinfo, frame_tail);
3622 wfdielen = build_invitation_req_wfd_ie(wdinfo, frame_tail);
3624 case P2P_INVIT_RESP:
3625 wfdielen = build_invitation_resp_wfd_ie(wdinfo, frame_tail);
3627 case P2P_PROVISION_DISC_REQ:
3628 wfdielen = build_provdisc_req_wfd_ie(wdinfo, frame_tail);
3630 case P2P_PROVISION_DISC_RESP:
3631 wfdielen = build_provdisc_resp_wfd_ie(wdinfo, frame_tail);
3633 case P2P_DEVDISC_REQ:
3634 case P2P_DEVDISC_RESP:
3640 } else if (category == RTW_WLAN_CATEGORY_P2P) {
3641 OUI_Subtype = frame_body[5];
3642 dialogToken = frame_body[6];
3644 #ifdef CONFIG_DEBUG_CFG80211
3645 RTW_INFO("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n"
3646 , cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);
3649 switch (OUI_Subtype) {
3650 case P2P_NOTICE_OF_ABSENCE:
3652 case P2P_PRESENCE_REQUEST:
3654 case P2P_PRESENCE_RESPONSE:
3656 case P2P_GO_DISC_REQUEST:
3662 RTW_INFO("%s, action frame category=%d\n", __func__, category);
3664 xframe->attrib.pktlen += wfdielen;
3668 #endif /* CONFIG_WFD */
3670 bool rtw_xframe_del_wfd_ie(struct xmit_frame *xframe)
3672 #define DBG_XFRAME_DEL_WFD_IE 0
3674 _adapter *adapter = xframe->padapter;
3675 u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
3676 u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
3677 u8 *frame_tail = frame + xframe->attrib.pktlen;
3678 u8 category, action, OUI_Subtype;
3680 uint ies_len_ori = 0;
3683 category = frame_body[0];
3684 if (category == RTW_WLAN_CATEGORY_PUBLIC) {
3685 action = frame_body[1];
3686 if (action == ACT_PUBLIC_VENDOR
3687 && _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
3689 OUI_Subtype = frame_body[6];
3691 switch (OUI_Subtype) {
3692 case P2P_GO_NEGO_REQ:
3693 case P2P_GO_NEGO_RESP:
3694 case P2P_GO_NEGO_CONF:
3696 case P2P_INVIT_RESP:
3697 case P2P_PROVISION_DISC_REQ:
3698 case P2P_PROVISION_DISC_RESP:
3699 ies = frame_body + 8;
3700 ies_len_ori = frame_tail - (frame_body + 8);
3706 if (ies && ies_len_ori) {
3707 ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_XFRAME_DEL_WFD_IE ? __func__ : NULL);
3708 xframe->attrib.pktlen -= (ies_len_ori - ies_len);
3711 return ies_len_ori != ies_len;
3715 * rtw_xframe_chk_wfd_ie -
3718 void rtw_xframe_chk_wfd_ie(struct xmit_frame *xframe)
3720 _adapter *adapter = xframe->padapter;
3721 u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
3722 u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
3723 u8 *frame_tail = frame + xframe->attrib.pktlen;
3725 struct wifidirect_info *wdinfo = &adapter->wdinfo;
3726 struct mlme_priv *mlme = &adapter->mlmepriv;
3730 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
3733 #ifdef CONFIG_IOCTL_CFG80211
3734 if (_TRUE == wdinfo->wfd_info->wfd_enable)
3739 rtw_xframe_del_wfd_ie(xframe);
3743 rtw_xframe_build_wfd_ie(xframe);
3747 u8 *dump_p2p_attr_ch_list(u8 *p2p_ie, uint p2p_ielen, u8 *buf, u32 buf_len)
3749 uint attr_contentlen = 0;
3754 bool continuous = _FALSE;
3756 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, &attr_contentlen);
3757 if (pattr != NULL) {
3760 u8 *pattr_temp = pattr + 3 ;
3762 attr_contentlen -= 3;
3764 _rtw_memset(ch_list, 0, 40);
3766 while (attr_contentlen > 0) {
3767 num_of_ch = *(pattr_temp + 1);
3769 for (i = 0; i < num_of_ch; i++) {
3770 for (j = 0; j < ch_cnt; j++) {
3771 if (ch_list[j] == *(pattr_temp + 2 + i))
3775 ch_list[ch_cnt++] = *(pattr_temp + 2 + i);
3779 pattr_temp += (2 + num_of_ch);
3780 attr_contentlen -= (2 + num_of_ch);
3783 for (j = 0; j < ch_cnt; j++) {
3785 w_sz += snprintf(buf + w_sz, buf_len - w_sz, "%u", ch_list[j]);
3786 else if (ch_list[j] - ch_list[j - 1] != 1)
3787 w_sz += snprintf(buf + w_sz, buf_len - w_sz, ", %u", ch_list[j]);
3788 else if (j != ch_cnt - 1 && ch_list[j + 1] - ch_list[j] == 1) {
3791 w_sz += snprintf(buf + w_sz, buf_len - w_sz, "-%u", ch_list[j]);
3798 * return _TRUE if requester is GO, _FALSE if responder is GO
3800 bool rtw_p2p_nego_intent_compare(u8 req, u8 resp)
3802 if (req >> 1 == resp >> 1)
3803 return req & 0x01 ? _TRUE : _FALSE;
3804 else if (req >> 1 > resp >> 1)
3810 int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx)
3812 int is_p2p_frame = (-1);
3813 unsigned char *frame_body;
3814 u8 category, action, OUI_Subtype, dialogToken = 0;
3817 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
3819 u8 ch_list_buf[128] = {'\0'};
3826 frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));
3827 category = frame_body[0];
3828 /* just for check */
3829 if (category == RTW_WLAN_CATEGORY_PUBLIC) {
3830 action = frame_body[1];
3831 if (action == ACT_PUBLIC_VENDOR
3832 && _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
3834 OUI_Subtype = frame_body[6];
3835 dialogToken = frame_body[7];
3836 is_p2p_frame = OUI_Subtype;
3838 #ifdef CONFIG_DEBUG_CFG80211
3839 RTW_INFO("ACTION_CATEGORY_PUBLIC: ACT_PUBLIC_VENDOR, OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
3840 cpu_to_be32(*((u32 *)(frame_body + 2))), OUI_Subtype, dialogToken);
3843 p2p_ie = rtw_get_p2p_ie(
3844 (u8 *)buf + sizeof(struct rtw_ieee80211_hdr_3addr) + _PUBLIC_ACTION_IE_OFFSET_
3845 , len - sizeof(struct rtw_ieee80211_hdr_3addr) - _PUBLIC_ACTION_IE_OFFSET_
3846 , NULL, &p2p_ielen);
3848 switch (OUI_Subtype) { /* OUI Subtype */
3851 case P2P_GO_NEGO_REQ: {
3852 struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
3855 #ifdef CONFIG_DRV_ISSUE_PROV_REQ /* IOT FOR S2 */
3856 if (pwdev_priv->provdisc_req_issued == _FALSE)
3857 rtw_cfg80211_issue_p2p_provision_request(padapter, buf, len);
3858 #endif /* CONFIG_DRV_ISSUE_PROV_REQ */
3860 /* pwdev_priv->provdisc_req_issued = _FALSE; */
3862 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3863 if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3864 rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
3868 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
3870 op_ch = *(cont + 4);
3871 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, NULL, &cont_len);
3873 listen_ch = *(cont + 4);
3874 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len);
3877 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, NULL, &cont_len);
3878 if (cont && cont_len == 6)
3881 if (nego_info->token != dialogToken)
3882 rtw_wdev_nego_info_init(nego_info);
3884 _rtw_memcpy(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN);
3886 _rtw_memcpy(tx ? nego_info->iface_addr : nego_info->peer_iface_addr, iaddr, ETH_ALEN);
3887 nego_info->active = tx ? 1 : 0;
3888 nego_info->token = dialogToken;
3889 nego_info->req_op_ch = op_ch;
3890 nego_info->req_listen_ch = listen_ch;
3891 nego_info->req_intent = intent;
3892 nego_info->state = 0;
3894 dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
3895 RTW_INFO("RTW_%s:P2P_GO_NEGO_REQ, dialogToken=%d, intent:%u%s, listen_ch:%d, op_ch:%d, ch_list:%s"
3896 , (tx == _TRUE) ? "Tx" : "Rx" , dialogToken , (intent >> 1) , intent & 0x1 ? "+" : "-" , listen_ch , op_ch , ch_list_buf);
3898 _RTW_INFO(", iaddr:"MAC_FMT, MAC_ARG(iaddr));
3902 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3903 if (rtw_mi_check_status(padapter, MI_LINKED)
3904 && rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE
3905 && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
3906 RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
3907 rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
3914 case P2P_GO_NEGO_RESP: {
3915 struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
3918 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3919 if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3920 rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
3924 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
3926 op_ch = *(cont + 4);
3927 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len);
3930 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3933 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, NULL, &cont_len);
3934 if (cont && cont_len == 6)
3937 if (nego_info->token == dialogToken && nego_info->state == 0
3938 && _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE
3941 _rtw_memcpy(tx ? nego_info->iface_addr : nego_info->peer_iface_addr, iaddr, ETH_ALEN);
3942 nego_info->status = (status == -1) ? 0xff : status;
3943 nego_info->rsp_op_ch = op_ch;
3944 nego_info->rsp_intent = intent;
3945 nego_info->state = 1;
3947 nego_info->token = 0; /* init */
3950 dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
3951 RTW_INFO("RTW_%s:P2P_GO_NEGO_RESP, dialogToken=%d, intent:%u%s, status:%d, op_ch:%d, ch_list:%s"
3952 , (tx == _TRUE) ? "Tx" : "Rx", dialogToken, (intent >> 1), intent & 0x1 ? "+" : "-", status, op_ch, ch_list_buf);
3954 _RTW_INFO(", iaddr:"MAC_FMT, MAC_ARG(iaddr));
3958 pwdev_priv->provdisc_req_issued = _FALSE;
3959 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3960 if (rtw_mi_check_status(padapter, MI_LINKED)
3961 && rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE
3962 && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
3963 RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
3964 rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
3971 case P2P_GO_NEGO_CONF: {
3972 struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
3973 bool is_go = _FALSE;
3976 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3977 if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3978 rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
3982 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
3984 op_ch = *(cont + 4);
3985 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3989 if (nego_info->token == dialogToken && nego_info->state == 1
3990 && _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE
3992 nego_info->status = (status == -1) ? 0xff : status;
3993 nego_info->conf_op_ch = (op_ch == -1) ? 0 : op_ch;
3994 nego_info->state = 2;
3997 if (rtw_p2p_nego_intent_compare(nego_info->req_intent, nego_info->rsp_intent) ^ !tx)
4001 nego_info->token = 0; /* init */
4004 dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4005 RTW_INFO("RTW_%s:P2P_GO_NEGO_CONF, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n"
4006 , (tx == _TRUE) ? "Tx" : "Rx", dialogToken, status, op_ch, ch_list_buf);
4013 case P2P_INVIT_REQ: {
4014 struct rtw_wdev_invit_info *invit_info = &pwdev_priv->invit_info;
4018 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4019 if (rtw_mi_check_status(padapter, MI_LINKED)
4020 && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
4021 rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
4025 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len);
4028 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
4030 op_ch = *(cont + 4);
4031 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, NULL, &cont_len);
4032 if (cont && cont_len == 6)
4035 if (invit_info->token != dialogToken)
4036 rtw_wdev_invit_info_init(invit_info);
4038 _rtw_memcpy(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN);
4040 _rtw_memcpy(invit_info->group_bssid, gbssid, ETH_ALEN);
4041 invit_info->active = tx ? 1 : 0;
4042 invit_info->token = dialogToken;
4043 invit_info->flags = (flags == -1) ? 0x0 : flags;
4044 invit_info->req_op_ch = op_ch;
4045 invit_info->state = 0;
4047 dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4048 RTW_INFO("RTW_%s:P2P_INVIT_REQ, dialogToken=%d, flags:0x%02x, op_ch:%d, ch_list:%s"
4049 , (tx == _TRUE) ? "Tx" : "Rx", dialogToken, flags, op_ch, ch_list_buf);
4051 _RTW_INFO(", gbssid:"MAC_FMT, MAC_ARG(gbssid));
4055 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4056 if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
4057 if (op_ch != -1 && rtw_chk_p2pie_op_ch_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
4058 RTW_INFO(FUNC_ADPT_FMT" op_ch:%u has no intersect with buddy\n", FUNC_ADPT_ARG(padapter), op_ch);
4059 rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
4060 } else if (rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
4061 RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
4062 rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
4070 case P2P_INVIT_RESP: {
4071 struct rtw_wdev_invit_info *invit_info = &pwdev_priv->invit_info;
4074 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4075 if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
4076 rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
4080 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
4082 #ifdef CONFIG_P2P_INVITE_IOT
4083 if (tx && *cont == 7) {
4084 RTW_INFO("TX_P2P_INVITE_RESP, status is no common channel, change to unknown group\n");
4085 *cont = 8; /* unknow group status */
4087 #endif /* CONFIG_P2P_INVITE_IOT */
4090 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
4092 op_ch = *(cont + 4);
4093 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, NULL, &cont_len);
4094 if (cont && cont_len == 6)
4097 if (invit_info->token == dialogToken && invit_info->state == 0
4098 && _rtw_memcmp(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE
4100 invit_info->status = (status == -1) ? 0xff : status;
4101 invit_info->rsp_op_ch = op_ch;
4102 invit_info->state = 1;
4103 invit_info->token = 0; /* init */
4106 dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4107 RTW_INFO("RTW_%s:P2P_INVIT_RESP, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s"
4108 , (tx == _TRUE) ? "Tx" : "Rx", dialogToken, status, op_ch, ch_list_buf);
4110 _RTW_INFO(", gbssid:"MAC_FMT, MAC_ARG(gbssid));
4118 case P2P_DEVDISC_REQ:
4119 RTW_INFO("RTW_%s:P2P_DEVDISC_REQ, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
4121 case P2P_DEVDISC_RESP:
4122 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
4123 RTW_INFO("RTW_%s:P2P_DEVDISC_RESP, dialogToken=%d, status:%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken, cont ? *cont : -1);
4125 case P2P_PROVISION_DISC_REQ: {
4126 size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);
4129 uint contentlen = 0;
4131 RTW_INFO("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
4135 pwdev_priv->provdisc_req_issued = _FALSE;
4137 p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
4140 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, NULL, &contentlen)) {
4141 pwdev_priv->provdisc_req_issued = _FALSE;/* case: p2p_client join p2p GO */
4143 #ifdef CONFIG_DEBUG_CFG80211
4144 RTW_INFO("provdisc_req_issued is _TRUE\n");
4145 #endif /*CONFIG_DEBUG_CFG80211*/
4146 pwdev_priv->provdisc_req_issued = _TRUE;/* case: p2p_devices connection before Nego req. */
4153 case P2P_PROVISION_DISC_RESP:
4154 RTW_INFO("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
4157 RTW_INFO("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", OUI_Subtype, dialogToken);
4163 } else if (category == RTW_WLAN_CATEGORY_P2P) {
4164 OUI_Subtype = frame_body[5];
4165 dialogToken = frame_body[6];
4167 #ifdef CONFIG_DEBUG_CFG80211
4168 RTW_INFO("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
4169 cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);
4172 is_p2p_frame = OUI_Subtype;
4174 switch (OUI_Subtype) {
4175 case P2P_NOTICE_OF_ABSENCE:
4176 RTW_INFO("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken=%d\n", (tx == _TRUE) ? "TX" : "RX", dialogToken);
4178 case P2P_PRESENCE_REQUEST:
4179 RTW_INFO("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken=%d\n", (tx == _TRUE) ? "TX" : "RX", dialogToken);
4181 case P2P_PRESENCE_RESPONSE:
4182 RTW_INFO("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken=%d\n", (tx == _TRUE) ? "TX" : "RX", dialogToken);
4184 case P2P_GO_DISC_REQUEST:
4185 RTW_INFO("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken=%d\n", (tx == _TRUE) ? "TX" : "RX", dialogToken);
4188 RTW_INFO("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx == _TRUE) ? "TX" : "RX", OUI_Subtype, dialogToken);
4193 RTW_INFO("RTW_%s:action frame category=%d\n", (tx == _TRUE) ? "TX" : "RX", category);
4195 return is_p2p_frame;
4198 void rtw_init_cfg80211_wifidirect_info(_adapter *padapter)
4200 struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
4202 _rtw_memset(pcfg80211_wdinfo, 0x00, sizeof(struct cfg80211_wifidirect_info));
4204 _init_timer(&pcfg80211_wdinfo->remain_on_ch_timer, padapter->pnetdev, ro_ch_timer_process, padapter);
4206 #endif /* CONFIG_IOCTL_CFG80211 */
4208 s32 p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)
4210 int ret = H2C_SUCCESS;
4211 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4213 switch (intCmdType) {
4214 case P2P_FIND_PHASE_WK:
4215 find_phase_handler(padapter);
4218 case P2P_RESTORE_STATE_WK:
4219 restore_p2p_state_handler(padapter);
4222 case P2P_PRE_TX_PROVDISC_PROCESS_WK:
4223 #ifdef CONFIG_CONCURRENT_MODE
4224 if (rtw_mi_check_status(padapter, MI_LINKED))
4225 p2p_concurrent_handler(padapter);
4227 pre_tx_provdisc_handler(padapter);
4229 pre_tx_provdisc_handler(padapter);
4233 case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
4234 #ifdef CONFIG_CONCURRENT_MODE
4235 if (rtw_mi_check_status(padapter, MI_LINKED))
4236 p2p_concurrent_handler(padapter);
4238 pre_tx_invitereq_handler(padapter);
4240 pre_tx_invitereq_handler(padapter);
4244 case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
4245 #ifdef CONFIG_CONCURRENT_MODE
4246 if (rtw_mi_check_status(padapter, MI_LINKED))
4247 p2p_concurrent_handler(padapter);
4249 pre_tx_negoreq_handler(padapter);
4251 pre_tx_negoreq_handler(padapter);
4255 #ifdef CONFIG_CONCURRENT_MODE
4256 case P2P_AP_P2P_CH_SWITCH_PROCESS_WK:
4257 p2p_concurrent_handler(padapter);
4261 #ifdef CONFIG_IOCTL_CFG80211
4263 ret = ro_ch_handler(padapter, buf);
4265 case P2P_CANCEL_RO_CH_WK:
4266 ret = cancel_ro_ch_handler(padapter, buf);
4278 int process_p2p_cross_connect_ie(PADAPTER padapter, u8 *IEs, u32 IELength)
4285 u8 p2p_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */
4286 u32 attr_contentlen = 0;
4288 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4291 if (IELength <= _BEACON_IE_OFFSET_)
4294 ies = IEs + _BEACON_IE_OFFSET_;
4295 ies_len = IELength - _BEACON_IE_OFFSET_;
4297 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
4300 /* Get P2P Manageability IE. */
4301 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_MANAGEABILITY, p2p_attr, &attr_contentlen)) {
4302 if ((p2p_attr[0] & (BIT(0) | BIT(1))) == 0x01)
4306 /* Get the next P2P IE */
4307 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
4313 #ifdef CONFIG_P2P_PS
4314 void process_p2p_ps_ie(PADAPTER padapter, u8 *IEs, u32 IELength)
4320 u8 noa_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */
4321 u32 attr_contentlen = 0;
4323 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4324 u8 find_p2p = _FALSE, find_p2p_ps = _FALSE;
4325 u8 noa_offset, noa_num, noa_index;
4328 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4330 #ifdef CONFIG_CONCURRENT_MODE
4331 if (padapter->hw_port != HW_PORT0)
4334 if (IELength <= _BEACON_IE_OFFSET_)
4337 ies = IEs + _BEACON_IE_OFFSET_;
4338 ies_len = IELength - _BEACON_IE_OFFSET_;
4340 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
4344 /* Get Notice of Absence IE. */
4345 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen)) {
4346 find_p2p_ps = _TRUE;
4347 noa_index = noa_attr[0];
4349 if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
4350 (noa_index != pwdinfo->noa_index)) { /* if index change, driver should reconfigure related setting. */
4351 pwdinfo->noa_index = noa_index;
4352 pwdinfo->opp_ps = noa_attr[1] >> 7;
4353 pwdinfo->ctwindow = noa_attr[1] & 0x7F;
4357 /* NoA length should be n*(13) + 2 */
4358 if (attr_contentlen > 2) {
4359 while (noa_offset < attr_contentlen) {
4360 /* _rtw_memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
4361 pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
4364 _rtw_memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
4367 _rtw_memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
4370 _rtw_memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
4376 pwdinfo->noa_num = noa_num;
4378 if (pwdinfo->opp_ps == 1) {
4379 pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
4380 /* driver should wait LPS for entering CTWindow */
4381 if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
4382 p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
4383 } else if (pwdinfo->noa_num > 0) {
4384 pwdinfo->p2p_ps_mode = P2P_PS_NOA;
4385 p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
4386 } else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)
4387 p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
4390 break; /* find target, just break. */
4393 /* Get the next P2P IE */
4394 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
4398 if (find_p2p == _TRUE) {
4399 if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == _FALSE))
4400 p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
4405 void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state)
4407 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
4408 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4411 /* Pre action for p2p state */
4412 switch (p2p_ps_state) {
4413 case P2P_PS_DISABLE:
4414 pwdinfo->p2p_ps_state = p2p_ps_state;
4416 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4418 pwdinfo->noa_index = 0;
4419 pwdinfo->ctwindow = 0;
4420 pwdinfo->opp_ps = 0;
4421 pwdinfo->noa_num = 0;
4422 pwdinfo->p2p_ps_mode = P2P_PS_NONE;
4423 if (pwrpriv->bFwCurrentInPSMode == _TRUE) {
4424 if (pwrpriv->smart_ps == 0) {
4425 pwrpriv->smart_ps = 2;
4426 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));
4431 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
4432 #ifdef CONFIG_MCC_MODE
4433 if (MCC_EN(padapter)) {
4434 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
4435 RTW_INFO("P2P PS enble under MCC\n");
4440 #endif /* CONFIG_MCC_MODE */
4441 pwdinfo->p2p_ps_state = p2p_ps_state;
4443 if (pwdinfo->ctwindow > 0) {
4444 if (pwrpriv->smart_ps != 0) {
4445 pwrpriv->smart_ps = 0;
4446 RTW_INFO("%s(): Enter CTW, change SmartPS\n", __FUNCTION__);
4447 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));
4450 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4454 case P2P_PS_SCAN_DONE:
4455 case P2P_PS_ALLSTASLEEP:
4456 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
4457 pwdinfo->p2p_ps_state = p2p_ps_state;
4458 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4467 u8 p2p_ps_wk_cmd(_adapter *padapter, u8 p2p_ps_state, u8 enqueue)
4469 struct cmd_obj *ph2c;
4470 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4471 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4472 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4476 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
4477 #ifdef CONFIG_CONCURRENT_MODE
4478 || (padapter->hw_port != HW_PORT0)
4484 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4490 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4491 if (pdrvextra_cmd_parm == NULL) {
4492 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
4497 pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
4498 pdrvextra_cmd_parm->type = p2p_ps_state;
4499 pdrvextra_cmd_parm->size = 0;
4500 pdrvextra_cmd_parm->pbuf = NULL;
4502 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
4504 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4506 p2p_ps_wk_hdl(padapter, p2p_ps_state);
4514 #endif /* CONFIG_P2P_PS */
4516 static void reset_ch_sitesurvey_timer_process(void *FunctionContext)
4518 _adapter *adapter = (_adapter *)FunctionContext;
4519 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4521 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4524 RTW_INFO("[%s] In\n", __FUNCTION__);
4525 /* Reset the operation channel information */
4526 pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
4527 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
4528 pwdinfo->rx_invitereq_info.operation_ch[1] = 0;
4529 pwdinfo->rx_invitereq_info.operation_ch[2] = 0;
4530 pwdinfo->rx_invitereq_info.operation_ch[3] = 0;
4531 #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
4532 pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
4535 static void reset_ch_sitesurvey_timer_process2(void *FunctionContext)
4537 _adapter *adapter = (_adapter *)FunctionContext;
4538 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4540 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4543 RTW_INFO("[%s] In\n", __FUNCTION__);
4544 /* Reset the operation channel information */
4545 pwdinfo->p2p_info.operation_ch[0] = 0;
4546 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
4547 pwdinfo->p2p_info.operation_ch[1] = 0;
4548 pwdinfo->p2p_info.operation_ch[2] = 0;
4549 pwdinfo->p2p_info.operation_ch[3] = 0;
4550 #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
4551 pwdinfo->p2p_info.scan_op_ch_only = 0;
4554 static void restore_p2p_state_timer_process(void *FunctionContext)
4556 _adapter *adapter = (_adapter *)FunctionContext;
4557 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4559 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4562 p2p_protocol_wk_cmd(adapter, P2P_RESTORE_STATE_WK);
4565 static void pre_tx_scan_timer_process(void *FunctionContext)
4567 _adapter *adapter = (_adapter *) FunctionContext;
4568 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4570 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
4573 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4576 _enter_critical_bh(&pmlmepriv->lock, &irqL);
4579 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
4580 if (_TRUE == pwdinfo->tx_prov_disc_info.benable) { /* the provision discovery request frame is trigger to send or not */
4581 p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);
4582 /* issue_probereq_p2p(adapter, NULL); */
4583 /* _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); */
4585 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
4586 if (_TRUE == pwdinfo->nego_req_info.benable)
4587 p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);
4588 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
4589 if (_TRUE == pwdinfo->invitereq_info.benable)
4590 p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);
4592 RTW_INFO("[%s] p2p_state is %d, ignore!!\n", __FUNCTION__, rtw_p2p_state(pwdinfo));
4594 _exit_critical_bh(&pmlmepriv->lock, &irqL);
4597 static void find_phase_timer_process(void *FunctionContext)
4599 _adapter *adapter = (_adapter *)FunctionContext;
4600 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4602 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4605 adapter->wdinfo.find_phase_state_exchange_cnt++;
4607 p2p_protocol_wk_cmd(adapter, P2P_FIND_PHASE_WK);
4610 #ifdef CONFIG_CONCURRENT_MODE
4611 void ap_p2p_switch_timer_process(void *FunctionContext)
4613 _adapter *adapter = (_adapter *)FunctionContext;
4614 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4615 #ifdef CONFIG_IOCTL_CFG80211
4616 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
4619 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4622 #ifdef CONFIG_IOCTL_CFG80211
4623 ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
4626 p2p_protocol_wk_cmd(adapter, P2P_AP_P2P_CH_SWITCH_PROCESS_WK);
4630 void reset_global_wifidirect_info(_adapter *padapter)
4632 struct wifidirect_info *pwdinfo;
4634 pwdinfo = &padapter->wdinfo;
4635 pwdinfo->persistent_supported = 0;
4636 pwdinfo->session_available = _TRUE;
4637 rtw_tdls_wfd_enable(padapter, 0);
4638 pwdinfo->wfd_tdls_weaksec = _TRUE;
4642 int rtw_init_wifi_display_info(_adapter *padapter)
4645 struct wifi_display_info *pwfd_info = &padapter->wfd_info;
4647 /* Used in P2P and TDLS */
4648 pwfd_info->init_rtsp_ctrlport = 554;
4649 #ifdef CONFIG_IOCTL_CFG80211
4650 pwfd_info->rtsp_ctrlport = 0;
4652 pwfd_info->rtsp_ctrlport = pwfd_info->init_rtsp_ctrlport; /* set non-zero value for legacy wfd */
4654 pwfd_info->tdls_rtsp_ctrlport = 0;
4655 pwfd_info->peer_rtsp_ctrlport = 0; /* Reset to 0 */
4656 pwfd_info->wfd_enable = _FALSE;
4657 pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
4658 pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
4661 pwfd_info->peer_session_avail = _TRUE;
4662 pwfd_info->wfd_pc = _FALSE;
4665 _rtw_memset(pwfd_info->ip_address, 0x00, 4);
4666 _rtw_memset(pwfd_info->peer_ip_address, 0x00, 4);
4671 inline void rtw_wfd_enable(_adapter *adapter, bool on)
4673 struct wifi_display_info *wfdinfo = &adapter->wfd_info;
4676 wfdinfo->rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;
4677 wfdinfo->wfd_enable = _TRUE;
4680 wfdinfo->wfd_enable = _FALSE;
4681 wfdinfo->rtsp_ctrlport = 0;
4685 inline void rtw_wfd_set_ctrl_port(_adapter *adapter, u16 port)
4687 struct wifi_display_info *wfdinfo = &adapter->wfd_info;
4689 wfdinfo->init_rtsp_ctrlport = port;
4690 if (wfdinfo->wfd_enable == _TRUE)
4691 wfdinfo->rtsp_ctrlport = port;
4692 if (adapter->wdinfo.wfd_tdls_enable == 1)
4693 wfdinfo->tdls_rtsp_ctrlport = port;
4696 inline void rtw_tdls_wfd_enable(_adapter *adapter, bool on)
4698 struct wifi_display_info *wfdinfo = &adapter->wfd_info;
4701 wfdinfo->tdls_rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;
4702 adapter->wdinfo.wfd_tdls_enable = 1;
4705 adapter->wdinfo.wfd_tdls_enable = 0;
4706 wfdinfo->tdls_rtsp_ctrlport = 0;
4710 u32 rtw_append_beacon_wfd_ie(_adapter *adapter, u8 *pbuf)
4712 struct wifidirect_info *wdinfo = &adapter->wdinfo;
4713 struct mlme_priv *mlme = &adapter->mlmepriv;
4714 u8 build_ie_by_self = 0;
4717 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4720 #ifdef CONFIG_IOCTL_CFG80211
4721 if (_TRUE == wdinfo->wfd_info->wfd_enable)
4723 build_ie_by_self = 1;
4725 if (build_ie_by_self)
4726 len = build_beacon_wfd_ie(wdinfo, pbuf);
4727 #ifdef CONFIG_IOCTL_CFG80211
4728 else if (mlme->wfd_beacon_ie && mlme->wfd_beacon_ie_len > 0) {
4729 len = mlme->wfd_beacon_ie_len;
4730 _rtw_memcpy(pbuf, mlme->wfd_beacon_ie, len);
4738 u32 rtw_append_probe_req_wfd_ie(_adapter *adapter, u8 *pbuf)
4740 struct wifidirect_info *wdinfo = &adapter->wdinfo;
4741 struct mlme_priv *mlme = &adapter->mlmepriv;
4742 u8 build_ie_by_self = 0;
4745 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4748 #ifdef CONFIG_IOCTL_CFG80211
4749 if (_TRUE == wdinfo->wfd_info->wfd_enable)
4751 build_ie_by_self = 1;
4753 if (build_ie_by_self)
4754 len = build_probe_req_wfd_ie(wdinfo, pbuf);
4755 #ifdef CONFIG_IOCTL_CFG80211
4756 else if (mlme->wfd_probe_req_ie && mlme->wfd_probe_req_ie_len > 0) {
4757 len = mlme->wfd_probe_req_ie_len;
4758 _rtw_memcpy(pbuf, mlme->wfd_probe_req_ie, len);
4766 u32 rtw_append_probe_resp_wfd_ie(_adapter *adapter, u8 *pbuf)
4768 struct wifidirect_info *wdinfo = &adapter->wdinfo;
4769 struct mlme_priv *mlme = &adapter->mlmepriv;
4770 u8 build_ie_by_self = 0;
4773 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4776 #ifdef CONFIG_IOCTL_CFG80211
4777 if (_TRUE == wdinfo->wfd_info->wfd_enable)
4779 build_ie_by_self = 1;
4781 if (build_ie_by_self)
4782 len = build_probe_resp_wfd_ie(wdinfo, pbuf, 0);
4783 #ifdef CONFIG_IOCTL_CFG80211
4784 else if (mlme->wfd_probe_resp_ie && mlme->wfd_probe_resp_ie_len > 0) {
4785 len = mlme->wfd_probe_resp_ie_len;
4786 _rtw_memcpy(pbuf, mlme->wfd_probe_resp_ie, len);
4794 u32 rtw_append_assoc_req_wfd_ie(_adapter *adapter, u8 *pbuf)
4796 struct wifidirect_info *wdinfo = &adapter->wdinfo;
4797 struct mlme_priv *mlme = &adapter->mlmepriv;
4798 u8 build_ie_by_self = 0;
4801 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4804 #ifdef CONFIG_IOCTL_CFG80211
4805 if (_TRUE == wdinfo->wfd_info->wfd_enable)
4807 build_ie_by_self = 1;
4809 if (build_ie_by_self)
4810 len = build_assoc_req_wfd_ie(wdinfo, pbuf);
4811 #ifdef CONFIG_IOCTL_CFG80211
4812 else if (mlme->wfd_assoc_req_ie && mlme->wfd_assoc_req_ie_len > 0) {
4813 len = mlme->wfd_assoc_req_ie_len;
4814 _rtw_memcpy(pbuf, mlme->wfd_assoc_req_ie, len);
4822 u32 rtw_append_assoc_resp_wfd_ie(_adapter *adapter, u8 *pbuf)
4824 struct wifidirect_info *wdinfo = &adapter->wdinfo;
4825 struct mlme_priv *mlme = &adapter->mlmepriv;
4826 u8 build_ie_by_self = 0;
4829 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4832 #ifdef CONFIG_IOCTL_CFG80211
4833 if (_TRUE == wdinfo->wfd_info->wfd_enable)
4835 build_ie_by_self = 1;
4837 if (build_ie_by_self)
4838 len = build_assoc_resp_wfd_ie(wdinfo, pbuf);
4839 #ifdef CONFIG_IOCTL_CFG80211
4840 else if (mlme->wfd_assoc_resp_ie && mlme->wfd_assoc_resp_ie_len > 0) {
4841 len = mlme->wfd_assoc_resp_ie_len;
4842 _rtw_memcpy(pbuf, mlme->wfd_assoc_resp_ie, len);
4850 #endif /* CONFIG_WFD */
4852 void rtw_init_wifidirect_timers(_adapter *padapter)
4854 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4856 _init_timer(&pwdinfo->find_phase_timer, padapter->pnetdev, find_phase_timer_process, padapter);
4857 _init_timer(&pwdinfo->restore_p2p_state_timer, padapter->pnetdev, restore_p2p_state_timer_process, padapter);
4858 _init_timer(&pwdinfo->pre_tx_scan_timer, padapter->pnetdev, pre_tx_scan_timer_process, padapter);
4859 _init_timer(&pwdinfo->reset_ch_sitesurvey, padapter->pnetdev, reset_ch_sitesurvey_timer_process, padapter);
4860 _init_timer(&pwdinfo->reset_ch_sitesurvey2, padapter->pnetdev, reset_ch_sitesurvey_timer_process2, padapter);
4861 #ifdef CONFIG_CONCURRENT_MODE
4862 _init_timer(&pwdinfo->ap_p2p_switch_timer, padapter->pnetdev, ap_p2p_switch_timer_process, padapter);
4866 void rtw_init_wifidirect_addrs(_adapter *padapter, u8 *dev_addr, u8 *iface_addr)
4869 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4871 /*init device&interface address */
4873 _rtw_memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
4875 _rtw_memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
4879 void init_wifidirect_info(_adapter *padapter, enum P2P_ROLE role)
4881 struct wifidirect_info *pwdinfo;
4883 struct wifi_display_info *pwfd_info = &padapter->wfd_info;
4886 pwdinfo = &padapter->wdinfo;
4888 pwdinfo->padapter = padapter;
4890 /* 1, 6, 11 are the social channel defined in the WiFi Direct specification. */
4891 pwdinfo->social_chan[0] = 1;
4892 pwdinfo->social_chan[1] = 6;
4893 pwdinfo->social_chan[2] = 11;
4894 pwdinfo->social_chan[3] = 0; /* channel 0 for scanning ending in site survey function. */
4896 if (role != P2P_ROLE_DISABLE
4897 && pwdinfo->driver_interface != DRIVER_CFG80211
4899 #ifdef CONFIG_CONCURRENT_MODE
4900 if (rtw_mi_check_status(padapter, MI_LINKED))
4901 union_ch = rtw_mi_get_union_chan(padapter);
4903 if (union_ch != 0 &&
4904 (union_ch == 1 || union_ch == 6 || union_ch == 11)
4906 /* Use the AP's channel as the listen channel */
4907 /* This will avoid the channel switch between AP's channel and listen channel */
4908 pwdinfo->listen_channel = union_ch;
4910 #endif /* CONFIG_CONCURRENT_MODE */
4912 /* Use the channel 11 as the listen channel */
4913 pwdinfo->listen_channel = 11;
4917 if (role == P2P_ROLE_DEVICE) {
4918 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4919 #ifdef CONFIG_CONCURRENT_MODE
4920 if (rtw_mi_check_status(padapter, MI_LINKED))
4921 rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
4924 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
4926 pwdinfo->intent = 1;
4927 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
4928 } else if (role == P2P_ROLE_CLIENT) {
4929 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4930 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
4931 pwdinfo->intent = 1;
4932 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
4933 } else if (role == P2P_ROLE_GO) {
4934 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
4935 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
4936 pwdinfo->intent = 15;
4937 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
4940 /* Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 ) */
4941 pwdinfo->support_rate[0] = 0x8c; /* 6(B) */
4942 pwdinfo->support_rate[1] = 0x92; /* 9(B) */
4943 pwdinfo->support_rate[2] = 0x18; /* 12 */
4944 pwdinfo->support_rate[3] = 0x24; /* 18 */
4945 pwdinfo->support_rate[4] = 0x30; /* 24 */
4946 pwdinfo->support_rate[5] = 0x48; /* 36 */
4947 pwdinfo->support_rate[6] = 0x60; /* 48 */
4948 pwdinfo->support_rate[7] = 0x6c; /* 54 */
4950 _rtw_memcpy((void *) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
4952 _rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
4953 pwdinfo->device_name_len = 0;
4955 _rtw_memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));
4956 pwdinfo->invitereq_info.token = 3; /* Token used for P2P invitation request frame. */
4958 _rtw_memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));
4959 pwdinfo->inviteresp_info.token = 0;
4961 pwdinfo->profileindex = 0;
4962 _rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
4964 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
4966 pwdinfo->listen_dwell = (u8)((rtw_get_current_time() % 3) + 1);
4967 /* RTW_INFO( "[%s] listen_dwell time is %d00ms\n", __FUNCTION__, pwdinfo->listen_dwell ); */
4969 _rtw_memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));
4970 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
4972 _rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
4974 pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
4975 pwdinfo->negotiation_dialog_token = 1;
4977 _rtw_memset(pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN);
4978 pwdinfo->nego_ssidlen = 0;
4980 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
4982 pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC;
4983 pwdinfo->wfd_info = pwfd_info;
4985 pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
4986 #endif /* CONFIG_WFD */
4987 pwdinfo->channel_list_attr_len = 0;
4988 _rtw_memset(pwdinfo->channel_list_attr, 0x00, 100);
4990 _rtw_memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);
4991 _rtw_memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);
4992 _rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
4993 #ifdef CONFIG_CONCURRENT_MODE
4994 #ifdef CONFIG_IOCTL_CFG80211
4995 pwdinfo->ext_listen_interval = 1000; /* The interval to be available with legacy AP during p2p0-find/scan */
4996 pwdinfo->ext_listen_period = 3000; /* The time period to be available for P2P during nego */
4997 #else /* !CONFIG_IOCTL_CFG80211 */
4998 /* pwdinfo->ext_listen_interval = 3000; */
4999 /* pwdinfo->ext_listen_period = 400; */
5000 pwdinfo->ext_listen_interval = 1000;
5001 pwdinfo->ext_listen_period = 1000;
5002 #endif /* !CONFIG_IOCTL_CFG80211 */
5005 /* Commented by Kurt 20130319
5006 * For WiDi purpose: Use CFG80211 interface but controled WFD/RDS frame by driver itself. */
5007 #ifdef CONFIG_IOCTL_CFG80211
5008 pwdinfo->driver_interface = DRIVER_CFG80211;
5010 pwdinfo->driver_interface = DRIVER_WEXT;
5011 #endif /* CONFIG_IOCTL_CFG80211 */
5013 pwdinfo->wfd_tdls_enable = 0;
5014 _rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
5015 _rtw_memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);
5017 pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
5018 pwdinfo->rx_invitereq_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
5019 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5020 pwdinfo->rx_invitereq_info.operation_ch[2] = 0;
5021 pwdinfo->rx_invitereq_info.operation_ch[3] = 0;
5022 pwdinfo->rx_invitereq_info.operation_ch[4] = 0;
5023 #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
5024 pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
5025 pwdinfo->p2p_info.operation_ch[0] = 0;
5026 pwdinfo->p2p_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
5027 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5028 pwdinfo->p2p_info.operation_ch[2] = 0;
5029 pwdinfo->p2p_info.operation_ch[3] = 0;
5030 pwdinfo->p2p_info.operation_ch[4] = 0;
5031 #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
5032 pwdinfo->p2p_info.scan_op_ch_only = 0;
5035 #ifdef CONFIG_DBG_P2P
5038 * rtw_p2p_role_txt - Get the p2p role name as a text string
5040 * Returns: The state name as a printable text string
5042 const char *rtw_p2p_role_txt(enum P2P_ROLE role)
5045 case P2P_ROLE_DISABLE:
5046 return "P2P_ROLE_DISABLE";
5047 case P2P_ROLE_DEVICE:
5048 return "P2P_ROLE_DEVICE";
5049 case P2P_ROLE_CLIENT:
5050 return "P2P_ROLE_CLIENT";
5052 return "P2P_ROLE_GO";
5059 * rtw_p2p_state_txt - Get the p2p state name as a text string
5061 * Returns: The state name as a printable text string
5063 const char *rtw_p2p_state_txt(enum P2P_STATE state)
5066 case P2P_STATE_NONE:
5067 return "P2P_STATE_NONE";
5068 case P2P_STATE_IDLE:
5069 return "P2P_STATE_IDLE";
5070 case P2P_STATE_LISTEN:
5071 return "P2P_STATE_LISTEN";
5072 case P2P_STATE_SCAN:
5073 return "P2P_STATE_SCAN";
5074 case P2P_STATE_FIND_PHASE_LISTEN:
5075 return "P2P_STATE_FIND_PHASE_LISTEN";
5076 case P2P_STATE_FIND_PHASE_SEARCH:
5077 return "P2P_STATE_FIND_PHASE_SEARCH";
5078 case P2P_STATE_TX_PROVISION_DIS_REQ:
5079 return "P2P_STATE_TX_PROVISION_DIS_REQ";
5080 case P2P_STATE_RX_PROVISION_DIS_RSP:
5081 return "P2P_STATE_RX_PROVISION_DIS_RSP";
5082 case P2P_STATE_RX_PROVISION_DIS_REQ:
5083 return "P2P_STATE_RX_PROVISION_DIS_REQ";
5084 case P2P_STATE_GONEGO_ING:
5085 return "P2P_STATE_GONEGO_ING";
5086 case P2P_STATE_GONEGO_OK:
5087 return "P2P_STATE_GONEGO_OK";
5088 case P2P_STATE_GONEGO_FAIL:
5089 return "P2P_STATE_GONEGO_FAIL";
5090 case P2P_STATE_RECV_INVITE_REQ_MATCH:
5091 return "P2P_STATE_RECV_INVITE_REQ_MATCH";
5092 case P2P_STATE_PROVISIONING_ING:
5093 return "P2P_STATE_PROVISIONING_ING";
5094 case P2P_STATE_PROVISIONING_DONE:
5095 return "P2P_STATE_PROVISIONING_DONE";
5096 case P2P_STATE_TX_INVITE_REQ:
5097 return "P2P_STATE_TX_INVITE_REQ";
5098 case P2P_STATE_RX_INVITE_RESP_OK:
5099 return "P2P_STATE_RX_INVITE_RESP_OK";
5100 case P2P_STATE_RECV_INVITE_REQ_DISMATCH:
5101 return "P2P_STATE_RECV_INVITE_REQ_DISMATCH";
5102 case P2P_STATE_RECV_INVITE_REQ_GO:
5103 return "P2P_STATE_RECV_INVITE_REQ_GO";
5104 case P2P_STATE_RECV_INVITE_REQ_JOIN:
5105 return "P2P_STATE_RECV_INVITE_REQ_JOIN";
5106 case P2P_STATE_RX_INVITE_RESP_FAIL:
5107 return "P2P_STATE_RX_INVITE_RESP_FAIL";
5108 case P2P_STATE_RX_INFOR_NOREADY:
5109 return "P2P_STATE_RX_INFOR_NOREADY";
5110 case P2P_STATE_TX_INFOR_NOREADY:
5111 return "P2P_STATE_TX_INFOR_NOREADY";
5117 void dbg_rtw_p2p_set_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)
5119 if (!_rtw_p2p_chk_state(wdinfo, state)) {
5120 enum P2P_STATE old_state = _rtw_p2p_state(wdinfo);
5121 _rtw_p2p_set_state(wdinfo, state);
5122 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_state from %s to %s\n", caller, line
5123 , rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))
5126 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_state to same state %s\n", caller, line
5127 , rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))
5131 void dbg_rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)
5133 if (_rtw_p2p_pre_state(wdinfo) != state) {
5134 enum P2P_STATE old_state = _rtw_p2p_pre_state(wdinfo);
5135 _rtw_p2p_set_pre_state(wdinfo, state);
5136 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_pre_state from %s to %s\n", caller, line
5137 , rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))
5140 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_pre_state to same state %s\n", caller, line
5141 , rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))
5146 void dbg_rtw_p2p_restore_state(struct wifidirect_info *wdinfo, const char *caller, int line)
5148 if (wdinfo->pre_p2p_state != -1) {
5149 RTW_INFO("[CONFIG_DBG_P2P]%s:%d restore from %s to %s\n", caller, line
5150 , p2p_state_str[wdinfo->p2p_state], p2p_state_str[wdinfo->pre_p2p_state]
5152 _rtw_p2p_restore_state(wdinfo);
5154 RTW_INFO("[CONFIG_DBG_P2P]%s:%d restore no pre state, cur state %s\n", caller, line
5155 , p2p_state_str[wdinfo->p2p_state]
5160 void dbg_rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role, const char *caller, int line)
5162 if (wdinfo->role != role) {
5163 enum P2P_ROLE old_role = wdinfo->role;
5164 _rtw_p2p_set_role(wdinfo, role);
5165 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_role from %s to %s\n", caller, line
5166 , rtw_p2p_role_txt(old_role), rtw_p2p_role_txt(wdinfo->role)
5169 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_role to same role %s\n", caller, line
5170 , rtw_p2p_role_txt(wdinfo->role)
5174 #endif /* CONFIG_DBG_P2P */
5177 int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role)
5180 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5182 if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT || role == P2P_ROLE_GO) {
5183 u8 channel, ch_offset;
5186 #if defined(CONFIG_CONCURRENT_MODE) && (!defined(RTW_P2P_GROUP_INTERFACE) || !RTW_P2P_GROUP_INTERFACE)
5187 /* Commented by Albert 2011/12/30 */
5188 /* The driver just supports 1 P2P group operation. */
5189 /* So, this function will do nothing if the buddy adapter had enabled the P2P function. */
5190 /*if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
5192 /*The buddy adapter had enabled the P2P function.*/
5193 if (rtw_mi_buddy_stay_in_p2p_mode(padapter))
5195 #endif /* CONFIG_CONCURRENT_MODE */
5197 /* leave IPS/Autosuspend */
5198 if (_FAIL == rtw_pwr_wakeup(padapter)) {
5203 /* Added by Albert 2011/03/22 */
5204 /* In the P2P mode, the driver should not support the b mode. */
5205 /* So, the Tx packet shouldn't use the CCK rate */
5206 #ifdef CONFIG_IOCTL_CFG80211
5207 if (rtw_cfg80211_iface_has_p2p_group_cap(padapter))
5209 update_tx_basic_rate(padapter, WIRELESS_11AGN);
5211 /* Enable P2P function */
5212 init_wifidirect_info(padapter, role);
5214 #ifdef CONFIG_IOCTL_CFG80211
5215 if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
5216 adapter_wdev_data(padapter)->p2p_enabled = _TRUE;
5219 rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, _TRUE);
5221 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
5222 rtw_hal_set_odm_var(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, _TRUE);
5225 } else if (role == P2P_ROLE_DISABLE) {
5226 #ifdef CONFIG_INTEL_WIDI
5227 if (padapter->mlmepriv.p2p_reject_disable == _TRUE)
5229 #endif /* CONFIG_INTEL_WIDI */
5231 #ifdef CONFIG_IOCTL_CFG80211
5232 if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
5233 adapter_wdev_data(padapter)->p2p_enabled = _FALSE;
5236 pwdinfo->listen_channel = 0;
5238 /* Disable P2P function */
5239 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
5240 _cancel_timer_ex(&pwdinfo->find_phase_timer);
5241 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
5242 _cancel_timer_ex(&pwdinfo->pre_tx_scan_timer);
5243 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
5244 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey2);
5245 reset_ch_sitesurvey_timer_process(padapter);
5246 reset_ch_sitesurvey_timer_process2(padapter);
5247 #ifdef CONFIG_CONCURRENT_MODE
5248 _cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
5250 rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
5251 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_NONE);
5252 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
5253 _rtw_memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
5255 /* Remove profiles in wifidirect_info structure. */
5256 _rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
5257 pwdinfo->profileindex = 0;
5260 rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, _FALSE);
5262 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
5263 rtw_hal_set_odm_var(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, _FALSE);
5266 if (_FAIL == rtw_pwr_wakeup(padapter)) {
5271 /* Restore to initial setting. */
5272 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
5274 #ifdef CONFIG_INTEL_WIDI
5275 rtw_reset_widi_info(padapter);
5276 #endif /* CONFIG_INTEL_WIDI */
5278 /* For WiDi purpose. */
5279 #ifdef CONFIG_IOCTL_CFG80211
5280 pwdinfo->driver_interface = DRIVER_CFG80211;
5282 pwdinfo->driver_interface = DRIVER_WEXT;
5283 #endif /* CONFIG_IOCTL_CFG80211 */
5291 #endif /* CONFIG_P2P */