/**
 * @file hv_mw_PowerManager.c
 * @brief PowerManager module driver
 * @details This module provide interfaces for Hiview-Madia-Ware.
 * @author HiView SoC Software Team
 * @version 0.0.1
 * @date 20220903
 * @copyright Copyright(c),2022-9, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author                         <th>Date             <th>Details
 * <tr><td>HiView SoC Software Team       <td>20220903         <td>Create and first Version.
 * </table>
 **/
#include <string.h>
#include "hv_comm_Assert.h"
#include "hv_comm_Define.h"
#include "hv_comm_Event.h"
#include "hv_comm_Timer.h"

#if (defined(CONFIG_USER_USB_OTA_ON) || defined(CONFIG_USER_USB_BILLBOARD_ON))
#include "hv_mw_UsbTask.h"
#endif
#include "hv_mw_PowerManager.h"
#include "hv_mw_PanelManager.h"
#include "hv_mw_InputPortManager.h"
#include "hv_mw_Channel_Manager.h"
#include "hv_mw_SystemManager.h"
#include "hv_drv_PLL.h"
#include "hv_drv_Flash.h"
#include "hv_drv_Gpio.h"
#include "hv_drv_Mailbox.h"
#include "PanelConfig.h"
#include "hv_mw_Led.h"
#ifdef CONFIG_USER_TYPE_C_ON
#include "hv_drv_TypecStdInc.h"
#include "hv_mw_TypecTask.h"
#endif
#include "hv_mw_DisplayPort.h"

#define POWROFF_PERIOD_1HOUR_TIMER_LENGTH      0x36EE80 //0xEA60
#define POWER_SIGNAL_DETECT_TIMER              1000      //50S

typedef struct _PowerStateMachine
{
    USHORT16        usAcceptState;
    PowerEventId    enEventId;
    Status          (*pfActionHandle)(const SystemEvent* pstEvent, PowerManager* pstPowerManager);
    PowerState      enNextState;
}PowerStateMachine;


static PowerManager s_stPowerManager;
/****************************inner function declare begin*************************************************/
static Status PowerStateMachineHandler_PowerOn(const SystemEvent* pstEvent, PowerManager * pstPowerManager);
static Status PowerStateMachineHandler_PowerNormal(const SystemEvent* pstEvent, PowerManager * pstPowerManager);
static Status PowerStateMachineHandler_FirstEnterStandby(const SystemEvent* pstEvent, PowerManager * pstPowerManager);
static Status PowerStateMachineHandler_EnterPm51(const SystemEvent* pstEvent, PowerManager* pstPowerManager);
static Status PowerStateMachineHandler_EnterPowerOff(const SystemEvent* pstEvent, PowerManager * pstPowerManager);
#ifdef CONFIG_USER_TYPE_C_ON
static Status PowerStateMachineHandler_TypeCPlugOut(const SystemEvent* pstEvent, PowerManager * pstPowerManager);
static Status PowerStateMachineHandler_EnterDelivery(const SystemEvent* pstEvent, PowerManager* pstPowerManager);
static Status PowerStateMachineHandler_TypeCVdmDone(const SystemEvent* pstEvent, PowerManager* pstPowerManager);
#endif
static Status PowerStateMachineHandler_EnterStandby(const SystemEvent* pstEvent, PowerManager* pstPowerManager);
static Status PowerStateMachineHandler_EnterResume(const SystemEvent* pstEvent, PowerManager * pstPowerManager);

/****************************inner function declare end*************************************************/

static const PowerStateMachine s_astPowerStateMachine[] = 
{
    {POWER_STATE_POWER_ON,   POWER_EVENT_ID_POWER_ON,                    PowerStateMachineHandler_PowerOn,           POWER_STATE_NORMAL},
    {POWER_STATE_NORMAL,     POWER_EVENT_ID_ON_FIRST_ENTER_STATE,        PowerStateMachineHandler_PowerNormal,       POWER_STATE_NORMAL},
    {POWER_STATE_NORMAL,     POWER_EVENT_ID_APP_TIME_OUT_OR_NO_SIGNAL,   PowerStateMachineHandler_EnterStandby,      POWER_STATE_STANDBY},

    {POWER_STATE_STANDBY,    POWER_EVENT_ID_ON_FIRST_ENTER_STATE,        PowerStateMachineHandler_FirstEnterStandby, POWER_STATE_STANDBY},    
    {POWER_STATE_STANDBY,    POWER_EVENT_ID_SIGNAL_NORMAL,               PowerStateMachineHandler_EnterResume,       POWER_STATE_NORMAL},
#ifdef CONFIG_USER_TYPE_C_ON 
    {POWER_STATE_ANY_STATE,  POWER_EVENT_ID_TYPE_C_DETAIL_PD_DONE,       PowerStateMachineHandler_EnterDelivery,     POWER_STATE_ANY_STATE},
    {POWER_STATE_ANY_STATE,  POWER_EVENT_ID_TYPE_C_PLUG_OUT,             PowerStateMachineHandler_TypeCPlugOut,      POWER_STATE_ANY_STATE},
    {POWER_STATE_ANY_STATE,  POWER_EVENT_ID_TYPE_C_DETAIL_VDM_DONE,      PowerStateMachineHandler_TypeCVdmDone,      POWER_STATE_ANY_STATE},
#endif    
    {POWER_STATE_ANY_STATE,  POWER_EVENT_ID_POWER_OFF_KEY,               PowerStateMachineHandler_EnterPowerOff,     POWER_STATE_ANY_STATE},
    {POWER_STATE_ANY_STATE,  POWER_EVENT_ID_STSTEM_STANDBY_READY,        PowerStateMachineHandler_EnterPm51,         POWER_STATE_OFF},
    {POWER_STATE_ANY_STATE,  SYS_EVENT_TIMER_POWER_SIGNAL_CHECK,         PowerStateMachineHandler_EnterPm51,         POWER_STATE_ANY_STATE},
};


#ifdef HV_SCALER_DEBUG_VERSION
static CHAR8* StateMachineStateConvert(PowerState enType)
{
    UINT32 uiIndex = 0;
    UINT32 uiLoop = 0;
    CHAR8* paType[] =
    {
        "POWER_ON",
        "NORMAL",
        "STANDBY",
        "OFF",
        "ANY_STATE",
    };
    if(0xFFFF == enType)
    {
        uiIndex = 4;
    }
    else
    {
        for(uiLoop = 0; uiLoop < 4; uiLoop++)
        {
            if((enType >> uiLoop) & 0x1)
            {
                uiIndex = uiLoop;
                break;
            }
        }
        if(uiLoop >= 4)
        {
            uiIndex = 4;
        }
    }
    return paType[uiIndex];
}

static CHAR8* ReasonTypeConvert(UINT32 uiReason)
{
    CHAR8* paType[] =
    {
        "Ac on",
        "HDMI Cable",
        "DP Cable",
        "Type-c Cable",
        "HDMI TMDS",
        "HDMI CEC",
        "DP Aux",
        "Type-c CC Command",
        "Power Key",
        "IR Key",
        "DP GPIO",
        "PowerOff"
    };
    if(uiReason >= sizeof(paType) / sizeof(paType[0]))
    {
        return "NULL";
    }
    else
    {
        return paType[uiReason];
    }
}

#endif

static VOID PowerOnLedIndicate(BOOL bEn)
{
    /*产品板开机指示灯*/

    return;
}

static Status PowerStateMachineHandler_PowerOn(const SystemEvent* pstEvent, PowerManager* pstPowerManager)
{
    HV_LOG_INFO(PM, "Monitor start working reason %s ,%u", ReasonTypeConvert(pstEvent->uiValue),pstEvent->uiValue);

    Hv_Drv_Ktx_SetPowerState(POWER_STATE_POWER_ON);
    Hv_Drv_Ktx_SetPowerOnReason(pstEvent->uiValue);
#ifdef HV_BOARD_CONFIG_GPIO_PANEL_LDC_BLESSEN
    Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_PANEL_LDC_BLESSEN, GPIO_LEVEL_HIGH);
#endif

#ifdef HV_BOARD_CONFIG_GPIO_PANEL_LDC_BKLESSEN
    Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_PANEL_LDC_BKLESSEN, GPIO_LEVEL_HIGH);
#endif
//    Hv_Vos_Delayus(2000000);
    if (pstEvent->uiValue == POWER_ON_REASON_TYPE_POWER_OFF)
    {
        pstPowerManager->bPowerOffFlag = 1;
        PowerStateMachineHandler_EnterPm51(pstEvent, pstPowerManager);
        /* wait poweroff here */
        return HV_CONTINUE;
    }
    Hv_Mw_Led_SetLedMode(LED_POWERON);
    pstPowerManager->enPowerOnReasonType = pstEvent->uiValue;
    s_stPowerManager.bFakeStandy = HV_FALSE;
    return HV_SUCCESS; 
}
#ifdef CONFIG_USER_TYPE_C_ON
static Status PowerStateMachineHandler_TypeCPlugOut(const SystemEvent* pstEvent, PowerManager* pstPowerManager)
{
    s_stPowerManager.bPowerDeliveryFlag = HV_FALSE;
    HV_LOG_INFO(PM, "TypeC Plug Out");
#if 0
    if(s_stPowerManager.enCurrentPowerState == POWER_STATE_STANDBY)
    {
        /* set power state to database for pm. */
        HV_COMMON_DATABASE_SET(TimeRec, ucPmPowerMode, POWER_STATE_STANDBY);
        HV_VOS_QUEUE_S *pstEventHubQueue = Hv_Mw_System_GetEventHubQueue();
        HV_ASSERT_VALID_PTR(pstEventHubQueue);
        Event stEvent = {0};
        stEvent.usEventId = EVENT_HUB_REV_MSG_ID_ENTER_STANDBY;
        stEvent.usValue = 0;
        HV_ASSERT_TRUE(Hv_Vos_QueueSend(pstEventHubQueue, &stEvent));
        HV_LOG_DEBUG(PM, "send standby message to EventHub success!!!");
    }
#endif
    return HV_SUCCESS;
}

static Status PowerStateMachineHandler_EnterDelivery(const SystemEvent* pstEvent, PowerManager* pstPowerManager)
{
    s_stPowerManager.bPowerDeliveryFlag = HV_TRUE;
    HV_LOG_INFO(PM, "TypeC start charging...");
    return HV_SUCCESS;
}

static Status PowerStateMachineHandler_TypeCVdmDone(const SystemEvent* pstEvent, PowerManager* pstPowerManager)
{
    HV_LOG_DEBUG(PM, "PowerTypeCVdmDoneHandler!!!");
    return HV_SUCCESS; 
}
#endif
static Status PowerStateMachineHandler_PowerNormal(const SystemEvent* pstEvent, PowerManager* pstPowerManager)
{
    Hv_Drv_Ktx_SetPowerState(POWER_STATE_NORMAL);
    s_stPowerManager.bFakeStandy = HV_FALSE;
    if (pstPowerManager->bSystemInit)
    {
        /*从假待机模式下返回normal态仅需要打开屏幕显示*/
        Hv_Mw_Led_SetRedLed(HV_FALSE);
        PanelEvent stPanelEvent = {0};
        stPanelEvent.usEventId = PANEL_EVENT_ID_PANEL_POWER_ON;
        HV_ASSERT_SUCCESS(Hv_Mw_Panel_SendInnerMsg(&stPanelEvent));
        HV_LOG_DEBUG(PM, "PANEL_EVENT_ID_PANEL_POWER_ON!!!");
        Hv_Mw_Led_SetLedMode(LED_POWERON);
    }
    else
    {
        pstPowerManager->bSystemInit = HV_TRUE;
        PanelEvent stPanelEvent = {0};
        stPanelEvent.usEventId = PANEL_EVENT_ID_PANEL_POWER_ON;
        HV_ASSERT_SUCCESS(Hv_Mw_Panel_SendInnerMsg(&stPanelEvent));
        HV_LOG_DEBUG(PM, "send PANEL_EVENT_ID_PANEL_POWER_ON success!!!");

        ChannelEvent stChannelEvent = {0};
        stChannelEvent.usEventId = CHANNEL_EVENT_ID_START;
        stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
        HV_ASSERT_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
        HV_LOG_DEBUG(PM, "send main CHANNEL_EVENT_ID_START success!!!");

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
        /*开启了PXP模式上电固定启动*/
        if (0 != (HV_COMMON_DATABASE_GET(UserData, ucPxPMode) || HV_COMMON_DATABASE_GET(UserData, bMagnifyGlassSw)))
        {
            stChannelEvent.usEventId = CHANNEL_EVENT_ID_START;
            stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
            HV_ASSERT_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            HV_LOG_DEBUG(PM, "send sub CHANNEL_EVENT_ID_START success!!!");
        }
#endif

        InputPortEvent stInputPortEvent = {0};
#if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
        stInputPortEvent.usEventId = InputPortEventId_HDMI_IdleStart;
        stInputPortEvent.enPortIndex = LINK_PORT_INDEX_HDMI_RX0;
        HV_ASSERT_SUCCESS(Hv_Mw_InputPort_SendInnerMsg(&stInputPortEvent));
        HV_LOG_DEBUG(PM, "send InputPortEventId_HDMI_IdleStart RX0 success!!!");
#endif
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
        stInputPortEvent.usEventId = InputPortEventId_HDMI_IdleStart;
        stInputPortEvent.enPortIndex = LINK_PORT_INDEX_HDMI_RX1;
        HV_ASSERT_SUCCESS(Hv_Mw_InputPort_SendInnerMsg(&stInputPortEvent));
        HV_LOG_DEBUG(PM, "send InputPortEventId_HDMI_IdleStart RX1 success!!!");
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
        stInputPortEvent.usEventId = InputPortEventId_DP_IdleStart;
        stInputPortEvent.enPortIndex = LINK_PORT_INDEX_DP_RX0;
        HV_ASSERT_SUCCESS(Hv_Mw_InputPort_SendInnerMsg(&stInputPortEvent));
        HV_LOG_DEBUG(PM, "send InputPortEventId_DP_IdleStart RX0 success!!!");
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        stInputPortEvent.usEventId = InputPortEventId_DP_IdleStart;
        stInputPortEvent.enPortIndex = LINK_PORT_INDEX_DP_RX1;
        HV_ASSERT_SUCCESS(Hv_Mw_InputPort_SendInnerMsg(&stInputPortEvent));
        HV_LOG_DEBUG(PM, "send InputPortEventId_DP_IdleStart RX1 success!!!");
#endif
    }

    return HV_SUCCESS;
}

static Status PowerStateMachineHandler_EnterStandby(const SystemEvent* pstEvent, PowerManager* pstPowerManager)
{
    HV_LOG_DEBUG(PM, "Power Enter Standby ");
    return HV_SUCCESS;
}

static Status PowerStateMachineHandler_FirstEnterStandby(const SystemEvent* pstEvent, PowerManager* pstPowerManager)
{
    HV_LOG_DEBUG(PM, "Enter standby");
    Hv_Drv_Ktx_SetPowerState(POWER_STATE_STANDBY);
    s_stPowerManager.bFakeStandy = HV_FALSE;
    /*关闭背光*/
    Hv_Mw_Panel_SetTimingChangeFlag(HV_FALSE);
    PanelEvent stPanelEvent = {0};
    stPanelEvent.usEventId = PANEL_EVENT_ID_BLK_OFF;
    HV_ASSERT_SUCCESS(Hv_Mw_Panel_SendInnerMsg(&stPanelEvent));
    HV_LOG_INFO(PM, "Be about to enter Standby,turn off backlight!");
    pstPowerManager->bPowerOffFlag = 0;

    Hv_Mw_Channel_StopAvWatchdogTimer();

    /*立即保存database数据!!!*/
    Hv_Mw_DataBase_Sync();
    return HV_SUCCESS;
}

static Status PowerStateMachineHandler_EnterPowerOff(const SystemEvent* pstEvent, PowerManager* pstPowerManager)
{
    HV_LOG_DEBUG(PM, "Enter Power off");
    Hv_Drv_Ktx_SetPowerState(POWER_STATE_OFF);
    /*关闭背光*/
    Hv_Mw_Panel_SetTimingChangeFlag(HV_FALSE);
    PanelEvent stPanelEvent = {0};
    stPanelEvent.usEventId = PANEL_EVENT_ID_BLK_OFF;
    HV_ASSERT_SUCCESS(Hv_Mw_Panel_SendInnerMsg(&stPanelEvent));
    HV_LOG_DEBUG(PM, "Be about to enter Power off,turn off backlight!");
    pstPowerManager->bPowerOffFlag = 1;

    Hv_Mw_Channel_StopAvWatchdogTimer();

    if (1 == HV_COMMON_DATABASE_GET(SystemData, bFactoryMode))
    {
        /*DC关机要退出工厂模式、退出老化*/
        HV_COMMON_DATABASE_SET(SystemData, bFactoryMode, 0);
        HV_COMMON_DATABASE_SET(SystemData, bBurnInEnable, 0);
    }
    /*立即保存database数据!!!*/
    Hv_Mw_DataBase_Sync();

    return HV_SUCCESS;
}

static void SendPoweroffEventToPowerManager(void* Arg, USHORT16 usEvent)
{
    HV_VOS_QUEUE_S *pstSystemQueue = Hv_Mw_System_GetSystemQueue();
    HV_ASSERT_VALID_PTR_VOID(pstSystemQueue);
    SystemEvent stEvent = {0};
    stEvent.enEventType = SYSTEM_REV_EVENT_TYPE_POWER;
    stEvent.usEventId = POWER_EVENT_ID_POWER_OFF_KEY;
    HV_ASSERT_TRUE_VOID(Hv_Vos_QueueSend(pstSystemQueue, &stEvent));
    HV_LOG_INFO(PM, "Send Power off key %u %u", stEvent.enEventType, stEvent.usEventId);
    return;
}

VOID Hv_Mw_Power_WakeUpFromStandby(VOID)
{
    HV_VOS_QUEUE_S *pstSystemQueue = Hv_Mw_System_GetSystemQueue();
    HV_ASSERT_VALID_PTR_VOID(pstSystemQueue);
    SystemEvent stEvent = {0};
    stEvent.enEventType = SYSTEM_REV_EVENT_TYPE_POWER;
    stEvent.usEventId = POWER_EVENT_ID_SIGNAL_NORMAL;
    HV_ASSERT_TRUE_VOID(Hv_Vos_QueueSend(pstSystemQueue, &stEvent));
}

static HV_TIMER_S*   s_pstPoweroffTimer = NULL;
static HV_TIMER_INIT_PARAMS s_stPoweroffTimerParam = \
    {"PoweroffTimer", POWROFF_PERIOD_1HOUR_TIMER_LENGTH, HV_FALSE, NULL, SendPoweroffEventToPowerManager, 0};

VOID Hv_Mw_Power_TimerStart(UINT32 uiHours)
{
    if (uiHours > 24)
    {
        uiHours = 24;
    }

    if (NULL != s_pstPoweroffTimer)
    {
        Hv_Vos_Timer_Delete(s_pstPoweroffTimer);
        s_pstPoweroffTimer = NULL;
    }

    if (uiHours != 0)
    {
        s_stPoweroffTimerParam.periodMs = POWROFF_PERIOD_1HOUR_TIMER_LENGTH * uiHours;
        s_pstPoweroffTimer = Hv_Vos_Timer_Create(&s_stPoweroffTimerParam);
        HV_ASSERT_VALID_PTR_VOID(s_pstPoweroffTimer);
        Hv_Vos_Timer_Start(s_pstPoweroffTimer);
    }

    return;
}

static Status PowerStateMachineHandler_EnterPm51(const SystemEvent* pstEvent, PowerManager* pstPowerManager)
{
    UCHAR8 ucFixMode = HV_FALSE;
    Event stEvent = {0};
    stEvent.usEventId = E_MAILBOX_CMD_RISC_TO_PM_FIX_MODE_OFF;
    stEvent.usValue = 0;
    HV_VOS_QUEUE_S *pstEventHubQueue = Hv_Mw_System_GetEventHubQueue();
    HV_ASSERT_VALID_PTR(pstEventHubQueue);

    //Event stEventMsg;
    //HV_MEMSET(&stEventMsg, 0 ,sizeof(Event));
    MailboxMsg stMailboxMsg = { 0 };
    InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    HV_ASSERT_VALID_PTR(pstInputPortManager);

    /*立即保存database数据!!!*/
    Hv_Mw_DataBase_Sync();
    HV_LOG_DEBUG(PM, "Enter pm51");
    if(0 == pstPowerManager->bPowerOffFlag)
    {
        if (s_stPowerManager.usSignalChecker == 0)
        {
            /*关闭PCB软件运行指示灯*/
            Hv_Mw_Led_SetLedMode(LED_POWERSTANDBY);
        }
        if(s_stPowerManager.usSignalChecker < 50)
        {
            Hv_Vos_Timer_Rstart(s_stPowerManager.pstSignalCheckTimer,0);

            if ((HV_FALSE == Hv_Mw_DpRx_GetAuxState(pstInputPortManager->enMainPortIndex))
            && (HV_FALSE == Hv_Mw_DpRx_GetAuxState(pstInputPortManager->enSubPortIndex)))
            {
                s_stPowerManager.usSignalChecker = 50;
            }
            else
            {
                s_stPowerManager.usSignalChecker++;
            }
            HV_LOG_INFO(PM, "Power Signal check!!");
            return HV_CONTINUE;
        }
        else
        {
            s_stPowerManager.usSignalChecker = 0;
            Hv_Vos_Timer_Rstop(s_stPowerManager.pstSignalCheckTimer);

            Hv_Vos_Delayus(25*1000);
            if (HV_FALSE == pstPowerManager->bPowerDeliveryFlag)
            {
                (Hv_Mw_InputPort_GetManagerPtr())->pfEnterStandby();

                /* set power state to database for pm. */
                HV_COMMON_DATABASE_SET(TimeRec, ucPmPowerMode, POWER_STATE_STANDBY);
                if (HV_TRUE != HV_COMMON_DATABASE_GET(UserData, bAutoVideoSrcSelSw))
                {
                    ucFixMode = HV_TRUE;
                }

                if (HV_TRUE == ucFixMode)
                {
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_FIX_MODE_ON;
                    Hv_Drv_MailboxSendMsg(&stMailboxMsg);
                    Hv_Vos_Delayus(25*1000);
                    #ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
                    if ((PXP_MODE_PIP_ENABLE == Hv_Mw_Channel_GetPxpMode())
                        || (PXP_MODE_PBP_ENABLE == Hv_Mw_Channel_GetPxpMode()))
                    {
                        stMailboxMsg.stMsgHeader.u8MsgType = (E_MAILBOX_CMD_RISC_TO_PM_CUR_SUB_CHANNEL_HDMI0 + HV_COMMON_DATABASE_GET(UserData, ucPxPVideoSource));
                        Hv_Drv_MailboxSendMsg(&stMailboxMsg);
                        Hv_Vos_Delayus(25*1000);
                    }
                    #endif
                    stMailboxMsg.stMsgHeader.u8MsgType = (E_MAILBOX_CMD_RISC_TO_PM_CUR_MAIN_CHANNEL_HDMI0 + HV_COMMON_DATABASE_GET(UserData, ucVideoSource));
                    Hv_Drv_MailboxSendMsg(&stMailboxMsg);
                }
                else
                {
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_FIX_MODE_OFF;
                    Hv_Drv_MailboxSendMsg(&stMailboxMsg);
                }

                Hv_Mw_DataBase_Sync();
                Hv_Drv_Flash_InWritting();
                Hv_Vos_Delayus(50*1000);
                stEvent.usEventId = EVENT_HUB_REV_MSG_ID_ENTER_STANDBY;
                HV_LOG_DEBUG(PM, "send EVENT_HUB_REV_MSG_ID_ENTER_STANDBY to EventHub !!!");
                Hv_Vos_FlushLogBuf();
                HV_ASSERT_TRUE(Hv_Vos_QueueSend(pstEventHubQueue, &stEvent));
                s_stPowerManager.bFakeStandy = HV_FALSE;
            }
            else
            {
                /*返回continue,假待机状态*/
                HV_LOG_INFO(PM, "TypeC be charging,fake standby");
                stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_SET_LED_OFF + HV_COMMON_DATABASE_GET(SystemData, ucPowerLedMode);
                Hv_Drv_MailboxSendMsg(&stMailboxMsg);
                s_stPowerManager.bFakeStandy = HV_TRUE;
                pstPowerManager->enPowerOnReasonType = POWER_ON_REASON_TYPE_TYPE_C_CABLE;
                return HV_CONTINUE;
            }
        }
    }
    else
    {
        /*关闭PCB软件运行指示灯*/
        Hv_Mw_Led_SetLedMode(LED_POWEROFF);
        Hv_Vos_Delayus(25*1000);

        (Hv_Mw_InputPort_GetManagerPtr())->pfEnterPowerOff();

#ifdef CONFIG_USER_TYPE_C_ON
        HV_PSF_HOOK_VBUS_PWR_SET(0, 0);
        TypeC_SetVBUSCompONOFF(0, 0);
        Hv_Typec_RegWriteByte(0, UPD_REG_TYPEC_VBUS_VALUE, 0);
#endif
        /* set power state to database for pm. */
        HV_COMMON_DATABASE_SET(TimeRec, ucPmPowerMode, POWER_STATE_OFF);
        Hv_Mw_DataBase_Sync();
        Hv_Drv_Flash_InWritting();
        /*给51发送待机消息*/
        stEvent.usEventId = EVENT_HUB_REV_MSG_ID_ENTER_POWEROFF;
        HV_LOG_DEBUG(PM, "send EVENT_HUB_REV_MSG_ID_ENTER_POWEROFF to EventHub !!!");
        Hv_Vos_FlushLogBuf();
        Hv_Vos_Delayus(50*1000);
        HV_ASSERT_TRUE(Hv_Vos_QueueSend(pstEventHubQueue, &stEvent));
    }

    return HV_SUCCESS;
}

static Status PowerStateMachineHandler_EnterResume(const SystemEvent* pstEvent, PowerManager* pstPowerManager)
{
    HV_LOG_INFO(PM, "Receive Signal Normal, Exit Standby");
    /*为了加快亮屏在panel init中给panel上电，所以这里需要重新上电*/
    s_stPowerManager.usSignalChecker = 0;
    Hv_Vos_Timer_Rstop(s_stPowerManager.pstSignalCheckTimer);
    Hv_Drv_Ktx_PanelVideoPower(1);
    s_stPowerManager.bFakeStandy = HV_FALSE;
    InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    pstInputPortManager->pfEnterResume();
    Hv_Mw_Led_SetLedMode(LED_POWERON);
    return HV_SUCCESS;
}

static Status RunPowerStateMachine(const SystemEvent* pstSystemEvent, PowerManager* pstPowerManager, BOOL* pbNeedChangeState)
{
    Status uiRetStatus = HV_FAILURE;
    *pbNeedChangeState = HV_FALSE;/*很关键必须置位false，否则convert消息如果在for循环中无法找到则pbNeedChangeState无法赋值为false，导致while死循环*/
    PowerState enNextState = POWER_STATE_ANY_STATE;
    for (USHORT16 usIndex = 0; usIndex < ARRAY_SIZE(s_astPowerStateMachine); ++usIndex)
    {
        if ((pstPowerManager->enCurrentPowerState & s_astPowerStateMachine[usIndex].usAcceptState)
           && (pstSystemEvent->usEventId == s_astPowerStateMachine[usIndex].enEventId))
        {
            uiRetStatus = s_astPowerStateMachine[usIndex].pfActionHandle(pstSystemEvent, pstPowerManager);
            if (HV_CONTINUE != uiRetStatus)
            {
                enNextState = s_astPowerStateMachine[usIndex].enNextState;
                HV_LOG_INFO(PM, "PM %s, next: %s", StateMachineStateConvert(pstPowerManager->enCurrentPowerState), StateMachineStateConvert(enNextState));
            }
            else
            {
                /*continue 以及其他返回值场景*/
                HV_LOG_INFO(PM, "PM %s, not change", StateMachineStateConvert(pstPowerManager->enCurrentPowerState));
            }

            if ((pstPowerManager->enCurrentPowerState != enNextState) && (POWER_STATE_ANY_STATE != enNextState))
            {
                pstPowerManager->enCurrentPowerState = enNextState;
                *pbNeedChangeState = HV_TRUE;
            }
            else
            {
                *pbNeedChangeState = HV_FALSE;
            }
            /*匹配之后 需要break!只能匹配一次*/
            break;
        }
    }
    return HV_SUCCESS;
}
#ifdef HV_SCALER_DEBUG_VERSION
static CHAR8* EventTypeConvert(SystemRevEventType enEventType)
{
    CHAR8* paEventType[] =
    {
        "power",
        "osd",
        "channel",
        "inputport",
        "panel",
        "timer",
        "ddc/ci"    
    };
    if(enEventType >= sizeof(paEventType) / sizeof(paEventType[0]))
    {
        return "NULL";
    }
    else
    {
        return paEventType[enEventType];
    }
}
static CHAR8* PowerEventIDConvert(USHORT16 enEventType)
{
    CHAR8* paEventIDType[] =
    {
        "first enter",
        "power on",
        "no signal",
        "signal normal",
        "power key off",
        "system standby ready",
#ifdef CONFIG_USER_TYPE_C_ON 
        "typec pd done",
        "type vdm done",
        "typec plugout",
#endif
    };
    if(enEventType >= sizeof(paEventIDType) / sizeof(paEventIDType[0]))
    {
        return "NULL";
    }
    else
    {
        return paEventIDType[enEventType];
    }

    return paEventIDType[enEventType];
}
#endif
Status Hv_Mw_Power_SystemQueueMsgProc(const SystemEvent* pstSystemEvent)
{
    BOOL bNeedChangeState = HV_FALSE;
#ifdef HV_SCALER_DEBUG_VERSION
    if(SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType)
    {
        HV_LOG_INFO(POWER, "PM %s ,%s, 0x%03x", EventTypeConvert(pstSystemEvent->enEventType),TimerEventIDConvert((TIMER_EVENT_E)pstSystemEvent->usEventId), pstSystemEvent->uiValue);
    }
    if(SYSTEM_REV_EVENT_TYPE_POWER == pstSystemEvent->enEventType)
    {
        HV_LOG_INFO(POWER, "PM %s, %s,0x%03x", EventTypeConvert(pstSystemEvent->enEventType),PowerEventIDConvert(pstSystemEvent->usEventId), pstSystemEvent->uiValue);
    }
#endif
    do
    {
        if (bNeedChangeState)
        {
            SystemEvent stConvertEvent;
            HV_MEMSET(&stConvertEvent, 0, sizeof(stConvertEvent));
            stConvertEvent.enEventType = SYSTEM_REV_EVENT_TYPE_POWER;
            stConvertEvent.usEventId = POWER_EVENT_ID_ON_FIRST_ENTER_STATE;
            RunPowerStateMachine(&stConvertEvent, &s_stPowerManager, &bNeedChangeState);
        }
        else
        {
            RunPowerStateMachine(pstSystemEvent, &s_stPowerManager, &bNeedChangeState);
        }
    } while (bNeedChangeState);
    
    return HV_SUCCESS;
}

const PowerManager* Hv_Mw_Power_GetManagerPtr(VOID)
{
    return &s_stPowerManager;
}

Status Hv_Mw_Power_ManagerInit(VOID)
{
    s_stPowerManager.enCurrentPowerState = POWER_STATE_POWER_ON;

    /*Typec发送通知消息更新PowerDeliveryFlag. power状态机使用该标志前会被typec正确的更新*/
    s_stPowerManager.bPowerDeliveryFlag = HV_FALSE;
    s_stPowerManager.bSystemInit = HV_FALSE;
    s_stPowerManager.bFakeStandy = HV_FALSE;
    HV_TIMER_INIT_PARAMS stSignalCheckTimerParam = \
    {"SignalCheckTimer", POWER_SIGNAL_DETECT_TIMER, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_POWER_SIGNAL_CHECK};
    s_stPowerManager.pstSignalCheckTimer = Hv_Vos_Timer_Create(&stSignalCheckTimerParam);
    HV_ASSERT_VALID_PTR(s_stPowerManager.pstSignalCheckTimer);
    return HV_SUCCESS;
}

PowerOnReasonType Hv_Mw_Power_GetPowerOnReasonType(VOID)
{
    return s_stPowerManager.enPowerOnReasonType;
}

Status Hv_Mw_Power_UpdatePowerManagerInfo(PowerManager stPowerManager)
{
    s_stPowerManager.bPowerOffFlag = stPowerManager.bPowerOffFlag;
    s_stPowerManager.bPowerDeliveryFlag = stPowerManager.bPowerDeliveryFlag;
    return HV_SUCCESS;
}

BOOL Hv_Mw_Power_GetPowerManagerFakeStandyFlag(VOID)
{
    return s_stPowerManager.bFakeStandy;
}

Status Hv_Mw_Power_SendPoweroffToPowerManager(VOID)
{
    HV_VOS_QUEUE_S *pstSystemQueue = Hv_Mw_System_GetSystemQueue();
    HV_ASSERT_VALID_PTR(pstSystemQueue);
    SystemEvent stEvent = {0};
#ifdef CONFIG_USER_USB_OTA_ON
    if(USB_STATE_OTA_IN_PROCESSING == Hv_Mw_USB_GetUsbState())
    {
        return HV_SUCCESS;
    }
#endif

    stEvent.enEventType = SYSTEM_REV_EVENT_TYPE_POWER;
    stEvent.usEventId = POWER_EVENT_ID_POWER_OFF_KEY;
    HV_ASSERT_TRUE(Hv_Vos_QueueSend(pstSystemQueue, &stEvent));
    HV_LOG_INFO(PM, "--send poweroff to system!");

    return HV_SUCCESS;
}
