summaryrefslogtreecommitdiff
path: root/network/wlan/WDI/COMMON/P2PSvc_Construct.c
diff options
context:
space:
mode:
authorDaiqian Hu <[email protected]>2016-11-21 08:54:24 +0800
committerDaiqian Hu <[email protected]>2016-11-21 08:54:24 +0800
commita95eaad088f61aa55da9d73015cf1ed86e64a67e (patch)
tree15b498a08a4aee4b7f8b1627d39c965b3aa3ba98 /network/wlan/WDI/COMMON/P2PSvc_Construct.c
parent1aa0338ec5418345ea0c383e92b4fa19f7c98425 (diff)
Re-submit for WDI sample driver to GitHub
Submit WDI sample driver to GitHub for RS1.
Diffstat (limited to 'network/wlan/WDI/COMMON/P2PSvc_Construct.c')
-rw-r--r--network/wlan/WDI/COMMON/P2PSvc_Construct.c992
1 files changed, 992 insertions, 0 deletions
diff --git a/network/wlan/WDI/COMMON/P2PSvc_Construct.c b/network/wlan/WDI/COMMON/P2PSvc_Construct.c
new file mode 100644
index 00000000..3a8428b3
--- /dev/null
+++ b/network/wlan/WDI/COMMON/P2PSvc_Construct.c
@@ -0,0 +1,992 @@
+#include "Mp_Precomp.h"
+
+#include "P2PSvc_Internal.h"
+
+#if (P2P_SUPPORT == 1)
+#if (P2PSVC_SUPPORT == 1)
+
+//-----------------------------------------------------------------------------
+// Local
+//-----------------------------------------------------------------------------
+
+BOOLEAN
+p2psvc_MatchSvcNameHash_org_wi_fi_wfds(
+ IN POCTET_STRING posSvcNameHash
+)
+{
+ BOOLEAN bMatched = FALSE;
+
+ u4Byte nHashes = posSvcNameHash->Length / 6;
+ u4Byte iterReqHash = 0;
+
+ for(iterReqHash = 0; iterReqHash < nHashes; iterReqHash++)
+ {
+ if(0 == PlatformCompareMemory(posSvcNameHash->Octet + (6 * iterReqHash), gP2PSVC_NameHashTab[0].hash, 6))
+ {// check if it is prefix search
+ bMatched = TRUE;
+ break;
+ }
+ }
+
+ return bMatched;
+}
+
+BOOLEAN
+p2psvc_MatchSvcNameHash(
+ IN PP2PSVC_REQ_INFO_ENTRY pInfoEntry,
+ IN POCTET_STRING posSvcNameHash
+ )
+{
+ BOOLEAN bMatch = FALSE;
+ PRT_OBJECT_HEADER pSvcNameHashObj = NULL;
+ u4Byte nHashes = posSvcNameHash->Length / 6;
+ u4Byte iterReqHash = 0;
+
+ if(NULL == (pSvcNameHashObj = P2PSvc_GetParam(&pInfoEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_SVC_NAME_HASH, 0)))
+ {// shall not happen since we have validated when set this req
+ return FALSE;
+ }
+
+ RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "adv svc hash:\n", pSvcNameHashObj->Value, pSvcNameHashObj->Length);
+
+ for(iterReqHash = 0; iterReqHash < nHashes; iterReqHash++)
+ {
+ if(0 == PlatformCompareMemory(posSvcNameHash->Octet + (6 * iterReqHash), pSvcNameHashObj->Value, 6))
+ {
+ RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "Match svc-name-hash:\n", pSvcNameHashObj->Value, pSvcNameHashObj->Length);
+ bMatch = TRUE;
+ break;
+ }
+ }
+
+ return bMatch;
+}
+
+u2Byte
+p2psvc_EvalSvcAdvInfoAttrLen(
+ IN PP2PSVC_INFO pP2PSvcInfo,
+ IN POCTET_STRING posSvcNameHash
+ )
+{
+ u2Byte reqLen = 0;
+ u1Byte nSvcToAttach = 0;
+
+ do
+ {
+ PRT_LIST_ENTRY pEntry = NULL;
+
+ if(p2psvc_MatchSvcNameHash_org_wi_fi_wfds(posSvcNameHash))
+ {// Spec 3.4.3.2: if prefix search, send org.wi-fi.wfds service name
+
+ reqLen += (u2Byte)( sizeof(u4Byte) // adv-id
+ + 2 // config-method
+ + sizeof(u1Byte) // svc-name len
+ + strlen(P2PSVC_WIFI_WFDS_SERVICE_NAME) // svc-name
+ + 0);
+
+ nSvcToAttach++;
+ }
+ else
+ {
+ for(pEntry = RTGetHeadList(&pP2PSvcInfo->advSvcList); pEntry != &pP2PSvcInfo->advSvcList; pEntry = RTNextEntryList(pEntry))
+ {
+ PP2PSVC_REQ_INFO_ENTRY pInfoEntry = (PP2PSVC_REQ_INFO_ENTRY)pEntry;
+ PRT_OBJECT_HEADER pAdvIdObj = NULL;
+ PRT_OBJECT_HEADER pSvcNameObj = NULL;
+
+ if(!p2psvc_MatchSvcNameHash(pInfoEntry, posSvcNameHash)) continue;
+
+ pAdvIdObj = P2PSvc_GetParam(&pInfoEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_ADV_ID, 0);
+ pSvcNameObj = P2PSvc_GetParam(&pInfoEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_SVC_NAME, 0);
+
+ reqLen += (u2Byte)(pAdvIdObj->Length // adv-id
+ + 2 // config-method
+ + sizeof(u1Byte) // svc-name len
+ + pSvcNameObj->Length // svc-name
+ + 0);
+
+ nSvcToAttach++;
+ }
+ }
+ }while(FALSE);
+
+ if(0 == nSvcToAttach) reqLen = 0;
+
+ return reqLen;
+}
+
+RT_STATUS
+p2psvc_MakePDSvcNameHash(
+ IN PP2PSVC_INFO pP2PSvcInfo,
+ OUT FRAME_BUF *pBuf
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ pu1Byte pLen = NULL;
+
+ P2PSVC_FUNC_IN(DBG_LOUD);
+
+ do
+ {
+ PRT_LIST_ENTRY pEntry = NULL;
+
+ PP2PSVC_PD_ENTRY pPDEntry = NULL;
+ PRT_OBJECT_HEADER pSvcNameHashObj = NULL;
+
+ if(!P2PSvc_PDSessionInProgress(pP2PSvcInfo, &pPDEntry))
+ {
+ rtStatus = RT_STATUS_INVALID_STATE;
+ break;
+ }
+
+ if(!pPDEntry->bInitor)
+ {
+ rtStatus = RT_STATUS_INVALID_STATE;
+ break;
+ }
+
+ if(NULL == (pSvcNameHashObj = P2PSvc_GetParam(P2PSvc_Get_PDEntryObjList(pPDEntry), P2PSVC_OBJ_HDR_ID_DATA_SVC_NAME_HASH, 0))
+ || 6 != pSvcNameHashObj->Length
+ )
+ {// shall not happen since we have validated when set this req
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+ }
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) break;
+
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_SVC_HASH);
+ FrameBuf_Add_le_u2(pBuf, (u2Byte)pSvcNameHashObj->Length);
+ FrameBuf_Add_Data(pBuf, pSvcNameHashObj->Value, (u2Byte)pSvcNameHashObj->Length);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+ }while(FALSE);
+
+ P2PSVC_FUNC_OUT(DBG_LOUD, rtStatus);
+
+ return rtStatus;
+}
+
+
+RT_STATUS
+p2psvc_MakeSeekSvcNameHash(
+ IN PP2PSVC_INFO pP2PSvcInfo,
+ OUT FRAME_BUF *pBuf
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ pu1Byte pLen = NULL;
+
+ P2PSVC_FUNC_IN(DBG_TRACE);
+
+ do
+ {
+ PRT_LIST_ENTRY pEntry = NULL;
+ pu2Byte pAttrLen = NULL;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) break;
+
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_SVC_HASH);
+ FrameBuf_Add_le_u2(pBuf, (u2Byte) pP2PSvcInfo->seekReqListCnt * 6);
+
+ // Construct the hash list
+ for(pEntry = RTGetHeadList(&pP2PSvcInfo->seekReqList); pEntry != &pP2PSvcInfo->seekReqList; pEntry = RTNextEntryList(pEntry))
+ {
+ PP2PSVC_REQ_INFO_ENTRY pInfoEntry = (PP2PSVC_REQ_INFO_ENTRY)pEntry;
+ PRT_OBJECT_HEADER pSvcNameHashObj = NULL;
+
+ pSvcNameHashObj = P2PSvc_GetParam(&pInfoEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_SVC_NAME_HASH, 0);
+ FrameBuf_Add_Data(pBuf, pSvcNameHashObj->Value, 6);
+ }
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+ }while(FALSE);
+
+ P2PSVC_FUNC_OUT(DBG_TRACE, rtStatus);
+
+ return rtStatus;
+}
+
+
+//-----------------------------------------------------------------------------
+// Exported
+//-----------------------------------------------------------------------------
+
+
+
+//
+// Description:
+// Make adv-svc-info attr.
+// The attr is carried in a independent P2P IE and if the IE is too big
+// to fit in a single P2P IE, it is splitted into several.
+// If error occurs during the process, length of the posMsdu member
+// will not be updated therefore no change is made to the original
+// constructing frame.
+//
+RT_STATUS
+P2PSvc_MakeAdvSvcInfo(
+ IN PP2PSVC_INFO pP2PSvcInfo,
+ IN POCTET_STRING posSvcNameHash,
+ OUT FRAME_BUF *pBuf
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ PP2P_INFO pP2PInfo = GET_P2P_INFO(pP2PSvcInfo->pAdapter);
+ pu1Byte pLen = NULL;
+
+ P2PSVC_FUNC_IN(DBG_TRACE);
+
+ PLATFORM_ACQUIRE_RT_SPINLOCK(pP2PSvcInfo->lock);
+
+ do
+ {
+ PRT_LIST_ENTRY pEntry = NULL;
+ u2Byte attrLen = 0;
+ u2Byte bytesWritten = 0;
+
+ if(0 == (attrLen = p2psvc_EvalSvcAdvInfoAttrLen(pP2PSvcInfo, posSvcNameHash)))
+ {// no matching svc
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+ }
+
+ if(0 == attrLen) break;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) break;
+
+ // Attr id and len
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_ADV_SVC_INFO);
+ FrameBuf_Add_le_u2(pBuf, attrLen);
+
+ // advertise-svc-desc
+ if(p2psvc_MatchSvcNameHash_org_wi_fi_wfds(posSvcNameHash))
+ {// Spec 3.4.3.2: if prefix search, send org.wi-fi.wfds service name
+
+ u4Byte AdvIdZero = 0;
+
+ // Main spec v0.43:
+ // If ASP finds a match with the Service Hash value of
+ // "org.wi-fi.wfds" (i.e. advertises one of the Wi-Fi alliance
+ // defined services listed in 3.2), then the ConfigMethods value
+ // in Probe Response shall be ignored.
+
+ // Attach [adv-id, config-method, svc-name len, svc-name]
+ FrameBuf_Add_le_u4(pBuf, AdvIdZero);
+ FrameBuf_Add_le_u2(pBuf, 0);
+ FrameBuf_Add_u1(pBuf, (u1Byte)(strlen(P2PSVC_WIFI_WFDS_SERVICE_NAME)));
+ FrameBuf_Add_Data(pBuf, P2PSVC_WIFI_WFDS_SERVICE_NAME, (u2Byte) strlen(P2PSVC_WIFI_WFDS_SERVICE_NAME));
+ }
+ else
+ {
+ // Attr payload
+ for(pEntry = RTGetHeadList(&pP2PSvcInfo->advSvcList); pEntry != &pP2PSvcInfo->advSvcList; pEntry = RTNextEntryList(pEntry))
+ {
+ PP2PSVC_REQ_INFO_ENTRY pInfoEntry = (PP2PSVC_REQ_INFO_ENTRY)pEntry;
+ u2Byte svcConfigMethod = pP2PInfo->WpsAttributes.ConfigMethod;
+
+ PRT_OBJECT_HEADER pNetworkConfigObj = NULL;
+ PRT_OBJECT_HEADER pAdvIdObj = NULL;
+ PRT_OBJECT_HEADER pSvcNameObj = NULL;
+
+ if(!p2psvc_MatchSvcNameHash(pInfoEntry, posSvcNameHash)) continue;
+
+ pAdvIdObj = P2PSvc_GetParam(&pInfoEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_ADV_ID, 0);
+ pSvcNameObj = P2PSvc_GetParam(&pInfoEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_SVC_NAME, 0);
+ pNetworkConfigObj = P2PSvc_GetParam(&pInfoEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_NETWORK_CONFIG, 0);
+
+ if(2 == *(PUCHAR)pNetworkConfigObj->Value)
+ {// WSC PIN method only
+ CLEAR_FLAG(svcConfigMethod, P2P_WPS_CONFIG_METHODS_SVC_DEFAULT_PIN);
+ }
+
+ // Attach [adv-id, config-method, svc-name len, svc-name]
+ FrameBuf_Add_le_u4(pBuf, *(pu4Byte)pAdvIdObj->Value);
+ FrameBuf_Add_be_u2(pBuf, svcConfigMethod);
+ FrameBuf_Add_u1(pBuf, (u1Byte)pSvcNameObj->Length);
+ FrameBuf_Add_Data(pBuf, pSvcNameObj->Value, (u2Byte)pSvcNameObj->Length);
+
+ //RT_PRINT_STR(COMP_P2P, DBG_TRACE, "Advertise svc-name:\n", pSvcNameObj->Value, pSvcNameObj->Length);
+ }
+ }
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+ }while(FALSE);
+
+ PLATFORM_RELEASE_RT_SPINLOCK(pP2PSvcInfo->lock);
+
+ P2PSVC_FUNC_OUT(DBG_TRACE, rtStatus);
+
+ return rtStatus;
+}
+
+//
+// Description:
+// Build independent P2P IEs for carrying the hash values
+//
+RT_STATUS
+P2PSvc_MakeSvcNameHash(
+ IN PP2PSVC_INFO pP2PSvcInfo,
+ OUT FRAME_BUF *pBuf
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+
+ P2PSVC_FUNC_IN(DBG_TRACE);
+
+ PLATFORM_ACQUIRE_RT_SPINLOCK(pP2PSvcInfo->lock);
+
+ do
+ {
+ if(pP2PSvcInfo->pdSessionListCnt)
+ {
+ if(RT_STATUS_SUCCESS != (rtStatus = p2psvc_MakePDSvcNameHash(pP2PSvcInfo, pBuf)))
+ {
+ break;
+ }
+ }
+ else if(pP2PSvcInfo->seekReqListCnt)
+ {
+ if(RT_STATUS_SUCCESS != (rtStatus = p2psvc_MakeSeekSvcNameHash(pP2PSvcInfo, pBuf)))
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }while(FALSE);
+
+ PLATFORM_RELEASE_RT_SPINLOCK(pP2PSvcInfo->lock);
+
+ P2PSVC_FUNC_OUT(DBG_TRACE, rtStatus);
+
+ return rtStatus;
+}
+
+
+RT_STATUS
+P2PSvc_MakeInitorPDReqIE(
+ IN PP2PSVC_INFO pP2PSvcInfo,
+ IN PP2PSVC_PD_ENTRY pPDEntry,
+ OUT FRAME_BUF *pBuf
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ PP2P_INFO pP2PInfo = GET_P2P_INFO(pP2PSvcInfo->pAdapter);
+ PP2PSVC_INITOR_PD_ENTRY pInitorPDEntry = (PP2PSVC_INITOR_PD_ENTRY)pPDEntry;
+ pu1Byte pLen = NULL;
+
+ do
+ {
+ PRT_OBJECT_HEADER pObj = NULL;
+ pu1Byte peerDevAddr = NULL;
+ u4Byte advId = 0;
+ pu1Byte selfDevAddr = NULL;
+ u4Byte sessionId = 0;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) break;
+
+ // Comment out because already appended by P2PConstructProvisionDiscoveryReq
+ // P2P-cap, always present
+ //bytesCopied = P2PMakeP2PCapability(pP2PInfo, Type_Action, osAttr.Octet + osAttr.Length);
+ //osAttr.Length += bytesCopied;
+
+ // Comment out because already appended by P2PConstructProvisionDiscoveryReq
+ // P2P-dev-info, always present
+ //bytesCopied = P2PMakeP2PDeviceInfo(pP2PInfo, Type_Action, osAttr.Octet + osAttr.Length);
+ //osAttr.Length += bytesCopied;
+
+ // Group-id, contains NEW or GO
+ if(TEST_FLAG(pPDEntry->selfConnCap, P2PSVC_CONN_CAP_BMP_NEW | P2PSVC_CONN_CAP_BMP_GO))
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_GROUP_ID);
+ FrameBuf_Add_le_u2(pBuf, 6 + pPDEntry->selfGrpInfo.ssidLen);
+ FrameBuf_Add_Data(pBuf, pPDEntry->selfGrpInfo.grpDevAddr, 6);
+ FrameBuf_Add_Data(pBuf, pPDEntry->selfGrpInfo.ssidBuf, pPDEntry->selfGrpInfo.ssidLen);
+ }
+
+ // Intended-intf-addr, contains NEW or GO
+ if(TEST_FLAG(pPDEntry->selfConnCap, P2PSVC_CONN_CAP_BMP_NEW | P2PSVC_CONN_CAP_BMP_GO))
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_INTENDED_INTERFACE_ADDRESS);
+ FrameBuf_Add_le_u2(pBuf, 6);
+ FrameBuf_Add_Data(pBuf, pPDEntry->selfGrpInfo.grpIntfAddr, 6);
+ }
+
+ // Status, NONE
+
+ // Operating-channel, contains NEW or GO
+ if(TEST_FLAG(pPDEntry->selfConnCap, P2PSVC_CONN_CAP_BMP_NEW | P2PSVC_CONN_CAP_BMP_GO))
+ {
+ P2PAttr_Make_OperatingChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, pP2PInfo->OperatingChannel);
+ }
+
+ // Channel-list, contains NEW
+ if(TEST_FLAG(pPDEntry->selfConnCap, P2PSVC_CONN_CAP_BMP_NEW))
+ {
+ P2PAttr_Make_ChannelList(pBuf, pP2PInfo, &pP2PInfo->ChannelEntryList);
+ }
+
+ // session-info-data-info (n <= 144), present if session-info is not 0
+ pObj = P2PSvc_GetParam(&pInitorPDEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_SESSION_INFO, 0);
+ if(0 < pObj->Length && pObj->Length < 144)
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_SESSION_INFO_DATA_INFO);
+ FrameBuf_Add_le_u2(pBuf, (u2Byte)pObj->Length);
+ FrameBuf_Add_Data(pBuf, pObj->Value, (u2Byte)pObj->Length);
+ }
+
+ // conn-cap, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_CONN_CAP_INFO);
+ FrameBuf_Add_le_u2(pBuf, 1);
+ FrameBuf_Add_u1(pBuf, pPDEntry->selfConnCap);
+
+ // adv-id (adv-id, svc-mac), always present
+ pObj = P2PSvc_GetParam(&pInitorPDEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_DEV_ADDR, 0);
+ peerDevAddr = pObj->Value;
+ pObj = P2PSvc_GetParam(&pInitorPDEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_ADV_ID, 0);
+ advId = *(pu4Byte)pObj->Value;
+
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_ADV_ID_INFO);
+ FrameBuf_Add_le_u2(pBuf, 4 + 6);
+ FrameBuf_Add_le_u4(pBuf, advId);
+ FrameBuf_Add_Data(pBuf, peerDevAddr, 6);
+
+ // Config-timeout, contains NEW or GO
+ if(TEST_FLAG(pPDEntry->selfConnCap, P2PSVC_CONN_CAP_BMP_NEW | P2PSVC_CONN_CAP_BMP_GO))
+ {
+ P2PAttr_Make_ConfigTimeout(pBuf, pP2PInfo->GOConfigurationTimeout, pP2PInfo->ClientConfigurationTimeout);
+ }
+
+ // Listen-channel, contains NEW or CLI
+ if(TEST_FLAG(pPDEntry->selfConnCap, P2PSVC_CONN_CAP_BMP_NEW | P2PSVC_CONN_CAP_BMP_CLI))
+ {
+ P2PAttr_Make_ListenChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, pP2PInfo->ListenChannel);
+ }
+
+ // session-id (session-id, self dev-addr), always present
+ selfDevAddr = pP2PInfo->DeviceAddress;
+ pObj = P2PSvc_GetParam(&pInitorPDEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_SESSION_ID, 0);
+ sessionId = *(pu4Byte)pObj->Value;
+
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_SESSION_ID_INFO);
+ FrameBuf_Add_le_u2(pBuf, 4 + 6);
+ FrameBuf_Add_le_u4(pBuf, sessionId);
+ FrameBuf_Add_Data(pBuf, selfDevAddr, 6);
+
+ // Feature-cap, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_FEATURE_CAP_INFO);
+ FrameBuf_Add_le_u2(pBuf, 2);
+ FrameBuf_Add_le_u2(pBuf, 0x0001);
+
+ // Persistent-grp-info, present if persistent grp available and ASP intent using it
+ // TODO:
+
+ //4 Indicate P2P attrs sent
+ P2PSvc_IndicateFrameSent(pP2PSvcInfo,
+ P2PSVC_OBJ_HDR_ID_INDIC_INITOR_PD_REQ_SENT,
+ peerDevAddr,
+ (u2Byte)(FrameBuf_Tail(pBuf) - 1 - pLen),
+ pLen + 1);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+ }while(FALSE);
+
+ return rtStatus;
+}
+
+RT_STATUS
+P2PSvc_MakeRspdorFOPDReqIE(
+ IN PP2PSVC_INFO pP2PSvcInfo,
+ IN PP2PSVC_PD_ENTRY pPDEntry,
+ OUT FRAME_BUF *pBuf
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ PP2P_INFO pP2PInfo = GET_P2P_INFO(pP2PSvcInfo->pAdapter);
+ pu1Byte pLen = NULL;
+
+ P2PSVC_FUNC_IN(DBG_LOUD);
+
+ do
+ {
+ PP2PSVC_RSPDOR_PD_ENTRY pRspdorPDEntry = (PP2PSVC_RSPDOR_PD_ENTRY)pPDEntry;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) break;
+
+ // Comment out because already appended by P2PConstructProvisionDiscoveryReq
+ // P2P-cap, always present
+ //bytesCopied = P2PMakeP2PCapability(pP2PInfo, Type_Action, osAttr.Octet + osAttr.Length);
+ //osAttr.Length += bytesCopied;
+
+ // Comment out because already appended by P2PConstructProvisionDiscoveryReq
+ // Dev-info, always present
+ //bytesCopied = P2PMakeP2PDeviceInfo(pP2PInfo, Type_Action, osAttr.Octet + osAttr.Length);
+ //osAttr.Length += bytesCopied;
+
+ // Group-id, contains NEW or GO
+ if(TEST_FLAG(pRspdorPDEntry->fopdReqConnCap, P2PSVC_CONN_CAP_BMP_NEW | P2PSVC_CONN_CAP_BMP_GO))
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_GROUP_ID);
+ FrameBuf_Add_le_u2(pBuf, 6 + pPDEntry->selfGrpInfo.ssidLen);
+ FrameBuf_Add_Data(pBuf, pP2PInfo->DeviceAddress, 6);
+ FrameBuf_Add_Data(pBuf, pPDEntry->selfGrpInfo.ssidBuf, pPDEntry->selfGrpInfo.ssidLen);
+ }
+
+ // Intended-intf-addr, contains NEW or GO
+ if(TEST_FLAG(pRspdorPDEntry->fopdReqConnCap, P2PSVC_CONN_CAP_BMP_NEW | P2PSVC_CONN_CAP_BMP_GO))
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_INTENDED_INTERFACE_ADDRESS);
+ FrameBuf_Add_le_u2(pBuf, 6);
+ FrameBuf_Add_Data(pBuf, pPDEntry->selfGrpInfo.grpIntfAddr, 6);
+ }
+
+ // Status, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_STATUS);
+ FrameBuf_Add_le_u2(pBuf, 1);
+ FrameBuf_Add_u1(pBuf, (u1Byte)pRspdorPDEntry->fopdReqStatus);
+
+ // Op-channel, contains NEW or GO
+ if(TEST_FLAG(pRspdorPDEntry->fopdReqConnCap, P2PSVC_CONN_CAP_BMP_NEW | P2PSVC_CONN_CAP_BMP_GO))
+ {
+ P2PAttr_Make_OperatingChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, pP2PInfo->OperatingChannel);
+ }
+
+ // Channel-list, contains NEW
+ if(TEST_FLAG(pRspdorPDEntry->fopdReqConnCap, P2PSVC_CONN_CAP_BMP_NEW))
+ {
+ P2PAttr_Make_ChannelList(pBuf, pP2PInfo, &pP2PInfo->ChannelEntryList);
+ }
+
+ // Session-info-data-info, NONE
+
+ // Conn-cap, present if accepted
+ if(P2P_STATUS_SUCCESS_ACCEPTED_BY_USER == pRspdorPDEntry->fopdReqStatus)
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_CONN_CAP_INFO);
+ FrameBuf_Add_le_u2(pBuf, 1);
+ FrameBuf_Add_u1(pBuf, pRspdorPDEntry->fopdReqConnCap);
+ }
+
+ // Adv-id (adv-id, svc-mac), always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_ADV_ID_INFO);
+ FrameBuf_Add_le_u2(pBuf, 4 + 6);
+ FrameBuf_Add_le_u4(pBuf, pRspdorPDEntry->super.advId);
+ FrameBuf_Add_Data(pBuf, pP2PInfo->DeviceAddress, 6);
+
+ // Config-timeout, contains NEW or GO
+ if(TEST_FLAG(pRspdorPDEntry->fopdReqConnCap, P2PSVC_CONN_CAP_BMP_NEW | P2PSVC_CONN_CAP_BMP_GO))
+ {
+ P2PAttr_Make_ConfigTimeout(pBuf, pP2PInfo->GOConfigurationTimeout, pP2PInfo->ClientConfigurationTimeout);
+ }
+
+ // Listen-channel, contains NEW or CLI
+ if(TEST_FLAG(pRspdorPDEntry->fopdReqConnCap, P2PSVC_CONN_CAP_BMP_NEW | P2PSVC_CONN_CAP_BMP_CLI))
+ {
+ P2PAttr_Make_ListenChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, pP2PInfo->ListenChannel);
+ }
+
+ // Session-id-info, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_SESSION_ID_INFO);
+ FrameBuf_Add_le_u2(pBuf, 4 + 6);
+ FrameBuf_Add_le_u4(pBuf, pRspdorPDEntry->super.sessionId);
+ FrameBuf_Add_Data(pBuf, pRspdorPDEntry->super.peerDevAddr, 6);
+
+ // Feature-cap, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_FEATURE_CAP_INFO);
+ FrameBuf_Add_le_u2(pBuf, 2);
+ FrameBuf_Add_le_u2(pBuf, 0x0001);
+
+ // Persistent-grp-info, present if persistent grp available and ASP intend using it
+ // TODO:
+
+ //4 Indicate P2P attrs sent
+ P2PSvc_IndicateFrameSent(pP2PSvcInfo,
+ P2PSVC_OBJ_HDR_ID_INDIC_RSPDOR_FOPD_REQ_SENT,
+ pRspdorPDEntry->super.peerDevAddr,
+ (u2Byte)(FrameBuf_Tail(pBuf) - 1 - pLen),
+ pLen + 1);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+ }while(FALSE);
+
+ P2PSVC_FUNC_OUT(DBG_LOUD, rtStatus);
+
+ return rtStatus;
+}
+
+RT_STATUS
+P2PSvc_MakeInitorFOPDRspIE(
+ IN PP2PSVC_INFO pP2PSvcInfo,
+ IN PP2PSVC_PD_ENTRY pPDEntry,
+ IN POCTET_STRING posP2PAttrs,
+ OUT FRAME_BUF *pBuf
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ PP2P_INFO pP2PInfo = GET_P2P_INFO(pP2PSvcInfo->pAdapter);
+ PP2PSVC_INITOR_PD_ENTRY pInitorPDEntry = (PP2PSVC_INITOR_PD_ENTRY)pPDEntry;
+ pu1Byte pLen = NULL;
+
+ P2PSVC_FUNC_IN(DBG_LOUD);
+
+ do
+ {
+ OCTET_STRING osConnCap = {NULL, 0};
+ PRT_OBJECT_HEADER pObj = NULL;
+ pu1Byte peerDevAddr = NULL;
+ u4Byte advId = 0;
+ PP2P_WPS_ATTRIBUTES pWps = &pP2PInfo->WpsAttributes;
+
+ if(!P2PSvc_GetP2PAttr(posP2PAttrs, P2P_ATTR_CONN_CAP_INFO, 1, &osConnCap))
+ {
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+ }
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) break;
+
+ // P2P-cap, always present
+ if(p2p_ActingAs_Go(pP2PInfo))
+ RT_TRACE_F(COMP_P2P, DBG_WARNING, ("Invalid role\n"));
+ P2PAttr_Make_Capability(pBuf,
+ pP2PInfo->DeviceCapability & ~P2P_DEV_CAP_CLIENT_DISCOVERABILITY, // this cap valid only in P2P Group Info and AssocReq
+ pP2PInfo->GroupCapability);
+
+ // Dev-info, always present
+ P2PAttr_Make_DevInfo(pBuf,
+ pP2PInfo->DeviceAddress,
+ pWps->ConfigMethod,
+ &pWps->PrimaryDeviceType,
+ pWps->SecondaryDeviceTypeLength,
+ pWps->SecondaryDeviceTypeList,
+ pWps->DeviceNameLength,
+ pWps->DeviceName);
+
+ // Group-id, connCap IS GO
+ if(P2PSVC_CONN_CAP_BMP_GO == pInitorPDEntry->fopdRspConnCap)
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_GROUP_ID);
+ FrameBuf_Add_le_u2(pBuf, 6 + pPDEntry->selfGrpInfo.ssidLen);
+ FrameBuf_Add_Data(pBuf, pP2PInfo->DeviceAddress, 6);
+ FrameBuf_Add_Data(pBuf, pPDEntry->selfGrpInfo.ssidBuf, pPDEntry->selfGrpInfo.ssidLen);
+ }
+
+ // Intended-intf-addr, connCap IS GO
+ if(P2PSVC_CONN_CAP_BMP_GO == pInitorPDEntry->fopdRspConnCap)
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_INTENDED_INTERFACE_ADDRESS);
+ FrameBuf_Add_le_u2(pBuf, 6);
+ FrameBuf_Add_Data(pBuf, pPDEntry->selfGrpInfo.grpIntfAddr, 6);
+ }
+
+ // Status, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_STATUS);
+ FrameBuf_Add_le_u2(pBuf, 1);
+ FrameBuf_Add_u1(pBuf, (u1Byte)pInitorPDEntry->fopdRspStatus);
+
+ // Op-channel, connCap IS GO
+ if(P2PSVC_CONN_CAP_BMP_GO == pInitorPDEntry->fopdRspConnCap)
+ {
+ P2PAttr_Make_OperatingChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, pP2PInfo->OperatingChannel);
+ }
+
+ // Channel-list, IS CLI or GO
+ if(P2PSVC_CONN_CAP_BMP_GO == pInitorPDEntry->fopdRspConnCap
+ || P2PSVC_CONN_CAP_BMP_CLI == pInitorPDEntry->fopdRspConnCap
+ )
+ {
+ P2PAttr_Make_ChannelList(pBuf, pP2PInfo, &pP2PInfo->ChannelEntryList);
+ }
+
+ // Session-info-data-info, NONE
+
+ // Conn-cap, always present?
+ if(P2P_STATUS_SUCCESS == pInitorPDEntry->fopdRspStatus)
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_CONN_CAP_INFO);
+ FrameBuf_Add_le_u2(pBuf, 1);
+ FrameBuf_Add_u1(pBuf, pInitorPDEntry->fopdRspConnCap);
+ }
+
+ // Adv-id (adv-id, svc-mac), always present
+ pObj = P2PSvc_GetParam(&pInitorPDEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_DEV_ADDR, 0);
+ peerDevAddr = pObj->Value;
+ pObj = P2PSvc_GetParam(&pInitorPDEntry->objList, P2PSVC_OBJ_HDR_ID_DATA_ADV_ID, 0);
+ advId = *(pu4Byte)pObj->Value;
+
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_ADV_ID_INFO);
+ FrameBuf_Add_le_u2(pBuf, 4 + 6);
+ FrameBuf_Add_le_u4(pBuf, advId);
+ FrameBuf_Add_Data(pBuf, pInitorPDEntry->super.peerDevAddr, 6);
+
+ // Config-timeout, IS GO or CLI
+ // Always add config-time out since WFA is checking this even when PD is failed
+ //if(P2PSVC_CONN_CAP_BMP_GO == pInitorPDEntry->fopdRspConnCap
+ // || P2PSVC_CONN_CAP_BMP_CLI == pInitorPDEntry->fopdRspConnCap
+ // )
+ {
+ P2PAttr_Make_ConfigTimeout(pBuf, pP2PInfo->GOConfigurationTimeout, pP2PInfo->ClientConfigurationTimeout);
+ }
+
+ // Listen-channel, NONE
+
+ // Session-id-info, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_SESSION_ID_INFO);
+ FrameBuf_Add_le_u2(pBuf, 4 + 6);
+ FrameBuf_Add_le_u4(pBuf, pInitorPDEntry->super.sessionId);
+ FrameBuf_Add_Data(pBuf, pP2PInfo->DeviceAddress, 6);
+
+ // Feature-cap, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_FEATURE_CAP_INFO);
+ FrameBuf_Add_le_u2(pBuf, 2);
+ FrameBuf_Add_le_u2(pBuf, 0x0001);
+
+ // Persistent-grp-info, NONE
+
+ //4 Indicate P2P attrs sent
+ P2PSvc_IndicateFrameSent(pP2PSvcInfo,
+ P2PSVC_OBJ_HDR_ID_INDIC_INITOR_FOPD_RSP_SENT,
+ peerDevAddr,
+ (u2Byte)(FrameBuf_Tail(pBuf) - 1 - pLen),
+ pLen + 1);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+ }while(FALSE);
+
+ P2PSVC_FUNC_OUT(DBG_LOUD, rtStatus);
+
+ return rtStatus;
+
+}
+
+RT_STATUS
+P2PSvc_MakeRspdorPDRspIE(
+ IN PP2PSVC_INFO pP2PSvcInfo,
+ IN PP2PSVC_PD_ENTRY pPDEntry,
+ IN POCTET_STRING posP2PAttrs,
+ OUT FRAME_BUF *pBuf
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ PP2P_INFO pP2PInfo = GET_P2P_INFO(pP2PSvcInfo->pAdapter);
+ PP2PSVC_RSPDOR_PD_ENTRY pRspdorPDEntry = (PP2PSVC_RSPDOR_PD_ENTRY)pPDEntry;
+ pu1Byte pLen = NULL;
+
+ P2PSVC_FUNC_IN(DBG_LOUD);
+
+ do
+ {
+ PP2P_WPS_ATTRIBUTES pWps = &pP2PInfo->WpsAttributes;
+
+ if(NULL == (pLen = p2p_add_IEHdr(pBuf))) break;
+
+ // P2P-cap, always present
+ if(p2p_ActingAs_Go(pP2PInfo))
+ RT_TRACE_F(COMP_P2P, DBG_WARNING, ("Invalid role\n"));
+ P2PAttr_Make_Capability(pBuf,
+ pP2PInfo->DeviceCapability & ~P2P_DEV_CAP_CLIENT_DISCOVERABILITY, // this cap valid only in P2P Group Info and AssocReq
+ pP2PInfo->GroupCapability);
+
+ // P2P-dev-info, always present
+ P2PAttr_Make_DevInfo(pBuf,
+ pP2PInfo->DeviceAddress,
+ pWps->ConfigMethod,
+ &pWps->PrimaryDeviceType,
+ pWps->SecondaryDeviceTypeLength,
+ pWps->SecondaryDeviceTypeList,
+ pWps->DeviceNameLength,
+ pWps->DeviceName);
+
+ // Group-id, IS GO
+ if(P2PSVC_CONN_CAP_BMP_GO == pRspdorPDEntry->pdRspConnCap)
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_GROUP_ID);
+ FrameBuf_Add_le_u2(pBuf, 6 + pPDEntry->selfGrpInfo.ssidLen);
+ FrameBuf_Add_Data(pBuf, pPDEntry->selfGrpInfo.grpDevAddr, 6);
+ FrameBuf_Add_Data(pBuf, pPDEntry->selfGrpInfo.ssidBuf, pPDEntry->selfGrpInfo.ssidLen);
+ }
+
+ // Intended-intf-addr, contains NEW or GO
+ if(TEST_FLAG(pRspdorPDEntry->pdRspConnCap, P2PSVC_CONN_CAP_BMP_GO))
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_INTENDED_INTERFACE_ADDRESS);
+ FrameBuf_Add_le_u2(pBuf, 6);
+ FrameBuf_Add_Data(pBuf, pPDEntry->selfGrpInfo.grpIntfAddr, 6);
+ }
+
+ // Status, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_STATUS);
+ FrameBuf_Add_le_u2(pBuf, 1);
+ FrameBuf_Add_u1(pBuf, pRspdorPDEntry->pdRspStatus);
+
+ // Operating-channel, IS GO
+ if(P2PSVC_CONN_CAP_BMP_GO == pRspdorPDEntry->pdRspConnCap)
+ {
+ P2PAttr_Make_OperatingChannel(pBuf, pP2PInfo->CountryString, pP2PInfo->RegulatoryClass, pP2PInfo->OperatingChannel);
+ }
+
+ // Channel-list, IS CLI or GO
+ if(P2PSVC_CONN_CAP_BMP_GO == pRspdorPDEntry->pdRspConnCap
+ || P2PSVC_CONN_CAP_BMP_CLI == pRspdorPDEntry->pdRspConnCap
+ )
+ {
+ P2PAttr_Make_ChannelList(pBuf, pP2PInfo, &pP2PInfo->ChannelEntryList);
+ }
+
+ // session-info-data-info, NONE
+
+ // conn-cap, always present, present if SUCCESS
+ if(P2P_STATUS_SUCCESS == pRspdorPDEntry->pdRspStatus)
+ {
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_CONN_CAP_INFO);
+ FrameBuf_Add_le_u2(pBuf, 1);
+ FrameBuf_Add_u1(pBuf, pRspdorPDEntry->pdRspConnCap);
+ }
+
+ // adv-id (adv-id, svc-mac), always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_ADV_ID_INFO);
+ FrameBuf_Add_le_u2(pBuf, 4 + 6);
+ FrameBuf_Add_le_u4(pBuf, pRspdorPDEntry->super.advId);
+ FrameBuf_Add_Data(pBuf, pP2PInfo->DeviceAddress, 6);
+
+ // Config-timeout, IS GO or CLI
+ // Always add config-timeout since WFA is checking this even status is failed
+ //if(P2PSVC_CONN_CAP_BMP_GO == pRspdorPDEntry->pdRspConnCap
+ // || P2PSVC_CONN_CAP_BMP_CLI == pRspdorPDEntry->pdRspConnCap
+ // )
+ {
+ P2PAttr_Make_ConfigTimeout(pBuf, pP2PInfo->GOConfigurationTimeout, pP2PInfo->ClientConfigurationTimeout);
+ }
+
+ // Listen-channel, NONE
+
+ // Session-id-info, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_SESSION_ID_INFO);
+ FrameBuf_Add_le_u2(pBuf, 4 + 6);
+ FrameBuf_Add_le_u4(pBuf, pRspdorPDEntry->super.sessionId);
+ FrameBuf_Add_Data(pBuf, pRspdorPDEntry->super.peerDevAddr, 6);
+
+ // Feature-cap, always present
+ FrameBuf_Add_u1(pBuf, P2P_ATTR_FEATURE_CAP_INFO);
+ FrameBuf_Add_le_u2(pBuf, 2);
+ FrameBuf_Add_le_u2(pBuf, 0x0001);
+
+ // Persistent-grp-info, present if persistent grp known and ASP intent using it
+ // TODO:
+
+ //4 Indicate P2P attrs sent
+ P2PSvc_IndicateFrameSent(pP2PSvcInfo,
+ P2PSVC_OBJ_HDR_ID_INDIC_RSPDOR_PD_RSP_SENT,
+ pRspdorPDEntry->super.peerDevAddr,
+ (u2Byte)(FrameBuf_Tail(pBuf) - 1 - pLen),
+ pLen + 1);
+
+ p2p_update_IeHdrLen(pBuf, pLen);
+ }while(FALSE);
+
+ P2PSVC_FUNC_OUT(DBG_LOUD, rtStatus);
+
+ return rtStatus;
+
+}
+
+RT_STATUS
+P2PSvc_MakeSvcInfoDesc(
+ IN PP2PSVC_INFO pP2PSvcInfo,
+ IN PP2PSVC_REQ_INFO_ENTRY pAdvInfoEntry,
+ IN u1Byte svcInfoReqLen,
+ IN pu1Byte pSvcInfoReqBuf,
+ OUT FRAME_BUF *pBuf
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ PP2P_INFO pP2PInfo = GET_P2P_INFO(pP2PSvcInfo->pAdapter);
+ PP2PSVC_OBJ_LIST pAdvSvcObjList = &pAdvInfoEntry->objList;
+
+ P2PSVC_FUNC_IN(DBG_LOUD);
+
+ do
+ {
+ PRT_OBJECT_HEADER pAdvIdObj = NULL;
+ PRT_OBJECT_HEADER pNetworkConfigObj = NULL;
+ PRT_OBJECT_HEADER pSvcNameObj = NULL;
+ PRT_OBJECT_HEADER pSvcStatusObj = NULL;
+ PRT_OBJECT_HEADER pSvcInfoObj = NULL;
+
+ u2Byte svcConfigMethod = pP2PInfo->WpsAttributes.ConfigMethod;
+
+ // Get info from the advertised svc
+ if(NULL == (pAdvIdObj = P2PSvc_GetParam(pAdvSvcObjList, P2PSVC_OBJ_HDR_ID_DATA_ADV_ID, 0)))
+ {
+ break;
+ }
+
+ if(NULL == (pNetworkConfigObj = P2PSvc_GetParam(pAdvSvcObjList, P2PSVC_OBJ_HDR_ID_DATA_NETWORK_CONFIG, 0)))
+ {
+ break;
+ }
+
+ if(NULL == (pSvcNameObj = P2PSvc_GetParam(pAdvSvcObjList, P2PSVC_OBJ_HDR_ID_DATA_SVC_NAME, 0)))
+ {
+ break;
+ }
+
+ if(NULL == (pSvcStatusObj = P2PSvc_GetParam(pAdvSvcObjList, P2PSVC_OBJ_HDR_ID_DATA_SVC_STATUS, 0)))
+ {
+ break;
+ }
+
+ if(NULL == (pSvcInfoObj = P2PSvc_GetParam(pAdvSvcObjList, P2PSVC_OBJ_HDR_ID_DATA_SVC_INFO, 0)))
+ {
+ break;
+ }
+
+ // Construct svc info desc (ref addendum v0.43 Table G3)
+ // [adv-id(4), config-method(2), svc-name-len(1), svc-name(n), svc-status(1), svc-info-len(2), svc-info(n)]
+
+ // adv-id
+ FrameBuf_Add_le_u4(pBuf, *(pu4Byte)pAdvIdObj->Value);
+
+ // config-method
+ // TODO: (v0.43) set to the config method set from upper layer
+ //P2PSVC_SET_ATTR_2Byte(&rtStatus, posSvcInfoDesc, maxBufLen, 1);
+ if(2 == *(PUCHAR)pNetworkConfigObj->Value)
+ {// WSC PIN method only
+ CLEAR_FLAG(svcConfigMethod, P2P_WPS_CONFIG_METHODS_SVC_DEFAULT_PIN);
+ }
+ FrameBuf_Add_be_u2(pBuf, svcConfigMethod);
+
+ // svc-name-len
+ FrameBuf_Add_u1(pBuf, (u1Byte)pSvcNameObj->Length);
+
+ // svc-name
+ FrameBuf_Add_Data(pBuf, pSvcNameObj->Value, (u2Byte)pSvcNameObj->Length);
+
+ // svc-status
+ FrameBuf_Add_u1(pBuf, *(pu1Byte)pSvcStatusObj->Value);
+
+ // svc-info
+ if(P2PSvc_MatchSubstring(pSvcInfoObj->Value, pSvcInfoObj->Length, pSvcInfoReqBuf, svcInfoReqLen))
+ {
+ // svc-info-len
+ FrameBuf_Add_le_u2(pBuf, (u2Byte)pSvcInfoObj->Length);
+
+ // svc-info
+ FrameBuf_Add_Data(pBuf, pSvcInfoObj->Value, (u2Byte)pSvcInfoObj->Length);
+ }
+ else
+ {
+ // svc-info-len
+ FrameBuf_Add_le_u2(pBuf, 0);
+ }
+ }while(FALSE);
+
+ P2PSVC_FUNC_OUT(DBG_LOUD, rtStatus);
+
+ return rtStatus;
+}
+
+#endif // #if (P2PSVC_SUPPORT == 1)
+#endif // #if (P2P_SUPPORT == 1)