summaryrefslogtreecommitdiff
path: root/network/wlan/WDI/COMMON/P2P_Build_PublicAction.c
diff options
context:
space:
mode:
authorAdam Shapiro <[email protected]>2016-02-04 13:02:45 -0800
committerAdam Shapiro <[email protected]>2016-02-04 13:02:45 -0800
commit3c8ac8624f815e66b370ef412bbf13cbd2c732e2 (patch)
tree9e1e9654be00272763677a6fe6891f7cb5fb4995 /network/wlan/WDI/COMMON/P2P_Build_PublicAction.c
parent921231effe018f3939f5b67fc7e44560aa6f3998 (diff)
WDI Sample
Adding WDI sample from partner enablement-China
Diffstat (limited to 'network/wlan/WDI/COMMON/P2P_Build_PublicAction.c')
-rw-r--r--network/wlan/WDI/COMMON/P2P_Build_PublicAction.c1060
1 files changed, 1060 insertions, 0 deletions
diff --git a/network/wlan/WDI/COMMON/P2P_Build_PublicAction.c b/network/wlan/WDI/COMMON/P2P_Build_PublicAction.c
new file mode 100644
index 00000000..a048e74d
--- /dev/null
+++ b/network/wlan/WDI/COMMON/P2P_Build_PublicAction.c
@@ -0,0 +1,1060 @@
+#include "Mp_Precomp.h"
+
+#if WPP_SOFTWARE_TRACE
+#include "P2P_Build_PublicAction.tmh"
+#endif
+
+#include "P2P_Internal.h"
+
+#if (P2P_SUPPORT == 1)
+
+//-----------------------------------------------------------------------------
+// Local
+//-----------------------------------------------------------------------------
+
+static
+VOID
+p2p_build_GoNegReqIe(
+ IN FRAME_BUF *pBuf,
+ IN P2P_INFO *pP2PInfo
+ )
+{
+ pu1Byte pLen = NULL;
+ u1Byte grpCap = 0;
+ P2P_WPS_ATTRIBUTES *pWps = &pP2PInfo->WpsAttributes;
+
+ u1Byte intent = 0;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) return;
+
+ if(p2p_ActingAs_Go(pP2PInfo))
+ RT_TRACE_F(COMP_P2P, DBG_WARNING, ("Invalid role\n"));
+
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ {
+ grpCap = (u1Byte)pP2PInfo->NegotiationRequestGroupCapability;
+ }
+ else
+ grpCap = pP2PInfo->GroupCapability;
+
+ P2PAttr_Make_Capability(pBuf,
+ pP2PInfo->DeviceCapability & ~P2P_DEV_CAP_CLIENT_DISCOVERABILITY, // this cap valid only in P2P Group Info and AssocReq
+ grpCap);
+
+ if(pP2PInfo->ConnectionContext.bProbePeerChannelList)
+ intent = 0; // make sure that peer will become the GO, note that the tie breaker bit is 0
+ else
+ intent = pP2PInfo->GOIntent;
+ P2PAttr_Make_GoIntent(pBuf, intent);
+
+ P2PAttr_Make_ConfigTimeout(pBuf, pP2PInfo->GOConfigurationTimeout, pP2PInfo->ClientConfigurationTimeout);
+ P2PAttr_Make_ListenChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, pP2PInfo->ListenChannel);
+ P2PAttr_Make_ExtListenTiming(pBuf, pP2PInfo->ExtListenTimingDuration, pP2PInfo->ExtListenTimingPeriod);
+ P2PAttr_Make_IntendedIntfAddr(pBuf, pP2PInfo->InterfaceAddress);
+
+ P2PAttr_Make_ChannelList(pBuf, pP2PInfo, &pP2PInfo->ChannelEntryList);
+
+ P2PAttr_Make_DevInfo(pBuf,
+ pP2PInfo->DeviceAddress,
+ pWps->ConfigMethod,
+ &pWps->PrimaryDeviceType,
+ pWps->SecondaryDeviceTypeLength, pWps->SecondaryDeviceTypeList,
+ pWps->DeviceNameLength, pWps->DeviceName);
+
+ P2PAttr_Make_OperatingChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, pP2PInfo->OperatingChannel);
+ //RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Op Chnl: %d\n", pP2PInfo->OperatingChannel));
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+
+ return;
+}
+
+static
+VOID
+p2p_build_GoNegRspIe(
+ IN FRAME_BUF *pBuf,
+ IN P2P_INFO *pP2PInfo,
+ IN const u1Byte *da
+ )
+{
+ pu1Byte pLen = NULL;
+ u1Byte grpCap = 0;
+ PP2P_WPS_ATTRIBUTES pWps = &pP2PInfo->WpsAttributes;
+
+ u1Byte status = 0;
+ u1Byte intent = 0;
+ pu1Byte pGrpDevAddr = NULL;
+ pu1Byte pGrpSsidBuf = NULL;
+ u1Byte grpSsidLen = 0;
+
+ const P2P_DEV_LIST_ENTRY *pDev = NULL;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) return;
+
+ pDev = p2p_DevList_Find(&pP2PInfo->devList, da, P2P_DEV_TYPE_DEV);
+
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ status = pP2PInfo->NegotiationResponseStatus;
+ else
+ status = pP2PInfo->Status;
+ P2PAttr_Make_Status(pBuf, status);
+
+ if(p2p_ActingAs_Go(pP2PInfo))
+ RT_TRACE_F(COMP_P2P, DBG_WARNING, ("Invalid role\n"));
+
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ {
+ grpCap = (u1Byte)pP2PInfo->NegotiationResponseGroupCapability;
+ }
+ else
+ grpCap = pP2PInfo->GroupCapability;
+
+ P2PAttr_Make_Capability(pBuf,
+ pP2PInfo->DeviceCapability & ~P2P_DEV_CAP_CLIENT_DISCOVERABILITY, // this cap valid only in P2P Group Info and AssocReq
+ grpCap);
+
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ {
+ intent = pP2PInfo->GOIntent;
+ }
+ else
+ {
+ // TODO: this is bad doing jobs other than making IE here!!!
+ // The tie breaker bit in a GONRsp shall be toggled from the corresponding GONReq
+ //
+ pP2PInfo->GOIntent = (pP2PInfo->GOIntent | !(pP2PInfo->ConnectionContext.ConnectingDevice.GOIntent & 0x01));
+
+ intent = pP2PInfo->GOIntent;
+ }
+
+ P2PAttr_Make_GoIntent(pBuf, intent);
+
+ P2PAttr_Make_ConfigTimeout(pBuf, pP2PInfo->GOConfigurationTimeout, pP2PInfo->ClientConfigurationTimeout);
+ P2PAttr_Make_IntendedIntfAddr(pBuf, pP2PInfo->InterfaceAddress);
+
+ if(pP2PInfo->ConnectionContext.bGoingToBeGO)
+ P2PAttr_Make_ChannelList(pBuf, pP2PInfo, &pDev->p2p->commonChannels);
+ else
+ P2PAttr_Make_ChannelList(pBuf, pP2PInfo, &pP2PInfo->ChannelEntryList);
+
+ P2PAttr_Make_DevInfo(pBuf,
+ pP2PInfo->DeviceAddress,
+ pWps->ConfigMethod,
+ &pWps->PrimaryDeviceType,
+ pWps->SecondaryDeviceTypeLength, pWps->SecondaryDeviceTypeList,
+ pWps->DeviceNameLength, pWps->DeviceName);
+
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ {
+ if(pP2PInfo->bNegotiationResponseUseGroupID)
+ {
+ pGrpDevAddr = pP2PInfo->NegotiationResponseGroupIDDeviceAddress;
+ pGrpSsidBuf = pP2PInfo->NegotiationResponseGroupIDSSID;
+ grpSsidLen = pP2PInfo->uNegotiationResponseGroupIDSSIDLength;
+ }
+ }
+ else
+ {
+ if(pP2PInfo->ConnectionContext.bGoingToBeGO &&
+ P2P_STATUS_SUCCESS == pP2PInfo->ConnectionContext.Status)
+ {
+ pGrpDevAddr = pP2PInfo->DeviceAddress;
+ pGrpSsidBuf = pP2PInfo->SSIDBuf;
+ grpSsidLen = pP2PInfo->SSIDLen;
+ }
+ }
+
+ if(pGrpDevAddr)
+ P2PAttr_Make_GroupId(pBuf, pGrpDevAddr, pGrpSsidBuf, grpSsidLen);
+
+ //
+ // Going to be GO:
+ // The Operating Channel attribute shall indicate the intended Operating Channel
+ // of the P2P Group. The channel indicated in the Operating Channel attribute shall
+ // be one of the channels in the Channel List attribute in the GO Negotiation Response
+ // frame.
+ //
+ // Going to be Client:
+ // The Operating Channel attribute may indicate a preferred Operating Channel of the
+ // P2P Group, or may be omitted. Any channel indicated in the Operating Channel attribute
+ // shall be one of the channels in the Channel List attribute in the GO Negotiation Response frame.
+ //
+ P2PAttr_Make_OperatingChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, pP2PInfo->OperatingChannel);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+
+ return;
+}
+
+static
+VOID
+p2p_build_GoNegConfIe(
+ IN FRAME_BUF *pBuf,
+ IN P2P_INFO *pP2PInfo,
+ IN const u1Byte *da
+ )
+{
+ pu1Byte pLen = NULL;
+ u1Byte grpCap = 0;
+
+ u1Byte status = 0;
+ pu1Byte pGrpDevAddr = NULL;
+ pu1Byte pGrpSsidBuf = NULL;
+ u1Byte grpSsidLen = 0;
+ u1Byte opChannel = 0;
+
+ const P2P_DEV_LIST_ENTRY *pDev = NULL;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) return;
+
+ pDev = p2p_DevList_Find(&pP2PInfo->devList, da, P2P_DEV_TYPE_DEV);
+
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ status = pP2PInfo->NegotiationConfirmStatus;
+ else
+ status = pP2PInfo->Status;
+ P2PAttr_Make_Status(pBuf, pP2PInfo->Status);
+
+ if(p2p_ActingAs_Go(pP2PInfo))
+ RT_TRACE_F(COMP_P2P, DBG_WARNING, ("Invalid role\n"));
+
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ {
+ grpCap = (u1Byte)pP2PInfo->NegotiationConfirmGroupCapability;
+ }
+ else
+ grpCap = pP2PInfo->GroupCapability;
+
+ P2PAttr_Make_Capability(pBuf,
+ pP2PInfo->DeviceCapability & ~P2P_DEV_CAP_CLIENT_DISCOVERABILITY, // this cap valid only in P2P Group Info and AssocReq
+ grpCap);
+
+ P2PAttr_Make_ChannelList(pBuf, pP2PInfo, &pDev->p2p->commonChannels);
+
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ {
+ if(pP2PInfo->bNegotiationConfirmUseGroupID)
+ {
+ pGrpDevAddr = pP2PInfo->NegotiationConfirmGroupIDDeviceAddress;
+ pGrpSsidBuf = pP2PInfo->NegotiationConfirmGroupIDSSID;
+ grpSsidLen = pP2PInfo->uNegotiationConfirmGroupIDSSIDLength;
+ }
+ }
+ else
+ {
+ if(pP2PInfo->ConnectionContext.bGoingToBeGO &&
+ P2P_STATUS_SUCCESS == pP2PInfo->ConnectionContext.Status)
+ {
+ pGrpDevAddr = pP2PInfo->DeviceAddress;
+ pGrpSsidBuf = pP2PInfo->SSIDBuf;
+ grpSsidLen = pP2PInfo->SSIDLen;
+ }
+ }
+
+ if(pGrpDevAddr)
+ P2PAttr_Make_GroupId(pBuf, pGrpDevAddr, pGrpSsidBuf, grpSsidLen);
+
+ //
+ // Going to be GO:
+ // The Operating Channel attribute shall indicate the intended Operating Channel of the
+ // P2P Group. The channel indicated in the Operating Channel attribute shall be one of the
+ // channels in the Channel List attribute in the GO Negotiation Confirmation frame.
+ //
+ // Going to be Client:
+ // The Operating Channel attribute in the GO Negotiation Confirmation frame shall be the
+ // Operating Channel attribute from the GO Negotiation Response frame.
+ //
+ if(pP2PInfo->ConnectionContext.bGoingToBeGO)
+ {
+ opChannel = pP2PInfo->OperatingChannel;
+ }
+ else
+ {//Chnl from the GONRsp
+ opChannel = pP2PInfo->ConnectionContext.ConnectingDevice.OperatingChannel;
+ }
+
+ P2PAttr_Make_OperatingChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, opChannel);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+
+ return;
+}
+
+static
+VOID
+p2p_build_InvitationReqIe(
+ IN FRAME_BUF *pBuf,
+ IN P2P_INFO *pP2PInfo,
+ IN const u1Byte *da
+ )
+{
+ pu1Byte pLen = NULL;
+ PP2P_WPS_ATTRIBUTES pWps = &pP2PInfo->WpsAttributes;
+
+ u1Byte goTimeout = 0;
+ u1Byte cliTimeout = 0;
+ u1Byte opChannel = 0;
+ u1Byte invitFlag = 0;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) return;
+
+ if(pP2PInfo->InvitationContext.bPersistentInvitation)
+ {// in persistent case, we have to tell the peer our conf time
+ // No matter GO or client, we fill them with the max value
+ goTimeout = pP2PInfo->GOConfigurationTimeout;
+ cliTimeout = pP2PInfo->ClientConfigurationTimeout;
+ }
+ else
+ {// otherwise, we're either a GO or client in operating phase, wo we don't have to fill the conf time
+ // Ref Clause 3.1.5.1, a normal invitation always have them to be 0
+ goTimeout = 0;
+ cliTimeout = 0;
+ }
+ P2PAttr_Make_ConfigTimeout(pBuf, goTimeout, cliTimeout);
+
+ P2PAttr_Make_GroupBssid(pBuf, pP2PInfo->InvitationContext.GroupBssid);
+
+ P2PAttr_Make_ChannelList(pBuf, pP2PInfo, &pP2PInfo->ChannelEntryList);
+
+ P2PAttr_Make_DevInfo(pBuf,
+ pP2PInfo->DeviceAddress,
+ pWps->ConfigMethod,
+ &pWps->PrimaryDeviceType,
+ pWps->SecondaryDeviceTypeLength,
+ pWps->SecondaryDeviceTypeList,
+ pWps->DeviceNameLength,
+ pWps->DeviceName);
+
+ P2PAttr_Make_GroupId(pBuf,
+ pP2PInfo->InvitationContext.GODeviceAddress,
+ pP2PInfo->InvitationContext.SsidBuf,
+ pP2PInfo->InvitationContext.SsidLen);
+
+ //
+ // GO:
+ // the Operating Channel attribute indicates the Operating Channel of the P2P Group
+ //
+ // Peristent GO:
+ // the Operating Channel attribute indicates the intended Operating Channel of the P2P Group
+ //
+ // Client:
+ // an Operating Channel attribute shall also be present, indicating the Operating Channel of the P2P Group
+ //
+ // Persistent Client:
+ // an Operating Channel attribute may be present to indicate a preferred Operating Channel
+ //
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)
+ && 0 != pP2PInfo->uInvitationRequestOperatingChannelNumber
+ )
+ {
+ opChannel = (u1Byte)pP2PInfo->uInvitationRequestOperatingChannelNumber;
+ }
+ else
+ {
+ if(pP2PInfo->InvitationContext.bPersistentInvitation)
+ {
+ if(0 == pP2PInfo->InvitationContext.OpChannel)
+ {// follow op ch
+ opChannel = pP2PInfo->OperatingChannel;
+ }
+ else
+ {// forced op ch
+ opChannel = pP2PInfo->InvitationContext.OpChannel;
+ }
+ }
+ else
+ {
+ opChannel = pP2PInfo->InvitationContext.OpChannel;
+ }
+ }
+
+ P2PAttr_Make_OperatingChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, opChannel);
+
+ if(pP2PInfo->InvitationContext.bPersistentInvitation)
+ SET_FLAG(invitFlag, P2P_INVITATION_FLAGS_TYPE);
+
+ P2PAttr_Make_InvitationFlags(pBuf, invitFlag);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+
+ return;
+}
+
+static
+VOID
+p2p_build_InvitationRspIe(
+ IN FRAME_BUF *pBuf,
+ IN P2P_INFO *pP2PInfo,
+ IN const u1Byte *da
+ )
+{
+ pu1Byte pLen = NULL;
+
+ u1Byte status = 0;
+ u1Byte goTimeout = 0;
+ u1Byte cliTimeout = 0;
+ u1Byte opChannel = 0;
+
+ const P2P_DEV_LIST_ENTRY *pDev = NULL;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) return;
+
+ pDev = p2p_DevList_Find(&pP2PInfo->devList, da, P2P_DEV_TYPE_DEV);
+
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ status = pP2PInfo->InvitationResponseStatus;
+ else
+ status = pP2PInfo->Status;
+
+ P2PAttr_Make_Status(pBuf, status);
+
+ if(pP2PInfo->InvitationContext.bPersistentInvitation)
+ {// in persistent case, we have to tell the peer our conf time
+ // No matter GO or client, we fill them with the max value
+ goTimeout = pP2PInfo->GOConfigurationTimeout;
+ cliTimeout = pP2PInfo->ClientConfigurationTimeout;
+ }
+ else
+ {// non persistent case
+ goTimeout = 0;
+ cliTimeout = 0;
+ }
+ P2PAttr_Make_ConfigTimeout(pBuf, goTimeout, cliTimeout);
+
+ P2PAttr_Make_GroupBssid(pBuf, pP2PInfo->InvitationContext.GroupBssid);
+
+ P2PAttr_Make_ChannelList(pBuf, pP2PInfo, &pDev->p2p->commonChannels);
+
+ //
+ // GO or Persisstent GO:
+ // intended Operating Channel
+ //
+ // Client or Persistent Client (optional):
+ // not specified in the spec
+ //
+ if(pP2PInfo->InvitationContext.bPersistentInvitation)
+ {
+ //
+ // if GO => intended op chnl, shall be one of the channels in the channel list in the InvitationReq
+ // if Client => intended op chnl.
+ //
+ if(P2P_CLIENT == pP2PInfo->InvitationContext.InvitorRole // peer is Cli
+ && pP2PInfo->InvitationContext.bPersistentInvitation // persistent
+ )
+ {// I'm persistent GO
+ opChannel = pP2PInfo->InvitationContext.OpChannel;
+ }
+ else
+ {
+ opChannel = pP2PInfo->InvitationContext.InvitedDevice.OperatingChannel;
+ }
+ }
+ else
+ {// we are invited
+ //
+ // Not defined in the spec.
+ // Follow the op channel of the peer.
+ //
+ opChannel = pP2PInfo->InvitationContext.InvitedDevice.OperatingChannel;
+ }
+
+ P2PAttr_Make_OperatingChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, opChannel);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+
+ return;
+}
+
+static
+VOID
+p2p_build_DevDiscReqIe(
+ IN FRAME_BUF *pBuf,
+ IN P2P_INFO *pP2PInfo
+ )
+{
+ pu1Byte pLen = NULL;
+
+ PP2P_DEVICE_DISCOVERABILITY_CONTEXT pDevDiscContext = &pP2PInfo->DeviceDiscoverabilityContext;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) return;
+
+ P2PAttr_Make_DevId(pBuf, pP2PInfo->DeviceDiscoverabilityContext.ClientDeviceAddress);
+ P2PAttr_Make_GroupId(pBuf, pDevDiscContext->GODeviceAddr, pP2PInfo->SSIDBuf, pP2PInfo->SSIDLen);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+
+ return;
+}
+
+static
+VOID
+p2p_build_DevDiscRspIe(
+ IN FRAME_BUF *pBuf,
+ IN P2P_INFO *pP2PInfo,
+ IN u1Byte status
+ )
+{
+ pu1Byte pLen = NULL;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) return;
+
+ P2PAttr_Make_Status(pBuf, status);
+ p2p_update_IeHdrLen(pBuf, pLen);
+
+ return;
+}
+
+static
+VOID
+p2p_build_PdReqIe(
+ IN FRAME_BUF *pBuf,
+ IN P2P_INFO *pP2PInfo
+ )
+{
+ pu1Byte pLen = NULL;
+ PP2P_WPS_ATTRIBUTES pWps = &pP2PInfo->WpsAttributes;
+ u1Byte grpCap = 0;
+
+ pu1Byte pGrpDevAddr = NULL;
+ pu1Byte pGrpSsidBuf = NULL;
+ u1Byte grpSsidLen = 0;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) return;
+
+ if(p2p_ActingAs_Go(pP2PInfo))
+ RT_TRACE_F(COMP_P2P, DBG_WARNING, ("Invalid role\n"));
+
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ {
+ grpCap = (u1Byte)pP2PInfo->ProvisionRequestGroupCapability;
+ }
+ else
+ grpCap = pP2PInfo->GroupCapability;
+
+ P2PAttr_Make_Capability(pBuf,
+ pP2PInfo->DeviceCapability & ~P2P_DEV_CAP_CLIENT_DISCOVERABILITY, // this cap valid only in P2P Group Info and AssocReq
+ grpCap);
+
+ P2PAttr_Make_DevInfo(pBuf,
+ pP2PInfo->DeviceAddress,
+ pWps->ConfigMethod,
+ &pWps->PrimaryDeviceType,
+ pWps->SecondaryDeviceTypeLength,
+ pWps->SecondaryDeviceTypeList,
+ pWps->DeviceNameLength,
+ pWps->DeviceName);
+
+ if(pP2PInfo->ProvisionDiscoveryContext.go)
+ {// connecting to GO
+ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter))
+ {
+ if(pP2PInfo->bProvisionRequestUseGroupID)
+ {
+ pGrpDevAddr = pP2PInfo->ProvisionRequestGroupIDDeviceAddress;
+ pGrpSsidBuf = pP2PInfo->ProvisionRequestGroupIDSSID;
+ grpSsidLen = pP2PInfo->uProvisionRequestGroupIDSSIDLength;
+ }
+ }
+ else
+ {
+ pGrpDevAddr = pP2PInfo->ProvisionDiscoveryContext.devAddr;
+ pGrpSsidBuf = pP2PInfo->ProvisionDiscoveryContext.SsidBuf;
+ grpSsidLen = pP2PInfo->ProvisionDiscoveryContext.SsidLen;
+ }
+
+ if(pGrpDevAddr)
+ P2PAttr_Make_GroupId(pBuf, pGrpDevAddr, pGrpSsidBuf, grpSsidLen);
+ }
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+
+ return;
+}
+
+static
+VOID
+p2p_build_PdRspIe(
+ IN FRAME_BUF *pBuf,
+ IN P2P_INFO *pP2PInfo
+ )
+{
+ /* Nothing to Append */
+ return;
+}
+
+static
+VOID
+p2p_add_WpsIeConfigMethods(
+ IN FRAME_BUF *pBuf,
+ IN u2Byte configMethods
+ )
+{
+ pu1Byte pLen = NULL;
+
+ FrameBuf_Add_u1(pBuf, (u1Byte)EID_Vendor);
+
+ pLen = FrameBuf_Add(pBuf, 1);
+
+ FrameBuf_Add_be_u4(pBuf, 0x0050F204);
+
+ // Version
+ FrameBuf_Add_be_u2(pBuf, P2P_WPS_ATTR_TAG_VERSION);
+ FrameBuf_Add_be_u2(pBuf, 1);
+ FrameBuf_Add_u1(pBuf, 0x10);
+
+ // Config Method
+ FrameBuf_Add_be_u2(pBuf, P2P_WPS_ATTR_TAG_CONFIG_METHODS);
+ FrameBuf_Add_be_u2(pBuf, 2);
+ FrameBuf_Add_be_u2(pBuf, configMethods);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+
+ return;
+}
+
+//-----------------------------------------------------------------------------
+// Exported
+//-----------------------------------------------------------------------------
+
+VOID
+p2p_add_P2PPublicActionHdr(
+ IN FRAME_BUF *pBuf,
+ IN u1Byte subtype,
+ IN u1Byte dialogToken
+ )
+{
+ RT_TRACE_F(COMP_P2P, pBuf->dbgLevel, ("token: %u\n", dialogToken));
+
+ FrameBuf_Add_u1(pBuf, WLAN_ACTION_PUBLIC);
+ FrameBuf_Add_u1(pBuf, WLAN_PA_VENDOR_SPECIFIC);
+ FrameBuf_Add_be_u4(pBuf, P2P_IE_VENDOR_TYPE);
+ FrameBuf_Add_u1(pBuf, subtype);
+ FrameBuf_Add_u1(pBuf, dialogToken);
+
+ return;
+}
+
+VOID
+p2p_Construct_GoNegReq(
+ IN P2P_INFO *pP2PInfo,
+ IN FRAME_BUF *pBuf,
+ IN const u1Byte *da,
+ IN u1Byte dialogToken
+ )
+{
+ FunctionIn(COMP_P2P);
+
+ // MAC Header
+ p2p_add_ActionFrameMacHdr(pBuf, da, pP2PInfo->DeviceAddress, da);
+
+ // Action Header
+ p2p_add_P2PPublicActionHdr(pBuf, P2P_GO_NEG_REQ, dialogToken);
+
+ // P2P IE
+ p2p_build_GoNegReqIe(pBuf, pP2PInfo);
+
+ // Additional IE
+ P2P_AddIe_Append(&pP2PInfo->AdditionalIEs, P2P_ADD_IE_GO_NEGOTIATION_REQUEST, pBuf);
+
+ // WPS IE
+ WPS_AppendElement(pP2PInfo->pAdapter, &pBuf->os, TRUE, WPS_INFO_PROBEREQ_IE);
+
+ // WFD IE
+ WFD_AppendP2pGoNegReqIEs(pP2PInfo->pAdapter, FrameBuf_Cap(pBuf), &pBuf->os);
+
+ RT_TRACE(COMP_P2P, DBG_LOUD,
+ ("%s(): intent = %u, tie breaker: %u, dialog token: %u\n",
+ __FUNCTION__,
+ pP2PInfo->GOIntent >> 1,
+ pP2PInfo->GOIntent & 0x01,
+ dialogToken));
+
+ FrameBuf_Dump(pBuf, 0, DBG_LOUD, __FUNCTION__);
+
+ FunctionOut(COMP_P2P);
+
+ return;
+}
+
+VOID
+p2p_Construct_GoNegRsp(
+ IN P2P_INFO *pP2PInfo,
+ IN u1Byte dialogToken,
+ IN FRAME_BUF *pBuf,
+ IN const u1Byte *da
+ )
+{
+ FunctionIn(COMP_P2P);
+
+ // MAC Header
+ p2p_add_ActionFrameMacHdr(pBuf, da, pP2PInfo->DeviceAddress, pP2PInfo->DeviceAddress);
+
+ // Action Header
+ p2p_add_P2PPublicActionHdr(pBuf, P2P_GO_NEG_RSP, dialogToken);
+
+ // P2P IE
+ p2p_build_GoNegRspIe(pBuf, pP2PInfo, da);
+
+ // Additional IE
+ P2P_AddIe_Append(&pP2PInfo->AdditionalIEs, P2P_ADD_IE_GO_NEGOTIATION_RESPONSE, pBuf);
+
+ // WPS IE
+ WPS_AppendElement(pP2PInfo->pAdapter, &pBuf->os, TRUE, WPS_INFO_PROBERSP_IE);
+
+ // WFD IE
+ WFD_AppendP2pGoNegRspIEs(pP2PInfo->pAdapter, FrameBuf_Cap(pBuf), &pBuf->os);
+
+ RT_TRACE(COMP_P2P, DBG_LOUD,
+ ("%s(): intent = %u, tie breaker: %u, dialog token: %u\n",
+ __FUNCTION__,
+ pP2PInfo->GOIntent >> 1,
+ pP2PInfo->GOIntent & 0x01,
+ dialogToken));
+
+ FrameBuf_Dump(pBuf, 0, DBG_LOUD, __FUNCTION__);
+
+ FunctionOut(COMP_P2P);
+
+ return;
+}
+
+VOID
+p2p_Construct_GoNegConf(
+ IN P2P_INFO *pP2PInfo,
+ IN u1Byte dialogToken,
+ IN FRAME_BUF *pBuf,
+ IN const u1Byte *da
+ )
+{
+ FunctionIn(COMP_P2P);
+
+ // MAC Header
+ p2p_add_ActionFrameMacHdr(pBuf, da, pP2PInfo->DeviceAddress, da);
+
+ // Action Header
+ p2p_add_P2PPublicActionHdr(pBuf, P2P_GO_NEG_CONF, dialogToken);
+
+ // P2P IE
+ p2p_build_GoNegConfIe(pBuf, pP2PInfo, da);
+
+ // Additional IE
+ P2P_AddIe_Append(&pP2PInfo->AdditionalIEs, P2P_ADD_IE_GO_NEGOTIATION_CONFIRM, pBuf);
+
+ // WFD IE
+ WFD_AppendP2pGoNegConfirmIEs(pP2PInfo->pAdapter, FrameBuf_Cap(pBuf), &pBuf->os);
+
+ FrameBuf_Dump(pBuf, 0, DBG_LOUD, __FUNCTION__);
+
+ FunctionOut(COMP_P2P);
+
+ return;
+}
+
+VOID
+p2p_Construct_InvitationReq(
+ IN P2P_INFO *pP2PInfo,
+ IN FRAME_BUF *pBuf,
+ IN const u1Byte *da,
+ IN u1Byte dialogToken
+ )
+{
+ FunctionIn(COMP_P2P);
+
+ // MAC Header
+ p2p_add_ActionFrameMacHdr(pBuf, da, pP2PInfo->DeviceAddress, da);
+
+ // Action Header
+ p2p_add_P2PPublicActionHdr(pBuf, P2P_INVITATION_REQ, dialogToken);
+
+ // P2P IE
+ p2p_build_InvitationReqIe(pBuf, pP2PInfo, da);
+
+ // Additional IE
+ P2P_AddIe_Append(&pP2PInfo->AdditionalIEs, P2P_ADD_IE_INVITATION_REQUEST, pBuf);
+
+ /* Below use octet string ONLY */
+ {
+ WFD_AppendP2pInvitationReqIEs(pP2PInfo->pAdapter, FrameBuf_Cap(pBuf), &pBuf->os);
+ }
+
+ FrameBuf_Dump(pBuf, 0, DBG_LOUD, __FUNCTION__);
+
+ FunctionOut(COMP_P2P);
+
+ return;
+}
+
+VOID
+p2p_Construct_InvitationRsp(
+ IN P2P_INFO *pP2PInfo,
+ IN u1Byte dialogToken,
+ IN FRAME_BUF *pBuf,
+ IN const u1Byte *da
+ )
+{
+ //
+ // Assume that pP2PInfo->Status has been set.
+ //
+
+ FunctionIn(COMP_P2P);
+
+ // MAC Header
+ p2p_add_ActionFrameMacHdr(pBuf, da, pP2PInfo->DeviceAddress, pP2PInfo->DeviceAddress);
+
+ // Action Header
+ p2p_add_P2PPublicActionHdr(pBuf, P2P_INVITATION_RSP, dialogToken);
+
+ // P2P IE
+ p2p_build_InvitationRspIe(pBuf, pP2PInfo, da);
+
+ // Additional IE
+ P2P_AddIe_Append(&pP2PInfo->AdditionalIEs, P2P_ADD_IE_INVITATION_RESPONSE, pBuf);
+
+ // WFD IE
+ WFD_AppendP2pInvitationRspIEs(pP2PInfo->pAdapter, FrameBuf_Cap(pBuf), &pBuf->os);
+
+ FrameBuf_Dump(pBuf, 0, DBG_LOUD, __FUNCTION__);
+
+ FunctionOut(COMP_P2P);
+
+ return;
+}
+
+VOID
+p2p_Construct_DevDiscReq(
+ IN P2P_INFO *pP2PInfo,
+ IN u1Byte dialogToken,
+ IN FRAME_BUF *pBuf,
+ IN const u1Byte *da,
+ IN const u1Byte *bssid
+ )
+{
+ FunctionIn(COMP_P2P);
+
+ // MAC Header
+ p2p_add_ActionFrameMacHdr(pBuf, bssid, pP2PInfo->DeviceAddress, bssid);
+
+ // Action Header
+ p2p_add_P2PPublicActionHdr(pBuf, P2P_DEV_DISC_REQ, dialogToken);
+
+ // P2P IE
+ p2p_build_DevDiscReqIe(pBuf, pP2PInfo);
+
+ FrameBuf_Dump(pBuf, 0, DBG_LOUD, __FUNCTION__);
+
+ FunctionOut(COMP_P2P);
+
+ return;
+}
+
+VOID
+p2p_Construct_DevDiscRsp(
+ IN P2P_INFO *pP2PInfo,
+ IN u1Byte dialogToken,
+ IN FRAME_BUF *pBuf,
+ IN const u1Byte *da,
+ IN u1Byte status
+ )
+{
+ FunctionIn(COMP_P2P);
+
+ // MAC Header
+ p2p_add_ActionFrameMacHdr(pBuf, da, pP2PInfo->DeviceAddress, pP2PInfo->DeviceAddress);
+
+ // Action Header
+ p2p_add_P2PPublicActionHdr(pBuf, P2P_DEV_DISC_RSP, dialogToken);
+
+ // P2P IE
+ p2p_build_DevDiscRspIe(pBuf, pP2PInfo, status);
+
+ FrameBuf_Dump(pBuf, 0, DBG_LOUD, __FUNCTION__);
+
+ FunctionOut(COMP_P2P);
+
+ return;
+}
+
+VOID
+p2p_Construct_PDReq(
+ IN P2P_INFO *pP2PInfo,
+ IN FRAME_BUF *pBuf,
+ IN const u1Byte *da,
+ IN u1Byte dialogToken,
+ IN u2Byte configMethod
+ )
+{
+ FunctionIn(COMP_P2P);
+
+ // MAC Header
+ p2p_add_ActionFrameMacHdr(pBuf, da, pP2PInfo->DeviceAddress, da);
+
+ // Action Header
+ p2p_add_P2PPublicActionHdr(pBuf, P2P_PROV_DISC_REQ, dialogToken);
+
+ // P2P IE
+ p2p_build_PdReqIe(pBuf, pP2PInfo);
+
+ // Additional IE
+ if(0 == P2P_AddIe_Append(&pP2PInfo->AdditionalIEs, P2P_ADD_IE_PROVISION_DISCOVERY_REQUEST, pBuf))
+ {
+ p2p_add_WpsIeConfigMethods(pBuf, configMethod);
+ }
+
+ // WFDS IE
+ P2PSvc_MakePDReqIE(pP2PInfo->pP2PSvcInfo, pBuf);
+
+ // WFD IE
+ WFD_AppendP2pProvDiscoveryReqIEs(pP2PInfo->pAdapter, FrameBuf_Cap(pBuf), &pBuf->os);
+
+ FrameBuf_Dump(pBuf, 0, DBG_LOUD, __FUNCTION__);
+
+ FunctionOut(COMP_P2P);
+
+ return;
+}
+
+VOID
+p2p_Construct_PDRsp(
+ IN P2P_INFO *pP2PInfo,
+ IN u1Byte dialogToken,
+ IN OCTET_STRING *posP2PAttrs,
+ IN u2Byte configMethod,
+ IN FRAME_BUF *pBuf,
+ IN const u1Byte *da
+ )
+{
+ FunctionIn(COMP_P2P);
+
+ // MAC Header
+ p2p_add_ActionFrameMacHdr(pBuf, da, pP2PInfo->DeviceAddress, pP2PInfo->DeviceAddress);
+
+ // Action Header
+ p2p_add_P2PPublicActionHdr(pBuf, P2P_PROV_DISC_RSP, dialogToken);
+
+ // P2P IE
+ p2p_build_PdRspIe(pBuf, pP2PInfo);
+
+ // Additional IE
+ if(0 == P2P_AddIe_Append(&pP2PInfo->AdditionalIEs, P2P_ADD_IE_PROVISION_DISCOVERY_RESPONSE, pBuf))
+ {
+ // TODO: we temporarilly accept all confing method in ProvisionDiscoveryReq
+ p2p_add_WpsIeConfigMethods(pBuf, configMethod);
+ }
+
+ // WFDS IE
+ P2PSvc_MakePDRspIE(pP2PInfo->pP2PSvcInfo, posP2PAttrs, pBuf);
+
+ // WFD IE
+ WFD_AppendP2pProvDiscoveryRspIEs(pP2PInfo->pAdapter, FrameBuf_Cap(pBuf), &pBuf->os);
+
+ FrameBuf_Dump(pBuf, 0, DBG_LOUD, __FUNCTION__);
+
+ FunctionOut(COMP_P2P);
+
+ return;
+}
+
+VOID
+p2p_build_FakeInvitationRspIe(
+ IN FRAME_BUF *pBuf,
+ IN P2P_INFO *pP2PInfo,
+ IN const u1Byte *da
+ )
+{
+ p2p_build_InvitationRspIe(pBuf, pP2PInfo, da);
+
+ return;
+}
+
+//
+// Description:
+// Construct fake provision discovery response frame by the device which is considered as the
+// respondor and fill the content by the previous received information.
+// Arguments:
+// [in] pP2PInfo -
+// P2P information context.
+// [in] pRspDev -
+// The device which sends the provision discovery response frame.
+// [in] da -
+// The destination which the response frame is sent to.
+// [out] -pBuf
+// The context of FRAME_BUF to put the frame.
+// Return:
+// Return RT_STATUS_SUCCESS if the construction of this response frame succeeds.
+// By Bruce, 2015-02-17.
+//
+RT_STATUS
+p2p_Construct_FakePDRsp(
+ IN P2P_INFO *pP2PInfo,
+ IN P2P_DEV_LIST_ENTRY *pRspDev,
+ IN const u1Byte *da,
+ OUT FRAME_BUF *pBuf
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ pu1Byte pPdReqFrame = NULL;
+ OCTET_STRING osPdReq, osTmpIe;
+ pu1Byte pPdRspTa = NULL;;
+
+ FunctionIn(COMP_P2P);
+
+ do
+ {
+ if(!pRspDev)
+ {
+ RT_ASSERT(FALSE, ("pRspDev = NULL\n"));
+ rtStatus = RT_STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if(!pRspDev->txFrames[P2P_FID_PD_REQ])
+ {
+ RT_ASSERT(FALSE, ("pRspDev->txFrames[P2P_FID_PD_REQ] = NULL\n"));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+ }
+
+ if(0 == pRspDev->txFrames[P2P_FID_PD_REQ]->frameLen)
+ {
+ RT_TRACE_F(COMP_P2P, DBG_WARNING, ("pRspDev->txFrames[P2P_FID_PD_REQ].frameLen = 0\n"));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+ }
+
+ FillOctetString(osPdReq, pRspDev->txFrames[P2P_FID_PD_REQ]->frame, pRspDev->txFrames[P2P_FID_PD_REQ]->frameLen);
+
+ pPdReqFrame = pRspDev->txFrames[P2P_FID_PD_REQ]->frame;
+ pPdRspTa = Frame_pDaddr(osPdReq);
+
+ // MAC Header
+ p2p_add_ActionFrameMacHdr(pBuf, da, pPdRspTa, pPdRspTa);
+
+ // Action Header
+ p2p_add_P2PPublicActionHdr(pBuf, P2P_PROV_DISC_RSP, pRspDev->txFrames[P2P_FID_PD_REQ]->token);
+
+ // WPS IE, getting from the original PD request
+ osTmpIe = PacketGetElement(osPdReq, EID_Vendor, OUI_SUB_SimpleConfig, OUI_SUB_DONT_CARE);
+ if(osTmpIe.Length > 0)
+ {
+ PacketMakeElement(&(pBuf->os), EID_Vendor, osTmpIe);
+ }
+
+ // WFD IE
+ if(pRspDev->rxFrames[P2P_FID_PROBE_RSP]->frameLen > 0)
+ {
+ osTmpIe = PacketGetElement(osPdReq, EID_Vendor, OUI_SUB_WIFI_DISPLAY, OUI_SUB_DONT_CARE);
+ if(osTmpIe.Length > 0)
+ {
+ PacketMakeElement(&(pBuf->os), EID_Vendor, osTmpIe);
+ }
+ }
+ FrameBuf_Dump(pBuf, 0, DBG_LOUD, __FUNCTION__);
+ }while(FALSE);
+
+ FunctionOut(COMP_P2P);
+
+ return rtStatus;
+}
+
+#endif
+