blob: 8e92f71fff52a048b1512ceacdd65a179331d212 [file] [log] [blame]
/******************************************************************************
*
* This file is provided under a dual license. When you use or
* distribute this software, you may choose to be licensed under
* version 2 of the GNU General Public License ("GPLv2 License")
* or BSD License.
*
* GPLv2 License
*
* Copyright(C) 2016 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See http://www.gnu.org/licenses/gpl-2.0.html for more details.
*
* BSD LICENSE
*
* Copyright(C) 2016 MediaTek Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include "precomp.h"
BOOLEAN
p2pDevStateInit_IDLE(IN P_ADAPTER_T prAdapter,
IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState)
{
BOOLEAN fgIsTransition = FALSE, fgIsShareInterface = TRUE;
UINT_32 u4Idx = 0;
P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL;
do {
ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo) && (peNextState != NULL));
if (!LINK_IS_EMPTY(&(prChnlReqInfo->rP2pChnlReqLink))) {
fgIsTransition = TRUE;
*peNextState = P2P_DEV_STATE_REQING_CHANNEL;
break;
}
/* Check the interface shared by P2P_DEV and P2P_ROLE or not? */
/* If not shared, we shall let BSSID4 alive to receive PROVISION REQUEST from GC */
prGlueInfo = prAdapter->prGlueInfo;
if (prGlueInfo) {
for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) {
if ((prGlueInfo->prP2PInfo[u4Idx] != NULL) &&
(prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler != NULL) &&
(prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler !=
prGlueInfo->prP2PInfo[u4Idx]->prDevHandler)) {
fgIsShareInterface = FALSE;
break;
}
}
}
/************************* End *************************/
if (fgIsShareInterface) {
/* Stay in IDLE state. */
UNSET_NET_ACTIVE(prAdapter, P2P_DEV_BSS_INDEX);
nicDeactivateNetwork(prAdapter, P2P_DEV_BSS_INDEX);
}
} while (FALSE);
return fgIsTransition;
} /* p2pDevStateInit_IDLE */
VOID p2pDevStateAbort_IDLE(IN P_ADAPTER_T prAdapter)
{
/* Currently Aobrt IDLE do nothing. */
} /* p2pDevStateAbort_IDLE */
BOOLEAN
p2pDevStateInit_REQING_CHANNEL(IN P_ADAPTER_T prAdapter,
IN UINT_8 ucBssIdx,
IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState)
{
BOOLEAN fgIsTransition = FALSE;
P_MSG_P2P_CHNL_REQUEST_T prP2pMsgChnlReq = (P_MSG_P2P_CHNL_REQUEST_T) NULL;
P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL;
#if CFG_SUPPORT_DBDC
CNM_DBDC_CAP_T rDbdcCap;
#endif /*CFG_SUPPORT_DBDC*/
do {
ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL) && (peNextState != NULL));
prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx);
if (LINK_IS_EMPTY(&(prChnlReqInfo->rP2pChnlReqLink))) {
/* NO Channel Request Pending. */
DBGLOG(P2P, ERROR, "NO Pending Channel Request, but enter Req Channel State\n");
fgIsTransition = TRUE;
*peNextState = P2P_DEV_STATE_IDLE;
break;
}
LINK_REMOVE_HEAD(&(prChnlReqInfo->rP2pChnlReqLink), prP2pMsgChnlReq, P_MSG_P2P_CHNL_REQUEST_T);
ASSERT(prP2pMsgChnlReq);
#if (CFG_HW_WMM_BY_BSS == 1)
if (prBssInfo->fgIsWmmInited == FALSE)
prBssInfo->ucWmmQueSet = MAX_HW_WMM_INDEX;
#endif
#if CFG_SUPPORT_DBDC
cnmGetDbdcCapability(prAdapter,
prBssInfo->ucBssIndex,
prP2pMsgChnlReq->rChannelInfo.eBand,
prP2pMsgChnlReq->rChannelInfo.ucChannelNum,
wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex),
&rDbdcCap);
prBssInfo->eDBDCBand = ENUM_BAND_AUTO;
prBssInfo->ucNss = rDbdcCap.ucNss;
#if (CFG_HW_WMM_BY_BSS == 0)
prBssInfo->ucWmmQueSet = rDbdcCap.ucWmmSetIndex;
#endif
#endif /*CFG_SUPPORT_DBDC*/
prChnlReqInfo->u4MaxInterval = prP2pMsgChnlReq->u4Duration;
prChnlReqInfo->ucReqChnlNum = prP2pMsgChnlReq->rChannelInfo.ucChannelNum;
prChnlReqInfo->eChnlSco = prP2pMsgChnlReq->eChnlSco;
prChnlReqInfo->eBand = prP2pMsgChnlReq->rChannelInfo.eBand;
prChnlReqInfo->u8Cookie = prP2pMsgChnlReq->u8Cookie;
prChnlReqInfo->eChnlReqType = prP2pMsgChnlReq->eChnlReqType;
prChnlReqInfo->eChannelWidth = prBssInfo->ucVhtChannelWidth;
prChnlReqInfo->ucCenterFreqS1 = prBssInfo->ucVhtChannelFrequencyS1;
prChnlReqInfo->ucCenterFreqS2 = prBssInfo->ucVhtChannelFrequencyS2;
p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo);
} while (FALSE);
if (prP2pMsgChnlReq)
cnmMemFree(prAdapter, prP2pMsgChnlReq);
return fgIsTransition;
} /* p2pDevStateInit_REQING_CHANNEL */
VOID
p2pDevStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter,
IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN ENUM_P2P_DEV_STATE_T eNextState)
{
do {
ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL) && (eNextState < P2P_DEV_STATE_NUM));
switch (eNextState) {
case P2P_DEV_STATE_IDLE:
/* Channel abort case. */
p2pFuncReleaseCh(prAdapter, P2P_DEV_BSS_INDEX, prChnlReqInfo);
break;
case P2P_DEV_STATE_CHNL_ON_HAND:
/* Channel on hand case. */
break;
default:
/* Un-expected state transition. */
DBGLOG(P2P, ERROR, "Unexpected State Transition(eNextState=%d)\n", eNextState);
ASSERT(FALSE);
break;
}
} while (FALSE);
} /* p2pDevStateAbort_REQING_CHANNEL */
VOID
p2pDevStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter,
IN P_BSS_INFO_T prP2pBssInfo,
IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo)
{
do {
ASSERT_BREAK((prAdapter != NULL) && (prP2pDevFsmInfo != NULL) && (prChnlReqInfo != NULL));
ASSERT(prChnlReqInfo->eChnlReqType == CH_REQ_TYPE_P2P_LISTEN);
prChnlReqInfo->ucOriChnlNum = prP2pBssInfo->ucPrimaryChannel;
prChnlReqInfo->eOriBand = prP2pBssInfo->eBand;
prChnlReqInfo->eOriChnlSco = prP2pBssInfo->eBssSCO;
prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum;
prP2pBssInfo->eBand = prChnlReqInfo->eBand;
prP2pBssInfo->eBssSCO = prChnlReqInfo->eChnlSco;
cnmTimerStartTimer(prAdapter, &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer), prChnlReqInfo->u4MaxInterval);
kalP2PIndicateChannelReady(prAdapter->prGlueInfo,
prChnlReqInfo->u8Cookie,
prChnlReqInfo->ucReqChnlNum,
prChnlReqInfo->eBand, prChnlReqInfo->eChnlSco, prChnlReqInfo->u4MaxInterval);
} while (FALSE);
} /* p2pDevStateInit_CHNL_ON_HAND */
VOID
p2pDevStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter,
IN P_BSS_INFO_T prP2pBssInfo,
IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo)
{
do {
ASSERT_BREAK((prAdapter != NULL) || (prChnlReqInfo != NULL));
cnmTimerStopTimer(prAdapter, &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer));
prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucOriChnlNum;
prP2pBssInfo->eBand = prChnlReqInfo->eOriBand;
prP2pBssInfo->eBssSCO = prChnlReqInfo->eOriChnlSco;
kalP2PIndicateChannelExpired(prAdapter->prGlueInfo,
prChnlReqInfo->u8Cookie,
prChnlReqInfo->ucReqChnlNum,
prChnlReqInfo->eBand, prChnlReqInfo->eChnlSco);
p2pFuncReleaseCh(prAdapter, prP2pDevFsmInfo->ucBssIndex, prChnlReqInfo);
} while (FALSE);
} /* p2pDevStateAbort_CHNL_ON_HAND */
VOID p2pDevStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo)
{
do {
ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL));
prScanReqInfo->fgIsScanRequest = TRUE;
p2pFuncRequestScan(prAdapter, ucBssIndex, prScanReqInfo);
} while (FALSE);
} /* p2pDevStateInit_CHNL_ON_HAND */
VOID p2pDevStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo)
{
P_P2P_SCAN_REQ_INFO_T prScanInfo = (P_P2P_SCAN_REQ_INFO_T) NULL;
do {
ASSERT_BREAK((prAdapter != NULL) && (prP2pDevFsmInfo != NULL));
prScanInfo = &(prP2pDevFsmInfo->rScanReqInfo);
p2pFuncCancelScan(prAdapter, prP2pDevFsmInfo->ucBssIndex, prScanInfo);
kalP2PIndicateScanDone(prAdapter->prGlueInfo, 0xFF, prScanInfo->fgIsAbort);
} while (FALSE);
} /* p2pDevStateAbort_CHNL_ON_HAND */
BOOLEAN
p2pDevStateInit_OFF_CHNL_TX(IN P_ADAPTER_T prAdapter,
IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo,
IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo,
IN P_P2P_MGMT_TX_REQ_INFO_T prP2pMgmtTxInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState)
{
P_P2P_OFF_CHNL_TX_REQ_INFO_T prP2pOffChnlTxPkt = (P_P2P_OFF_CHNL_TX_REQ_INFO_T) NULL;
BOOLEAN fgIsTransition = FALSE;
do {
ASSERT_BREAK((prAdapter != NULL) && (prP2pMgmtTxInfo != NULL)
&& (peNextState != NULL));
if (!LINK_IS_EMPTY(&(prP2pMgmtTxInfo->rP2pTxReqLink))) {
prP2pOffChnlTxPkt =
LINK_PEEK_HEAD(&(prP2pMgmtTxInfo->rP2pTxReqLink), P2P_OFF_CHNL_TX_REQ_INFO_T, rLinkEntry);
if (prP2pOffChnlTxPkt == NULL) {
DBGLOG(P2P, ERROR, "Fetal Error, Link not empty but get NULL pointer.\n");
ASSERT(FALSE);
break;
}
if (prChnlReqInfo->ucReqChnlNum != prP2pOffChnlTxPkt->rChannelInfo.ucChannelNum) {
prChnlReqInfo->ucReqChnlNum = prP2pOffChnlTxPkt->rChannelInfo.ucChannelNum;
prChnlReqInfo->eChnlSco = prP2pOffChnlTxPkt->eChnlExt;
prChnlReqInfo->eBand = prP2pOffChnlTxPkt->rChannelInfo.eBand;
prChnlReqInfo->u8Cookie = 0;
prChnlReqInfo->eChannelWidth = CW_20_40MHZ;
prChnlReqInfo->ucCenterFreqS1 = 0;
prChnlReqInfo->ucCenterFreqS2 = 0;
ASSERT(prChnlReqInfo->eChnlReqType == CH_REQ_TYPE_OFFCHNL_TX);
p2pFuncAcquireCh(prAdapter, prP2pDevFsmInfo->ucBssIndex, prChnlReqInfo);
} else {
LINK_REMOVE_HEAD(&(prP2pMgmtTxInfo->rP2pTxReqLink),
prP2pOffChnlTxPkt, P_P2P_OFF_CHNL_TX_REQ_INFO_T);
p2pFuncTxMgmtFrame(prAdapter,
prP2pDevFsmInfo->ucBssIndex,
prP2pOffChnlTxPkt->prMgmtTxMsdu, prP2pOffChnlTxPkt->fgNoneCckRate);
prP2pMgmtTxInfo->prMgmtTxMsdu = prP2pOffChnlTxPkt->prMgmtTxMsdu;
prP2pMgmtTxInfo->fgIsWaitRsp = prP2pOffChnlTxPkt->fgIsWaitRsp;
}
} else {
/* Link is empty, return back to IDLE. */
*peNextState = P2P_DEV_STATE_IDLE;
fgIsTransition = TRUE;
}
} while (FALSE);
return fgIsTransition;
} /* p2pDevSateInit_OFF_CHNL_TX */
VOID
p2pDevStateAbort_OFF_CHNL_TX(IN P_ADAPTER_T prAdapter,
IN P_P2P_MGMT_TX_REQ_INFO_T prP2pMgmtTxInfo,
IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN ENUM_P2P_DEV_STATE_T eNextState)
{
P_P2P_OFF_CHNL_TX_REQ_INFO_T prP2pOffChnlTxPkt = (P_P2P_OFF_CHNL_TX_REQ_INFO_T) NULL;
if (eNextState != P2P_DEV_STATE_OFF_CHNL_TX) {
while (!LINK_IS_EMPTY(&(prP2pMgmtTxInfo->rP2pTxReqLink))) {
LINK_REMOVE_HEAD(&(prP2pMgmtTxInfo->rP2pTxReqLink),
prP2pOffChnlTxPkt, P_P2P_OFF_CHNL_TX_REQ_INFO_T);
if (prP2pOffChnlTxPkt)
kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo,
prP2pOffChnlTxPkt->prMgmtTxMsdu, FALSE);
else
DBGLOG(P2P, INFO, "No packet for indicating Tx status!\n");
}
p2pFuncReleaseCh(prAdapter, P2P_DEV_BSS_INDEX, prChnlReqInfo);
}
} /* p2pDevSateAbort_OFF_CHNL_TX */