[WCNCR00151917] softap: Change building assoc resp's extra IEs from CFG80211

[Description]
Change building extra IEs for assoc resp (Ex: WPS IE) from CFG80211.

1. CFG hook function: .start_ap & .change_beacon
   Store the extra IEs for assoc resp in cfg80211_beacon_data struct.
2. p2pRoleFsmRunEventBeaconUpdate
   Store WPS IE in extra IEs into struct of aucWSCIE.
3. rsnGenerateWSCIEForAssocRsp
   Append the WPS IE for Assoc Resp depends on the struct of aucWSCIE.

Unit Test:
1. Hostapd with extra IEs setting: Assoc resp with WPS IE.
2. Hostapd without extra IEs setting: Assoc resp without WPS IE.

Change-Id: If053b762061164401bc7481467d999fcc1faa385
Feature: softap
Signed-off-by: Evelyn <evelyn.tsai@mediatek.com>
CR-Id: WCNCR00151917
diff --git a/include/mgmt/p2p_func.h b/include/mgmt/p2p_func.h
index 8f9c0bc..7dca620 100644
--- a/include/mgmt/p2p_func.h
+++ b/include/mgmt/p2p_func.h
@@ -183,6 +183,10 @@
 		    prBcnUpdateInfo, IN PUINT_8 pucNewBcnHdr, IN UINT_32 u4NewHdrLen, IN PUINT_8 pucNewBcnBody, IN
 		    UINT_32 u4NewBodyLen);
 
+WLAN_STATUS
+p2pFuncAssocRespUpdate(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN PUINT_8 AssocRespIE, IN
+		    UINT_32 u4AssocRespLen);
+
 BOOLEAN
 p2pFuncValidateAuth(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T
 		    pprStaRec, OUT PUINT_16 pu2StatusCode);
diff --git a/include/mgmt/p2p_role.h b/include/mgmt/p2p_role.h
index e528daa..917c684 100644
--- a/include/mgmt/p2p_role.h
+++ b/include/mgmt/p2p_role.h
@@ -103,9 +103,11 @@
 	UINT_8 ucRoleIndex;
 	UINT_32 u4BcnHdrLen;
 	UINT_32 u4BcnBodyLen;
+	UINT_32 u4AssocRespLen;
 	PUINT_8 pucBcnHdr;
 	PUINT_8 pucBcnBody;
-	UINT_8 aucBuffer[1];	/* Header & Body are put here. */
+	PUINT_8 pucAssocRespIE;
+	UINT_8 aucBuffer[1];	/* Header & Body & Extra IEs are put here. */
 } MSG_P2P_BEACON_UPDATE_T, *P_MSG_P2P_BEACON_UPDATE_T;
 
 typedef struct _MSG_P2P_MGMT_FRAME_UPDATE_T {
diff --git a/mgmt/p2p_func.c b/mgmt/p2p_func.c
index cba7f64..e1fdea1 100644
--- a/mgmt/p2p_func.c
+++ b/mgmt/p2p_func.c
@@ -1590,6 +1590,39 @@
 	return rWlanStatus;
 }				/* p2pFuncBeaconUpdate */
 
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief    This function is to update extra IEs (ex: WPS) for assoc resp.
+*           Caller should sanity check the params.
+*
+* \param[in] prAdapter      Pointer of ADAPTER_T
+* \param[in] prP2pBssInfo   Pointer to BSS_INFO_T structure
+* \param[in] AssocRespIE    Pointer to extra IEs for assoc resp
+* \param[in] u4AssocRespLen Length of extra IEs for assoc resp
+*
+* \return WLAN_STATUS
+*/
+/*----------------------------------------------------------------------------*/
+
+WLAN_STATUS
+p2pFuncAssocRespUpdate(IN P_ADAPTER_T prAdapter,
+		    IN P_BSS_INFO_T prP2pBssInfo,
+		    IN PUINT_8 AssocRespIE, IN UINT_32 u4AssocRespLen)
+{
+	UINT_8 ucOuiType = 0;
+	UINT_16 u2SubTypeVersion = 0;
+
+	if (!rsnParseCheckForWFAInfoElem(prAdapter, AssocRespIE, &ucOuiType, &u2SubTypeVersion))
+		return WLAN_STATUS_FAILURE;
+
+	if (ucOuiType == VENDOR_OUI_TYPE_WPS) {
+		kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 3, (PUINT_8)AssocRespIE, IE_SIZE(AssocRespIE),
+			(UINT_8) (prP2pBssInfo->u4PrivateData));
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
 #endif
 
 #if 0
diff --git a/mgmt/p2p_role_fsm.c b/mgmt/p2p_role_fsm.c
index d57a271..e0bb4de 100644
--- a/mgmt/p2p_role_fsm.c
+++ b/mgmt/p2p_role_fsm.c
@@ -2301,11 +2301,16 @@
 		DBGLOG(P2P, TRACE, "p2pRoleFsmRunEventBeaconUpdate\n");
 
 		prBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) prMsgHdr;
+		if (prBcnUpdateMsg->ucRoleIndex >= BSS_P2P_NUM)
+			break;
 
 		prRoleP2pFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prBcnUpdateMsg->ucRoleIndex);
-
+		if (!prRoleP2pFsmInfo)
+			break;
 
 		prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prRoleP2pFsmInfo->ucBssIndex);
+		if (!(prP2pBssInfo->fgIsNetActive))
+			break;
 
 		prBcnUpdateInfo = &(prRoleP2pFsmInfo->rBeaconUpdateInfo);
 
@@ -2316,6 +2321,18 @@
 				    prBcnUpdateMsg->u4BcnHdrLen,
 				    prBcnUpdateMsg->pucBcnBody, prBcnUpdateMsg->u4BcnBodyLen);
 
+		if (prBcnUpdateMsg->pucAssocRespIE != NULL && prBcnUpdateMsg->u4AssocRespLen > 0) {
+			DBGLOG(P2P, TRACE, "Copy extra IEs for assoc resp (Length= %d)\n",
+								prBcnUpdateMsg->u4AssocRespLen);
+			DBGLOG_MEM8(P2P, INFO, prBcnUpdateMsg->pucAssocRespIE, prBcnUpdateMsg->u4AssocRespLen);
+
+			if (p2pFuncAssocRespUpdate(prAdapter,
+				prP2pBssInfo,
+				prBcnUpdateMsg->pucAssocRespIE,
+				prBcnUpdateMsg->u4AssocRespLen) == WLAN_STATUS_FAILURE)
+				DBGLOG(P2P, ERROR, "Update extra IEs for asso resp fail!\n");
+
+		}
 
 
 		if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) &&
diff --git a/mgmt/rsn.c b/mgmt/rsn.c
index 0843aa7..c34ca52 100644
--- a/mgmt/rsn.c
+++ b/mgmt/rsn.c
@@ -2364,9 +2364,9 @@
 
 VOID rsnGenerateWSCIEForAssocRsp(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo)
 {
-	P_IE_HDR_T PucIE;
-	PUINT_8 puc;
 	P_WIFI_VAR_T prWifiVar = NULL;
+	P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL;
+	UINT_16 u2IELen = 0;
 
 	ASSERT(prAdapter);
 	ASSERT(prMsduInfo);
@@ -2375,51 +2375,21 @@
 	prWifiVar = &(prAdapter->rWifiVar);
 	ASSERT(prWifiVar);
 
-	if (!prWifiVar->ucApWpsMode)	/* Todo::Only at WPS certification ? */
+	DBGLOG(RSN, TRACE, "WPS: Building WPS IE for (Re)Association Response");
+	prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex);
+
+	if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P)
 		return;
 
-	DBGLOG(RSN, TRACE, "WPS: Building WPS IE for (Re)Association Response");
+	u2IELen = kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 3, (UINT_8) prP2pBssInfo->u4PrivateData);
 
-	PucIE = (P_IE_HDR_T) (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength);
-
-	PucIE->ucId = ELEM_ID_VENDOR;
-
-	puc = PucIE->aucInfo;
-
-	WLAN_SET_FIELD_BE32(puc, WPS_DEV_OUI_WFA);
-	puc += 4;
-
-	WLAN_SET_FIELD_BE16(puc, ATTR_VERSION);
-	puc += 2;
-	WLAN_SET_FIELD_BE16(puc, 1);
-	puc += 2;
-	*puc = 0x10;
-	puc++;
-
-	WLAN_SET_FIELD_BE16(puc, ATTR_RESPONSE_TYPE);
-	puc += 2;
-	WLAN_SET_FIELD_BE16(puc, 1);
-	puc += 2;
-	*puc = 0x3;
-	puc++;
-
-	WLAN_SET_FIELD_BE16(puc, ATTR_VENDOR_EXT);
-	puc += 2;
-	WLAN_SET_FIELD_BE16(puc, 6);
-	puc += 2;
-	WLAN_SET_FIELD_BE24(puc, 14122);
-	puc += 3;
-	*puc = 0x00;		/* Version 2 */
-	puc++;
-	*puc = 0x01;
-	puc++;
-	*puc = 0x20;		/* WPS2.0 */
-	puc++;
-
-	PucIE->ucLength = puc - PucIE->aucInfo;
-
-	prMsduInfo->u2FrameLength += IE_SIZE(PucIE);
-
+	kalP2PGenWSC_IE(prAdapter->prGlueInfo,
+		3,
+		(PUINT_8) ((ULONG) prMsduInfo->prPacket +
+			   (ULONG) prMsduInfo->u2FrameLength),
+			   (UINT_8) prP2pBssInfo->u4PrivateData);
+	prMsduInfo->u2FrameLength += (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 3,
+		(UINT_8) prP2pBssInfo->u4PrivateData);
 }
 
 #endif
diff --git a/os/linux/gl_p2p_cfg80211.c b/os/linux/gl_p2p_cfg80211.c
index 314c6e4..3f5ffaf 100644
--- a/os/linux/gl_p2p_cfg80211.c
+++ b/os/linux/gl_p2p_cfg80211.c
@@ -1227,7 +1227,8 @@
 									    (sizeof(MSG_P2P_BEACON_UPDATE_T)
 									     +
 									     settings->beacon.head_len +
-									     settings->beacon.tail_len));
+									     settings->beacon.tail_len +
+									     settings->beacon.assocresp_ies_len));
 
 		if (prP2pBcnUpdateMsg == NULL) {
 			ASSERT(FALSE);
@@ -1247,7 +1248,7 @@
 
 			prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer;
 
-			pucBuffer = (PUINT_8) ((ULONG) pucBuffer + (ULONG) settings->beacon.head_len);
+			pucBuffer += settings->beacon.head_len;
 		} else {
 			prP2pBcnUpdateMsg->u4BcnHdrLen = 0;
 
@@ -1261,12 +1262,23 @@
 			kalMemCopy(pucBuffer, settings->beacon.tail, settings->beacon.tail_len);
 
 			prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen;
+
+			pucBuffer += settings->beacon.tail_len;
 		} else {
 			prP2pBcnUpdateMsg->u4BcnBodyLen = 0;
 
 			prP2pBcnUpdateMsg->pucBcnBody = NULL;
 		}
 
+		if (settings->beacon.assocresp_ies_len != 0 && settings->beacon.assocresp_ies != NULL) {
+			prP2pBcnUpdateMsg->pucAssocRespIE = pucBuffer;
+			kalMemCopy(pucBuffer, settings->beacon.assocresp_ies, settings->beacon.assocresp_ies_len);
+			prP2pBcnUpdateMsg->u4AssocRespLen = settings->beacon.assocresp_ies_len;
+		} else {
+			prP2pBcnUpdateMsg->u4AssocRespLen = 0;
+			prP2pBcnUpdateMsg->pucAssocRespIE = NULL;
+		}
+
 		mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pBcnUpdateMsg, MSG_SEND_METHOD_BUF);
 
 		prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) cnmMemAlloc(prGlueInfo->prAdapter,
@@ -1647,7 +1659,8 @@
 			prP2pBcnUpdateMsg =
 			    (P_MSG_P2P_BEACON_UPDATE_T) cnmMemAlloc(prGlueInfo->prAdapter,
 								    RAM_TYPE_MSG, (sizeof(MSG_P2P_BEACON_UPDATE_T)
-										   + info->head_len + info->tail_len));
+										   + info->head_len + info->tail_len
+										   + info->assocresp_ies_len));
 
 			if (prP2pBcnUpdateMsg == NULL) {
 				ASSERT(FALSE);
@@ -1666,7 +1679,7 @@
 
 				prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer;
 
-				pucBuffer = (PUINT_8) ((ULONG) pucBuffer + (ULONG) info->head_len);
+				pucBuffer += info->head_len;
 			} else {
 				prP2pBcnUpdateMsg->u4BcnHdrLen = 0;
 
@@ -1680,11 +1693,23 @@
 				kalMemCopy(pucBuffer, info->tail, info->tail_len);
 
 				prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen;
+
+				pucBuffer += info->tail_len;
 			} else {
 				prP2pBcnUpdateMsg->u4BcnBodyLen = 0;
 				prP2pBcnUpdateMsg->pucBcnBody = NULL;
 			}
 
+			if (info->assocresp_ies_len != 0 && info->assocresp_ies != NULL) {
+
+				prP2pBcnUpdateMsg->pucAssocRespIE = pucBuffer;
+				kalMemCopy(pucBuffer, info->assocresp_ies, info->assocresp_ies_len);
+				prP2pBcnUpdateMsg->u4AssocRespLen = info->assocresp_ies_len;
+			} else {
+				prP2pBcnUpdateMsg->u4AssocRespLen = 0;
+				prP2pBcnUpdateMsg->pucAssocRespIE = NULL;
+			}
+
 			kalP2PSetRole(prGlueInfo, 2, ucRoleIdx);
 
 			mboxSendMsg(prGlueInfo->prAdapter,
diff --git a/os/linux/gl_p2p_kal.c b/os/linux/gl_p2p_kal.c
index e132ca7..cd709b6 100644
--- a/os/linux/gl_p2p_kal.c
+++ b/os/linux/gl_p2p_kal.c
@@ -493,7 +493,7 @@
 {
 	ASSERT(prGlueInfo);
 
-	ASSERT(ucType < 3);
+	ASSERT(ucType < 4);
 
 	return prGlueInfo->prP2PInfo[ucRoleIdx]->u2WSCIELen[ucType];
 }
@@ -514,7 +514,7 @@
 	P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL;
 
 	do {
-		if ((prGlueInfo == NULL) || (ucType >= 3) || (pucBuffer == NULL))
+		if ((prGlueInfo == NULL) || (ucType >= 4) || (pucBuffer == NULL))
 			break;
 
 		prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx];
@@ -531,7 +531,7 @@
 	P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL;
 
 	do {
-		if ((prGlueInfo == NULL) || (ucType >= 3) || ((u2BufferLength > 0) && (pucBuffer == NULL)))
+		if ((prGlueInfo == NULL) || (ucType >= 4) || ((u2BufferLength > 0) && (pucBuffer == NULL)))
 			break;
 
 		if (u2BufferLength > 400) {
diff --git a/os/linux/include/gl_p2p_os.h b/os/linux/include/gl_p2p_os.h
index e6cf890..0862987 100644
--- a/os/linux/include/gl_p2p_os.h
+++ b/os/linux/include/gl_p2p_os.h
@@ -172,8 +172,8 @@
 	UINT_32 u4CipherPairwise;
 	/*UINT_8 ucWSCRunning;*//* TH3 multiple P2P */
 
-	UINT_8 aucWSCIE[3][400];	/* 0 for beacon, 1 for probe req, 2 for probe response */
-	UINT_16 u2WSCIELen[3];
+	UINT_8 aucWSCIE[4][400];	/* 0 for beacon, 1 for probe req, 2 for probe response, 3 for assoc response */
+	UINT_16 u2WSCIELen[4];
 
 #if CFG_SUPPORT_WFD
 	UINT_8 aucWFDIE[400];	/* 0 for beacon, 1 for probe req, 2 for probe response */