/**
 * @file  hv_drv_TypecPolicyEngineSink.c
 * @brief  This file contains the function definitions for Sink Policy Engine state-machine
 * @details This file provides the following functions: \n
 *          (1) \n
 *          (2) \n
 *          (3) \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-25
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author                         <th>Date         <th>Change Description
 * <tr><td>Hiview SoC Software Team       <td>2022-08-25   <td>init
 * </table>
*/

#include <hv_drv_TypecStdInc.h>

extern UINT64 uiPDTimeTick;

#if (HV_TRUE == INCLUDE_PD_SINK)

void PE_RunSnkStateMachine (UINT8 u8PortNum, const UINT8 *pu8DataBuf, UINT32 u32Header)
{
    UINT8 u8TypeCState = TYPEC_INVALID_STATE;
    UINT8 u8TypeCSubState = TYPEC_INVALID_SUBSTATE;
    UINT8 u8aDataObj[PRL_MAX_DATA_OBJ_COUNT*PRL_SINGLE_DATAOBJ_SIZE_IN_BYTES] = {SET_TO_ZERO};
    UINT16 u16TransmitHeader = SET_TO_ZERO;
    PRLTxCallback pfnTransmitCB = PE_StateChange_TransmitCB;
    UINT32 u32TransmitTmrIDTxSt = SET_TO_ZERO;
    UINT8 u8IsTransmit = HV_FALSE;
    
    /*Getting Type-C state and Type-C Sub State from DPM to find Type C detach event*/
    DPM_GetTypeCStates (u8PortNum, &u8TypeCState, &u8TypeCSubState);
    
    /*If the Device is detached, set the Policy Engine State to PE_SNK_STARTUP */
    if (((TYPEC_UNATTACHED_SNK == u8TypeCState) || ((TYPEC_ATTACHWAIT_SNK == u8TypeCState))) && \
        ((gasPolicyEngine[u8PortNum].ePEState != ePE_SNK_STARTUP) \
        && (gasPolicyEngine[u8PortNum].ePEState != ePE_SNK_DISCOVERY)))
    {
        /*Reset the HardResetCounter*/
        gasPolicyEngine[u8PortNum].u8HardResetCounter = RESET_TO_ZERO;
        gasPolicyEngine[u8PortNum].ePEState = ePE_SNK_STARTUP;
        
        /* Set cable spec revision to default spec revision on every detach */
        DPM_UpdatePDSpecRev (u8PortNum, CONFIG_PD_DEFAULT_SPEC_REV, PRL_SOP_P_TYPE);        
    }
  
    switch (gasPolicyEngine[u8PortNum].ePEState)
    {
        case ePE_SNK_STARTUP:
        {         
            DEBUG_PRINT_PORT_STR (u8PortNum,"PE_SNK_STARTUP\r\n");
 
            /*Reset the Protocol Layer */
            PRL_ResetProtocolLayer (u8PortNum);

            /*Explicit Contract becomes invalid once this state is reached 
            from Hard Reset or Initial Power up*/
            gasPolicyEngine[u8PortNum].u8PEPortSts &= (~PE_EXPLICIT_CONTRACT);
        
            /*Reset the all the sink status set*/
            gasCfgStatusData.sPerPortData[u8PortNum].u32PortConnectStatus &= \
                        ~(DPM_PORT_SINK_CAPABILITY_MISMATCH_STATUS |
                            DPM_PORT_AS_SNK_LAST_REQ_PS_RDY_STATUS |
                            DPM_PORT_AS_SNK_LAST_REQ_ACCEPT_STATUS |
                            DPM_PORT_AS_SNK_LAST_REQ_REJECT_STATUS);           
            
            #if (HV_FALSE != INCLUDE_PDFU)
            if ((HV_FALSE != gsPdfuInfo.u8IsPDFUActive) && (u8PortNum == gsPdfuInfo.u8PDFUPortNum))
            {
                PE_FwUpdtInitialize();
            }
            #endif

            gasPolicyEngine[u8PortNum].ePEState = ePE_SNK_DISCOVERY;
            
            break;
        }            

        case ePE_SNK_DISCOVERY:
        {
            /*This State will be useful in getting the VBUS status, if the state machine comes 
            from ePE_SNK_TRANSITION_TO_DEFAULT state*/
    
            /*Query the Device policy manager for VBUS of 5V Presence*/
            if ((TYPEC_VBUS_5V == DPM_GetVBUSVoltage (u8PortNum)) && \
                (TYPEC_ATTACHED_SNK == u8TypeCState))
            {
                DEBUG_PRINT_PORT_STR (u8PortNum,"PE_SNK_DISCOVERY\r\n");
                
                gasPolicyEngine[u8PortNum].u8PEPortSts &= ~PE_HARDRESET_PROGRESS_MASK;
                  /* Enable Power fault thresholds for TYPEC_VBUS_5V to detect Power faults*/
                TypeC_ConfigureVBUSThr (u8PortNum, TYPEC_VBUS_5V, \
                    gasDPM[u8PortNum].u16SinkOperatingCurrInmA, TYPEC_CONFIG_PWR_FAULT_THR);
                
                gasPolicyEngine[u8PortNum].ePEState = ePE_SNK_WAIT_FOR_CAPABILITIES;
                gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_WAIT_FOR_CAPABILITIES_ENTRY_SS;
            }
            else
            {
                /* Hook to notify PE state machine entry into idle sub-state */
                HV_PSF_HOOK_NOTIFY_IDLE(u8PortNum, eIDLE_PE_NOTIFY);
            }
            break;                
        }
           
        case ePE_SNK_WAIT_FOR_CAPABILITIES:
        {
            switch (gasPolicyEngine[u8PortNum].ePESubState)
            {
                case ePE_SNK_WAIT_FOR_CAPABILITIES_ENTRY_SS:
                {   
                    //DEBUG_PRINT_PORT_STR (u8PortNum,"PE_SNK_WAIT_FOR_CAPABILITIES_ENTRY_SS\r\n");
                    
                    if (gasPolicyEngine[u8PortNum].u8HardResetCounter <= PE_N_HARD_RESET_COUNT)
                    {
                        /*Start the PE_SINKWAITCAP_TIMEOUT_MS to wait for the source 
                        capability message*/
                        /*Set the timer callback to transition to 
                        ePE_SNK_HARD_RESET and ePE_SNK_HARD_RESET_SEND_SS sub state if timeout happens*/
                        gasPolicyEngine[u8PortNum].u8PETimerID = PDTimer_Start (\
                                                                 PE_SINKWAITCAP_TIMEOUT_MS,\
                                                                 PE_SSChngAndTimeoutValidate_TimerCB,\
                                                                 u8PortNum, \
                                                                 (UINT8)ePE_SNK_HARD_RESET_SEND_SS);
                    }
                    else 
                    {
                        /*if u8HardResetCounter is greater than PE_N_HARD_RESET_COUNT*/
                        /*Stay in PE_SNK_Wait_for_Capabilities State if HardReset Counter Overflowed*/
                        /*Update EN_SINK based on implicit current from source 
                          and Wait for Source capability message*/
                        PWRCTRL_ConfigEnSink (u8PortNum, HV_TRUE);
                    }

                    gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_WAIT_FOR_CAPABILITIES_WAIT_SS;                    
                    
                    break;
                }
                /*Wait in this sub-state for the reception of Source capability message 
                from source partner*/    
                case ePE_SNK_WAIT_FOR_CAPABILITIES_WAIT_SS:
                {
                    #if 0
                    UINT8 u8Data = SET_TO_ZERO;
                    /* BIT2: 0 pref source
                             1 pref sink*/
                    UINT8 u8Pref = Hv_Typec_RegReadByte(u8PortNum, UPD_REG_RW_CONFIG_LOW);
                    if (u8Pref&BIT_2)
                    {
                        u8Pref = 1;// pref sink
                    }
                    else
                    {
                        u8Pref = 0;
                    }

                    /* BIT0 RD cc1
                       BIT1 RD cc2
                       BIT2 RP cc1
                       BIT3 RP cc2 */
                    UINT8 u8RegVal = Hv_Typec_RegReadByte(u8PortNum, UPD_REG_RW_CC_RPRD_SET);

                    /*Get the state being advertised from DRP_CTL_HIGH register*/
                    Hv_Typec_RegisterReadISR (u8PortNum, UPD_REG_RO_FSM_STATE, &u8Data, BYTE_LEN_1);

                    DEBUG_PRINT_PORT_STR (u8RegVal<<24 | u8Data<<16 | u8Pref<<8,"u8RegVal fsm pref=====\r\n");

                    #endif
                    /* Hook to notify PE state machine entry into idle sub-state */
                    HV_PSF_HOOK_NOTIFY_IDLE(u8PortNum, eIDLE_PE_NOTIFY);
                    
                    break; 
                }
                default:
                {
                    break;
                }
            }
            break;
        }
        /*This State is set by the PE_ReceiveMsgHandler API if the source capability message has been received*/    
        case ePE_SNK_EVALUATE_CAPABILITY:
        {     
            DEBUG_PRINT_PORT_STR (u8PortNum,"PE_SNK_EVALUATE_CAPABILITY\r\n");
              
            if (gasDPM[u8PortNum].u16InternalEvntInProgress != DPM_INT_EVT_INITIATE_RENEGOTIATION)
            {
                /* Notify the new source capability is received*/
                (void)DPM_NotifyClient (u8PortNum, eHV_PSF_NEW_SRC_CAPS_RCVD);
            }

            /*Reset the HardResetCounter*/
            gasPolicyEngine[u8PortNum].u8HardResetCounter = RESET_TO_ZERO;                            

            /*Ask the Device policy manager to evaluate the received source capability message*/
            DPM_EvaluateRcvdSrcCaps (u8PortNum, (UINT16) u32Header, pu8DataBuf);
#if (HV_TRUE == CONFIG_HOOK_DEBUG_MSG)
            DPM_EvaluatePartnerCapabilities(u8PortNum);
#endif
            /*Invalid Source Capability Message results in Sink request object count to be 0*/
            if (SET_TO_ZERO == gasCfgStatusData.sPerPortData[u8PortNum].u32RDO)
            //if (0)
            {
                /*Transition to Ready state if already in PD contract*/
                if (PE_EXPLICIT_CONTRACT == (gasPolicyEngine[u8PortNum].u8PEPortSts \
                        & PE_PDCONTRACT_MASK))
                {
                     gasPolicyEngine[u8PortNum].ePEState = ePE_SNK_READY;
                     gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_READY_END_AMS_SS;
                }
                 /*Transition to sink wait for capabilities state if not in PD contract*/
                else
                {
                    gasPolicyEngine[u8PortNum].ePEState = ePE_SNK_WAIT_FOR_CAPABILITIES;
                    gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_WAIT_FOR_CAPABILITIES_ENTRY_SS;
                }            
            }
            /*Valid Source capability results in transition to ePE_SNK_SELECT_CAPABILITY state*/
            else
            {     
                gasPolicyEngine[u8PortNum].ePEState = ePE_SNK_SELECT_CAPABILITY;
                gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_SELECT_CAPABILITY_SEND_REQ_SS;            
            }
            break;
        }           
        case ePE_SNK_SELECT_CAPABILITY:
        {
            switch (gasPolicyEngine[u8PortNum].ePESubState)
            {
                case ePE_SNK_SELECT_CAPABILITY_SEND_REQ_SS:
                {    
                    DEBUG_PRINT_PORT_STR (u8PortNum,"PE_SNK_SELECT_CAPABILITY_SEND_REQ_SS\r\n");
                    
                    /*Set the PD message transmitter API variables to send Sink Data request Message*/                    
                    u16TransmitHeader = PRL_FormSOPTypeMsgHeader (u8PortNum, PE_DATA_REQUEST,\
                                            PE_OBJECT_COUNT_1, PE_NON_EXTENDED_MSG);
                    
                    //u32aDataObj[INDEX_0] = gasCfgStatusData.sPerPortData[u8PortNum].u32RDO;   
                    HV_PSF_HOOK_MEMCPY8_FROM_WORD(u8aDataObj, &gasCfgStatusData.sPerPortData[u8PortNum].u32RDO, SIZEOF(UINT32));
                    
                    /*Set the transmitter callback to transition to Soft reset state if
                    message transmission fails*/
                    u32TransmitTmrIDTxSt = PRL_BUILD_PKD_TXST_U32(ePE_SNK_SELECT_CAPABILITY,\
                                             ePE_SNK_SELECT_CAPABILITY_REQ_SENT_SS,\
                                             ePE_SEND_SOFT_RESET,\
                                             ePE_SEND_SOFT_RESET_ENTRY_SS );
                    
                    u8IsTransmit = HV_TRUE;
                    
                    gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_SELECT_CAPABILITY_SEND_REQ_IDLE_SS;
                    
                    break;                                   
                }
                 /*Wait here until the Sink data request message is sent*/
                case ePE_SNK_SELECT_CAPABILITY_SEND_REQ_IDLE_SS:
                {    
                    /* Hook to notify PE state machine entry into idle sub-state */
                    HV_PSF_HOOK_NOTIFY_IDLE(u8PortNum, eIDLE_PE_NOTIFY);
                    
                    break;
                }
                    
                case ePE_SNK_SELECT_CAPABILITY_REQ_SENT_SS:
                {
                    /*Start the PE_SENDERRESPONSE_TIMEOUT_MS for the Sink Data request message sent*/
                    /*Set the timer callback to transition to 
                    ePE_SNK_HARD_RESET state and ePE_SNK_HARD_RESET_SEND_SS sub state if timeout happens*/
                    DEBUG_PRINT_PORT_STR (u8PortNum,"ePE_SNK_SELECT_CAPABILITY_REQ_SENT_SS \r\n");

                    if (PD_SPEC_REVISION_3_0 == DPM_GET_CURRENT_PD_SPEC_REV (u8PortNum))
                    {
                        gasPolicyEngine[u8PortNum].u8PETimerID = PDTimer_Start (\
                                                                PE_SOURCECAPRESPONSE_TIMEOUT_MS,\
                                                                PE_SSChngAndTimeoutValidate_TimerCB,\
                                                                u8PortNum,(UINT8) ePE_SNK_HARD_RESET_SEND_SS);
                    }
                    else
                    {
                        gasPolicyEngine[u8PortNum].u8PETimerID = PDTimer_Start (\
                                                                PE_SENDERRESPONSE_TIMEOUT_MS,\
                                                                PE_SSChngAndTimeoutValidate_TimerCB,\
                                                                u8PortNum,(UINT8) ePE_SNK_HARD_RESET_SEND_SS);
                    }

                    gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_SELECT_CAPABILITY_WAIT_FOR_ACCEPT_SS;
                    
                    break;
                }
                
                /*Wait here for the accept message from Source for the sink data request*/
                case ePE_SNK_SELECT_CAPABILITY_WAIT_FOR_ACCEPT_SS:
                {
                    /* Hook to notify PE state machine entry into idle sub-state */
                    HV_PSF_HOOK_NOTIFY_IDLE(u8PortNum, eIDLE_PE_NOTIFY);
                    
                    break;
                }
                default:
                {
                    break;
                }
            }
            break;
        }
        /*This State is set by the PE_ReceiveMsgHandler API if the accept message has been received*/
        case ePE_SNK_TRANSITION_SINK:
        {
            switch (gasPolicyEngine[u8PortNum].ePESubState)
            {
                case ePE_SNK_TRANSITION_SINK_ENTRY_SS:
                {                    
                    DEBUG_PRINT_PORT_STR (gasCfgStatusData.sPerPortData[u8PortNum].u16NegoVoltageInmV,"PE_SNK_TRANSITION_SINK_ENTRY_SS\r\n");                                                       
                    DEBUG_PRINT_PORT_STR (gasDPM[u8PortNum].u32NegotiatedPDO,"u32NegotiatedPDO\r\n");
                    
                    /* Configure VBUS Threshold for the requested PDO */
                    TypeC_ConfigureVBUSThr (u8PortNum, \
                            gasCfgStatusData.sPerPortData[u8PortNum].u16NegoVoltageInmV, \
                                gasDPM[u8PortNum].u16SinkOperatingCurrInmA, \
                                    TYPEC_CONFIG_NON_PWR_FAULT_THR);
                
                    /* Requested current controlling */
                    // PWRCTRL_ConfigSinkHW 调用被移除，因为它没有实际作用
                    // PWRCTRL_ConfigSinkHW (u8PortNum, DPM_GET_VOLTAGE_FROM_PDO_MILLI_V(gasDPM[u8PortNum].u32NegotiatedPDO), gasDPM[u8PortNum].u16SinkOperatingCurrInmA);
                    
                    /*Initialize and run PE_PSTRANSITION_TIMEOUT_MS*/
                    /*Set the timer callback to transition to 
                    ePE_SNK_HARD_RESET and ePE_SNK_HARD_RESET_SEND_SS sub state if timeout happens*/
                    gasPolicyEngine[u8PortNum].u8PETimerID = PDTimer_Start (\
                                                              PE_PSTRANSITION_TIMEOUT_MS,\
                                                              PE_SSChngAndTimeoutValidate_TimerCB,\
                                                              u8PortNum, (UINT8)ePE_SNK_HARD_RESET_SEND_SS);
                    
                    gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_TRANSITION_SINK_WAIT_FOR_PSRDY_SS;
                    
                    break;
                }              
                /*Wait here for the PS Ready message from Source for the sink data request*/
                case ePE_SNK_TRANSITION_SINK_WAIT_FOR_PSRDY_SS:
                {
                    /* Hook to notify PE state machine entry into idle sub-state */
                    HV_PSF_HOOK_NOTIFY_IDLE(u8PortNum, eIDLE_PE_NOTIFY);
                    
                    break;
                }
                default:
                {
                    break;
                }               
            }
            break;
        }
        
        /*This State is set by the PE_ReceiveMsgHandler API if the PS_RDY message has been received*/
        case ePE_SNK_READY:
        {
            switch (gasPolicyEngine[u8PortNum].ePESubState)
            {
                case ePE_SNK_READY_ENTRY_SS:
                {                    
                    DEBUG_PRINT_PORT_STR (u8PortNum,"PE_SNK_READY_ENTRY_SS\r\n");
                    
                    /* Configure threshold to detect faults*/
                       DPM_EnablePowerFaultDetection (u8PortNum);
                    
                    /*Setting the explicit contract as True*/
                    gasPolicyEngine[u8PortNum].u8PEPortSts |= (PE_EXPLICIT_CONTRACT);                    
                                    
                    /*Set EN_SINK*/
                    PWRCTRL_ConfigEnSink (u8PortNum, HV_TRUE);

                    gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_READY_END_AMS_SS;
                    
                    /*Notify that contract is established*/
                    (void)DPM_NotifyClient (u8PortNum, eHV_PSF_PD_CONTRACT_NEGOTIATED);
                                        
                    if (DPM_PORT_SINK_CAPABILITY_MISMATCH_STATUS & \
                            gasCfgStatusData.sPerPortData[u8PortNum].u32PortConnectStatus)
                    {
                        /* Notify the capability mismatch*/
                        (void)DPM_NotifyClient (u8PortNum, eHV_PSF_CAPS_MISMATCH);
                    }
                    
                    break;
                }
                
                case ePE_SNK_READY_END_AMS_SS:
                {                 
                    DEBUG_PRINT_PORT_STR (u8PortNum,"PE_SNK_READY_END_AMS_SS\r\n");
                    
                    /* Request DPM to initiate internal events*/
                    DPM_InitiateInternalEvts (u8PortNum);
                    
                    gasDPM[u8PortNum].u16InternalEvntInProgress = RESET_TO_ZERO;                        

                    gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_READY_IDLE_SS;                                                           
                                        
                    break;
                }
                
                case ePE_SNK_READY_IDLE_SS:
                {
                    /* Hook to notify PE state machine entry into idle sub-state */
                    HV_PSF_HOOK_NOTIFY_IDLE(u8PortNum, eIDLE_PE_NOTIFY);
                    
                    break;
                }
                default:
                {
                    break;
                }               
            }
            break;
        }
        /*This State is entered if hard reset is to be transmitted to the port partner*/   
        case ePE_SNK_HARD_RESET:
        {
           switch (gasPolicyEngine[u8PortNum].ePESubState)
           {           
               case ePE_SNK_HARD_RESET_SEND_SS:
               {                     
                    DEBUG_PRINT_PORT_STR (u8PortNum,"PE_SNK_HARD_RESET_SEND_SS\r\n");

                    /*Kill All the Active timers of policy engine for the port*/
                    PE_KillPolicyEngineTimer (u8PortNum);
                    
                    /*Setting the Hard Reset IN progress bit to avoid VBUS discharge
                    when VBUS drops below VSinkDisconnnect*/
                    gasPolicyEngine[u8PortNum].u8PEPortSts |= PE_HARDRESET_PROGRESS_MASK;                   
                    
                    /* API to send HardReset is called*/
                    PRL_SendCableorHardReset (u8PortNum, PRL_SEND_HARD_RESET,\
                                             NULL, SET_TO_ZERO);
                    
                    /*Increment HardReset Counter*/
                    gasPolicyEngine[u8PortNum].u8HardResetCounter++; 

                    gasPolicyEngine[u8PortNum].ePEState = ePE_SNK_TRANSITION_TO_DEFAULT;
                    gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_TRANSITION_TO_DEFAULT_ENTRY_SS;            
                    
                    break;
               }
               default:
               {
                    break;
               }
            
            }
            break;               
        }
        /*This state is entered after the completion of Hard reset signal sent or 
        if any hard reset signal is received from port partner*/
        case ePE_SNK_TRANSITION_TO_DEFAULT:
        {            
           switch (gasPolicyEngine[u8PortNum].ePESubState)
           {                  
               case ePE_SNK_TRANSITION_TO_DEFAULT_ENTRY_SS:
               { 
                    DEBUG_PRINT_PORT_STR (u8PortNum,"PE_SNK_TRANSITION_TO_DEFAULT_ENTRY_SS\r\n");
                    
                    /*Setting the Hard Reset IN progress bit to avoid VBUS discharge
                    when VBUS drops below VSinkDisconnnect*/
                    gasPolicyEngine[u8PortNum].u8PEPortSts |= PE_HARDRESET_PROGRESS_MASK;
                     
                    /*Turn OFF VCONN if it sources currently*/
                    if (DPM_IsPortVCONNSource (u8PortNum))
                    {
                        TypeC_EnabDisVCONN (u8PortNum, TYPEC_VCONN_DISABLE); 
                        
                        /*Start the VCONN_OFF timer*/
                        /*This Timeout is implemented outside of the PD Specification to track 
                        VCONN Turn OFF error*/
                        gasPolicyEngine[u8PortNum].u8PETimerID = PDTimer_Start (\
                                                                  PE_VCONNOFF_TIMEOUT_MS,\
                                                                  DPM_VBUSOnOffOrVCONNOff_TimerCB,\
                                                                  u8PortNum,\
                                                                  (UINT8)SET_TO_ZERO); 
                    
                        gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_TRANSITION_TO_DEFAULT_WAIT_FOR_VCONN_OFF_SS;                    
                    }
                    else
                    {
                        gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_TRANSITION_TO_DEFAULT_RESETHW_SS;                    
                    }
                                       
                    break;                    
               }
               
               case ePE_SNK_TRANSITION_TO_DEFAULT_WAIT_FOR_VCONN_OFF_SS:
               {                
                    if(!DPM_IsPortVCONNSource (u8PortNum))
                    {                        
                        /*Stop the VCONN_OFF timer*/
                        PE_KillPolicyEngineTimer (u8PortNum);
                    
                        gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_TRANSITION_TO_DEFAULT_RESETHW_SS;                    
                    }
                    else
                    {
                        /* Hook to notify PE state machine entry into idle sub-state */
                        HV_PSF_HOOK_NOTIFY_IDLE(u8PortNum, eIDLE_PE_NOTIFY);
                    }
                    
                    break;                 
               }
                                                                     
               case ePE_SNK_TRANSITION_TO_DEFAULT_RESETHW_SS:
               {    
                    #if (HV_TRUE == INCLUDE_PD_FR_SWAP)
                    /* Disable FRS Signal Detection */
                    DPM_DISABLE_FRS_DET_EN(u8PortNum);
                    
                    /* De-assert EN_FRS pin */
                    PWRCTRL_DisableEnFRS (u8PortNum);
                    #endif 

                    /* Configuring VBUS threshold to detect VSafe0V and VSafe5V
                     as on reception of HardReset Source will transition to VSafe0V*/
                    TypeC_ConfigureVBUSThr (u8PortNum, TYPEC_VBUS_0V, \
                            gasDPM[u8PortNum].u16SinkOperatingCurrInmA, \
                            TYPEC_CONFIG_NON_PWR_FAULT_THR);
                    
                    gasPolicyEngine[u8PortNum].ePESubState = ePE_SNK_TRANSITION_TO_DEFAULT_WAIT_SS;
                    
                    break;                    
               }
               case ePE_SNK_TRANSITION_TO_DEFAULT_WAIT_SS:
               {                     
                    /*Transition only after the VBUS from Source has gone down to 0V*/
                    if (TYPEC_VBUS_0V == DPM_GetVBUSVoltage (u8PortNum))
                    {
                        /*Disable the VBUS discharge functionality since VBUS has reached vSafe0V*/                  
                        PWRCTRL_ConfigVBUSDischarge (u8PortNum, HV_FALSE);

                        /*Inform Protocol Layer about Hard Reset Complete */
                        PRL_OnHardResetComplete (u8PortNum);

                        /* ����Ӳ����λ�� VBUS�Ѿ�������0�� ���ǲ��ܽ��뵽TYPEC_ATTACHED_SNK_PD_DEB_TIMEOUT_SS������̣�
                            �������������̵Ļ��� �ͻ����detach������� ���ǲ�Ը�⿴��������, sourc������hard reset��vbus�ᱻ���ߵ���5V��
                            ���ʱ��ȥ���PE_HARDRESET_PROGRESS_MASK, ��ʱ��CC״̬���Ų������TYPEC_ATTACHED_SNK_PD_DEB_TIMEOUT_SS������
                            ��ʩ�ǰ��������Ķ�������ePE_SNK_DISCOVERY״̬�� */

                        gasPolicyEngine[u8PortNum].ePEState = ePE_SNK_STARTUP;
    
                        /* Post eHV_PSF_HARD_RESET_COMPLETE notification */
                        (void) DPM_NotifyClient (u8PortNum, eHV_PSF_HARD_RESET_COMPLETE);
                    }
                    else
                    {
                        /* Hook to notify PE state machine entry into idle sub-state */
                        HV_PSF_HOOK_NOTIFY_IDLE(u8PortNum, eIDLE_PE_NOTIFY);                        
                    }
                    break;                                 
               }
               default:
               {
                    break;
               }
           }
           break;        
        }            
  
        default:
        {
            break;
        }
    }  

    /*Send PD message if the variable "u8IsTransmit" is set as true inside the state machine*/
    if (u8IsTransmit)
    {
        (void) PRL_TransmitMsg (u8PortNum, PRL_SOP_TYPE, u16TransmitHeader, u8aDataObj,\
                        pfnTransmitCB, u32TransmitTmrIDTxSt);
    }

}
#endif
