/**
 * @file hv_mw_Hdcp.c
 * @brief MiddleWare Hdcp c file.
 * @details This file provides the following functions: \n
 *          (1) Initialization and reset functions \n
 *          (2) Set Hdcp Version functions \n
 *          (3) Hdcp Version Check functions \n
 *          (4) Hdcp1x FSM function for DP \n
 *          (5) Hdcp2x FSM function for DP \n
 *          (6) Hdcp1x FSM function for HDMI \n
 *          (7) Hdcp2x FSM function for HDMI \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-31
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author         <th>Date        <th>Change Description
 * <tr><td>dp group      <td>2022-08-31   <td>init
 * </table>
*/


#include "hv_mw_Hdcp.h"
#include "hv_comm_Define.h"
#include "hv_comm_DataType.h"
#include "hv_mw_SystemManager.h"
#include "hv_vos_Comm.h"
#include "hv_vos_Task.h"
#include "hv_mw_DisplayPort.h"

#define HDCP2x_DEBUG                0

/*
 * B0: Unauthenticated
 * B1: Compute Km
 * B2: Compute L
 * B3: Compute Ks
 * B4: Authenticated
 */

Status Hv_Mw_Hdcp1x_DpRxB1Computations(HdcpCtrlData* pstHdcpData)
{
    HV_ASSERT_VALID_PTR(pstHdcpData);

    HdcpRx* pstHdcpRx = &(pstHdcpData->stHdcpRx);
    UCHAR8 ucPortIndex = pstHdcpData->ucPortIndex;
    USHORT16 usR0;
    UCHAR8 ucHdcpPortIndex = pstHdcpData->ucHdcpIndex;

    /*检查入参*/
    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Drv_Hdcp1x_DpRxGetMsg(pstHdcpRx, ucPortIndex);

    Hv_Engine_RxCalcKm(pstHdcpRx->stHdcp1xRx.stParams.AKsv,pstHdcpRx->stHdcp1xRx.stParams.Km, ucHdcpPortIndex);

    Hv_Engine_RxBlockCipher(pstHdcpRx->stHdcp1xRx.stParams.An,pstHdcpRx->stHdcp1xRx.stParams.Km, 0,
            pstHdcpRx->stHdcp1xRx.stParams.Ks, pstHdcpRx->stHdcp1xRx.stParams.M0, &(pstHdcpRx->stHdcp1xRx.stParams.R0), ucHdcpPortIndex);

    usR0 = pstHdcpRx->stHdcp1xRx.stParams.R0;

    Hv_Drv_Hdcp1x_DpRxSetRI(usR0, ucPortIndex);
    Hv_Drv_Hdcp1x_DpRxAuthStart(ucPortIndex, ucHdcpPortIndex);
    Hv_Drv_Hdcp1x_NotifyTxIrq(HV_HDCP_1X_RX_STATUS_R0_AVAILABLE, ucPortIndex, ucHdcpPortIndex);
    Hv_Mw_DpRx_IrqHpd(pstHdcpData->enInputPortIndex);

    HV_LOG_INFO(HDCP, "DP%d HDCP1X on HDCP%d AUTHENTICATED with R0 :%x", ucPortIndex, ucHdcpPortIndex, usR0);

    return HV_SUCCESS;
}

static Status Hv_Mw_Hdcp2x_DpRxB1AKESendHPrime(HdcpCtrlData* pstHdcpData)
{
    HV_ASSERT_VALID_PTR(pstHdcpData);

    HdcpRx* pstHdcpRx = &(pstHdcpData->stHdcpRx);
    UCHAR8 ucPortIndex = pstHdcpData->ucPortIndex;

    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Engine_RxComputeHPrime(pstHdcpRx->stHdcp2xRx.stParams.Rrx, pstHdcpRx->stHdcp2xRx.stParams.RxCaps,
    pstHdcpRx->stHdcp2xRx.stParams.Rtx, pstHdcpRx->stHdcp2xRx.stParams.TxCaps, pstHdcpRx->stHdcp2xRx.stParams.Km,
    pstHdcpRx->stHdcp2xRx.stParams.HPrime);
#if HDCP2x_DEBUG
    HV_LOG_INFO(HDCP, "DP 2x SendH!");
#endif
    Hv_Drv_Hdcp2x_DpSaveHPrimeToReg(pstHdcpRx->stHdcp2xRx.stParams.HPrime, ucPortIndex);
    Hv_Drv_Hdcp2x_NotifyTxIrq(HV_HDCP_2X_RX_STATUS_H_AVAILABLE, ucPortIndex, pstHdcpData->ucHdcpIndex);
    Hv_Mw_DpRx_IrqHpd(pstHdcpData->enInputPortIndex);

    return HV_SUCCESS;
}

Status Hv_Mw_Hdcp2x_DpRxB0ProcMsgAKESendCert(HdcpCtrlData* pstHdcpData)
{
    /*检查入参*/
    HV_ASSERT_VALID_PTR(pstHdcpData);

    HdcpRx* pstHdcpRx = &(pstHdcpData->stHdcpRx);
    UCHAR8 ucPortIndex = pstHdcpData->ucPortIndex;
    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    if (HV_SUCCESS == Hv_Drv_Hdcp2x_DpRxGetMsg(pstHdcpRx, HV_HDCP_2X_RX_MSG_ID_AKEINIT, ucPortIndex))
    {
        Hv_Drv_Hdcp2x_RxGenRrxAndCaps(pstHdcpRx, HV_HDCP_RECEIVER);
        Hv_Drv_Hdcp2x_DpRxSaveRrxToReg(pstHdcpRx->stHdcp2xRx.stParams.Rrx, ucPortIndex);
        pstHdcpData->bAuth = HV_FALSE;
    }
    else
    {
        HV_LOG_INFO(HDCP, "Hdcp 2x Get AKE Init Failed!");
        return HV_FAILURE;
    }

    HV_LOG_DEBUG(HDCP, "HDCP%d have received the AKE_INIT Massage on DP%d and Sent the cert.",
        pstHdcpData->ucHdcpIndex, pstHdcpData->ucPortIndex);

    return HV_SUCCESS;
}

Status Hv_Mw_Hdcp2x_DpRxB1ProcMsgAKENoStoredKm(HdcpCtrlData* pstHdcpData)
{
    /*检查入参*/
    HV_ASSERT_VALID_PTR(pstHdcpData);

    HdcpRx* pstHdcpRx = &(pstHdcpData->stHdcpRx);
    UCHAR8  ucPortIndex = pstHdcpData->ucPortIndex;
    INT32   Size;

    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Drv_Hdcp2x_DpRxGetMsg(pstHdcpRx, HV_HDCP_2X_RX_MSG_ID_AKENOSTOREDKM, ucPortIndex);

    if (HV_SUCCESS == Hv_Engine_RxRsaesOaepDecrypt(&pstHdcpRx->stHdcp2xRx, (HDCP2X_RX_KPriv *)pstHdcpRx->stHdcp2xRx.pucPrivKey,
            pstHdcpRx->stHdcp2xRx.stParams.EKpubKm, pstHdcpRx->stHdcp2xRx.stParams.Km, &Size))
    {
        Hv_Mw_Hdcp2x_DpRxB1AKESendHPrime(pstHdcpData);
    }
    else
    {
        HV_LOG_INFO(HDCP, "RsaesOaepDecrypt Failed!");
        return HV_FAILURE;
    }

    return HV_SUCCESS;
}


Status Hv_Mw_Hdcp2x_DpRxB1ProcMsgAKEStoredKm(HdcpCtrlData* pstHdcpData)
{
    /*检查入参*/
    HV_ASSERT_VALID_PTR(pstHdcpData);

    HdcpRx* pstHdcpRx = &(pstHdcpData->stHdcpRx);
    UCHAR8  ucPortIndex = pstHdcpData->ucPortIndex;

    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    pstHdcpRx->enKmStoreState = HV_HDCP_RX_STORED_KM;

    Hv_Drv_Hdcp2x_DpRxGetMsg(pstHdcpRx, HV_HDCP_2X_RX_MSG_ID_AKESTOREDKM, ucPortIndex);

    Hv_Engine_RxComputeEkh(pstHdcpRx->stHdcp2xRx.pucPrivKey, pstHdcpRx->stHdcp2xRx.stParams.EKh, pstHdcpRx->stHdcp2xRx.stParams.M, pstHdcpRx->stHdcp2xRx.stParams.Km);

#if HDCP2x_DEBUG
    HV_LOG_INFO(HDCP, "DP 2x StoredKm!");
#endif

    Hv_Mw_Hdcp2x_DpRxB1AKESendHPrime(pstHdcpData);

    return HV_SUCCESS;
}

Status Hv_Mw_Hdcp2x_DpRxB1ProcAKEPairing(HdcpCtrlData* pstHdcpData)
{
    /*检查入参*/
    HV_ASSERT_VALID_PTR(pstHdcpData);

    HdcpRx* pstHdcpRx = &(pstHdcpData->stHdcpRx);
    UCHAR8  ucPortIndex = pstHdcpData->ucPortIndex;
    UCHAR8 M[HV_HDCP_2X_RX_M_SIZE] = {0};
    /*检查入参*/
    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    if (HV_HDCP_NO_STORED_KM == pstHdcpRx->enKmStoreState)
    {
        /* Concatenate M = (Rtx || Rrx) */
        HV_MEMCPY(M, pstHdcpRx->stHdcp2xRx.stParams.Rtx, sizeof(pstHdcpRx->stHdcp2xRx.stParams.Rtx));
        HV_MEMCPY(M + sizeof(pstHdcpRx->stHdcp2xRx.stParams.Rtx), pstHdcpRx->stHdcp2xRx.stParams.Rrx, 
                sizeof(pstHdcpRx->stHdcp2xRx.stParams.Rrx));

        Hv_Engine_RxComputeEkh(pstHdcpRx->stHdcp2xRx.pucPrivKey, pstHdcpRx->stHdcp2xRx.stParams.Km, M, pstHdcpRx->stHdcp2xRx.stParams.EKh);

        Hv_Drv_Hdcp2x_DpSavePairingToReg(pstHdcpRx->stHdcp2xRx.stParams.EKh, ucPortIndex);

        Hv_Drv_Hdcp2x_NotifyTxIrq(HV_HDCP_2X_RX_STATUS_PAIRING_AVAILABLE, ucPortIndex, pstHdcpData->ucHdcpIndex);
        Hv_Mw_DpRx_IrqHpd(pstHdcpData->enInputPortIndex);
    }
    else
    {
        /* Do Noting */
    }
#if HDCP2x_DEBUG
    HV_LOG_INFO(HDCP, "DP 2x Send Pairing!");
#endif
    return HV_SUCCESS;
}

Status Hv_Mw_Hdcp2x_DpRxB2LCSendLPrime(HdcpCtrlData* pstHdcpData)
{
    /*检查入参*/
    HV_ASSERT_VALID_PTR(pstHdcpData);

    HdcpRx* pstHdcpRx = &(pstHdcpData->stHdcpRx);
    UCHAR8  ucPortIndex = pstHdcpData->ucPortIndex;

    /*检查入参*/
    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Drv_Hdcp2x_DpRxGetMsg(pstHdcpRx, HV_HDCP_2X_RX_MSG_ID_LCINIT, ucPortIndex);

    Hv_Engine_RxComputeLPrime(pstHdcpRx->stHdcp2xRx.stParams.Rn, pstHdcpRx->stHdcp2xRx.stParams.Km, pstHdcpRx->stHdcp2xRx.stParams.Rrx,
            pstHdcpRx->stHdcp2xRx.stParams.Rtx, pstHdcpRx->stHdcp2xRx.stParams.LPrime);

    Hv_Drv_Hdcp2x_DpSaveLPrimeToReg(pstHdcpRx->stHdcp2xRx.stParams.LPrime, ucPortIndex);

#if HDCP2x_DEBUG
    HV_LOG_INFO(HDCP, "DP 2x Send L!");
#endif

    return HV_SUCCESS;
}

Status Hv_Mw_Hdcp2x_DpRxB3ComputeKs(HdcpCtrlData* pstHdcpData)
{
    /*检查入参*/
    HV_ASSERT_VALID_PTR(pstHdcpData);

    HdcpRx* pstHdcpRx = &(pstHdcpData->stHdcpRx);
    UCHAR8  ucPortIndex = pstHdcpData->ucPortIndex;
    /*检查入参*/
    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    if(HV_SUCCESS == Hv_Drv_Hdcp2x_DpRxGetMsg(pstHdcpRx, HV_HDCP_2X_RX_MSG_ID_SKESENDEKS, ucPortIndex))
    {
        Hv_Engine_RxComputeKs(pstHdcpRx->stHdcp2xRx.stParams.Rrx, pstHdcpRx->stHdcp2xRx.stParams.Rtx, pstHdcpRx->stHdcp2xRx.stParams.Km,
                pstHdcpRx->stHdcp2xRx.stParams.Rn, pstHdcpRx->stHdcp2xRx.stParams.EDkeyKs, pstHdcpRx->stHdcp2xRx.stParams.Ks);
    }
    else
    {
        HV_LOG_INFO(HDCP, "HDCP 2X Get Msg Failed!\n");
        return HV_FAILURE;
    }

#if HDCP2x_DEBUG
    HV_LOG_INFO(HDCP, "DP 2x Compute Ks!");
#endif

    return HV_SUCCESS;
}

Status Hv_Mw_Hdcp2x_DpRxB4Authenticated(HdcpCtrlData* pstHdcpData)
{
    HV_ASSERT_VALID_PTR(pstHdcpData);
    
    HdcpRx* pstHdcpRx = &(pstHdcpData->stHdcpRx);
    UCHAR8  ucPortIndex = pstHdcpData->ucPortIndex;
    UCHAR8 ucHdcpPortIndex = pstHdcpData->ucHdcpIndex;
    /*检查入参*/
    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    HV_ASSERT_TRUE(ucHdcpPortIndex < HV_BOARD_CONFIG_MAX_HDCP_PORT_NUM);

    Hv_Drv_Hdcp2x_RxSaveKsRivToReg(pstHdcpRx->stHdcp2xRx.stParams.Ks, pstHdcpRx->stHdcp2xRx.stParams.Riv, ucHdcpPortIndex);

    return HV_SUCCESS;
}

Status Hv_Mw_Hdcp2x_DpRxB3ComputeKsB4Auth(HdcpCtrlData* pstHdcpData)
{
    HV_ASSERT_SUCCESS(Hv_Mw_Hdcp2x_DpRxB3ComputeKs(pstHdcpData));
    HV_ASSERT_SUCCESS(Hv_Mw_Hdcp2x_DpRxB4Authenticated(pstHdcpData));
    UCHAR8  ucPortIndex = pstHdcpData->ucPortIndex;
    UCHAR8 ucHdcpPortIndex = pstHdcpData->ucHdcpIndex;
    if (pstHdcpData->bAuth == HV_FALSE)
    {
        Hv_Drv_Hdcp2x_DpUpdateStreamType(ucPortIndex, ucHdcpPortIndex);
        Hv_Drv_Hdcp2x_DpRxAuthStart(ucPortIndex, ucHdcpPortIndex);
        pstHdcpData->bAuth = HV_TRUE;
        HV_LOG_INFO(HDCP, "DP%d HDCP2X on HDCP%d AUTHENTICATED!\n", ucPortIndex, ucHdcpPortIndex);
    }
    return HV_SUCCESS;
}

Status Hv_Mw_Hdcp2x_DpRxUpdateStreamType(HdcpCtrlData* pstHdcpData)
{
    HV_ASSERT_VALID_PTR(pstHdcpData);

    UCHAR8  ucPortIndex = pstHdcpData->ucPortIndex;
    UCHAR8 ucHdcpPortIndex = pstHdcpData->ucHdcpIndex;
    /*检查入参*/
    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    HV_ASSERT_TRUE(ucHdcpPortIndex < HV_BOARD_CONFIG_MAX_HDCP_PORT_NUM);

    Hv_Drv_Hdcp2x_DpUpdateStreamType(ucPortIndex, ucHdcpPortIndex);
    Hv_Drv_Hdcp2x_DpRxAuthStart(ucPortIndex, ucHdcpPortIndex);

    return HV_SUCCESS;
}

VOID Hv_Mw_Hdcp_DpResetLinkIntegrityFailure(UCHAR8 ucPortIndex)
{
    Hv_Drv_Hdcp1x_DpResetLinkIntegrityFailure(ucPortIndex);
    Hv_Drv_Hdcp2x_DpResetLinkIntegrityFailure(ucPortIndex);

    return;
}

/* Define Hdcp2x State Machine */
Hdcp2xRxStateMachine stDpHdcp2xRxStateMachine[] =
{
    {HdcpPortState_B0, Hdcp2xRxEvt_WrAKEInit,            Hv_Mw_Hdcp2x_DpRxB0ProcMsgAKESendCert,   HdcpPortState_B1, HdcpPortState_B0},
    {HdcpPortState_B1, Hdcp2xRxEvt_WrAKEInit,            Hv_Mw_Hdcp2x_DpRxB0ProcMsgAKESendCert,   HdcpPortState_B1, HdcpPortState_B0},
    {HdcpPortState_B1, Hdcp2xRxEvt_WrAKENoStoredKm,      Hv_Mw_Hdcp2x_DpRxB1ProcMsgAKENoStoredKm, HdcpPortState_B1, HdcpPortState_B0},
    {HdcpPortState_B1, Hdcp2xRxEvt_WrAKEStoredKm,        Hv_Mw_Hdcp2x_DpRxB1ProcMsgAKEStoredKm,   HdcpPortState_B2, HdcpPortState_B0},
    {HdcpPortState_B1, Hdcp2xRxEvt_RdHPrime,             Hv_Mw_Hdcp2x_DpRxB1ProcAKEPairing,       HdcpPortState_B2, HdcpPortState_B0},
    {HdcpPortState_B2, Hdcp2xRxEvt_WrAKEInit,            Hv_Mw_Hdcp2x_DpRxB0ProcMsgAKESendCert,   HdcpPortState_B1, HdcpPortState_B0},
    {HdcpPortState_B2, Hdcp2xRxEvt_WrLcInit,             Hv_Mw_Hdcp2x_DpRxB2LCSendLPrime,         HdcpPortState_B3, HdcpPortState_B0},
    {HdcpPortState_B3, Hdcp2xRxEvt_WrAKEInit,            Hv_Mw_Hdcp2x_DpRxB0ProcMsgAKESendCert,   HdcpPortState_B1, HdcpPortState_B0},
    {HdcpPortState_B3, Hdcp2xRxEvt_WrLcInit,             Hv_Mw_Hdcp2x_DpRxB2LCSendLPrime,         HdcpPortState_B3, HdcpPortState_B0},
    {HdcpPortState_B3, Hdcp2xRxEvt_WrAKESendEks,         Hv_Mw_Hdcp2x_DpRxB3ComputeKsB4Auth,      HdcpPortState_B4, HdcpPortState_B0},
    {HdcpPortState_B4, Hdcp2xRxEvt_WrAKEInit,            Hv_Mw_Hdcp2x_DpRxB0ProcMsgAKESendCert,   HdcpPortState_B1, HdcpPortState_B0},
    {HdcpPortState_B4, Hdcp2xRxEvt_UpdateStreamType,     Hv_Mw_Hdcp2x_DpRxUpdateStreamType,       HdcpPortState_B4, HdcpPortState_B0}
};

Status Hv_Mw_Hdcp_SetDpRxData(HdcpCtrlData* pstHdcpData, LinkPortIndex enInputPortIndex, UCHAR8 ucDpPortIndex)
{
    HV_ASSERT_VALID_PTR(pstHdcpData);
    UCHAR8 ucHdcpId = pstHdcpData->ucHdcpIndex;
    HV_ASSERT_TRUE(ucHdcpId < HV_BOARD_CONFIG_MAX_HDCP_PORT_NUM);

    pstHdcpData->enInputPortIndex = enInputPortIndex;
    pstHdcpData->enHdcpPortType = HdcpPortType_DisplayPort;
    pstHdcpData->ucPortIndex = ucDpPortIndex;
    pstHdcpData->stHdcpRx.stHdcp1xRx.BCaps = 1;
    pstHdcpData->enCurrentPort2xState = HdcpPortState_B0;
    pstHdcpData->stHdcpRx.enHdcp2xMsgState = HDCP2X_SEND_MSG_INVALID;
    pstHdcpData->stHdcpRx.stHdcp2xRx.stParams.RxCaps[0] = HdcpVesion_Hdcp2X;
    pstHdcpData->stHdcpRx.stHdcp2xRx.stParams.RxCaps[1] = 0;
    pstHdcpData->stHdcpRx.stHdcp2xRx.stParams.RxCaps[2] = HV_HDCP_RECEIVER;

    Hv_Drv_Hdcp_InitSel(ucHdcpId, 0);

    Hv_Drv_Hdcp_SetLaneClk(ucDpPortIndex, ucHdcpId);

    Hv_Drv_Hdcp_DpMuxSel(ucDpPortIndex, ucHdcpId);

    Hv_Drv_Hdcp_DpMixClr(ucHdcpId);

    return HV_SUCCESS;
}

Status Hv_Mw_Hdcp2x_RunDpRxFsm(HdcpRxEvtId uiHdcpRxEvt, HdcpCtrlData* pstHdcpData)
{   
    HdcpPort2xState enNxtState = HdcpPortState_Idle;
    USHORT16 usIndex = 0;
    UNUSED(enNxtState);
    HdcpPort2xState enHdcpCurState = pstHdcpData->enCurrentPort2xState;
    //HV_LOG_INFO(HDCP, "Dp 2x Fsm Get Evt:%d on Current State:%d.\n", uiHdcpRxEvt, enHdcpCurState);

    for (usIndex = 0; usIndex < sizeof(stDpHdcp2xRxStateMachine)/sizeof(stDpHdcp2xRxStateMachine[0]); usIndex++)
    {
        if ((uiHdcpRxEvt == stDpHdcp2xRxStateMachine[usIndex].enEvtId)
          &&(enHdcpCurState == stDpHdcp2xRxStateMachine[usIndex].enCurState))
        {
            if (HV_SUCCESS == stDpHdcp2xRxStateMachine[usIndex].pfEvtHandler(pstHdcpData))
            {
               enNxtState = stDpHdcp2xRxStateMachine[usIndex].enNxtSucState;
            }
            else
            {
               enNxtState = stDpHdcp2xRxStateMachine[usIndex].enNxtFailState;
            }

            HV_ASSERT_TRUE(HdcpPortState_Idle != enNxtState);

            if (enNxtState != stDpHdcp2xRxStateMachine[usIndex].enCurState)
            {
                pstHdcpData->enCurrentPort2xState = enNxtState;
            }
            else
            {
                //HV_LOG_INFO(HDCP, "Current State %d", stDpHdcp2xRxStateMachine[usIndex].enCurState);
            }
            break;
        }
        else
        {
            /*Do Noting*/
        }
    }
    return HV_SUCCESS;
}

static Status  Hv_Mw_Hdcp_DpEventHandler(HdcpRxEvtId uiHdcpRxEvt, HdcpCtrlData* pstHdcpData)
{
    HV_ASSERT_VALID_PTR(pstHdcpData);

    UCHAR8 ucPortIndex          = pstHdcpData->ucPortIndex;
    UCHAR8 ucHdcpId             = pstHdcpData->ucHdcpIndex;

    switch (uiHdcpRxEvt)
    {
        case Hdcp1xRxEvt_WrAksv:
        {
            pstHdcpData->enHdcpVersion = HdcpVesion_Hdcp1X;

            Hv_Drv_Hdcp1x_DpSetHdcpPath(ucHdcpId);

            Hv_Drv_Hdcp_AttachDpPath(ucPortIndex);

            break;
        }

        case Hdcp2xRxEvt_WrAKEInit:
        {
            pstHdcpData->enHdcpVersion = HdcpVesion_Hdcp2X;

            Hv_Drv_Hdcp2x_DpResetLinkIntegrityFailure(ucPortIndex);

            Hv_Drv_Hdcp2x_DpSetHdcpPath(ucHdcpId);

            Hv_Drv_Hdcp_AttachDpPath(ucPortIndex);

            break;
        }

        case Hdcp2xRxEvt_WrAKENoStoredKm :
        {
            pstHdcpData->stHdcpRx.enKmStoreState = HV_HDCP_NO_STORED_KM;
            break;
        }

        case Hdcp2xRxEvt_WrAKEStoredKm :
        {
            pstHdcpData->stHdcpRx.enKmStoreState = HV_HDCP_RX_STORED_KM;
            break;
        }

        default:
        {
            break;
        }
    }

    return HV_SUCCESS;
}

VOID Hv_Mw_Hdcp_ProcDpHdcpMessage(const UrgentEvent *pstUrgentEvent)
{
    LinkPortIndex enLinkPortIndex = pstUrgentEvent->usPortIndex;
    HdcpRxEvtId uiHdcpRxEvt = HdcpRxEvt_Invalid;
    UCHAR8 ucHdcpPortId = HDCP_PORT_INDEX_INVALID;
    HdcpCtrlData* pstHdcpData = NULL;

    static UCHAR8 ucDpPirntCtol = 0;

    HV_ASSERT_TRUE_VOID(enLinkPortIndex < LINK_PORT_INDEX_INVALID);

    ucHdcpPortId = Hv_Mw_Hdcp_GetValidHdcpPortIndex(enLinkPortIndex);
    if(ucHdcpPortId >= HV_BOARD_CONFIG_MAX_HDCP_PORT_NUM)
    {
        if((ucDpPirntCtol & 0xF) == 0)
        {
            HV_LOG_INFO(HDCP, "There is not a valid HDCP for InputPort Index : %d", enLinkPortIndex);
        }

        ucDpPirntCtol ++;

        return;
    }

    pstHdcpData = Hv_Mw_Hdcp_GetHdcpData(ucHdcpPortId);
    HV_ASSERT_VALID_PTR_VOID(pstHdcpData);

    uiHdcpRxEvt = Hv_Drv_Hdcp_DpGetIrqEvent(&(pstUrgentEvent->uiValue), pstHdcpData->ucPortIndex, pstHdcpData ->stHdcpRx.enKmStoreState);

    Hv_Mw_Hdcp_DpEventHandler(uiHdcpRxEvt, pstHdcpData);

    if(Hdcp1xRxEvt_WrAksv == uiHdcpRxEvt)
    {
        Hv_Mw_Hdcp1x_DpRxB1Computations(pstHdcpData);
    }
    else
    {
        Hv_Mw_Hdcp2x_RunDpRxFsm(uiHdcpRxEvt, pstHdcpData);
    }

    return;
}

Status Hv_Mw_Hdcp_DpIsrHandler(UINT32 uiIrqMask)
{
    UCHAR8 ucHdcpIndex = 0;
    UCHAR8 ucPortIndex = 0;
    HdcpCtrlData* pstHdcpData = NULL;

    if(uiIrqMask & HV_HDCP0_COM_IRQ_DP_LIC_DONE)
    {
        pstHdcpData = Hv_Mw_Hdcp_GetHdcpData(0);
    }
    else if(uiIrqMask & HV_HDCP1_COM_IRQ_DP_LIC_DONE)
    {
        pstHdcpData = Hv_Mw_Hdcp_GetHdcpData(1);
    }
    else
    {
        return HV_SUCCESS;
    }

    HV_ASSERT_VALID_PTR(pstHdcpData);

    if(pstHdcpData->enHdcpPortType != HdcpPortType_DisplayPort
        || pstHdcpData->enHdcpVersion == HdcpVesion_None)
    {
        return HV_SUCCESS;
    }
    
    ucHdcpIndex = pstHdcpData->ucHdcpIndex;
    ucPortIndex = pstHdcpData->ucPortIndex;
    HV_ASSERT_TRUE(ucPortIndex <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    HV_ASSERT_TRUE(ucHdcpIndex <= HV_BOARD_CONFIG_MAX_HDCP_PORT_NUM);

    if(HdcpVesion_Hdcp2X == pstHdcpData->enHdcpVersion)
    {
        Hv_Drv_Hdcp2x_NotifyTxIrq(HV_HDCP_2X_RX_STATUS_LINK_INTERGITY_FAILTURE, ucPortIndex, ucHdcpIndex);
    }
    else
    {
        Hv_Drv_Hdcp1x_NotifyTxIrq(HV_HDCP_1X_RX_STATUS_LINK_INTERGITY_FAILTURE, ucPortIndex, ucHdcpIndex);
    }
    Hv_Mw_DpRx_IrqHpd(pstHdcpData->enInputPortIndex);

    return HV_SUCCESS;
}

