Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_p2p.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/14#define _RTW_P2P_C_1516#include <drv_types.h>1718#ifdef CONFIG_P2P1920int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8 *ch_list, u8 ch_cnt)21{22int found = 0, i = 0;2324for (i = 0; i < ch_cnt; i++) {25if (ch_list[i] == desired_ch) {26found = 1;27break;28}29}30return found ;31}3233int is_any_client_associated(_adapter *padapter)34{35return padapter->stapriv.asoc_list_cnt ? _TRUE : _FALSE;36}3738static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)39{40_irqL irqL;41_list *phead, *plist;42u32 len = 0;43u16 attr_len = 0;44u8 tmplen, *pdata_attr, *pstart, *pcur;45struct sta_info *psta = NULL;46_adapter *padapter = pwdinfo->padapter;47struct sta_priv *pstapriv = &padapter->stapriv;4849RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));5051pdata_attr = rtw_zmalloc(MAX_P2P_IE_LEN);5253if (NULL == pdata_attr) {54RTW_INFO("%s pdata_attr malloc failed\n", __FUNCTION__);55goto _exit;56}5758pstart = pdata_attr;59pcur = pdata_attr;6061_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);62phead = &pstapriv->asoc_list;63plist = get_next(phead);6465/* look up sta asoc_queue */66while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {67psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);6869plist = get_next(plist);707172if (psta->is_p2p_device) {73tmplen = 0;7475pcur++;7677/* P2P device address */78_rtw_memcpy(pcur, psta->dev_addr, ETH_ALEN);79pcur += ETH_ALEN;8081/* P2P interface address */82_rtw_memcpy(pcur, psta->cmn.mac_addr, ETH_ALEN);83pcur += ETH_ALEN;8485*pcur = psta->dev_cap;86pcur++;8788/* *(u16*)(pcur) = cpu_to_be16(psta->config_methods); */89RTW_PUT_BE16(pcur, psta->config_methods);90pcur += 2;9192_rtw_memcpy(pcur, psta->primary_dev_type, 8);93pcur += 8;9495*pcur = psta->num_of_secdev_type;96pcur++;9798_rtw_memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type * 8);99pcur += psta->num_of_secdev_type * 8;100101if (psta->dev_name_len > 0) {102/* *(u16*)(pcur) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); */103RTW_PUT_BE16(pcur, WPS_ATTR_DEVICE_NAME);104pcur += 2;105106/* *(u16*)(pcur) = cpu_to_be16( psta->dev_name_len ); */107RTW_PUT_BE16(pcur, psta->dev_name_len);108pcur += 2;109110_rtw_memcpy(pcur, psta->dev_name, psta->dev_name_len);111pcur += psta->dev_name_len;112}113114115tmplen = (u8)(pcur - pstart);116117*pstart = (tmplen - 1);118119attr_len += tmplen;120121/* pstart += tmplen; */122pstart = pcur;123124}125126127}128_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);129130if (attr_len > 0)131len = rtw_set_p2p_attr_content(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);132133rtw_mfree(pdata_attr, MAX_P2P_IE_LEN);134135_exit:136return len;137138}139140static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)141{142struct xmit_frame *pmgntframe;143struct pkt_attrib *pattrib;144unsigned char *pframe;145struct rtw_ieee80211_hdr *pwlanhdr;146unsigned short *fctrl;147_adapter *padapter = pwdinfo->padapter;148struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);149struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);150unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */151u32 p2poui = cpu_to_be32(P2POUI);152u8 oui_subtype = P2P_GO_DISC_REQUEST;153u8 dialogToken = 0;154155RTW_INFO("[%s]\n", __FUNCTION__);156157pmgntframe = alloc_mgtxmitframe(pxmitpriv);158if (pmgntframe == NULL)159return;160161/* update attribute */162pattrib = &pmgntframe->attrib;163update_mgntframe_attrib(padapter, pattrib);164165_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);166167pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;168pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;169170fctrl = &(pwlanhdr->frame_ctl);171*(fctrl) = 0;172173_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);174_rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);175_rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);176177SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);178pmlmeext->mgnt_seq++;179set_frame_sub_type(pframe, WIFI_ACTION);180181pframe += sizeof(struct rtw_ieee80211_hdr_3addr);182pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);183184/* Build P2P action frame header */185pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));186pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));187pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));188pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));189190/* there is no IE in this P2P action frame */191192pattrib->last_txcmdsz = pattrib->pktlen;193194dump_mgntframe(padapter, pmgntframe);195196}197198static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)199{200struct xmit_frame *pmgntframe;201struct pkt_attrib *pattrib;202unsigned char *pframe;203struct rtw_ieee80211_hdr *pwlanhdr;204unsigned short *fctrl;205_adapter *padapter = pwdinfo->padapter;206struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);207struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);208unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;209u8 action = P2P_PUB_ACTION_ACTION;210u32 p2poui = cpu_to_be32(P2POUI);211u8 oui_subtype = P2P_DEVDISC_RESP;212u8 p2pie[8] = { 0x00 };213u32 p2pielen = 0;214215RTW_INFO("[%s]\n", __FUNCTION__);216217pmgntframe = alloc_mgtxmitframe(pxmitpriv);218if (pmgntframe == NULL)219return;220221/* update attribute */222pattrib = &pmgntframe->attrib;223update_mgntframe_attrib(padapter, pattrib);224225_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);226227pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;228pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;229230fctrl = &(pwlanhdr->frame_ctl);231*(fctrl) = 0;232233_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);234_rtw_memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);235_rtw_memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);236237SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);238pmlmeext->mgnt_seq++;239set_frame_sub_type(pframe, WIFI_ACTION);240241pframe += sizeof(struct rtw_ieee80211_hdr_3addr);242pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);243244/* Build P2P public action frame header */245pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));246pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));247pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));248pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));249pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));250251252/* Build P2P IE */253/* P2P OUI */254p2pielen = 0;255p2pie[p2pielen++] = 0x50;256p2pie[p2pielen++] = 0x6F;257p2pie[p2pielen++] = 0x9A;258p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */259260/* P2P_ATTR_STATUS */261p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);262263pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);264265pattrib->last_txcmdsz = pattrib->pktlen;266267dump_mgntframe(padapter, pmgntframe);268269}270271static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8 *raddr, u8 *frame_body, u16 config_method)272{273_adapter *padapter = pwdinfo->padapter;274unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;275u8 action = P2P_PUB_ACTION_ACTION;276u8 dialogToken = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */277u32 p2poui = cpu_to_be32(P2POUI);278u8 oui_subtype = P2P_PROVISION_DISC_RESP;279u8 wpsie[100] = { 0x00 };280u8 wpsielen = 0;281#ifdef CONFIG_WFD282u32 wfdielen = 0;283#endif284285struct xmit_frame *pmgntframe;286struct pkt_attrib *pattrib;287unsigned char *pframe;288struct rtw_ieee80211_hdr *pwlanhdr;289unsigned short *fctrl;290struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);291struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);292293294pmgntframe = alloc_mgtxmitframe(pxmitpriv);295if (pmgntframe == NULL)296return;297298/* update attribute */299pattrib = &pmgntframe->attrib;300update_mgntframe_attrib(padapter, pattrib);301302_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);303304pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;305pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;306307fctrl = &(pwlanhdr->frame_ctl);308*(fctrl) = 0;309310_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);311_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);312_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);313314SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);315pmlmeext->mgnt_seq++;316set_frame_sub_type(pframe, WIFI_ACTION);317318pframe += sizeof(struct rtw_ieee80211_hdr_3addr);319pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);320321pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));322pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));323pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));324pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));325pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));326327wpsielen = 0;328/* WPS OUI */329/* *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI ); */330RTW_PUT_BE32(wpsie, WPSOUI);331wpsielen += 4;332333#if 0334/* WPS version */335/* Type: */336*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);337wpsielen += 2;338339/* Length: */340*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);341wpsielen += 2;342343/* Value: */344wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */345#endif346347/* Config Method */348/* Type: */349/* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD ); */350RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD);351wpsielen += 2;352353/* Length: */354/* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 ); */355RTW_PUT_BE16(wpsie + wpsielen, 0x0002);356wpsielen += 2;357358/* Value: */359/* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( config_method ); */360RTW_PUT_BE16(wpsie + wpsielen, config_method);361wpsielen += 2;362363pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);364365#ifdef CONFIG_WFD366wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe);367pframe += wfdielen;368pattrib->pktlen += wfdielen;369#endif370371pattrib->last_txcmdsz = pattrib->pktlen;372373dump_mgntframe(padapter, pmgntframe);374375return;376377}378379static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)380{381struct xmit_frame *pmgntframe;382struct pkt_attrib *pattrib;383unsigned char *pframe;384struct rtw_ieee80211_hdr *pwlanhdr;385unsigned short *fctrl;386_adapter *padapter = pwdinfo->padapter;387struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);388struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);389unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */390u32 p2poui = cpu_to_be32(P2POUI);391u8 oui_subtype = P2P_PRESENCE_RESPONSE;392u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };393u8 noa_attr_content[32] = { 0x00 };394u32 p2pielen = 0;395396RTW_INFO("[%s]\n", __FUNCTION__);397398pmgntframe = alloc_mgtxmitframe(pxmitpriv);399if (pmgntframe == NULL)400return;401402/* update attribute */403pattrib = &pmgntframe->attrib;404update_mgntframe_attrib(padapter, pattrib);405406_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);407408pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;409pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;410411fctrl = &(pwlanhdr->frame_ctl);412*(fctrl) = 0;413414_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);415_rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);416_rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);417418SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);419pmlmeext->mgnt_seq++;420set_frame_sub_type(pframe, WIFI_ACTION);421422pframe += sizeof(struct rtw_ieee80211_hdr_3addr);423pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);424425/* Build P2P action frame header */426pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));427pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));428pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));429pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));430431432/* Add P2P IE header */433/* P2P OUI */434p2pielen = 0;435p2pie[p2pielen++] = 0x50;436p2pie[p2pielen++] = 0x6F;437p2pie[p2pielen++] = 0x9A;438p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */439440/* Add Status attribute in P2P IE */441p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);442443/* Add NoA attribute in P2P IE */444noa_attr_content[0] = 0x1;/* index */445noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */446447/* todo: Notice of Absence Descriptor(s) */448449p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);450451452453pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &(pattrib->pktlen));454455456pattrib->last_txcmdsz = pattrib->pktlen;457458dump_mgntframe(padapter, pmgntframe);459460}461462u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)463{464u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };465u16 capability = 0;466u32 len = 0, p2pielen = 0;467468469/* P2P OUI */470p2pielen = 0;471p2pie[p2pielen++] = 0x50;472p2pie[p2pielen++] = 0x6F;473p2pie[p2pielen++] = 0x9A;474p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */475476477/* According to the P2P Specification, the beacon frame should contain 3 P2P attributes */478/* 1. P2P Capability */479/* 2. P2P Device ID */480/* 3. Notice of Absence ( NOA ) */481482/* P2P Capability ATTR */483/* Type: */484/* Length: */485/* Value: */486/* Device Capability Bitmap, 1 byte */487/* Be able to participate in additional P2P Groups and */488/* support the P2P Invitation Procedure */489/* Group Capability Bitmap, 1 byte */490capability = P2P_DEVCAP_INVITATION_PROC | P2P_DEVCAP_CLIENT_DISCOVERABILITY;491capability |= ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);492if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))493capability |= (P2P_GRPCAP_GROUP_FORMATION << 8);494495capability = cpu_to_le16(capability);496497p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8 *)&capability);498499500/* P2P Device ID ATTR */501p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);502503504/* Notice of Absence ATTR */505/* Type: */506/* Length: */507/* Value: */508509/* go_add_noa_attr(pwdinfo); */510511512pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);513514515return len;516517}518519#ifdef CONFIG_WFD520u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)521{522u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };523u16 val16 = 0;524u32 len = 0, wfdielen = 0;525_adapter *padapter = pwdinfo->padapter;526struct mlme_priv *pmlmepriv = &padapter->mlmepriv;527struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;528529if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))530goto exit;531532/* WFD OUI */533wfdielen = 0;534wfdie[wfdielen++] = 0x50;535wfdie[wfdielen++] = 0x6F;536wfdie[wfdielen++] = 0x9A;537wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */538539/* Commented by Albert 20110812 */540/* According to the WFD Specification, the beacon frame should contain 4 WFD attributes */541/* 1. WFD Device Information */542/* 2. Associated BSSID */543/* 3. Coupled Sink Information */544545546/* WFD Device Information ATTR */547/* Type: */548wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;549550/* Length: */551/* Note: In the WFD specification, the size of length field is 2. */552RTW_PUT_BE16(wfdie + wfdielen, 0x0006);553wfdielen += 2;554555/* Value1: */556/* WFD device information */557558if (P2P_ROLE_GO == pwdinfo->role) {559if (is_any_client_associated(pwdinfo->padapter)) {560/* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) */561val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD;562RTW_PUT_BE16(wfdie + wfdielen, val16);563} else {564/* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */565val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;566RTW_PUT_BE16(wfdie + wfdielen, val16);567}568569} else {570/* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */571val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;572RTW_PUT_BE16(wfdie + wfdielen, val16);573}574575wfdielen += 2;576577/* Value2: */578/* Session Management Control Port */579/* Default TCP port for RTSP messages is 554 */580RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);581wfdielen += 2;582583/* Value3: */584/* WFD Device Maximum Throughput */585/* 300Mbps is the maximum throughput */586RTW_PUT_BE16(wfdie + wfdielen, 300);587wfdielen += 2;588589/* Associated BSSID ATTR */590/* Type: */591wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;592593/* Length: */594/* Note: In the WFD specification, the size of length field is 2. */595RTW_PUT_BE16(wfdie + wfdielen, 0x0006);596wfdielen += 2;597598/* Value: */599/* Associated BSSID */600if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)601_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);602else603_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);604605wfdielen += ETH_ALEN;606607/* Coupled Sink Information ATTR */608/* Type: */609wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;610611/* Length: */612/* Note: In the WFD specification, the size of length field is 2. */613RTW_PUT_BE16(wfdie + wfdielen, 0x0007);614wfdielen += 2;615616/* Value: */617/* Coupled Sink Status bitmap */618/* Not coupled/available for Coupling */619wfdie[wfdielen++] = 0;620/* MAC Addr. */621wfdie[wfdielen++] = 0;622wfdie[wfdielen++] = 0;623wfdie[wfdielen++] = 0;624wfdie[wfdielen++] = 0;625wfdie[wfdielen++] = 0;626wfdie[wfdielen++] = 0;627628rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);629630exit:631return len;632}633634u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)635{636u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };637u16 val16 = 0;638u32 len = 0, wfdielen = 0;639_adapter *padapter = pwdinfo->padapter;640struct mlme_priv *pmlmepriv = &padapter->mlmepriv;641struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;642643if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))644goto exit;645646/* WFD OUI */647wfdielen = 0;648wfdie[wfdielen++] = 0x50;649wfdie[wfdielen++] = 0x6F;650wfdie[wfdielen++] = 0x9A;651wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */652653/* Commented by Albert 20110812 */654/* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */655/* 1. WFD Device Information */656/* 2. Associated BSSID */657/* 3. Coupled Sink Information */658659660/* WFD Device Information ATTR */661/* Type: */662wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;663664/* Length: */665/* Note: In the WFD specification, the size of length field is 2. */666RTW_PUT_BE16(wfdie + wfdielen, 0x0006);667wfdielen += 2;668669/* Value1: */670/* WFD device information */671672if (1 == pwdinfo->wfd_tdls_enable) {673/* WFD primary sink + available for WFD session + WiFi TDLS mode + WSC ( WFD Service Discovery ) */674val16 = pwfd_info->wfd_device_type |675WFD_DEVINFO_SESSION_AVAIL |676WFD_DEVINFO_WSD |677WFD_DEVINFO_PC_TDLS;678RTW_PUT_BE16(wfdie + wfdielen, val16);679} else {680/* WFD primary sink + available for WFD session + WiFi Direct mode + WSC ( WFD Service Discovery ) */681val16 = pwfd_info->wfd_device_type |682WFD_DEVINFO_SESSION_AVAIL |683WFD_DEVINFO_WSD;684RTW_PUT_BE16(wfdie + wfdielen, val16);685}686687wfdielen += 2;688689/* Value2: */690/* Session Management Control Port */691/* Default TCP port for RTSP messages is 554 */692RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);693wfdielen += 2;694695/* Value3: */696/* WFD Device Maximum Throughput */697/* 300Mbps is the maximum throughput */698RTW_PUT_BE16(wfdie + wfdielen, 300);699wfdielen += 2;700701/* Associated BSSID ATTR */702/* Type: */703wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;704705/* Length: */706/* Note: In the WFD specification, the size of length field is 2. */707RTW_PUT_BE16(wfdie + wfdielen, 0x0006);708wfdielen += 2;709710/* Value: */711/* Associated BSSID */712if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)713_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);714else715_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);716717wfdielen += ETH_ALEN;718719/* Coupled Sink Information ATTR */720/* Type: */721wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;722723/* Length: */724/* Note: In the WFD specification, the size of length field is 2. */725RTW_PUT_BE16(wfdie + wfdielen, 0x0007);726wfdielen += 2;727728/* Value: */729/* Coupled Sink Status bitmap */730/* Not coupled/available for Coupling */731wfdie[wfdielen++] = 0;732/* MAC Addr. */733wfdie[wfdielen++] = 0;734wfdie[wfdielen++] = 0;735wfdie[wfdielen++] = 0;736wfdie[wfdielen++] = 0;737wfdie[wfdielen++] = 0;738wfdie[wfdielen++] = 0;739740rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);741742exit:743return len;744}745746u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunneled)747{748u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };749u32 len = 0, wfdielen = 0;750_adapter *padapter = pwdinfo->padapter;751struct mlme_priv *pmlmepriv = &padapter->mlmepriv;752struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;753u16 v16 = 0;754755if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))756goto exit;757758/* WFD OUI */759wfdielen = 0;760wfdie[wfdielen++] = 0x50;761wfdie[wfdielen++] = 0x6F;762wfdie[wfdielen++] = 0x9A;763wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */764765/* Commented by Albert 20110812 */766/* According to the WFD Specification, the probe response frame should contain 4 WFD attributes */767/* 1. WFD Device Information */768/* 2. Associated BSSID */769/* 3. Coupled Sink Information */770/* 4. WFD Session Information */771772773/* WFD Device Information ATTR */774/* Type: */775wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;776777/* Length: */778/* Note: In the WFD specification, the size of length field is 2. */779RTW_PUT_BE16(wfdie + wfdielen, 0x0006);780wfdielen += 2;781782/* Value1: */783/* WFD device information */784/* WFD primary sink + available for WFD session + WiFi Direct mode */785786if (_TRUE == pwdinfo->session_available) {787if (P2P_ROLE_GO == pwdinfo->role) {788if (is_any_client_associated(pwdinfo->padapter)) {789if (pwdinfo->wfd_tdls_enable) {790/* TDLS mode + WSD ( WFD Service Discovery ) */791v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;792RTW_PUT_BE16(wfdie + wfdielen, v16);793} else {794/* WiFi Direct mode + WSD ( WFD Service Discovery ) */795v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;796RTW_PUT_BE16(wfdie + wfdielen, v16);797}798} else {799if (pwdinfo->wfd_tdls_enable) {800/* available for WFD session + TDLS mode + WSD ( WFD Service Discovery ) */801v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;802RTW_PUT_BE16(wfdie + wfdielen, v16);803} else {804/* available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */805v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;806RTW_PUT_BE16(wfdie + wfdielen, v16);807}808}809} else {810if (pwdinfo->wfd_tdls_enable) {811/* available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */812v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;813RTW_PUT_BE16(wfdie + wfdielen, v16);814} else {815/* available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */816v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;817RTW_PUT_BE16(wfdie + wfdielen, v16);818}819}820} else {821if (pwdinfo->wfd_tdls_enable) {822v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;823RTW_PUT_BE16(wfdie + wfdielen, v16);824} else {825v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;826RTW_PUT_BE16(wfdie + wfdielen, v16);827}828}829830wfdielen += 2;831832/* Value2: */833/* Session Management Control Port */834/* Default TCP port for RTSP messages is 554 */835RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);836wfdielen += 2;837838/* Value3: */839/* WFD Device Maximum Throughput */840/* 300Mbps is the maximum throughput */841RTW_PUT_BE16(wfdie + wfdielen, 300);842wfdielen += 2;843844/* Associated BSSID ATTR */845/* Type: */846wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;847848/* Length: */849/* Note: In the WFD specification, the size of length field is 2. */850RTW_PUT_BE16(wfdie + wfdielen, 0x0006);851wfdielen += 2;852853/* Value: */854/* Associated BSSID */855if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)856_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);857else858_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);859860wfdielen += ETH_ALEN;861862/* Coupled Sink Information ATTR */863/* Type: */864wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;865866/* Length: */867/* Note: In the WFD specification, the size of length field is 2. */868RTW_PUT_BE16(wfdie + wfdielen, 0x0007);869wfdielen += 2;870871/* Value: */872/* Coupled Sink Status bitmap */873/* Not coupled/available for Coupling */874wfdie[wfdielen++] = 0;875/* MAC Addr. */876wfdie[wfdielen++] = 0;877wfdie[wfdielen++] = 0;878wfdie[wfdielen++] = 0;879wfdie[wfdielen++] = 0;880wfdie[wfdielen++] = 0;881wfdie[wfdielen++] = 0;882883if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {884/* WFD Session Information ATTR */885/* Type: */886wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;887888/* Length: */889/* Note: In the WFD specification, the size of length field is 2. */890RTW_PUT_BE16(wfdie + wfdielen, 0x0000);891wfdielen += 2;892893/* Todo: to add the list of WFD device info descriptor in WFD group. */894895}896#ifdef CONFIG_CONCURRENT_MODE897#ifdef CONFIG_TDLS898{899int i;900_adapter *iface = NULL;901struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);902903for (i = 0; i < dvobj->iface_nums; i++) {904iface = dvobj->padapters[i];905if ((iface) && rtw_is_adapter_up(iface)) {906if (iface == padapter)907continue;908909if ((tunneled == 0) && (iface->wdinfo.wfd_tdls_enable == 1)) {910/* Alternative MAC Address ATTR911Type: */912wfdie[wfdielen++] = WFD_ATTR_ALTER_MAC;913914/* Length:915Note: In the WFD specification, the size of length field is 2.*/916RTW_PUT_BE16(wfdie + wfdielen, ETH_ALEN);917wfdielen += 2;918919/* Value:920Alternative MAC Address*/921_rtw_memcpy(wfdie + wfdielen, adapter_mac_addr(iface), ETH_ALEN);922wfdielen += ETH_ALEN;923}924}925}926}927928#endif /* CONFIG_TDLS*/929#endif /* CONFIG_CONCURRENT_MODE */930931pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);932933exit:934return len;935}936937u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)938{939u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };940u16 val16 = 0;941u32 len = 0, wfdielen = 0;942_adapter *padapter = NULL;943struct mlme_priv *pmlmepriv = NULL;944struct wifi_display_info *pwfd_info = NULL;945946padapter = pwdinfo->padapter;947pmlmepriv = &padapter->mlmepriv;948pwfd_info = padapter->wdinfo.wfd_info;949950if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))951goto exit;952953if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))954goto exit;955956/* WFD OUI */957wfdielen = 0;958wfdie[wfdielen++] = 0x50;959wfdie[wfdielen++] = 0x6F;960wfdie[wfdielen++] = 0x9A;961wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */962963/* Commented by Albert 20110812 */964/* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */965/* 1. WFD Device Information */966/* 2. Associated BSSID */967/* 3. Coupled Sink Information */968969970/* WFD Device Information ATTR */971/* Type: */972wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;973974/* Length: */975/* Note: In the WFD specification, the size of length field is 2. */976RTW_PUT_BE16(wfdie + wfdielen, 0x0006);977wfdielen += 2;978979/* Value1: */980/* WFD device information */981/* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */982val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;983RTW_PUT_BE16(wfdie + wfdielen, val16);984wfdielen += 2;985986/* Value2: */987/* Session Management Control Port */988/* Default TCP port for RTSP messages is 554 */989RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);990wfdielen += 2;991992/* Value3: */993/* WFD Device Maximum Throughput */994/* 300Mbps is the maximum throughput */995RTW_PUT_BE16(wfdie + wfdielen, 300);996wfdielen += 2;997998/* Associated BSSID ATTR */999/* Type: */1000wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;10011002/* Length: */1003/* Note: In the WFD specification, the size of length field is 2. */1004RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1005wfdielen += 2;10061007/* Value: */1008/* Associated BSSID */1009if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)1010_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);1011else1012_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);10131014wfdielen += ETH_ALEN;10151016/* Coupled Sink Information ATTR */1017/* Type: */1018wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;10191020/* Length: */1021/* Note: In the WFD specification, the size of length field is 2. */1022RTW_PUT_BE16(wfdie + wfdielen, 0x0007);1023wfdielen += 2;10241025/* Value: */1026/* Coupled Sink Status bitmap */1027/* Not coupled/available for Coupling */1028wfdie[wfdielen++] = 0;1029/* MAC Addr. */1030wfdie[wfdielen++] = 0;1031wfdie[wfdielen++] = 0;1032wfdie[wfdielen++] = 0;1033wfdie[wfdielen++] = 0;1034wfdie[wfdielen++] = 0;1035wfdie[wfdielen++] = 0;10361037rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);10381039exit:1040return len;1041}10421043u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)1044{1045u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };1046u32 len = 0, wfdielen = 0;1047u16 val16 = 0;1048_adapter *padapter = pwdinfo->padapter;1049struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1050struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;10511052if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))1053goto exit;10541055/* WFD OUI */1056wfdielen = 0;1057wfdie[wfdielen++] = 0x50;1058wfdie[wfdielen++] = 0x6F;1059wfdie[wfdielen++] = 0x9A;1060wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */10611062/* Commented by Albert 20110812 */1063/* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */1064/* 1. WFD Device Information */1065/* 2. Associated BSSID */1066/* 3. Coupled Sink Information */106710681069/* WFD Device Information ATTR */1070/* Type: */1071wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;10721073/* Length: */1074/* Note: In the WFD specification, the size of length field is 2. */1075RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1076wfdielen += 2;10771078/* Value1: */1079/* WFD device information */1080/* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */1081val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;1082RTW_PUT_BE16(wfdie + wfdielen, val16);1083wfdielen += 2;10841085/* Value2: */1086/* Session Management Control Port */1087/* Default TCP port for RTSP messages is 554 */1088RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);1089wfdielen += 2;10901091/* Value3: */1092/* WFD Device Maximum Throughput */1093/* 300Mbps is the maximum throughput */1094RTW_PUT_BE16(wfdie + wfdielen, 300);1095wfdielen += 2;10961097/* Associated BSSID ATTR */1098/* Type: */1099wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;11001101/* Length: */1102/* Note: In the WFD specification, the size of length field is 2. */1103RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1104wfdielen += 2;11051106/* Value: */1107/* Associated BSSID */1108if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)1109_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);1110else1111_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);11121113wfdielen += ETH_ALEN;11141115/* Coupled Sink Information ATTR */1116/* Type: */1117wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;11181119/* Length: */1120/* Note: In the WFD specification, the size of length field is 2. */1121RTW_PUT_BE16(wfdie + wfdielen, 0x0007);1122wfdielen += 2;11231124/* Value: */1125/* Coupled Sink Status bitmap */1126/* Not coupled/available for Coupling */1127wfdie[wfdielen++] = 0;1128/* MAC Addr. */1129wfdie[wfdielen++] = 0;1130wfdie[wfdielen++] = 0;1131wfdie[wfdielen++] = 0;1132wfdie[wfdielen++] = 0;1133wfdie[wfdielen++] = 0;1134wfdie[wfdielen++] = 0;11351136rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);11371138exit:1139return len;1140}11411142u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)1143{1144u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };1145u32 len = 0, wfdielen = 0;1146u16 val16 = 0;1147_adapter *padapter = pwdinfo->padapter;1148struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1149struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;11501151if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))1152goto exit;11531154/* WFD OUI */1155wfdielen = 0;1156wfdie[wfdielen++] = 0x50;1157wfdie[wfdielen++] = 0x6F;1158wfdie[wfdielen++] = 0x9A;1159wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */11601161/* Commented by Albert 20110825 */1162/* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */1163/* 1. WFD Device Information */1164/* 2. Associated BSSID ( Optional ) */1165/* 3. Local IP Adress ( Optional ) */116611671168/* WFD Device Information ATTR */1169/* Type: */1170wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;11711172/* Length: */1173/* Note: In the WFD specification, the size of length field is 2. */1174RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1175wfdielen += 2;11761177/* Value1: */1178/* WFD device information */1179/* WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */1180val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;1181RTW_PUT_BE16(wfdie + wfdielen, val16);1182wfdielen += 2;11831184/* Value2: */1185/* Session Management Control Port */1186/* Default TCP port for RTSP messages is 554 */1187RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);1188wfdielen += 2;11891190/* Value3: */1191/* WFD Device Maximum Throughput */1192/* 300Mbps is the maximum throughput */1193RTW_PUT_BE16(wfdie + wfdielen, 300);1194wfdielen += 2;11951196/* Associated BSSID ATTR */1197/* Type: */1198wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;11991200/* Length: */1201/* Note: In the WFD specification, the size of length field is 2. */1202RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1203wfdielen += 2;12041205/* Value: */1206/* Associated BSSID */1207if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)1208_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);1209else1210_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);12111212wfdielen += ETH_ALEN;12131214/* Coupled Sink Information ATTR */1215/* Type: */1216wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;12171218/* Length: */1219/* Note: In the WFD specification, the size of length field is 2. */1220RTW_PUT_BE16(wfdie + wfdielen, 0x0007);1221wfdielen += 2;12221223/* Value: */1224/* Coupled Sink Status bitmap */1225/* Not coupled/available for Coupling */1226wfdie[wfdielen++] = 0;1227/* MAC Addr. */1228wfdie[wfdielen++] = 0;1229wfdie[wfdielen++] = 0;1230wfdie[wfdielen++] = 0;1231wfdie[wfdielen++] = 0;1232wfdie[wfdielen++] = 0;1233wfdie[wfdielen++] = 0;12341235rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);12361237exit:1238return len;1239}12401241u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)1242{1243u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };1244u32 len = 0, wfdielen = 0;1245u16 val16 = 0;1246_adapter *padapter = pwdinfo->padapter;1247struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1248struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;12491250if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))1251goto exit;12521253/* WFD OUI */1254wfdielen = 0;1255wfdie[wfdielen++] = 0x50;1256wfdie[wfdielen++] = 0x6F;1257wfdie[wfdielen++] = 0x9A;1258wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */12591260/* Commented by Albert 20110825 */1261/* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */1262/* 1. WFD Device Information */1263/* 2. Associated BSSID ( Optional ) */1264/* 3. Local IP Adress ( Optional ) */126512661267/* WFD Device Information ATTR */1268/* Type: */1269wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;12701271/* Length: */1272/* Note: In the WFD specification, the size of length field is 2. */1273RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1274wfdielen += 2;12751276/* Value1: */1277/* WFD device information */1278/* WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */1279val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;1280RTW_PUT_BE16(wfdie + wfdielen, val16);1281wfdielen += 2;12821283/* Value2: */1284/* Session Management Control Port */1285/* Default TCP port for RTSP messages is 554 */1286RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);1287wfdielen += 2;12881289/* Value3: */1290/* WFD Device Maximum Throughput */1291/* 300Mbps is the maximum throughput */1292RTW_PUT_BE16(wfdie + wfdielen, 300);1293wfdielen += 2;12941295/* Associated BSSID ATTR */1296/* Type: */1297wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;12981299/* Length: */1300/* Note: In the WFD specification, the size of length field is 2. */1301RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1302wfdielen += 2;13031304/* Value: */1305/* Associated BSSID */1306if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)1307_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);1308else1309_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);13101311wfdielen += ETH_ALEN;13121313/* Coupled Sink Information ATTR */1314/* Type: */1315wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;13161317/* Length: */1318/* Note: In the WFD specification, the size of length field is 2. */1319RTW_PUT_BE16(wfdie + wfdielen, 0x0007);1320wfdielen += 2;13211322/* Value: */1323/* Coupled Sink Status bitmap */1324/* Not coupled/available for Coupling */1325wfdie[wfdielen++] = 0;1326/* MAC Addr. */1327wfdie[wfdielen++] = 0;1328wfdie[wfdielen++] = 0;1329wfdie[wfdielen++] = 0;1330wfdie[wfdielen++] = 0;1331wfdie[wfdielen++] = 0;1332wfdie[wfdielen++] = 0;133313341335rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);13361337exit:1338return len;1339}13401341u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)1342{1343u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };1344u32 len = 0, wfdielen = 0;1345u16 val16 = 0;1346_adapter *padapter = pwdinfo->padapter;1347struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1348struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;13491350if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))1351goto exit;13521353/* WFD OUI */1354wfdielen = 0;1355wfdie[wfdielen++] = 0x50;1356wfdie[wfdielen++] = 0x6F;1357wfdie[wfdielen++] = 0x9A;1358wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */13591360/* Commented by Albert 20110825 */1361/* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */1362/* 1. WFD Device Information */1363/* 2. Associated BSSID ( Optional ) */1364/* 3. Local IP Adress ( Optional ) */136513661367/* WFD Device Information ATTR */1368/* Type: */1369wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;13701371/* Length: */1372/* Note: In the WFD specification, the size of length field is 2. */1373RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1374wfdielen += 2;13751376/* Value1: */1377/* WFD device information */1378/* WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */1379val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;1380RTW_PUT_BE16(wfdie + wfdielen, val16);1381wfdielen += 2;13821383/* Value2: */1384/* Session Management Control Port */1385/* Default TCP port for RTSP messages is 554 */1386RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);1387wfdielen += 2;13881389/* Value3: */1390/* WFD Device Maximum Throughput */1391/* 300Mbps is the maximum throughput */1392RTW_PUT_BE16(wfdie + wfdielen, 300);1393wfdielen += 2;13941395/* Associated BSSID ATTR */1396/* Type: */1397wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;13981399/* Length: */1400/* Note: In the WFD specification, the size of length field is 2. */1401RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1402wfdielen += 2;14031404/* Value: */1405/* Associated BSSID */1406if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)1407_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);1408else1409_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);14101411wfdielen += ETH_ALEN;14121413/* Coupled Sink Information ATTR */1414/* Type: */1415wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;14161417/* Length: */1418/* Note: In the WFD specification, the size of length field is 2. */1419RTW_PUT_BE16(wfdie + wfdielen, 0x0007);1420wfdielen += 2;14211422/* Value: */1423/* Coupled Sink Status bitmap */1424/* Not coupled/available for Coupling */1425wfdie[wfdielen++] = 0;1426/* MAC Addr. */1427wfdie[wfdielen++] = 0;1428wfdie[wfdielen++] = 0;1429wfdie[wfdielen++] = 0;1430wfdie[wfdielen++] = 0;1431wfdie[wfdielen++] = 0;1432wfdie[wfdielen++] = 0;143314341435pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);14361437exit:1438return len;1439}14401441u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)1442{1443u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };1444u32 len = 0, wfdielen = 0;1445u16 val16 = 0;1446_adapter *padapter = pwdinfo->padapter;1447struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1448struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;14491450if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))1451goto exit;14521453/* WFD OUI */1454wfdielen = 0;1455wfdie[wfdielen++] = 0x50;1456wfdie[wfdielen++] = 0x6F;1457wfdie[wfdielen++] = 0x9A;1458wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */14591460/* Commented by Albert 20110825 */1461/* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */1462/* 1. WFD Device Information */1463/* 2. Associated BSSID ( Optional ) */1464/* 3. Local IP Adress ( Optional ) */146514661467/* WFD Device Information ATTR */1468/* Type: */1469wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;14701471/* Length: */1472/* Note: In the WFD specification, the size of length field is 2. */1473RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1474wfdielen += 2;14751476/* Value1: */1477/* WFD device information */1478/* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */1479val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;1480RTW_PUT_BE16(wfdie + wfdielen, val16);1481wfdielen += 2;14821483/* Value2: */1484/* Session Management Control Port */1485/* Default TCP port for RTSP messages is 554 */1486RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);1487wfdielen += 2;14881489/* Value3: */1490/* WFD Device Maximum Throughput */1491/* 300Mbps is the maximum throughput */1492RTW_PUT_BE16(wfdie + wfdielen, 300);1493wfdielen += 2;14941495/* Associated BSSID ATTR */1496/* Type: */1497wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;14981499/* Length: */1500/* Note: In the WFD specification, the size of length field is 2. */1501RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1502wfdielen += 2;15031504/* Value: */1505/* Associated BSSID */1506if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)1507_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);1508else1509_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);15101511wfdielen += ETH_ALEN;15121513/* Coupled Sink Information ATTR */1514/* Type: */1515wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;15161517/* Length: */1518/* Note: In the WFD specification, the size of length field is 2. */1519RTW_PUT_BE16(wfdie + wfdielen, 0x0007);1520wfdielen += 2;15211522/* Value: */1523/* Coupled Sink Status bitmap */1524/* Not coupled/available for Coupling */1525wfdie[wfdielen++] = 0;1526/* MAC Addr. */1527wfdie[wfdielen++] = 0;1528wfdie[wfdielen++] = 0;1529wfdie[wfdielen++] = 0;1530wfdie[wfdielen++] = 0;1531wfdie[wfdielen++] = 0;1532wfdie[wfdielen++] = 0;15331534if (P2P_ROLE_GO == pwdinfo->role) {1535/* WFD Session Information ATTR */1536/* Type: */1537wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;15381539/* Length: */1540/* Note: In the WFD specification, the size of length field is 2. */1541RTW_PUT_BE16(wfdie + wfdielen, 0x0000);1542wfdielen += 2;15431544/* Todo: to add the list of WFD device info descriptor in WFD group. */15451546}15471548rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);15491550exit:1551return len;1552}15531554u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)1555{1556u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };1557u16 val16 = 0;1558u32 len = 0, wfdielen = 0;1559_adapter *padapter = pwdinfo->padapter;1560struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1561struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;15621563if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))1564goto exit;15651566/* WFD OUI */1567wfdielen = 0;1568wfdie[wfdielen++] = 0x50;1569wfdie[wfdielen++] = 0x6F;1570wfdie[wfdielen++] = 0x9A;1571wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */15721573/* Commented by Albert 20110825 */1574/* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */1575/* 1. WFD Device Information */1576/* 2. Associated BSSID ( Optional ) */1577/* 3. Local IP Adress ( Optional ) */157815791580/* WFD Device Information ATTR */1581/* Type: */1582wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;15831584/* Length: */1585/* Note: In the WFD specification, the size of length field is 2. */1586RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1587wfdielen += 2;15881589/* Value1: */1590/* WFD device information */1591/* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */1592val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;1593RTW_PUT_BE16(wfdie + wfdielen, val16);1594wfdielen += 2;15951596/* Value2: */1597/* Session Management Control Port */1598/* Default TCP port for RTSP messages is 554 */1599RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);1600wfdielen += 2;16011602/* Value3: */1603/* WFD Device Maximum Throughput */1604/* 300Mbps is the maximum throughput */1605RTW_PUT_BE16(wfdie + wfdielen, 300);1606wfdielen += 2;16071608/* Associated BSSID ATTR */1609/* Type: */1610wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;16111612/* Length: */1613/* Note: In the WFD specification, the size of length field is 2. */1614RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1615wfdielen += 2;16161617/* Value: */1618/* Associated BSSID */1619if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)1620_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);1621else1622_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);16231624wfdielen += ETH_ALEN;16251626/* Coupled Sink Information ATTR */1627/* Type: */1628wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;16291630/* Length: */1631/* Note: In the WFD specification, the size of length field is 2. */1632RTW_PUT_BE16(wfdie + wfdielen, 0x0007);1633wfdielen += 2;16341635/* Value: */1636/* Coupled Sink Status bitmap */1637/* Not coupled/available for Coupling */1638wfdie[wfdielen++] = 0;1639/* MAC Addr. */1640wfdie[wfdielen++] = 0;1641wfdie[wfdielen++] = 0;1642wfdie[wfdielen++] = 0;1643wfdie[wfdielen++] = 0;1644wfdie[wfdielen++] = 0;1645wfdie[wfdielen++] = 0;16461647if (P2P_ROLE_GO == pwdinfo->role) {1648/* WFD Session Information ATTR */1649/* Type: */1650wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;16511652/* Length: */1653/* Note: In the WFD specification, the size of length field is 2. */1654RTW_PUT_BE16(wfdie + wfdielen, 0x0000);1655wfdielen += 2;16561657/* Todo: to add the list of WFD device info descriptor in WFD group. */16581659}16601661rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);16621663exit:1664return len;1665}16661667u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)1668{1669u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };1670u32 len = 0, wfdielen = 0;1671u16 val16 = 0;1672_adapter *padapter = pwdinfo->padapter;1673struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1674struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;16751676if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))1677goto exit;16781679/* WFD OUI */1680wfdielen = 0;1681wfdie[wfdielen++] = 0x50;1682wfdie[wfdielen++] = 0x6F;1683wfdie[wfdielen++] = 0x9A;1684wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */16851686/* Commented by Albert 20110825 */1687/* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */1688/* 1. WFD Device Information */1689/* 2. Associated BSSID ( Optional ) */1690/* 3. Local IP Adress ( Optional ) */169116921693/* WFD Device Information ATTR */1694/* Type: */1695wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;16961697/* Length: */1698/* Note: In the WFD specification, the size of length field is 2. */1699RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1700wfdielen += 2;17011702/* Value1: */1703/* WFD device information */1704/* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */1705val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;1706RTW_PUT_BE16(wfdie + wfdielen, val16);1707wfdielen += 2;17081709/* Value2: */1710/* Session Management Control Port */1711/* Default TCP port for RTSP messages is 554 */1712RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);1713wfdielen += 2;17141715/* Value3: */1716/* WFD Device Maximum Throughput */1717/* 300Mbps is the maximum throughput */1718RTW_PUT_BE16(wfdie + wfdielen, 300);1719wfdielen += 2;17201721/* Associated BSSID ATTR */1722/* Type: */1723wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;17241725/* Length: */1726/* Note: In the WFD specification, the size of length field is 2. */1727RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1728wfdielen += 2;17291730/* Value: */1731/* Associated BSSID */1732if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)1733_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);1734else1735_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);17361737wfdielen += ETH_ALEN;17381739/* Coupled Sink Information ATTR */1740/* Type: */1741wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;17421743/* Length: */1744/* Note: In the WFD specification, the size of length field is 2. */1745RTW_PUT_BE16(wfdie + wfdielen, 0x0007);1746wfdielen += 2;17471748/* Value: */1749/* Coupled Sink Status bitmap */1750/* Not coupled/available for Coupling */1751wfdie[wfdielen++] = 0;1752/* MAC Addr. */1753wfdie[wfdielen++] = 0;1754wfdie[wfdielen++] = 0;1755wfdie[wfdielen++] = 0;1756wfdie[wfdielen++] = 0;1757wfdie[wfdielen++] = 0;1758wfdie[wfdielen++] = 0;175917601761rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);17621763exit:1764return len;1765}17661767u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)1768{1769u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };1770u32 len = 0, wfdielen = 0;1771u16 val16 = 0;1772_adapter *padapter = pwdinfo->padapter;1773struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1774struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;17751776if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))1777goto exit;17781779/* WFD OUI */1780wfdielen = 0;1781wfdie[wfdielen++] = 0x50;1782wfdie[wfdielen++] = 0x6F;1783wfdie[wfdielen++] = 0x9A;1784wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */17851786/* Commented by Albert 20110825 */1787/* According to the WFD Specification, the provision discovery response frame should contain 3 WFD attributes */1788/* 1. WFD Device Information */1789/* 2. Associated BSSID ( Optional ) */1790/* 3. Local IP Adress ( Optional ) */179117921793/* WFD Device Information ATTR */1794/* Type: */1795wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;17961797/* Length: */1798/* Note: In the WFD specification, the size of length field is 2. */1799RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1800wfdielen += 2;18011802/* Value1: */1803/* WFD device information */1804/* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */1805val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;1806RTW_PUT_BE16(wfdie + wfdielen, val16);1807wfdielen += 2;18081809/* Value2: */1810/* Session Management Control Port */1811/* Default TCP port for RTSP messages is 554 */1812RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);1813wfdielen += 2;18141815/* Value3: */1816/* WFD Device Maximum Throughput */1817/* 300Mbps is the maximum throughput */1818RTW_PUT_BE16(wfdie + wfdielen, 300);1819wfdielen += 2;18201821/* Associated BSSID ATTR */1822/* Type: */1823wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;18241825/* Length: */1826/* Note: In the WFD specification, the size of length field is 2. */1827RTW_PUT_BE16(wfdie + wfdielen, 0x0006);1828wfdielen += 2;18291830/* Value: */1831/* Associated BSSID */1832if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)1833_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);1834else1835_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);18361837wfdielen += ETH_ALEN;18381839/* Coupled Sink Information ATTR */1840/* Type: */1841wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;18421843/* Length: */1844/* Note: In the WFD specification, the size of length field is 2. */1845RTW_PUT_BE16(wfdie + wfdielen, 0x0007);1846wfdielen += 2;18471848/* Value: */1849/* Coupled Sink Status bitmap */1850/* Not coupled/available for Coupling */1851wfdie[wfdielen++] = 0;1852/* MAC Addr. */1853wfdie[wfdielen++] = 0;1854wfdie[wfdielen++] = 0;1855wfdie[wfdielen++] = 0;1856wfdie[wfdielen++] = 0;1857wfdie[wfdielen++] = 0;1858wfdie[wfdielen++] = 0;18591860rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);18611862exit:1863return len;1864}1865#endif /* CONFIG_WFD */18661867u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)1868{1869u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };1870u32 len = 0, p2pielen = 0;18711872/* P2P OUI */1873p2pielen = 0;1874p2pie[p2pielen++] = 0x50;1875p2pie[p2pielen++] = 0x6F;1876p2pie[p2pielen++] = 0x9A;1877p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */18781879/* Commented by Albert 20100907 */1880/* According to the P2P Specification, the probe response frame should contain 5 P2P attributes */1881/* 1. P2P Capability */1882/* 2. Extended Listen Timing */1883/* 3. Notice of Absence ( NOA ) ( Only GO needs this ) */1884/* 4. Device Info */1885/* 5. Group Info ( Only GO need this ) */18861887/* P2P Capability ATTR */1888/* Type: */1889p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;18901891/* Length: */1892/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); */1893RTW_PUT_LE16(p2pie + p2pielen, 0x0002);1894p2pielen += 2;18951896/* Value: */1897/* Device Capability Bitmap, 1 byte */1898p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;18991900/* Group Capability Bitmap, 1 byte */1901if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {1902p2pie[p2pielen] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);19031904if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))1905p2pie[p2pielen] |= P2P_GRPCAP_GROUP_FORMATION;19061907p2pielen++;1908} else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {1909/* Group Capability Bitmap, 1 byte */1910if (pwdinfo->persistent_supported)1911p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;1912else1913p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;1914}19151916/* Extended Listen Timing ATTR */1917/* Type: */1918p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;19191920/* Length: */1921/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 ); */1922RTW_PUT_LE16(p2pie + p2pielen, 0x0004);1923p2pielen += 2;19241925/* Value: */1926/* Availability Period */1927/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF ); */1928RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);1929p2pielen += 2;19301931/* Availability Interval */1932/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF ); */1933RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);1934p2pielen += 2;193519361937/* Notice of Absence ATTR */1938/* Type: */1939/* Length: */1940/* Value: */1941if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {1942/* go_add_noa_attr(pwdinfo); */1943}19441945/* Device Info ATTR */1946/* Type: */1947p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;19481949/* Length: */1950/* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */1951/* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */1952/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); */1953RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);1954p2pielen += 2;19551956/* Value: */1957/* P2P Device Address */1958_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);1959p2pielen += ETH_ALEN;19601961/* Config Method */1962/* This field should be big endian. Noted by P2P specification. */1963/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm ); */1964RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm);1965p2pielen += 2;19661967{1968/* Primary Device Type */1969/* Category ID */1970/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA ); */1971RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);1972p2pielen += 2;19731974/* OUI */1975/* *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); */1976RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);1977p2pielen += 4;19781979/* Sub Category ID */1980/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER ); */1981RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);1982p2pielen += 2;1983}19841985/* Number of Secondary Device Types */1986p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */19871988/* Device Name */1989/* Type: */1990/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); */1991RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);1992p2pielen += 2;19931994/* Length: */1995/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len ); */1996RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);1997p2pielen += 2;19981999/* Value: */2000_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);2001p2pielen += pwdinfo->device_name_len;20022003/* Group Info ATTR */2004/* Type: */2005/* Length: */2006/* Value: */2007if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))2008p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);200920102011pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);201220132014return len;20152016}20172018u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)2019{2020u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };2021u32 len = 0, p2pielen = 0;20222023/* P2P OUI */2024p2pielen = 0;2025p2pie[p2pielen++] = 0x50;2026p2pie[p2pielen++] = 0x6F;2027p2pie[p2pielen++] = 0x9A;2028p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */20292030/* Commented by Albert 20110301 */2031/* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */2032/* 1. P2P Capability */2033/* 2. Device Info */2034/* 3. Group ID ( When joining an operating P2P Group ) */20352036/* P2P Capability ATTR */2037/* Type: */2038p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;20392040/* Length: */2041/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); */2042RTW_PUT_LE16(p2pie + p2pielen, 0x0002);2043p2pielen += 2;20442045/* Value: */2046/* Device Capability Bitmap, 1 byte */2047p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;20482049/* Group Capability Bitmap, 1 byte */2050if (pwdinfo->persistent_supported)2051p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;2052else2053p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;205420552056/* Device Info ATTR */2057/* Type: */2058p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;20592060/* Length: */2061/* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */2062/* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */2063/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); */2064RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);2065p2pielen += 2;20662067/* Value: */2068/* P2P Device Address */2069_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);2070p2pielen += ETH_ALEN;20712072/* Config Method */2073/* This field should be big endian. Noted by P2P specification. */2074if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC) {2075/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_PBC ); */2076RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC);2077} else {2078/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY ); */2079RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY);2080}20812082p2pielen += 2;20832084/* Primary Device Type */2085/* Category ID */2086/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA ); */2087RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);2088p2pielen += 2;20892090/* OUI */2091/* *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); */2092RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);2093p2pielen += 4;20942095/* Sub Category ID */2096/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER ); */2097RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);2098p2pielen += 2;20992100/* Number of Secondary Device Types */2101p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */21022103/* Device Name */2104/* Type: */2105/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); */2106RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);2107p2pielen += 2;21082109/* Length: */2110/* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len ); */2111RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);2112p2pielen += 2;21132114/* Value: */2115_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);2116p2pielen += pwdinfo->device_name_len;21172118if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {2119/* Added by Albert 2011/05/19 */2120/* In this case, the pdev_raddr is the device address of the group owner. */21212122/* P2P Group ID ATTR */2123/* Type: */2124p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;21252126/* Length: */2127/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + ussidlen ); */2128RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen);2129p2pielen += 2;21302131/* Value: */2132_rtw_memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN);2133p2pielen += ETH_ALEN;21342135_rtw_memcpy(p2pie + p2pielen, pssid, ussidlen);2136p2pielen += ussidlen;21372138}21392140pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);214121422143return len;21442145}214621472148u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)2149{2150u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };2151u32 len = 0, p2pielen = 0;21522153/* P2P OUI */2154p2pielen = 0;2155p2pie[p2pielen++] = 0x50;2156p2pie[p2pielen++] = 0x6F;2157p2pie[p2pielen++] = 0x9A;2158p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */21592160/* According to the P2P Specification, the Association response frame should contain 2 P2P attributes */2161/* 1. Status */2162/* 2. Extended Listen Timing (optional) */216321642165/* Status ATTR */2166p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);216721682169/* Extended Listen Timing ATTR */2170/* Type: */2171/* Length: */2172/* Value: */217321742175pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);21762177return len;21782179}21802181u32 build_deauth_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)2182{2183u32 len = 0;21842185return len;2186}21872188u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)2189{2190u8 *p;2191u32 ret = _FALSE;2192u8 *p2pie;2193u32 p2pielen = 0;2194int ssid_len = 0, rate_cnt = 0;21952196p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,2197len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);21982199if (rate_cnt <= 4) {2200int i, g_rate = 0;22012202for (i = 0; i < rate_cnt; i++) {2203if (((*(p + 2 + i) & 0xff) != 0x02) &&2204((*(p + 2 + i) & 0xff) != 0x04) &&2205((*(p + 2 + i) & 0xff) != 0x0B) &&2206((*(p + 2 + i) & 0xff) != 0x16))2207g_rate = 1;2208}22092210if (g_rate == 0) {2211/* There is no OFDM rate included in SupportedRates IE of this probe request frame */2212/* The driver should response this probe request. */2213return ret;2214}2215} else {2216/* rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */2217/* We should proceed the following check for this probe request. */2218}22192220/* Added comments by Albert 20100906 */2221/* There are several items we should check here. */2222/* 1. This probe request frame must contain the P2P IE. (Done) */2223/* 2. This probe request frame must contain the wildcard SSID. (Done) */2224/* 3. Wildcard BSSID. (Todo) */2225/* 4. Destination Address. ( Done in mgt_dispatcher function ) */2226/* 5. Requested Device Type in WSC IE. (Todo) */2227/* 6. Device ID attribute in P2P IE. (Todo) */22282229p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,2230len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);22312232ssid_len &= 0xff; /* Just last 1 byte is valid for ssid len of the probe request */2233if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {2234p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_ , len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_ , NULL, &p2pielen);2235if (p2pie) {2236if ((p != NULL) && _rtw_memcmp((void *)(p + 2), (void *) pwdinfo->p2p_wildcard_ssid , 7)) {2237/* todo: */2238/* Check Requested Device Type attributes in WSC IE. */2239/* Check Device ID attribute in P2P IE */22402241ret = _TRUE;2242} else if ((p != NULL) && (ssid_len == 0))2243ret = _TRUE;2244} else {2245/* non -p2p device */2246}22472248}224922502251return ret;22522253}22542255u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)2256{2257u8 status_code = P2P_STATUS_SUCCESS;2258u8 *pbuf, *pattr_content = NULL;2259u32 attr_contentlen = 0;2260u16 cap_attr = 0;2261unsigned short frame_type, ie_offset = 0;2262u8 *ies;2263u32 ies_len;2264u8 *p2p_ie;2265u32 p2p_ielen = 0;22662267if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))2268return P2P_STATUS_FAIL_REQUEST_UNABLE;22692270frame_type = get_frame_sub_type(pframe);2271if (frame_type == WIFI_ASSOCREQ)2272ie_offset = _ASOCREQ_IE_OFFSET_;2273else /* WIFI_REASSOCREQ */2274ie_offset = _REASOCREQ_IE_OFFSET_;22752276ies = pframe + WLAN_HDR_A3_LEN + ie_offset;2277ies_len = len - WLAN_HDR_A3_LEN - ie_offset;22782279p2p_ie = rtw_get_p2p_ie(ies , ies_len , NULL, &p2p_ielen);22802281if (!p2p_ie) {2282RTW_INFO("[%s] P2P IE not Found!!\n", __FUNCTION__);2283status_code = P2P_STATUS_FAIL_INVALID_PARAM;2284} else2285RTW_INFO("[%s] P2P IE Found!!\n", __FUNCTION__);22862287while (p2p_ie) {2288/* Check P2P Capability ATTR */2289if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *) &attr_contentlen)) {2290RTW_INFO("[%s] Got P2P Capability Attr!!\n", __FUNCTION__);2291cap_attr = le16_to_cpu(cap_attr);2292psta->dev_cap = cap_attr & 0xff;2293}22942295/* Check Extended Listen Timing ATTR */229622972298/* Check P2P Device Info ATTR */2299if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint *)&attr_contentlen)) {2300RTW_INFO("[%s] Got P2P DEVICE INFO Attr!!\n", __FUNCTION__);2301pattr_content = pbuf = rtw_zmalloc(attr_contentlen);2302if (pattr_content) {2303u8 num_of_secdev_type;2304u16 dev_name_len;230523062307rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO , pattr_content, (uint *)&attr_contentlen);23082309_rtw_memcpy(psta->dev_addr, pattr_content, ETH_ALEN);/* P2P Device Address */23102311pattr_content += ETH_ALEN;23122313_rtw_memcpy(&psta->config_methods, pattr_content, 2);/* Config Methods */2314psta->config_methods = be16_to_cpu(psta->config_methods);23152316pattr_content += 2;23172318_rtw_memcpy(psta->primary_dev_type, pattr_content, 8);23192320pattr_content += 8;23212322num_of_secdev_type = *pattr_content;2323pattr_content += 1;23242325if (num_of_secdev_type == 0)2326psta->num_of_secdev_type = 0;2327else {2328u32 len;23292330psta->num_of_secdev_type = num_of_secdev_type;23312332len = (sizeof(psta->secdev_types_list) < (num_of_secdev_type * 8)) ? (sizeof(psta->secdev_types_list)) : (num_of_secdev_type * 8);23332334_rtw_memcpy(psta->secdev_types_list, pattr_content, len);23352336pattr_content += (num_of_secdev_type * 8);2337}233823392340/* dev_name_len = attr_contentlen - ETH_ALEN - 2 - 8 - 1 - (num_of_secdev_type*8); */2341psta->dev_name_len = 0;2342if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(u16 *)pattr_content)) {2343dev_name_len = be16_to_cpu(*(u16 *)(pattr_content + 2));23442345psta->dev_name_len = (sizeof(psta->dev_name) < dev_name_len) ? sizeof(psta->dev_name) : dev_name_len;23462347_rtw_memcpy(psta->dev_name, pattr_content + 4, psta->dev_name_len);2348}23492350rtw_mfree(pbuf, attr_contentlen);23512352}23532354}23552356/* Get the next P2P IE */2357p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);23582359}23602361return status_code;23622363}23642365u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)2366{2367u8 *frame_body;2368u8 status, dialogToken;2369struct sta_info *psta = NULL;2370_adapter *padapter = pwdinfo->padapter;2371struct sta_priv *pstapriv = &padapter->stapriv;2372u8 *p2p_ie;2373u32 p2p_ielen = 0;23742375frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));23762377dialogToken = frame_body[7];2378status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;23792380p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);2381if (p2p_ie) {2382u8 groupid[38] = { 0x00 };2383u8 dev_addr[ETH_ALEN] = { 0x00 };2384u32 attr_contentlen = 0;23852386if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {2387if (_rtw_memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&2388_rtw_memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN, pwdinfo->p2p_group_ssid_len)) {2389attr_contentlen = 0;2390if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen)) {2391_irqL irqL;2392_list *phead, *plist;23932394_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);2395phead = &pstapriv->asoc_list;2396plist = get_next(phead);23972398/* look up sta asoc_queue */2399while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {2400psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);24012402plist = get_next(plist);24032404if (psta->is_p2p_device && (psta->dev_cap & P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&2405_rtw_memcmp(psta->dev_addr, dev_addr, ETH_ALEN)) {24062407/* _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); */2408/* issue GO Discoverability Request */2409issue_group_disc_req(pwdinfo, psta->cmn.mac_addr);2410/* _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); */24112412status = P2P_STATUS_SUCCESS;24132414break;2415} else2416status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;24172418}2419_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);24202421} else2422status = P2P_STATUS_FAIL_INVALID_PARAM;24232424} else2425status = P2P_STATUS_FAIL_INVALID_PARAM;24262427}24282429}243024312432/* issue Device Discoverability Response */2433issue_p2p_devdisc_resp(pwdinfo, get_addr2_ptr(pframe), status, dialogToken);243424352436return (status == P2P_STATUS_SUCCESS) ? _TRUE : _FALSE;24372438}24392440u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)2441{2442return _TRUE;2443}24442445u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)2446{2447u8 *frame_body;2448u8 *wpsie;2449uint wps_ielen = 0, attr_contentlen = 0;2450u16 uconfig_method = 0;245124522453frame_body = (pframe + sizeof(struct rtw_ieee80211_hdr_3addr));24542455wpsie = rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);2456if (wpsie) {2457if (rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD , (u8 *) &uconfig_method, &attr_contentlen)) {2458uconfig_method = be16_to_cpu(uconfig_method);2459switch (uconfig_method) {2460case WPS_CM_DISPLYA: {2461_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);2462break;2463}2464case WPS_CM_LABEL: {2465_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "lab", 3);2466break;2467}2468case WPS_CM_PUSH_BUTTON: {2469_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);2470break;2471}2472case WPS_CM_KEYPAD: {2473_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);2474break;2475}2476}2477issue_p2p_provision_resp(pwdinfo, get_addr2_ptr(pframe), frame_body, uconfig_method);2478}2479}2480RTW_INFO("[%s] config method = %s\n", __FUNCTION__, pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);2481return _TRUE;24822483}24842485u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe)2486{24872488return _TRUE;2489}24902491u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)2492{2493u8 i = 0, j = 0;2494u8 temp = 0;2495u8 ch_no = 0;2496ch_content += 3;2497ch_cnt -= 3;24982499while (ch_cnt > 0) {2500ch_content += 1;2501ch_cnt -= 1;2502temp = *ch_content;2503for (i = 0 ; i < temp ; i++, j++)2504peer_ch_list[j] = *(ch_content + 1 + i);2505ch_content += (temp + 1);2506ch_cnt -= (temp + 1);2507ch_no += temp ;2508}25092510return ch_no;2511}25122513u8 rtw_p2p_ch_inclusion(_adapter *adapter, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)2514{2515struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);2516int i = 0, j = 0, temp = 0;2517u8 ch_no = 0;25182519for (i = 0; i < peer_ch_num; i++) {2520for (j = temp; j < rfctl->max_chan_nums; j++) {2521if (*(peer_ch_list + i) == rfctl->channel_set[j].ChannelNum) {2522ch_list_inclusioned[ch_no++] = *(peer_ch_list + i);2523temp = j;2524break;2525}2526}2527}25282529return ch_no;2530}25312532u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)2533{2534_adapter *padapter = pwdinfo->padapter;2535u8 result = P2P_STATUS_SUCCESS;2536u32 p2p_ielen = 0, wps_ielen = 0;2537u8 *ies;2538u32 ies_len;2539u8 *p2p_ie;2540u8 *wpsie;2541u16 wps_devicepassword_id = 0x0000;2542uint wps_devicepassword_id_len = 0;2543#ifdef CONFIG_WFD2544#ifdef CONFIG_TDLS2545struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;2546#endif /* CONFIG_TDLS */2547#endif /* CONFIG_WFD */2548wpsie = rtw_get_wps_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);2549if (wpsie) {2550/* Commented by Kurt 20120113 */2551/* If some device wants to do p2p handshake without sending prov_disc_req */2552/* We have to get peer_req_cm from here. */2553if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {2554rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8 *) &wps_devicepassword_id, &wps_devicepassword_id_len);2555wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);25562557if (wps_devicepassword_id == WPS_DPID_USER_SPEC)2558_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);2559else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)2560_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);2561else2562_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);2563}2564} else {2565RTW_INFO("[%s] WPS IE not Found!!\n", __FUNCTION__);2566result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;2567rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2568return result ;2569}25702571ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;2572ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;25732574p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);25752576if (!p2p_ie) {2577RTW_INFO("[%s] P2P IE not Found!!\n", __FUNCTION__);2578result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;2579rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2580}25812582while (p2p_ie) {2583u8 attr_content = 0x00;2584u32 attr_contentlen = 0;2585u8 ch_content[100] = { 0x00 };2586uint ch_cnt = 0;2587u8 peer_ch_list[100] = { 0x00 };2588u8 peer_ch_num = 0;2589u8 ch_list_inclusioned[100] = { 0x00 };2590u8 ch_num_inclusioned = 0;2591u16 cap_attr;2592u8 listen_ch_attr[5] = { 0x00 };25932594rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);25952596/* Check P2P Capability ATTR */2597if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *)&attr_contentlen)) {2598cap_attr = le16_to_cpu(cap_attr);25992600#if defined(CONFIG_WFD) && defined(CONFIG_TDLS)2601if (!(cap_attr & P2P_GRPCAP_INTRABSS))2602ptdlsinfo->ap_prohibited = _TRUE;2603#endif /* defined(CONFIG_WFD) && defined(CONFIG_TDLS) */2604}26052606if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen)) {2607RTW_INFO("[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01);2608pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */26092610if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {2611/* Try to match the tie breaker value */2612if (pwdinfo->intent == P2P_MAX_INTENT) {2613rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);2614result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;2615} else {2616if (attr_content & 0x01)2617rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);2618else2619rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);2620}2621} else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))2622rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);2623else2624rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);26252626if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {2627/* Store the group id information. */2628_rtw_memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);2629_rtw_memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);2630}2631}26322633if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, (u8 *)listen_ch_attr, (uint *) &attr_contentlen) && attr_contentlen == 5)2634pwdinfo->nego_req_info.peer_ch = listen_ch_attr[4];26352636RTW_INFO(FUNC_ADPT_FMT" listen channel :%u\n", FUNC_ADPT_ARG(padapter), pwdinfo->nego_req_info.peer_ch);26372638attr_contentlen = 0;2639if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {2640if (attr_contentlen != ETH_ALEN)2641_rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);2642}26432644if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt)) {2645peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);2646ch_num_inclusioned = rtw_p2p_ch_inclusion(padapter, peer_ch_list, peer_ch_num, ch_list_inclusioned);26472648if (ch_num_inclusioned == 0) {2649RTW_INFO("[%s] No common channel in channel list!\n", __FUNCTION__);2650result = P2P_STATUS_FAIL_NO_COMMON_CH;2651rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2652break;2653}26542655if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {2656if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,2657ch_list_inclusioned, ch_num_inclusioned)) {2658#ifdef CONFIG_CONCURRENT_MODE2659if (rtw_mi_check_status(padapter, MI_LINKED)2660&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {2661RTW_INFO("[%s] desired channel NOT Found!\n", __FUNCTION__);2662result = P2P_STATUS_FAIL_NO_COMMON_CH;2663rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2664break;2665} else2666#endif /* CONFIG_CONCURRENT_MODE */2667{2668u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;2669attr_contentlen = 0;26702671if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))2672peer_operating_ch = operatingch_info[4];26732674if (rtw_p2p_is_channel_list_ok(peer_operating_ch,2675ch_list_inclusioned, ch_num_inclusioned)) {2676/**2677* Change our operating channel as peer's for compatibility.2678*/2679pwdinfo->operating_channel = peer_operating_ch;2680RTW_INFO("[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);2681} else {2682/* Take first channel of ch_list_inclusioned as operating channel */2683pwdinfo->operating_channel = ch_list_inclusioned[0];2684RTW_INFO("[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);2685}2686}26872688}2689}2690}26912692/* Get the next P2P IE */2693p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);2694}26952696if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) {2697result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;2698rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);2699return result;2700}27012702#ifdef CONFIG_WFD2703rtw_process_wfd_ies(padapter, pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, __func__);2704#endif27052706return result ;2707}27082709u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)2710{2711_adapter *padapter = pwdinfo->padapter;2712u8 result = P2P_STATUS_SUCCESS;2713u32 p2p_ielen, wps_ielen;2714u8 *ies;2715u32 ies_len;2716u8 *p2p_ie;2717#ifdef CONFIG_WFD2718#ifdef CONFIG_TDLS2719struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;2720#endif /* CONFIG_TDLS */2721#endif /* CONFIG_WFD */27222723ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;2724ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;27252726/* Be able to know which one is the P2P GO and which one is P2P client. */27272728if (rtw_get_wps_ie(ies, ies_len, NULL, &wps_ielen)) {27292730} else {2731RTW_INFO("[%s] WPS IE not Found!!\n", __FUNCTION__);2732result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;2733rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2734}27352736p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);2737if (!p2p_ie) {2738rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);2739rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2740result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;2741} else {27422743u8 attr_content = 0x00;2744u32 attr_contentlen = 0;2745u8 operatingch_info[5] = { 0x00 };2746u8 groupid[38];2747u16 cap_attr;2748u8 peer_ch_list[100] = { 0x00 };2749u8 peer_ch_num = 0;2750u8 ch_list_inclusioned[100] = { 0x00 };2751u8 ch_num_inclusioned = 0;27522753while (p2p_ie) { /* Found the P2P IE. */27542755/* Check P2P Capability ATTR */2756if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *)&attr_contentlen)) {2757cap_attr = le16_to_cpu(cap_attr);2758#ifdef CONFIG_TDLS2759if (!(cap_attr & P2P_GRPCAP_INTRABSS))2760ptdlsinfo->ap_prohibited = _TRUE;2761#endif /* CONFIG_TDLS */2762}27632764rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);2765if (attr_contentlen == 1) {2766RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content);2767if (attr_content == P2P_STATUS_SUCCESS) {2768/* Do nothing. */2769} else {2770if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content)2771rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);2772else2773rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2774rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);2775result = attr_content;2776break;2777}2778}27792780/* Try to get the peer's interface address */2781attr_contentlen = 0;2782if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {2783if (attr_contentlen != ETH_ALEN)2784_rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);2785}27862787/* Try to get the peer's intent and tie breaker value. */2788attr_content = 0x00;2789attr_contentlen = 0;2790if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen)) {2791RTW_INFO("[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01);2792pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */27932794if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {2795/* Try to match the tie breaker value */2796if (pwdinfo->intent == P2P_MAX_INTENT) {2797rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);2798result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;2799rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2800} else {2801rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);2802rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);2803if (attr_content & 0x01)2804rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);2805else2806rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);2807}2808} else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) {2809rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);2810rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);2811rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);2812} else {2813rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);2814rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);2815rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);2816}28172818if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {2819/* Store the group id information. */2820_rtw_memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);2821_rtw_memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);28222823}2824}28252826/* Try to get the operation channel information */28272828attr_contentlen = 0;2829if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {2830RTW_INFO("[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4]);2831pwdinfo->peer_operating_ch = operatingch_info[4];2832}28332834/* Try to get the channel list information */2835if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len)) {2836RTW_INFO("[%s] channel list attribute found, len = %d\n", __FUNCTION__, pwdinfo->channel_list_attr_len);28372838peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);2839ch_num_inclusioned = rtw_p2p_ch_inclusion(padapter, peer_ch_list, peer_ch_num, ch_list_inclusioned);28402841if (ch_num_inclusioned == 0) {2842RTW_INFO("[%s] No common channel in channel list!\n", __FUNCTION__);2843result = P2P_STATUS_FAIL_NO_COMMON_CH;2844rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2845break;2846}28472848if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {2849if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,2850ch_list_inclusioned, ch_num_inclusioned)) {2851#ifdef CONFIG_CONCURRENT_MODE2852if (rtw_mi_check_status(padapter, MI_LINKED)2853&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {2854RTW_INFO("[%s] desired channel NOT Found!\n", __FUNCTION__);2855result = P2P_STATUS_FAIL_NO_COMMON_CH;2856rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2857break;2858} else2859#endif /* CONFIG_CONCURRENT_MODE */2860{2861u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;2862attr_contentlen = 0;28632864if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))2865peer_operating_ch = operatingch_info[4];28662867if (rtw_p2p_is_channel_list_ok(peer_operating_ch,2868ch_list_inclusioned, ch_num_inclusioned)) {2869/**2870* Change our operating channel as peer's for compatibility.2871*/2872pwdinfo->operating_channel = peer_operating_ch;2873RTW_INFO("[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);2874} else {2875/* Take first channel of ch_list_inclusioned as operating channel */2876pwdinfo->operating_channel = ch_list_inclusioned[0];2877RTW_INFO("[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);2878}2879}28802881}2882}28832884} else2885RTW_INFO("[%s] channel list attribute not found!\n", __FUNCTION__);28862887/* Try to get the group id information if peer is GO */2888attr_contentlen = 0;2889_rtw_memset(groupid, 0x00, 38);2890if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {2891_rtw_memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);2892_rtw_memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);2893}28942895/* Get the next P2P IE */2896p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);2897}28982899}29002901#ifdef CONFIG_WFD2902rtw_process_wfd_ies(padapter, pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, __func__);2903#endif29042905return result ;29062907}29082909u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)2910{2911#ifdef CONFIG_CONCURRENT_MODE2912_adapter *padapter = pwdinfo->padapter;2913#endif2914u8 *ies;2915u32 ies_len;2916u8 *p2p_ie;2917u32 p2p_ielen = 0;2918u8 result = P2P_STATUS_SUCCESS;2919ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;2920ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;29212922p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);2923while (p2p_ie) { /* Found the P2P IE. */2924u8 attr_content = 0x00, operatingch_info[5] = { 0x00 };2925u8 groupid[38] = { 0x00 };2926u32 attr_contentlen = 0;29272928pwdinfo->negotiation_dialog_token = 1;2929rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);2930if (attr_contentlen == 1) {2931RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content);2932result = attr_content;29332934if (attr_content == P2P_STATUS_SUCCESS) {29352936_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);29372938/* Commented by Albert 20100911 */2939/* Todo: Need to handle the case which both Intents are the same. */2940rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);2941rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);2942if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1))2943rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);2944else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1))2945rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);2946else {2947/* Have to compare the Tie Breaker */2948if (pwdinfo->peer_intent & 0x01)2949rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);2950else2951rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);2952}29532954#ifdef CONFIG_CONCURRENT_MODE2955if (rtw_mi_check_status(padapter, MI_LINKED)2956&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {2957/* Switch back to the AP channel soon. */2958_set_timer(&pwdinfo->ap_p2p_switch_timer, 100);2959}2960#endif2961} else {2962rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);2963rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);2964break;2965}2966}29672968/* Try to get the group id information */2969attr_contentlen = 0;2970_rtw_memset(groupid, 0x00, 38);2971if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {2972RTW_INFO("[%s] Ssid = %s, ssidlen = %zu\n", __FUNCTION__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));2973_rtw_memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);2974_rtw_memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);2975}29762977attr_contentlen = 0;2978if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {2979RTW_INFO("[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4]);2980pwdinfo->peer_operating_ch = operatingch_info[4];2981}29822983/* Get the next P2P IE */2984p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);29852986}29872988return result ;2989}29902991u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)2992{2993u8 *frame_body;2994u8 dialogToken = 0;2995u8 status = P2P_STATUS_SUCCESS;29962997frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));29982999dialogToken = frame_body[6];30003001/* todo: check NoA attribute */30023003issue_p2p_presence_resp(pwdinfo, get_addr2_ptr(pframe), status, dialogToken);30043005return _TRUE;3006}30073008void find_phase_handler(_adapter *padapter)3009{3010struct wifidirect_info *pwdinfo = &padapter->wdinfo;3011struct mlme_priv *pmlmepriv = &padapter->mlmepriv;3012struct sitesurvey_parm parm;3013_irqL irqL;3014u8 _status = 0;301530163017rtw_init_sitesurvey_parm(padapter, &parm);3018_rtw_memcpy(&parm.ssid[0].Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);3019parm.ssid[0].SsidLength = P2P_WILDCARD_SSID_LEN;3020parm.ssid_num = 1;30213022rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);30233024_enter_critical_bh(&pmlmepriv->lock, &irqL);3025_status = rtw_sitesurvey_cmd(padapter, &parm);3026_exit_critical_bh(&pmlmepriv->lock, &irqL);302730283029}30303031void p2p_concurrent_handler(_adapter *padapter);30323033void restore_p2p_state_handler(_adapter *padapter)3034{3035struct wifidirect_info *pwdinfo = &padapter->wdinfo;30363037if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))3038rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);30393040#ifdef CONFIG_CONCURRENT_MODE3041if (rtw_mi_check_status(padapter, MI_LINKED)) {3042u8 union_ch = rtw_mi_get_union_chan(padapter);3043u8 union_bw = rtw_mi_get_union_bw(padapter);3044u8 union_offset = rtw_mi_get_union_offset(padapter);30453046if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP)) {3047set_channel_bwmode(padapter, union_ch, union_offset, union_bw);3048rtw_back_opch(padapter);3049}3050}3051#endif30523053rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));30543055if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {3056#ifdef CONFIG_CONCURRENT_MODE3057p2p_concurrent_handler(padapter);3058#else3059/* In the P2P client mode, the driver should not switch back to its listen channel */3060/* because this P2P client should stay at the operating channel of P2P GO. */3061set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);3062#endif3063}3064}30653066void pre_tx_invitereq_handler(_adapter *padapter)3067{3068struct wifidirect_info *pwdinfo = &padapter->wdinfo;3069u8 val8 = 1;30703071set_channel_bwmode(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);3072rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));3073issue_probereq_p2p(padapter, NULL);3074_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);30753076}30773078void pre_tx_provdisc_handler(_adapter *padapter)3079{3080struct wifidirect_info *pwdinfo = &padapter->wdinfo;3081u8 val8 = 1;30823083set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);3084rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));3085issue_probereq_p2p(padapter, NULL);3086_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);30873088}30893090void pre_tx_negoreq_handler(_adapter *padapter)3091{3092struct wifidirect_info *pwdinfo = &padapter->wdinfo;3093u8 val8 = 1;30943095set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);3096rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));3097issue_probereq_p2p(padapter , NULL);3098/* WIN Phone only accept unicast probe request when nego back */3099issue_probereq_p2p(padapter , pwdinfo->nego_req_info.peerDevAddr);3100_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);31013102}31033104#ifdef CONFIG_CONCURRENT_MODE3105void p2p_concurrent_handler(_adapter *padapter)3106{3107struct wifidirect_info *pwdinfo = &padapter->wdinfo;3108struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);3109u8 val8;31103111#ifdef CONFIG_IOCTL_CFG802113112if (pwdinfo->driver_interface == DRIVER_CFG802113113&& !rtw_cfg80211_get_is_roch(padapter))3114return;3115#endif31163117if (rtw_mi_check_status(padapter, MI_LINKED)) {3118u8 union_ch = rtw_mi_get_union_chan(padapter);3119u8 union_bw = rtw_mi_get_union_bw(padapter);3120u8 union_offset = rtw_mi_get_union_offset(padapter);31213122pwdinfo->operating_channel = union_ch;31233124if (pwdinfo->driver_interface == DRIVER_CFG80211) {3125RTW_INFO("%s, switch ch back to union=%u,%u, %u\n"3126, __func__, union_ch, union_bw, union_offset);3127set_channel_bwmode(padapter, union_ch, union_offset, union_bw);3128rtw_back_opch(padapter);31293130} else if (pwdinfo->driver_interface == DRIVER_WEXT) {3131if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {3132/* Now, the driver stays on the AP's channel. */3133/* If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel. */3134if (pwdinfo->ext_listen_period > 0) {3135RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period);31363137if (union_ch != pwdinfo->listen_channel) {3138rtw_leave_opch(padapter);3139set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);3140}31413142rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);31433144if (!rtw_mi_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) {3145val8 = 1;3146rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));3147}3148/* Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not. */3149_set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period);3150}31513152} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) ||3153rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) ||3154(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE) ||3155rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) {3156/* Now, the driver is in the listen state of P2P mode. */3157RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval);31583159/* Commented by Albert 2012/11/01 */3160/* If the AP's channel is the same as the listen channel, we should still be in the listen state */3161/* Other P2P device is still able to find this device out even this device is in the AP's channel. */3162/* So, configure this device to be able to receive the probe request frame and set it to listen state. */3163if (union_ch != pwdinfo->listen_channel) {31643165set_channel_bwmode(padapter, union_ch, union_offset, union_bw);3166if (!rtw_mi_check_status(padapter, MI_AP_MODE)) {3167val8 = 0;3168rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));3169}3170rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);3171rtw_back_opch(padapter);3172}31733174/* Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not. */3175_set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval);31763177} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) {3178/* The driver had finished the P2P handshake successfully. */3179val8 = 0;3180rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));3181set_channel_bwmode(padapter, union_ch, union_offset, union_bw);3182rtw_back_opch(padapter);31833184} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {3185val8 = 1;3186set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);3187rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));3188issue_probereq_p2p(padapter, NULL);3189_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);3190} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE) {3191val8 = 1;3192set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);3193rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));3194issue_probereq_p2p(padapter, NULL);3195_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);3196} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ) && pwdinfo->invitereq_info.benable == _TRUE) {3197/*3198val8 = 1;3199set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);3200rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));3201issue_probereq_p2p(padapter, NULL);3202_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );3203*/3204}3205}3206} else {3207/* In p2p+softap. When in P2P_STATE_GONEGO_OK, not back to listen channel.*/3208if (!rtw_p2p_chk_state(pwdinfo , P2P_STATE_GONEGO_OK) || padapter->registrypriv.full_ch_in_p2p_handshake == 0)3209set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);3210else3211RTW_INFO("%s, buddy not linked, go nego ok, not back to listen channel\n", __func__);3212}32133214}3215#endif32163217#ifdef CONFIG_IOCTL_CFG802113218u8 roch_stay_in_cur_chan(_adapter *padapter)3219{3220int i;3221_adapter *iface;3222struct mlme_priv *pmlmepriv;3223struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);3224u8 rst = _FALSE;32253226for (i = 0; i < dvobj->iface_nums; i++) {3227iface = dvobj->padapters[i];3228if (iface) {3229pmlmepriv = &iface->mlmepriv;32303231if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE) == _TRUE) {3232RTW_INFO(ADPT_FMT"- _FW_UNDER_LINKING |WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE (mlme state:0x%x)\n",3233ADPT_ARG(iface), get_fwstate(&iface->mlmepriv));3234rst = _TRUE;3235break;3236}3237#ifdef CONFIG_AP_MODE3238if (MLME_IS_AP(iface) || MLME_IS_MESH(iface)) {3239if (rtw_ap_sta_states_check(iface) == _TRUE) {3240rst = _TRUE;3241break;3242}3243}3244#endif3245}3246}32473248return rst;3249}32503251static int ro_ch_handler(_adapter *adapter, u8 *buf)3252{3253int ret = H2C_SUCCESS;3254struct p2p_roch_parm *roch_parm = (struct p2p_roch_parm *)buf;3255struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);3256struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &adapter->cfg80211_wdinfo;3257#ifdef CONFIG_CONCURRENT_MODE3258struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;3259#ifdef RTW_ROCH_BACK_OP3260struct wifidirect_info *pwdinfo = &adapter->wdinfo;3261#endif3262#endif3263u8 ready_on_channel = _FALSE;3264u8 remain_ch;3265unsigned int duration;32663267_enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);32683269if (rtw_cfg80211_get_is_roch(adapter) != _TRUE)3270goto exit;32713272remain_ch = (u8)ieee80211_frequency_to_channel(roch_parm->ch.center_freq);3273duration = roch_parm->duration;32743275RTW_INFO(FUNC_ADPT_FMT" ch:%u duration:%d, cookie:0x%llx\n"3276, FUNC_ADPT_ARG(adapter), remain_ch, roch_parm->duration, roch_parm->cookie);32773278if (roch_parm->wdev && roch_parm->cookie) {3279if (pcfg80211_wdinfo->ro_ch_wdev != roch_parm->wdev) {3280RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"3281, FUNC_ADPT_ARG(adapter), pcfg80211_wdinfo->ro_ch_wdev, roch_parm->wdev);3282rtw_warn_on(1);3283}32843285if (pcfg80211_wdinfo->remain_on_ch_cookie != roch_parm->cookie) {3286RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"3287, FUNC_ADPT_ARG(adapter), pcfg80211_wdinfo->remain_on_ch_cookie, roch_parm->cookie);3288rtw_warn_on(1);3289}3290}32913292if (roch_stay_in_cur_chan(adapter) == _TRUE) {3293remain_ch = rtw_mi_get_union_chan(adapter);3294RTW_INFO(FUNC_ADPT_FMT" stay in union ch:%d\n", FUNC_ADPT_ARG(adapter), remain_ch);3295}32963297#ifdef CONFIG_CONCURRENT_MODE3298if (rtw_mi_check_status(adapter, MI_LINKED) && (0 != rtw_mi_get_union_chan(adapter))) {3299if ((remain_ch != rtw_mi_get_union_chan(adapter)) && !check_fwstate(&adapter->mlmepriv, _FW_LINKED)) {3300if (remain_ch != pmlmeext->cur_channel3301#ifdef RTW_ROCH_BACK_OP3302|| ATOMIC_READ(&pwdev_priv->switch_ch_to) == 13303#endif3304) {3305rtw_leave_opch(adapter);33063307#ifdef RTW_ROCH_BACK_OP3308RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, duration - pwdinfo->ext_listen_interval);3309ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);3310_set_timer(&pwdinfo->ap_p2p_switch_timer, duration - pwdinfo->ext_listen_interval);3311#endif3312}3313}3314ready_on_channel = _TRUE;3315} else3316#endif /* CONFIG_CONCURRENT_MODE */3317{3318if (remain_ch != rtw_get_oper_ch(adapter))3319ready_on_channel = _TRUE;3320}33213322if (ready_on_channel == _TRUE) {3323#ifndef RTW_SINGLE_WIPHY3324if (!check_fwstate(&adapter->mlmepriv, _FW_LINKED))3325#endif3326{3327#ifdef CONFIG_CONCURRENT_MODE3328if (rtw_get_oper_ch(adapter) != remain_ch)3329#endif3330{3331/* if (!padapter->mlmepriv.LinkDetectInfo.bBusyTraffic) */3332set_channel_bwmode(adapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);3333}3334}3335}33363337#ifdef CONFIG_BT_COEXIST3338rtw_btcoex_ScanNotify(adapter, _TRUE);3339#endif33403341RTW_INFO("%s, set ro ch timer, duration=%d\n", __func__, duration);3342_set_timer(&pcfg80211_wdinfo->remain_on_ch_timer, duration);33433344exit:3345_exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);33463347return ret;3348}33493350static int cancel_ro_ch_handler(_adapter *padapter, u8 *buf)3351{3352int ret = H2C_SUCCESS;3353struct p2p_roch_parm *roch_parm = (struct p2p_roch_parm *)buf;3354struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);3355struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;3356struct wireless_dev *wdev;3357struct wifidirect_info *pwdinfo = &padapter->wdinfo;3358u8 ch, bw, offset;33593360_enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);33613362if (rtw_cfg80211_get_is_roch(padapter) != _TRUE)3363goto exit;33643365if (roch_parm->wdev && roch_parm->cookie) {3366if (pcfg80211_wdinfo->ro_ch_wdev != roch_parm->wdev) {3367RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"3368, FUNC_ADPT_ARG(padapter), pcfg80211_wdinfo->ro_ch_wdev, roch_parm->wdev);3369rtw_warn_on(1);3370}33713372if (pcfg80211_wdinfo->remain_on_ch_cookie != roch_parm->cookie) {3373RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"3374, FUNC_ADPT_ARG(padapter), pcfg80211_wdinfo->remain_on_ch_cookie, roch_parm->cookie);3375rtw_warn_on(1);3376}3377}33783379#if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE)3380_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);3381ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);3382#endif33833384if (rtw_mi_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) {3385if (0)3386RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",3387FUNC_ADPT_ARG(padapter), ch, bw, offset);3388} else if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->listen_channel) {3389ch = pwdinfo->listen_channel;3390bw = CHANNEL_WIDTH_20;3391offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;3392if (0)3393RTW_INFO(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n",3394FUNC_ADPT_ARG(padapter), ch, bw, offset);3395} else {3396ch = pcfg80211_wdinfo->restore_channel;3397bw = CHANNEL_WIDTH_20;3398offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;3399if (0)3400RTW_INFO(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n",3401FUNC_ADPT_ARG(padapter), ch, bw, offset);3402}34033404set_channel_bwmode(padapter, ch, offset, bw);3405rtw_back_opch(padapter);34063407rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));3408#ifdef CONFIG_DEBUG_CFG802113409RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));3410#endif34113412wdev = pcfg80211_wdinfo->ro_ch_wdev;34133414rtw_cfg80211_set_is_roch(padapter, _FALSE);3415pcfg80211_wdinfo->ro_ch_wdev = NULL;3416rtw_cfg80211_set_last_ro_ch_time(padapter);34173418rtw_cfg80211_remain_on_channel_expired(wdev3419, pcfg80211_wdinfo->remain_on_ch_cookie3420, &pcfg80211_wdinfo->remain_on_ch_channel3421, pcfg80211_wdinfo->remain_on_ch_type, GFP_KERNEL);34223423RTW_INFO("cfg80211_remain_on_channel_expired cookie:0x%llx\n"3424, pcfg80211_wdinfo->remain_on_ch_cookie);34253426#ifdef CONFIG_BT_COEXIST3427rtw_btcoex_ScanNotify(padapter, _FALSE);3428#endif34293430exit:3431_exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);34323433return ret;3434}34353436static void ro_ch_timer_process(void *FunctionContext)3437{3438_adapter *adapter = (_adapter *)FunctionContext;34393440p2p_cancel_roch_cmd(adapter, 0, NULL, 0);3441}34423443#if 03444static void rtw_change_p2pie_op_ch(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)3445{3446u8 *ies, *p2p_ie;3447u32 ies_len, p2p_ielen;34483449#ifdef CONFIG_MCC_MODE3450if (MCC_EN(padapter))3451return;3452#endif /* CONFIG_MCC_MODE */34533454ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);3455ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;34563457p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);34583459while (p2p_ie) {3460u32 attr_contentlen = 0;3461u8 *pattr = NULL;34623463/* Check P2P_ATTR_OPERATING_CH */3464attr_contentlen = 0;3465pattr = NULL;3466pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);3467if (pattr != NULL)3468*(pattr + 4) = ch;34693470/* Get the next P2P IE */3471p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);3472}3473}3474#endif34753476#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)3477static void rtw_change_p2pie_ch_list(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)3478{3479u8 *ies, *p2p_ie;3480u32 ies_len, p2p_ielen;34813482#ifdef CONFIG_MCC_MODE3483if (MCC_EN(padapter))3484return;3485#endif /* CONFIG_MCC_MODE */34863487ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);3488ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;34893490p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);34913492while (p2p_ie) {3493u32 attr_contentlen = 0;3494u8 *pattr = NULL;34953496/* Check P2P_ATTR_CH_LIST */3497pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);3498if (pattr != NULL) {3499int i;3500u32 num_of_ch;3501u8 *pattr_temp = pattr + 3 ;35023503attr_contentlen -= 3;35043505while (attr_contentlen > 0) {3506num_of_ch = *(pattr_temp + 1);35073508for (i = 0; i < num_of_ch; i++)3509*(pattr_temp + 2 + i) = ch;35103511pattr_temp += (2 + num_of_ch);3512attr_contentlen -= (2 + num_of_ch);3513}3514}35153516/* Get the next P2P IE */3517p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);3518}3519}3520#endif35213522#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)3523static bool rtw_chk_p2pie_ch_list_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)3524{3525bool fit = _FALSE;3526u8 *ies, *p2p_ie;3527u32 ies_len, p2p_ielen;3528u8 union_ch = rtw_mi_get_union_chan(padapter);35293530ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);3531ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;35323533p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);35343535while (p2p_ie) {3536u32 attr_contentlen = 0;3537u8 *pattr = NULL;35383539/* Check P2P_ATTR_CH_LIST */3540pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);3541if (pattr != NULL) {3542int i;3543u32 num_of_ch;3544u8 *pattr_temp = pattr + 3 ;35453546attr_contentlen -= 3;35473548while (attr_contentlen > 0) {3549num_of_ch = *(pattr_temp + 1);35503551for (i = 0; i < num_of_ch; i++) {3552if (*(pattr_temp + 2 + i) == union_ch) {3553RTW_INFO(FUNC_ADPT_FMT" ch_list fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), union_ch);3554fit = _TRUE;3555break;3556}3557}35583559pattr_temp += (2 + num_of_ch);3560attr_contentlen -= (2 + num_of_ch);3561}3562}35633564/* Get the next P2P IE */3565p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);3566}35673568return fit;3569}35703571#if defined(CONFIG_P2P_INVITE_IOT)3572static bool rtw_chk_p2pie_op_ch_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)3573{3574bool fit = _FALSE;3575u8 *ies, *p2p_ie;3576u32 ies_len, p2p_ielen;3577u8 union_ch = rtw_mi_get_union_chan(padapter);35783579ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);3580ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;35813582p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);35833584while (p2p_ie) {3585u32 attr_contentlen = 0;3586u8 *pattr = NULL;35873588/* Check P2P_ATTR_OPERATING_CH */3589attr_contentlen = 0;3590pattr = NULL;3591pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);3592if (pattr != NULL) {3593if (*(pattr + 4) == union_ch) {3594RTW_INFO(FUNC_ADPT_FMT" op_ch fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), union_ch);3595fit = _TRUE;3596break;3597}3598}35993600/* Get the next P2P IE */3601p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);3602}36033604return fit;3605}3606#endif36073608static void rtw_cfg80211_adjust_p2pie_channel(_adapter *padapter, const u8 *frame_body, u32 len)3609{3610u8 *ies, *p2p_ie;3611u32 ies_len, p2p_ielen;3612u8 union_ch = rtw_mi_get_union_chan(padapter);36133614#ifdef CONFIG_MCC_MODE3615if (MCC_EN(padapter))3616return;3617#endif /* CONFIG_MCC_MODE */36183619ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);3620ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;36213622p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);36233624while (p2p_ie) {3625u32 attr_contentlen = 0;3626u8 *pattr = NULL;36273628/* Check P2P_ATTR_CH_LIST */3629pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);3630if (pattr != NULL) {3631int i;3632u32 num_of_ch;3633u8 *pattr_temp = pattr + 3 ;36343635attr_contentlen -= 3;36363637while (attr_contentlen > 0) {3638num_of_ch = *(pattr_temp + 1);36393640for (i = 0; i < num_of_ch; i++) {3641if (*(pattr_temp + 2 + i) && *(pattr_temp + 2 + i) != union_ch) {3642#ifdef RTW_SINGLE_WIPHY3643RTW_ERR("replace ch_list:%u with:%u\n", *(pattr_temp + 2 + i), union_ch);3644#endif3645*(pattr_temp + 2 + i) = union_ch; /*forcing to the same channel*/3646}3647}36483649pattr_temp += (2 + num_of_ch);3650attr_contentlen -= (2 + num_of_ch);3651}3652}36533654/* Check P2P_ATTR_OPERATING_CH */3655attr_contentlen = 0;3656pattr = NULL;3657pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);3658if (pattr != NULL) {3659if (*(pattr + 4) && *(pattr + 4) != union_ch) {3660#ifdef RTW_SINGLE_WIPHY3661RTW_ERR("replace op_ch:%u with:%u\n", *(pattr + 4), union_ch);3662#endif3663*(pattr + 4) = union_ch; /*forcing to the same channel */3664}3665}36663667/* Get the next P2P IE */3668p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);36693670}36713672}3673#endif36743675#ifdef CONFIG_WFD3676u32 rtw_xframe_build_wfd_ie(struct xmit_frame *xframe)3677{3678_adapter *adapter = xframe->padapter;3679struct wifidirect_info *wdinfo = &adapter->wdinfo;3680u8 *frame = xframe->buf_addr + TXDESC_OFFSET;3681u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);3682u8 *frame_tail = frame + xframe->attrib.pktlen;3683u8 category, action, OUI_Subtype, dialogToken = 0;3684u32 wfdielen = 0;36853686category = frame_body[0];3687if (category == RTW_WLAN_CATEGORY_PUBLIC) {3688action = frame_body[1];3689if (action == ACT_PUBLIC_VENDOR3690&& _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE3691) {3692OUI_Subtype = frame_body[6];3693dialogToken = frame_body[7];36943695switch (OUI_Subtype) {3696case P2P_GO_NEGO_REQ:3697wfdielen = build_nego_req_wfd_ie(wdinfo, frame_tail);3698break;3699case P2P_GO_NEGO_RESP:3700wfdielen = build_nego_resp_wfd_ie(wdinfo, frame_tail);3701break;3702case P2P_GO_NEGO_CONF:3703wfdielen = build_nego_confirm_wfd_ie(wdinfo, frame_tail);3704break;3705case P2P_INVIT_REQ:3706wfdielen = build_invitation_req_wfd_ie(wdinfo, frame_tail);3707break;3708case P2P_INVIT_RESP:3709wfdielen = build_invitation_resp_wfd_ie(wdinfo, frame_tail);3710break;3711case P2P_PROVISION_DISC_REQ:3712wfdielen = build_provdisc_req_wfd_ie(wdinfo, frame_tail);3713break;3714case P2P_PROVISION_DISC_RESP:3715wfdielen = build_provdisc_resp_wfd_ie(wdinfo, frame_tail);3716break;3717case P2P_DEVDISC_REQ:3718case P2P_DEVDISC_RESP:3719default:3720break;3721}37223723}3724} else if (category == RTW_WLAN_CATEGORY_P2P) {3725OUI_Subtype = frame_body[5];3726dialogToken = frame_body[6];37273728#ifdef CONFIG_DEBUG_CFG802113729RTW_INFO("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n"3730, cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);3731#endif37323733switch (OUI_Subtype) {3734case P2P_NOTICE_OF_ABSENCE:3735break;3736case P2P_PRESENCE_REQUEST:3737break;3738case P2P_PRESENCE_RESPONSE:3739break;3740case P2P_GO_DISC_REQUEST:3741break;3742default:3743break;3744}3745} else3746RTW_INFO("%s, action frame category=%d\n", __func__, category);37473748xframe->attrib.pktlen += wfdielen;37493750return wfdielen;3751}3752#endif /* CONFIG_WFD */37533754bool rtw_xframe_del_wfd_ie(struct xmit_frame *xframe)3755{3756#define DBG_XFRAME_DEL_WFD_IE 03757u8 *frame = xframe->buf_addr + TXDESC_OFFSET;3758u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);3759u8 *frame_tail = frame + xframe->attrib.pktlen;3760u8 category, action, OUI_Subtype;3761u8 *ies = NULL;3762uint ies_len_ori = 0;3763uint ies_len = 0;37643765category = frame_body[0];3766if (category == RTW_WLAN_CATEGORY_PUBLIC) {3767action = frame_body[1];3768if (action == ACT_PUBLIC_VENDOR3769&& _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE3770) {3771OUI_Subtype = frame_body[6];37723773switch (OUI_Subtype) {3774case P2P_GO_NEGO_REQ:3775case P2P_GO_NEGO_RESP:3776case P2P_GO_NEGO_CONF:3777case P2P_INVIT_REQ:3778case P2P_INVIT_RESP:3779case P2P_PROVISION_DISC_REQ:3780case P2P_PROVISION_DISC_RESP:3781ies = frame_body + 8;3782ies_len_ori = frame_tail - (frame_body + 8);3783break;3784}3785}3786}37873788if (ies && ies_len_ori) {3789ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_XFRAME_DEL_WFD_IE ? __func__ : NULL);3790xframe->attrib.pktlen -= (ies_len_ori - ies_len);3791}37923793return ies_len_ori != ies_len;3794}37953796/*3797* rtw_xframe_chk_wfd_ie -3798*3799*/3800void rtw_xframe_chk_wfd_ie(struct xmit_frame *xframe)3801{3802_adapter *adapter = xframe->padapter;3803#ifdef CONFIG_IOCTL_CFG802113804struct wifidirect_info *wdinfo = &adapter->wdinfo;3805#endif3806u8 build = 0;3807u8 del = 0;38083809if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))3810del = 1;38113812#ifdef CONFIG_IOCTL_CFG802113813if (wdinfo->wfd_info->wfd_enable == _TRUE)3814#endif3815del = build = 1;38163817if (del)3818rtw_xframe_del_wfd_ie(xframe);38193820#ifdef CONFIG_WFD3821if (build)3822rtw_xframe_build_wfd_ie(xframe);3823#endif3824}38253826u8 *dump_p2p_attr_ch_list(u8 *p2p_ie, uint p2p_ielen, u8 *buf, u32 buf_len)3827{3828uint attr_contentlen = 0;3829u8 *pattr = NULL;3830int w_sz = 0;3831u8 ch_cnt = 0;3832u8 ch_list[40];38333834pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, &attr_contentlen);3835if (pattr != NULL) {3836int i, j;3837u32 num_of_ch;3838u8 *pattr_temp = pattr + 3 ;38393840attr_contentlen -= 3;38413842_rtw_memset(ch_list, 0, 40);38433844while (attr_contentlen > 0) {3845num_of_ch = *(pattr_temp + 1);38463847for (i = 0; i < num_of_ch; i++) {3848for (j = 0; j < ch_cnt; j++) {3849if (ch_list[j] == *(pattr_temp + 2 + i))3850break;3851}3852if (j >= ch_cnt)3853ch_list[ch_cnt++] = *(pattr_temp + 2 + i);38543855}38563857pattr_temp += (2 + num_of_ch);3858attr_contentlen -= (2 + num_of_ch);3859}38603861for (j = 0; j < ch_cnt; j++) {3862if (j == 0)3863w_sz += snprintf(buf + w_sz, buf_len - w_sz, "%u", ch_list[j]);3864else if (ch_list[j] - ch_list[j - 1] != 1)3865w_sz += snprintf(buf + w_sz, buf_len - w_sz, ", %u", ch_list[j]);3866else if (j != ch_cnt - 1 && ch_list[j + 1] - ch_list[j] == 1) {3867/* empty */3868} else3869w_sz += snprintf(buf + w_sz, buf_len - w_sz, "-%u", ch_list[j]);3870}3871}3872return buf;3873}38743875/*3876* return _TRUE if requester is GO, _FALSE if responder is GO3877*/3878bool rtw_p2p_nego_intent_compare(u8 req, u8 resp)3879{3880if (req >> 1 == resp >> 1)3881return req & 0x01 ? _TRUE : _FALSE;3882else if (req >> 1 > resp >> 1)3883return _TRUE;3884else3885return _FALSE;3886}38873888int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx)3889{3890int is_p2p_frame = (-1);3891unsigned char *frame_body;3892u8 category, action, OUI_Subtype, dialogToken = 0;3893u8 *p2p_ie = NULL;3894uint p2p_ielen = 0;3895struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);3896int status = -1;3897u8 ch_list_buf[128] = {'\0'};3898int op_ch = -1;3899int listen_ch = -1;3900u8 intent = 0;3901u8 *iaddr = NULL;3902u8 *gbssid = NULL;39033904frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));3905category = frame_body[0];3906/* just for check */3907if (category == RTW_WLAN_CATEGORY_PUBLIC) {3908action = frame_body[1];3909if (action == ACT_PUBLIC_VENDOR3910&& _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE3911) {3912OUI_Subtype = frame_body[6];3913dialogToken = frame_body[7];3914is_p2p_frame = OUI_Subtype;39153916#ifdef CONFIG_DEBUG_CFG802113917RTW_INFO("ACTION_CATEGORY_PUBLIC: ACT_PUBLIC_VENDOR, OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",3918cpu_to_be32(*((u32 *)(frame_body + 2))), OUI_Subtype, dialogToken);3919#endif39203921p2p_ie = rtw_get_p2p_ie(3922(u8 *)buf + sizeof(struct rtw_ieee80211_hdr_3addr) + _PUBLIC_ACTION_IE_OFFSET_3923, len - sizeof(struct rtw_ieee80211_hdr_3addr) - _PUBLIC_ACTION_IE_OFFSET_3924, NULL, &p2p_ielen);39253926switch (OUI_Subtype) { /* OUI Subtype */3927u8 *cont;3928uint cont_len;3929case P2P_GO_NEGO_REQ: {3930struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;39313932if (tx) {3933#ifdef CONFIG_DRV_ISSUE_PROV_REQ /* IOT FOR S2 */3934if (pwdev_priv->provdisc_req_issued == _FALSE)3935rtw_cfg80211_issue_p2p_provision_request(padapter, buf, len);3936#endif /* CONFIG_DRV_ISSUE_PROV_REQ */39373938/* pwdev_priv->provdisc_req_issued = _FALSE; */39393940#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)3941if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)3942rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));3943#endif3944}39453946cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);3947if (cont)3948op_ch = *(cont + 4);3949cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, NULL, &cont_len);3950if (cont)3951listen_ch = *(cont + 4);3952cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len);3953if (cont)3954intent = *cont;3955cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, NULL, &cont_len);3956if (cont && cont_len == 6)3957iaddr = cont;39583959if (nego_info->token != dialogToken)3960rtw_wdev_nego_info_init(nego_info);39613962_rtw_memcpy(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN);3963if (iaddr)3964_rtw_memcpy(tx ? nego_info->iface_addr : nego_info->peer_iface_addr, iaddr, ETH_ALEN);3965nego_info->active = tx ? 1 : 0;3966nego_info->token = dialogToken;3967nego_info->req_op_ch = op_ch;3968nego_info->req_listen_ch = listen_ch;3969nego_info->req_intent = intent;3970nego_info->state = 0;39713972dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);3973RTW_INFO("RTW_%s:P2P_GO_NEGO_REQ, dialogToken=%d, intent:%u%s, listen_ch:%d, op_ch:%d, ch_list:%s"3974, (tx == _TRUE) ? "Tx" : "Rx" , dialogToken , (intent >> 1) , intent & 0x1 ? "+" : "-" , listen_ch , op_ch , ch_list_buf);3975if (iaddr)3976_RTW_INFO(", iaddr:"MAC_FMT, MAC_ARG(iaddr));3977_RTW_INFO("\n");39783979if (!tx) {3980#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)3981if (rtw_mi_check_status(padapter, MI_LINKED)3982&& rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE3983&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {3984RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));3985rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);3986}3987#endif3988}39893990break;3991}3992case P2P_GO_NEGO_RESP: {3993struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;39943995if (tx) {3996#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)3997if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)3998rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));3999#endif4000}40014002cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);4003if (cont)4004op_ch = *(cont + 4);4005cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len);4006if (cont)4007intent = *cont;4008cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);4009if (cont)4010status = *cont;4011cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, NULL, &cont_len);4012if (cont && cont_len == 6)4013iaddr = cont;40144015if (nego_info->token == dialogToken && nego_info->state == 04016&& _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE4017) {4018if (iaddr)4019_rtw_memcpy(tx ? nego_info->iface_addr : nego_info->peer_iface_addr, iaddr, ETH_ALEN);4020nego_info->status = (status == -1) ? 0xff : status;4021nego_info->rsp_op_ch = op_ch;4022nego_info->rsp_intent = intent;4023nego_info->state = 1;4024if (status != 0)4025nego_info->token = 0; /* init */4026}40274028dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);4029RTW_INFO("RTW_%s:P2P_GO_NEGO_RESP, dialogToken=%d, intent:%u%s, status:%d, op_ch:%d, ch_list:%s"4030, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, (intent >> 1), intent & 0x1 ? "+" : "-", status, op_ch, ch_list_buf);4031if (iaddr)4032_RTW_INFO(", iaddr:"MAC_FMT, MAC_ARG(iaddr));4033_RTW_INFO("\n");40344035if (!tx) {4036pwdev_priv->provdisc_req_issued = _FALSE;4037#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)4038if (rtw_mi_check_status(padapter, MI_LINKED)4039&& rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE4040&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {4041RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));4042rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);4043}4044#endif4045}40464047break;4048}4049case P2P_GO_NEGO_CONF: {4050struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;4051bool is_go = _FALSE;40524053if (tx) {4054#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)4055if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)4056rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));4057#endif4058}40594060cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);4061if (cont)4062op_ch = *(cont + 4);4063cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);4064if (cont)4065status = *cont;40664067if (nego_info->token == dialogToken && nego_info->state == 14068&& _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE4069) {4070nego_info->status = (status == -1) ? 0xff : status;4071nego_info->conf_op_ch = (op_ch == -1) ? 0 : op_ch;4072nego_info->state = 2;40734074if (status == 0) {4075if (rtw_p2p_nego_intent_compare(nego_info->req_intent, nego_info->rsp_intent) ^ !tx)4076is_go = _TRUE;4077}40784079nego_info->token = 0; /* init */4080}40814082dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);4083RTW_INFO("RTW_%s:P2P_GO_NEGO_CONF, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n"4084, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, status, op_ch, ch_list_buf);40854086if (!tx) {4087}40884089break;4090}4091case P2P_INVIT_REQ: {4092struct rtw_wdev_invit_info *invit_info = &pwdev_priv->invit_info;4093int flags = -1;40944095if (tx) {4096#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)4097if (rtw_mi_check_status(padapter, MI_LINKED)4098&& padapter->registrypriv.full_ch_in_p2p_handshake == 0)4099rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));4100#endif4101}41024103cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len);4104if (cont)4105flags = *cont;4106cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);4107if (cont)4108op_ch = *(cont + 4);4109cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, NULL, &cont_len);4110if (cont && cont_len == 6)4111gbssid = cont;41124113if (invit_info->token != dialogToken)4114rtw_wdev_invit_info_init(invit_info);41154116_rtw_memcpy(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN);4117if (gbssid)4118_rtw_memcpy(invit_info->group_bssid, gbssid, ETH_ALEN);4119invit_info->active = tx ? 1 : 0;4120invit_info->token = dialogToken;4121invit_info->flags = (flags == -1) ? 0x0 : flags;4122invit_info->req_op_ch = op_ch;4123invit_info->state = 0;41244125dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);4126RTW_INFO("RTW_%s:P2P_INVIT_REQ, dialogToken=%d, flags:0x%02x, op_ch:%d, ch_list:%s"4127, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, flags, op_ch, ch_list_buf);4128if (gbssid)4129_RTW_INFO(", gbssid:"MAC_FMT, MAC_ARG(gbssid));4130_RTW_INFO("\n");41314132if (!tx) {4133#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)4134if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {4135#if defined(CONFIG_P2P_INVITE_IOT)4136if (op_ch != -1 && rtw_chk_p2pie_op_ch_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {4137RTW_INFO(FUNC_ADPT_FMT" op_ch:%u has no intersect with buddy\n", FUNC_ADPT_ARG(padapter), op_ch);4138rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);4139} else4140#endif4141if (rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {4142RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));4143rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);4144}4145}4146#endif4147}41484149break;4150}4151case P2P_INVIT_RESP: {4152struct rtw_wdev_invit_info *invit_info = &pwdev_priv->invit_info;41534154if (tx) {4155#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)4156if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)4157rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));4158#endif4159}41604161cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);4162if (cont) {4163#ifdef CONFIG_P2P_INVITE_IOT4164if (tx && *cont == 7) {4165RTW_INFO("TX_P2P_INVITE_RESP, status is no common channel, change to unknown group\n");4166*cont = 8; /* unknow group status */4167}4168#endif /* CONFIG_P2P_INVITE_IOT */4169status = *cont;4170}4171cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);4172if (cont)4173op_ch = *(cont + 4);4174cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, NULL, &cont_len);4175if (cont && cont_len == 6)4176gbssid = cont;41774178if (invit_info->token == dialogToken && invit_info->state == 04179&& _rtw_memcmp(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE4180) {4181invit_info->status = (status == -1) ? 0xff : status;4182invit_info->rsp_op_ch = op_ch;4183invit_info->state = 1;4184invit_info->token = 0; /* init */4185}41864187dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);4188RTW_INFO("RTW_%s:P2P_INVIT_RESP, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s"4189, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, status, op_ch, ch_list_buf);4190if (gbssid)4191_RTW_INFO(", gbssid:"MAC_FMT, MAC_ARG(gbssid));4192_RTW_INFO("\n");41934194if (!tx) {4195}41964197break;4198}4199case P2P_DEVDISC_REQ:4200RTW_INFO("RTW_%s:P2P_DEVDISC_REQ, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);4201break;4202case P2P_DEVDISC_RESP:4203cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);4204RTW_INFO("RTW_%s:P2P_DEVDISC_RESP, dialogToken=%d, status:%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken, cont ? *cont : -1);4205break;4206case P2P_PROVISION_DISC_REQ: {4207size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);4208u8 *p2p_ie;4209uint p2p_ielen = 0;4210uint contentlen = 0;42114212RTW_INFO("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);42134214/* if(tx) */4215{4216pwdev_priv->provdisc_req_issued = _FALSE;42174218p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);4219if (p2p_ie) {42204221if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, NULL, &contentlen)) {4222pwdev_priv->provdisc_req_issued = _FALSE;/* case: p2p_client join p2p GO */4223} else {4224#ifdef CONFIG_DEBUG_CFG802114225RTW_INFO("provdisc_req_issued is _TRUE\n");4226#endif /*CONFIG_DEBUG_CFG80211*/4227pwdev_priv->provdisc_req_issued = _TRUE;/* case: p2p_devices connection before Nego req. */4228}42294230}4231}4232}4233break;4234case P2P_PROVISION_DISC_RESP:4235RTW_INFO("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);4236break;4237default:4238RTW_INFO("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", OUI_Subtype, dialogToken);4239break;4240}42414242}42434244} else if (category == RTW_WLAN_CATEGORY_P2P) {4245OUI_Subtype = frame_body[5];4246dialogToken = frame_body[6];42474248#ifdef CONFIG_DEBUG_CFG802114249RTW_INFO("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",4250cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);4251#endif42524253is_p2p_frame = OUI_Subtype;42544255switch (OUI_Subtype) {4256case P2P_NOTICE_OF_ABSENCE:4257RTW_INFO("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);4258break;4259case P2P_PRESENCE_REQUEST:4260RTW_INFO("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);4261break;4262case P2P_PRESENCE_RESPONSE:4263RTW_INFO("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);4264break;4265case P2P_GO_DISC_REQUEST:4266RTW_INFO("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);4267break;4268default:4269RTW_INFO("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", OUI_Subtype, dialogToken);4270break;4271}42724273}42744275return is_p2p_frame;4276}42774278void rtw_init_cfg80211_wifidirect_info(_adapter *padapter)4279{4280struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;42814282_rtw_memset(pcfg80211_wdinfo, 0x00, sizeof(struct cfg80211_wifidirect_info));42834284rtw_init_timer(&pcfg80211_wdinfo->remain_on_ch_timer, padapter, ro_ch_timer_process, padapter);4285}4286#endif /* CONFIG_IOCTL_CFG80211 */42874288s32 p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)4289{4290int ret = H2C_SUCCESS;42914292switch (intCmdType) {4293case P2P_FIND_PHASE_WK:4294find_phase_handler(padapter);4295break;42964297case P2P_RESTORE_STATE_WK:4298restore_p2p_state_handler(padapter);4299break;43004301case P2P_PRE_TX_PROVDISC_PROCESS_WK:4302#ifdef CONFIG_CONCURRENT_MODE4303if (rtw_mi_check_status(padapter, MI_LINKED))4304p2p_concurrent_handler(padapter);4305else4306pre_tx_provdisc_handler(padapter);4307#else4308pre_tx_provdisc_handler(padapter);4309#endif4310break;43114312case P2P_PRE_TX_INVITEREQ_PROCESS_WK:4313#ifdef CONFIG_CONCURRENT_MODE4314if (rtw_mi_check_status(padapter, MI_LINKED))4315p2p_concurrent_handler(padapter);4316else4317pre_tx_invitereq_handler(padapter);4318#else4319pre_tx_invitereq_handler(padapter);4320#endif4321break;43224323case P2P_PRE_TX_NEGOREQ_PROCESS_WK:4324#ifdef CONFIG_CONCURRENT_MODE4325if (rtw_mi_check_status(padapter, MI_LINKED))4326p2p_concurrent_handler(padapter);4327else4328pre_tx_negoreq_handler(padapter);4329#else4330pre_tx_negoreq_handler(padapter);4331#endif4332break;43334334#ifdef CONFIG_CONCURRENT_MODE4335case P2P_AP_P2P_CH_SWITCH_PROCESS_WK:4336p2p_concurrent_handler(padapter);4337break;4338#endif43394340#ifdef CONFIG_IOCTL_CFG802114341case P2P_RO_CH_WK:4342ret = ro_ch_handler(padapter, buf);4343break;4344case P2P_CANCEL_RO_CH_WK:4345ret = cancel_ro_ch_handler(padapter, buf);4346break;4347#endif43484349default:4350rtw_warn_on(1);4351break;4352}43534354return ret;4355}43564357int process_p2p_cross_connect_ie(PADAPTER padapter, u8 *IEs, u32 IELength)4358{4359int ret = _TRUE;4360u8 *ies;4361u32 ies_len;4362u8 *p2p_ie;4363u32 p2p_ielen = 0;4364u8 p2p_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */4365u32 attr_contentlen = 0;4366436743684369if (IELength <= _BEACON_IE_OFFSET_)4370return ret;43714372ies = IEs + _BEACON_IE_OFFSET_;4373ies_len = IELength - _BEACON_IE_OFFSET_;43744375p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);43764377while (p2p_ie) {4378/* Get P2P Manageability IE. */4379if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_MANAGEABILITY, p2p_attr, &attr_contentlen)) {4380if ((p2p_attr[0] & (BIT(0) | BIT(1))) == 0x01)4381ret = _FALSE;4382break;4383}4384/* Get the next P2P IE */4385p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);4386}43874388return ret;4389}43904391#ifdef CONFIG_P2P_PS4392void process_p2p_ps_ie(PADAPTER padapter, u8 *IEs, u32 IELength)4393{4394u8 *ies;4395u32 ies_len;4396u8 *p2p_ie;4397u32 p2p_ielen = 0;4398u8 *noa_attr; /* NoA length should be n*(13) + 2 */4399u32 attr_contentlen = 0;44004401struct wifidirect_info *pwdinfo = &(padapter->wdinfo);4402u8 find_p2p = _FALSE, find_p2p_ps = _FALSE;4403u8 noa_offset, noa_num, noa_index;440444054406if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))4407return;4408#ifdef CONFIG_CONCURRENT_MODE4409#ifndef CONFIG_FW_MULTI_PORT_SUPPORT4410if (padapter->hw_port != HW_PORT0)4411return;4412#endif4413#endif4414if (IELength <= _BEACON_IE_OFFSET_)4415return;44164417ies = IEs + _BEACON_IE_OFFSET_;4418ies_len = IELength - _BEACON_IE_OFFSET_;44194420p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);44214422while (p2p_ie) {4423find_p2p = _TRUE;4424/* Get Notice of Absence IE. */4425noa_attr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, NULL, &attr_contentlen);4426if (noa_attr) {4427find_p2p_ps = _TRUE;4428noa_index = noa_attr[0];44294430if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||4431(noa_index != pwdinfo->noa_index)) { /* if index change, driver should reconfigure related setting. */4432pwdinfo->noa_index = noa_index;4433pwdinfo->opp_ps = noa_attr[1] >> 7;4434pwdinfo->ctwindow = noa_attr[1] & 0x7F;44354436noa_offset = 2;4437noa_num = 0;4438/* NoA length should be n*(13) + 2 */4439if (attr_contentlen > 2 && (attr_contentlen - 2) % 13 == 0) {4440while (noa_offset < attr_contentlen && noa_num < P2P_MAX_NOA_NUM) {4441/* _rtw_memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */4442pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];4443noa_offset += 1;44444445_rtw_memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);4446noa_offset += 4;44474448_rtw_memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);4449noa_offset += 4;44504451_rtw_memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);4452noa_offset += 4;44534454noa_num++;4455}4456}4457pwdinfo->noa_num = noa_num;44584459if (pwdinfo->opp_ps == 1) {4460pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;4461/* driver should wait LPS for entering CTWindow */4462if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)4463p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);4464} else if (pwdinfo->noa_num > 0) {4465pwdinfo->p2p_ps_mode = P2P_PS_NOA;4466p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);4467} else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)4468p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);4469}44704471break; /* find target, just break. */4472}44734474/* Get the next P2P IE */4475p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);44764477}44784479if (find_p2p == _TRUE) {4480if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == _FALSE))4481p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);4482}44834484}44854486void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state)4487{4488struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);4489struct wifidirect_info *pwdinfo = &(padapter->wdinfo);4490u32 ps_deny = 0;44914492/* Pre action for p2p state */4493switch (p2p_ps_state) {4494case P2P_PS_DISABLE:4495pwdinfo->p2p_ps_state = p2p_ps_state;44964497rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));44984499pwdinfo->noa_index = 0;4500pwdinfo->ctwindow = 0;4501pwdinfo->opp_ps = 0;4502pwdinfo->noa_num = 0;4503pwdinfo->p2p_ps_mode = P2P_PS_NONE;4504if (pwrpriv->bFwCurrentInPSMode == _TRUE) {4505if (pwrpriv->smart_ps == 0) {4506pwrpriv->smart_ps = 2;4507rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));4508}4509}4510break;4511case P2P_PS_ENABLE:4512_enter_pwrlock(&adapter_to_pwrctl(padapter)->lock);4513ps_deny = rtw_ps_deny_get(padapter);4514_exit_pwrlock(&adapter_to_pwrctl(padapter)->lock);45154516if ((ps_deny & (PS_DENY_SCAN | PS_DENY_JOIN))4517|| rtw_mi_check_fwstate(padapter, (_FW_UNDER_SURVEY | _FW_UNDER_LINKING))) {4518pwdinfo->p2p_ps_mode = P2P_PS_NONE;4519RTW_DBG(FUNC_ADPT_FMT" Block P2P PS under site survey or LINKING\n", FUNC_ADPT_ARG(padapter));4520return;4521}4522if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {4523#ifdef CONFIG_MCC_MODE4524if (MCC_EN(padapter)) {4525if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {4526RTW_INFO("P2P PS enble under MCC\n");4527rtw_warn_on(1);4528}45294530}4531#endif /* CONFIG_MCC_MODE */4532pwdinfo->p2p_ps_state = p2p_ps_state;45334534if (pwdinfo->ctwindow > 0) {4535if (pwrpriv->smart_ps != 0) {4536pwrpriv->smart_ps = 0;4537RTW_INFO("%s(): Enter CTW, change SmartPS\n", __FUNCTION__);4538rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));4539}4540}4541rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));4542}4543break;4544case P2P_PS_SCAN:4545case P2P_PS_SCAN_DONE:4546case P2P_PS_ALLSTASLEEP:4547if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {4548pwdinfo->p2p_ps_state = p2p_ps_state;4549rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));4550}4551break;4552default:4553break;4554}45554556#ifdef CONFIG_MCC_MODE4557rtw_hal_mcc_process_noa(padapter);4558#endif /* CONFIG_MCC_MODE */4559}45604561u8 p2p_ps_wk_cmd(_adapter *padapter, u8 p2p_ps_state, u8 enqueue)4562{4563struct cmd_obj *ph2c;4564struct drvextra_cmd_parm *pdrvextra_cmd_parm;4565struct wifidirect_info *pwdinfo = &(padapter->wdinfo);4566struct cmd_priv *pcmdpriv = &padapter->cmdpriv;4567u8 res = _SUCCESS;456845694570if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)4571#ifdef CONFIG_CONCURRENT_MODE4572#ifndef CONFIG_FW_MULTI_PORT_SUPPORT4573|| (padapter->hw_port != HW_PORT0)4574#endif4575#endif4576)4577return res;45784579if (enqueue) {4580ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));4581if (ph2c == NULL) {4582res = _FAIL;4583goto exit;4584}45854586pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));4587if (pdrvextra_cmd_parm == NULL) {4588rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));4589res = _FAIL;4590goto exit;4591}45924593pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;4594pdrvextra_cmd_parm->type = p2p_ps_state;4595pdrvextra_cmd_parm->size = 0;4596pdrvextra_cmd_parm->pbuf = NULL;45974598init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));45994600res = rtw_enqueue_cmd(pcmdpriv, ph2c);4601} else4602p2p_ps_wk_hdl(padapter, p2p_ps_state);46034604exit:460546064607return res;46084609}4610#endif /* CONFIG_P2P_PS */46114612static void reset_ch_sitesurvey_timer_process(void *FunctionContext)4613{4614_adapter *adapter = (_adapter *)FunctionContext;4615struct wifidirect_info *pwdinfo = &adapter->wdinfo;46164617if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))4618return;46194620RTW_INFO("[%s] In\n", __FUNCTION__);4621/* Reset the operation channel information */4622pwdinfo->rx_invitereq_info.operation_ch[0] = 0;4623#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH4624pwdinfo->rx_invitereq_info.operation_ch[1] = 0;4625pwdinfo->rx_invitereq_info.operation_ch[2] = 0;4626pwdinfo->rx_invitereq_info.operation_ch[3] = 0;4627#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */4628pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;4629}46304631static void reset_ch_sitesurvey_timer_process2(void *FunctionContext)4632{4633_adapter *adapter = (_adapter *)FunctionContext;4634struct wifidirect_info *pwdinfo = &adapter->wdinfo;46354636if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))4637return;46384639RTW_INFO("[%s] In\n", __FUNCTION__);4640/* Reset the operation channel information */4641pwdinfo->p2p_info.operation_ch[0] = 0;4642#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH4643pwdinfo->p2p_info.operation_ch[1] = 0;4644pwdinfo->p2p_info.operation_ch[2] = 0;4645pwdinfo->p2p_info.operation_ch[3] = 0;4646#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */4647pwdinfo->p2p_info.scan_op_ch_only = 0;4648}46494650static void restore_p2p_state_timer_process(void *FunctionContext)4651{4652_adapter *adapter = (_adapter *)FunctionContext;4653struct wifidirect_info *pwdinfo = &adapter->wdinfo;46544655if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))4656return;46574658p2p_protocol_wk_cmd(adapter, P2P_RESTORE_STATE_WK);4659}46604661static void pre_tx_scan_timer_process(void *FunctionContext)4662{4663_adapter *adapter = (_adapter *) FunctionContext;4664struct wifidirect_info *pwdinfo = &adapter->wdinfo;4665_irqL irqL;4666struct mlme_priv *pmlmepriv = &adapter->mlmepriv;46674668if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))4669return;46704671_enter_critical_bh(&pmlmepriv->lock, &irqL);467246734674if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {4675if (_TRUE == pwdinfo->tx_prov_disc_info.benable) { /* the provision discovery request frame is trigger to send or not */4676p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);4677/* issue_probereq_p2p(adapter, NULL); */4678/* _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); */4679}4680} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {4681if (_TRUE == pwdinfo->nego_req_info.benable)4682p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);4683} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {4684if (_TRUE == pwdinfo->invitereq_info.benable)4685p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);4686} else4687RTW_INFO("[%s] p2p_state is %d, ignore!!\n", __FUNCTION__, rtw_p2p_state(pwdinfo));46884689_exit_critical_bh(&pmlmepriv->lock, &irqL);4690}46914692static void find_phase_timer_process(void *FunctionContext)4693{4694_adapter *adapter = (_adapter *)FunctionContext;4695struct wifidirect_info *pwdinfo = &adapter->wdinfo;46964697if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))4698return;46994700adapter->wdinfo.find_phase_state_exchange_cnt++;47014702p2p_protocol_wk_cmd(adapter, P2P_FIND_PHASE_WK);4703}47044705#ifdef CONFIG_CONCURRENT_MODE4706void ap_p2p_switch_timer_process(void *FunctionContext)4707{4708_adapter *adapter = (_adapter *)FunctionContext;4709struct wifidirect_info *pwdinfo = &adapter->wdinfo;4710#ifdef CONFIG_IOCTL_CFG802114711struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);4712#endif47134714if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))4715return;47164717#ifdef CONFIG_IOCTL_CFG802114718ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);4719#endif47204721p2p_protocol_wk_cmd(adapter, P2P_AP_P2P_CH_SWITCH_PROCESS_WK);4722}4723#endif47244725void reset_global_wifidirect_info(_adapter *padapter)4726{4727struct wifidirect_info *pwdinfo;47284729pwdinfo = &padapter->wdinfo;4730pwdinfo->persistent_supported = 0;4731pwdinfo->session_available = _TRUE;4732rtw_tdls_wfd_enable(padapter, 0);4733pwdinfo->wfd_tdls_weaksec = _TRUE;4734}47354736#ifdef CONFIG_WFD4737int rtw_init_wifi_display_info(_adapter *padapter)4738{4739int res = _SUCCESS;4740struct wifi_display_info *pwfd_info = &padapter->wfd_info;47414742/* Used in P2P and TDLS */4743pwfd_info->init_rtsp_ctrlport = 554;4744#ifdef CONFIG_IOCTL_CFG802114745pwfd_info->rtsp_ctrlport = 0;4746#else4747pwfd_info->rtsp_ctrlport = pwfd_info->init_rtsp_ctrlport; /* set non-zero value for legacy wfd */4748#endif4749pwfd_info->tdls_rtsp_ctrlport = 0;4750pwfd_info->peer_rtsp_ctrlport = 0; /* Reset to 0 */4751pwfd_info->wfd_enable = _FALSE;4752pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;4753pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;47544755/* Used in P2P */4756pwfd_info->peer_session_avail = _TRUE;4757pwfd_info->wfd_pc = _FALSE;47584759/* Used in TDLS */4760_rtw_memset(pwfd_info->ip_address, 0x00, 4);4761_rtw_memset(pwfd_info->peer_ip_address, 0x00, 4);4762return res;47634764}47654766inline void rtw_wfd_enable(_adapter *adapter, bool on)4767{4768struct wifi_display_info *wfdinfo = &adapter->wfd_info;47694770if (on) {4771wfdinfo->rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;4772wfdinfo->wfd_enable = _TRUE;47734774} else {4775wfdinfo->wfd_enable = _FALSE;4776wfdinfo->rtsp_ctrlport = 0;4777}4778}47794780inline void rtw_wfd_set_ctrl_port(_adapter *adapter, u16 port)4781{4782struct wifi_display_info *wfdinfo = &adapter->wfd_info;47834784wfdinfo->init_rtsp_ctrlport = port;4785if (wfdinfo->wfd_enable == _TRUE)4786wfdinfo->rtsp_ctrlport = port;4787if (adapter->wdinfo.wfd_tdls_enable == 1)4788wfdinfo->tdls_rtsp_ctrlport = port;4789}47904791inline void rtw_tdls_wfd_enable(_adapter *adapter, bool on)4792{4793struct wifi_display_info *wfdinfo = &adapter->wfd_info;47944795if (on) {4796wfdinfo->tdls_rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;4797adapter->wdinfo.wfd_tdls_enable = 1;47984799} else {4800adapter->wdinfo.wfd_tdls_enable = 0;4801wfdinfo->tdls_rtsp_ctrlport = 0;4802}4803}48044805u32 rtw_append_beacon_wfd_ie(_adapter *adapter, u8 *pbuf)4806{4807struct wifidirect_info *wdinfo = &adapter->wdinfo;4808struct mlme_priv *mlme = &adapter->mlmepriv;4809u8 build_ie_by_self = 0;4810u32 len = 0;48114812if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))4813goto exit;48144815#ifdef CONFIG_IOCTL_CFG802114816if (_TRUE == wdinfo->wfd_info->wfd_enable)4817#endif4818build_ie_by_self = 1;48194820if (build_ie_by_self)4821len = build_beacon_wfd_ie(wdinfo, pbuf);4822#ifdef CONFIG_IOCTL_CFG802114823else if (mlme->wfd_beacon_ie && mlme->wfd_beacon_ie_len > 0) {4824len = mlme->wfd_beacon_ie_len;4825_rtw_memcpy(pbuf, mlme->wfd_beacon_ie, len);4826}4827#endif48284829exit:4830return len;4831}48324833u32 rtw_append_probe_req_wfd_ie(_adapter *adapter, u8 *pbuf)4834{4835struct wifidirect_info *wdinfo = &adapter->wdinfo;4836struct mlme_priv *mlme = &adapter->mlmepriv;4837u8 build_ie_by_self = 0;4838u32 len = 0;48394840if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))4841goto exit;48424843#ifdef CONFIG_IOCTL_CFG802114844if (_TRUE == wdinfo->wfd_info->wfd_enable)4845#endif4846build_ie_by_self = 1;48474848if (build_ie_by_self)4849len = build_probe_req_wfd_ie(wdinfo, pbuf);4850#ifdef CONFIG_IOCTL_CFG802114851else if (mlme->wfd_probe_req_ie && mlme->wfd_probe_req_ie_len > 0) {4852len = mlme->wfd_probe_req_ie_len;4853_rtw_memcpy(pbuf, mlme->wfd_probe_req_ie, len);4854}4855#endif48564857exit:4858return len;4859}48604861u32 rtw_append_probe_resp_wfd_ie(_adapter *adapter, u8 *pbuf)4862{4863struct wifidirect_info *wdinfo = &adapter->wdinfo;4864struct mlme_priv *mlme = &adapter->mlmepriv;4865u8 build_ie_by_self = 0;4866u32 len = 0;48674868if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))4869goto exit;48704871#ifdef CONFIG_IOCTL_CFG802114872if (_TRUE == wdinfo->wfd_info->wfd_enable)4873#endif4874build_ie_by_self = 1;48754876if (build_ie_by_self)4877len = build_probe_resp_wfd_ie(wdinfo, pbuf, 0);4878#ifdef CONFIG_IOCTL_CFG802114879else if (mlme->wfd_probe_resp_ie && mlme->wfd_probe_resp_ie_len > 0) {4880len = mlme->wfd_probe_resp_ie_len;4881_rtw_memcpy(pbuf, mlme->wfd_probe_resp_ie, len);4882}4883#endif48844885exit:4886return len;4887}48884889u32 rtw_append_assoc_req_wfd_ie(_adapter *adapter, u8 *pbuf)4890{4891struct wifidirect_info *wdinfo = &adapter->wdinfo;4892struct mlme_priv *mlme = &adapter->mlmepriv;4893u8 build_ie_by_self = 0;4894u32 len = 0;48954896if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))4897goto exit;48984899#ifdef CONFIG_IOCTL_CFG802114900if (_TRUE == wdinfo->wfd_info->wfd_enable)4901#endif4902build_ie_by_self = 1;49034904if (build_ie_by_self)4905len = build_assoc_req_wfd_ie(wdinfo, pbuf);4906#ifdef CONFIG_IOCTL_CFG802114907else if (mlme->wfd_assoc_req_ie && mlme->wfd_assoc_req_ie_len > 0) {4908len = mlme->wfd_assoc_req_ie_len;4909_rtw_memcpy(pbuf, mlme->wfd_assoc_req_ie, len);4910}4911#endif49124913exit:4914return len;4915}49164917u32 rtw_append_assoc_resp_wfd_ie(_adapter *adapter, u8 *pbuf)4918{4919struct wifidirect_info *wdinfo = &adapter->wdinfo;4920struct mlme_priv *mlme = &adapter->mlmepriv;4921u8 build_ie_by_self = 0;4922u32 len = 0;49234924if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))4925goto exit;49264927#ifdef CONFIG_IOCTL_CFG802114928if (_TRUE == wdinfo->wfd_info->wfd_enable)4929#endif4930build_ie_by_self = 1;49314932if (build_ie_by_self)4933len = build_assoc_resp_wfd_ie(wdinfo, pbuf);4934#ifdef CONFIG_IOCTL_CFG802114935else if (mlme->wfd_assoc_resp_ie && mlme->wfd_assoc_resp_ie_len > 0) {4936len = mlme->wfd_assoc_resp_ie_len;4937_rtw_memcpy(pbuf, mlme->wfd_assoc_resp_ie, len);4938}4939#endif49404941exit:4942return len;4943}49444945#endif /* CONFIG_WFD */49464947void rtw_init_wifidirect_timers(_adapter *padapter)4948{4949struct wifidirect_info *pwdinfo = &padapter->wdinfo;49504951rtw_init_timer(&pwdinfo->find_phase_timer, padapter, find_phase_timer_process, padapter);4952rtw_init_timer(&pwdinfo->restore_p2p_state_timer, padapter, restore_p2p_state_timer_process, padapter);4953rtw_init_timer(&pwdinfo->pre_tx_scan_timer, padapter, pre_tx_scan_timer_process, padapter);4954rtw_init_timer(&pwdinfo->reset_ch_sitesurvey, padapter, reset_ch_sitesurvey_timer_process, padapter);4955rtw_init_timer(&pwdinfo->reset_ch_sitesurvey2, padapter, reset_ch_sitesurvey_timer_process2, padapter);4956#ifdef CONFIG_CONCURRENT_MODE4957rtw_init_timer(&pwdinfo->ap_p2p_switch_timer, padapter, ap_p2p_switch_timer_process, padapter);4958#endif4959}49604961void rtw_init_wifidirect_addrs(_adapter *padapter, u8 *dev_addr, u8 *iface_addr)4962{4963#ifdef CONFIG_P2P4964struct wifidirect_info *pwdinfo = &padapter->wdinfo;49654966/*init device&interface address */4967if (dev_addr)4968_rtw_memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);4969if (iface_addr)4970_rtw_memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);4971#endif4972}49734974void init_wifidirect_info(_adapter *padapter, enum P2P_ROLE role)4975{4976struct wifidirect_info *pwdinfo;4977#ifdef CONFIG_WFD4978struct wifi_display_info *pwfd_info = &padapter->wfd_info;4979#endif4980pwdinfo = &padapter->wdinfo;49814982pwdinfo->padapter = padapter;49834984/* 1, 6, 11 are the social channel defined in the WiFi Direct specification. */4985pwdinfo->social_chan[0] = 1;4986pwdinfo->social_chan[1] = 6;4987pwdinfo->social_chan[2] = 11;4988pwdinfo->social_chan[3] = 0; /* channel 0 for scanning ending in site survey function. */49894990if (role != P2P_ROLE_DISABLE4991&& pwdinfo->driver_interface != DRIVER_CFG802114992) {4993#ifdef CONFIG_CONCURRENT_MODE4994u8 union_ch = 0;49954996if (rtw_mi_check_status(padapter, MI_LINKED))4997union_ch = rtw_mi_get_union_chan(padapter);49984999if (union_ch != 0 &&5000(union_ch == 1 || union_ch == 6 || union_ch == 11)5001) {5002/* Use the AP's channel as the listen channel */5003/* This will avoid the channel switch between AP's channel and listen channel */5004pwdinfo->listen_channel = union_ch;5005} else5006#endif /* CONFIG_CONCURRENT_MODE */5007{5008/* Use the channel 11 as the listen channel */5009pwdinfo->listen_channel = 11;5010}5011}50125013if (role == P2P_ROLE_DEVICE) {5014rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);5015#ifdef CONFIG_CONCURRENT_MODE5016if (rtw_mi_check_status(padapter, MI_LINKED))5017rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);5018else5019#endif5020rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);50215022pwdinfo->intent = 1;5023rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);5024} else if (role == P2P_ROLE_CLIENT) {5025rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);5026rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);5027pwdinfo->intent = 1;5028rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);5029} else if (role == P2P_ROLE_GO) {5030rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);5031rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);5032pwdinfo->intent = 15;5033rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);5034}50355036/* Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 ) */5037pwdinfo->support_rate[0] = 0x8c; /* 6(B) */5038pwdinfo->support_rate[1] = 0x92; /* 9(B) */5039pwdinfo->support_rate[2] = 0x18; /* 12 */5040pwdinfo->support_rate[3] = 0x24; /* 18 */5041pwdinfo->support_rate[4] = 0x30; /* 24 */5042pwdinfo->support_rate[5] = 0x48; /* 36 */5043pwdinfo->support_rate[6] = 0x60; /* 48 */5044pwdinfo->support_rate[7] = 0x6c; /* 54 */50455046_rtw_memcpy((void *) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);50475048_rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);5049pwdinfo->device_name_len = 0;50505051_rtw_memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));5052pwdinfo->invitereq_info.token = 3; /* Token used for P2P invitation request frame. */50535054_rtw_memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));5055pwdinfo->inviteresp_info.token = 0;50565057pwdinfo->profileindex = 0;5058_rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);50595060rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);50615062pwdinfo->listen_dwell = (u8)((rtw_get_current_time() % 3) + 1);5063/* RTW_INFO( "[%s] listen_dwell time is %d00ms\n", __FUNCTION__, pwdinfo->listen_dwell ); */50645065_rtw_memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));5066pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;50675068_rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));50695070pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;5071pwdinfo->negotiation_dialog_token = 1;50725073_rtw_memset(pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN);5074pwdinfo->nego_ssidlen = 0;50755076pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;5077#ifdef CONFIG_WFD5078pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC;5079pwdinfo->wfd_info = pwfd_info;5080#else5081pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;5082#endif /* CONFIG_WFD */5083pwdinfo->channel_list_attr_len = 0;5084_rtw_memset(pwdinfo->channel_list_attr, 0x00, 100);50855086_rtw_memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);5087_rtw_memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);5088_rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));5089#ifdef CONFIG_CONCURRENT_MODE5090#ifdef CONFIG_IOCTL_CFG802115091pwdinfo->ext_listen_interval = 1000; /* The interval to be available with legacy AP during p2p0-find/scan */5092pwdinfo->ext_listen_period = 3000; /* The time period to be available for P2P during nego */5093#else /* !CONFIG_IOCTL_CFG80211 */5094/* pwdinfo->ext_listen_interval = 3000; */5095/* pwdinfo->ext_listen_period = 400; */5096pwdinfo->ext_listen_interval = 1000;5097pwdinfo->ext_listen_period = 1000;5098#endif /* !CONFIG_IOCTL_CFG80211 */5099#endif51005101/* Commented by Kurt 201303195102* For WiDi purpose: Use CFG80211 interface but controled WFD/RDS frame by driver itself. */5103#ifdef CONFIG_IOCTL_CFG802115104pwdinfo->driver_interface = DRIVER_CFG80211;5105#else5106pwdinfo->driver_interface = DRIVER_WEXT;5107#endif /* CONFIG_IOCTL_CFG80211 */51085109pwdinfo->wfd_tdls_enable = 0;5110_rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);5111_rtw_memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);51125113pwdinfo->rx_invitereq_info.operation_ch[0] = 0;5114pwdinfo->rx_invitereq_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */5115#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH5116pwdinfo->rx_invitereq_info.operation_ch[2] = 0;5117pwdinfo->rx_invitereq_info.operation_ch[3] = 0;5118pwdinfo->rx_invitereq_info.operation_ch[4] = 0;5119#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */5120pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;5121pwdinfo->p2p_info.operation_ch[0] = 0;5122pwdinfo->p2p_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */5123#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH5124pwdinfo->p2p_info.operation_ch[2] = 0;5125pwdinfo->p2p_info.operation_ch[3] = 0;5126pwdinfo->p2p_info.operation_ch[4] = 0;5127#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */5128pwdinfo->p2p_info.scan_op_ch_only = 0;5129}51305131void _rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role)5132{5133if (wdinfo->role != role) {5134wdinfo->role = role;5135rtw_mi_update_iface_status(&(wdinfo->padapter->mlmepriv), 0);5136}5137}51385139#ifdef CONFIG_DBG_P2P51405141/**5142* rtw_p2p_role_txt - Get the p2p role name as a text string5143* @role: P2P role5144* Returns: The state name as a printable text string5145*/5146const char *rtw_p2p_role_txt(enum P2P_ROLE role)5147{5148switch (role) {5149case P2P_ROLE_DISABLE:5150return "P2P_ROLE_DISABLE";5151case P2P_ROLE_DEVICE:5152return "P2P_ROLE_DEVICE";5153case P2P_ROLE_CLIENT:5154return "P2P_ROLE_CLIENT";5155case P2P_ROLE_GO:5156return "P2P_ROLE_GO";5157default:5158return "UNKNOWN";5159}5160}51615162/**5163* rtw_p2p_state_txt - Get the p2p state name as a text string5164* @state: P2P state5165* Returns: The state name as a printable text string5166*/5167const char *rtw_p2p_state_txt(enum P2P_STATE state)5168{5169switch (state) {5170case P2P_STATE_NONE:5171return "P2P_STATE_NONE";5172case P2P_STATE_IDLE:5173return "P2P_STATE_IDLE";5174case P2P_STATE_LISTEN:5175return "P2P_STATE_LISTEN";5176case P2P_STATE_SCAN:5177return "P2P_STATE_SCAN";5178case P2P_STATE_FIND_PHASE_LISTEN:5179return "P2P_STATE_FIND_PHASE_LISTEN";5180case P2P_STATE_FIND_PHASE_SEARCH:5181return "P2P_STATE_FIND_PHASE_SEARCH";5182case P2P_STATE_TX_PROVISION_DIS_REQ:5183return "P2P_STATE_TX_PROVISION_DIS_REQ";5184case P2P_STATE_RX_PROVISION_DIS_RSP:5185return "P2P_STATE_RX_PROVISION_DIS_RSP";5186case P2P_STATE_RX_PROVISION_DIS_REQ:5187return "P2P_STATE_RX_PROVISION_DIS_REQ";5188case P2P_STATE_GONEGO_ING:5189return "P2P_STATE_GONEGO_ING";5190case P2P_STATE_GONEGO_OK:5191return "P2P_STATE_GONEGO_OK";5192case P2P_STATE_GONEGO_FAIL:5193return "P2P_STATE_GONEGO_FAIL";5194case P2P_STATE_RECV_INVITE_REQ_MATCH:5195return "P2P_STATE_RECV_INVITE_REQ_MATCH";5196case P2P_STATE_PROVISIONING_ING:5197return "P2P_STATE_PROVISIONING_ING";5198case P2P_STATE_PROVISIONING_DONE:5199return "P2P_STATE_PROVISIONING_DONE";5200case P2P_STATE_TX_INVITE_REQ:5201return "P2P_STATE_TX_INVITE_REQ";5202case P2P_STATE_RX_INVITE_RESP_OK:5203return "P2P_STATE_RX_INVITE_RESP_OK";5204case P2P_STATE_RECV_INVITE_REQ_DISMATCH:5205return "P2P_STATE_RECV_INVITE_REQ_DISMATCH";5206case P2P_STATE_RECV_INVITE_REQ_GO:5207return "P2P_STATE_RECV_INVITE_REQ_GO";5208case P2P_STATE_RECV_INVITE_REQ_JOIN:5209return "P2P_STATE_RECV_INVITE_REQ_JOIN";5210case P2P_STATE_RX_INVITE_RESP_FAIL:5211return "P2P_STATE_RX_INVITE_RESP_FAIL";5212case P2P_STATE_RX_INFOR_NOREADY:5213return "P2P_STATE_RX_INFOR_NOREADY";5214case P2P_STATE_TX_INFOR_NOREADY:5215return "P2P_STATE_TX_INFOR_NOREADY";5216default:5217return "UNKNOWN";5218}5219}52205221void dbg_rtw_p2p_set_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)5222{5223if (!_rtw_p2p_chk_state(wdinfo, state)) {5224enum P2P_STATE old_state = _rtw_p2p_state(wdinfo);5225_rtw_p2p_set_state(wdinfo, state);5226RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_state from %s to %s\n", caller, line5227, rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))5228);5229} else {5230RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_state to same state %s\n", caller, line5231, rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))5232);5233}5234}5235void dbg_rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)5236{5237if (_rtw_p2p_pre_state(wdinfo) != state) {5238enum P2P_STATE old_state = _rtw_p2p_pre_state(wdinfo);5239_rtw_p2p_set_pre_state(wdinfo, state);5240RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_pre_state from %s to %s\n", caller, line5241, rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))5242);5243} else {5244RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_pre_state to same state %s\n", caller, line5245, rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))5246);5247}5248}5249#if 05250void dbg_rtw_p2p_restore_state(struct wifidirect_info *wdinfo, const char *caller, int line)5251{5252if (wdinfo->pre_p2p_state != -1) {5253RTW_INFO("[CONFIG_DBG_P2P]%s:%d restore from %s to %s\n", caller, line5254, p2p_state_str[wdinfo->p2p_state], p2p_state_str[wdinfo->pre_p2p_state]5255);5256_rtw_p2p_restore_state(wdinfo);5257} else {5258RTW_INFO("[CONFIG_DBG_P2P]%s:%d restore no pre state, cur state %s\n", caller, line5259, p2p_state_str[wdinfo->p2p_state]5260);5261}5262}5263#endif5264void dbg_rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role, const char *caller, int line)5265{5266if (wdinfo->role != role) {5267enum P2P_ROLE old_role = wdinfo->role;5268_rtw_p2p_set_role(wdinfo, role);5269RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_role from %s to %s\n", caller, line5270, rtw_p2p_role_txt(old_role), rtw_p2p_role_txt(wdinfo->role)5271);5272} else {5273RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_role to same role %s\n", caller, line5274, rtw_p2p_role_txt(wdinfo->role)5275);5276}5277}5278#endif /* CONFIG_DBG_P2P */527952805281int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role)5282{5283int ret = _SUCCESS;5284struct wifidirect_info *pwdinfo = &(padapter->wdinfo);52855286if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT || role == P2P_ROLE_GO) {5287#if defined(CONFIG_CONCURRENT_MODE) && (!defined(RTW_P2P_GROUP_INTERFACE) || !RTW_P2P_GROUP_INTERFACE)5288/* Commented by Albert 2011/12/30 */5289/* The driver just supports 1 P2P group operation. */5290/* So, this function will do nothing if the buddy adapter had enabled the P2P function. */5291/*if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))5292return ret;*/5293/*The buddy adapter had enabled the P2P function.*/5294if (rtw_mi_buddy_stay_in_p2p_mode(padapter))5295return ret;5296#endif /* CONFIG_CONCURRENT_MODE */52975298/* leave IPS/Autosuspend */5299if (_FAIL == rtw_pwr_wakeup(padapter)) {5300ret = _FAIL;5301goto exit;5302}53035304/* Added by Albert 2011/03/22 */5305/* In the P2P mode, the driver should not support the b mode. */5306/* So, the Tx packet shouldn't use the CCK rate */5307#ifdef CONFIG_IOCTL_CFG802115308if (rtw_cfg80211_iface_has_p2p_group_cap(padapter))5309#endif5310update_tx_basic_rate(padapter, WIRELESS_11AGN);53115312/* Enable P2P function */5313init_wifidirect_info(padapter, role);53145315#ifdef CONFIG_IOCTL_CFG802115316if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)5317adapter_wdev_data(padapter)->p2p_enabled = _TRUE;5318#endif53195320rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, _TRUE);5321#ifdef CONFIG_WFD5322if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))5323rtw_hal_set_odm_var(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, _TRUE);5324#endif53255326} else if (role == P2P_ROLE_DISABLE) {53275328#ifdef CONFIG_IOCTL_CFG802115329if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)5330adapter_wdev_data(padapter)->p2p_enabled = _FALSE;5331#endif53325333pwdinfo->listen_channel = 0;53345335/* Disable P2P function */5336if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {5337_cancel_timer_ex(&pwdinfo->find_phase_timer);5338_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);5339_cancel_timer_ex(&pwdinfo->pre_tx_scan_timer);5340_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);5341_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey2);5342reset_ch_sitesurvey_timer_process(padapter);5343reset_ch_sitesurvey_timer_process2(padapter);5344#ifdef CONFIG_CONCURRENT_MODE5345_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);5346#endif5347rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);5348rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_NONE);5349rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);5350_rtw_memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));53515352/* Remove profiles in wifidirect_info structure. */5353_rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);5354pwdinfo->profileindex = 0;5355}53565357rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, _FALSE);5358#ifdef CONFIG_WFD5359if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))5360rtw_hal_set_odm_var(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, _FALSE);5361#endif53625363if (_FAIL == rtw_pwr_wakeup(padapter)) {5364ret = _FAIL;5365goto exit;5366}53675368/* Restore to initial setting. */5369update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);53705371/* For WiDi purpose. */5372#ifdef CONFIG_IOCTL_CFG802115373pwdinfo->driver_interface = DRIVER_CFG80211;5374#else5375pwdinfo->driver_interface = DRIVER_WEXT;5376#endif /* CONFIG_IOCTL_CFG80211 */53775378}53795380exit:5381return ret;5382}53835384#endif /* CONFIG_P2P */538553865387