/**
 * @file hv_app_DdcciFactory.c
 * @brief hisense ddcci factory c file.
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2023-01-31
 * @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>2024-01-10  <td>create
 * </table>
 */


#include "hv_mw_Ddcci.h"
#include "hv_app_Ddcci.h"
#include "hv_app_DdcciFactory.h"
#include "hv_comm_DataBase.h"
#include "hv_comm_MemParser.h"
#include "hv_mw_Hdmi.h"
#include "hv_mw_DisplayPort.h"
#include "hv_drv_Flash.h"
#include "hv_mw_Factory.h"
#include "hv_app_PQ.h"
#include "hv_drv_PQ.h"
#include "hv_mw_PQ.h"
#include "hv_drv_Gamma.h"
#include "hv_mw_SystemManager.h"
#include "HV_REGS_HT7315.h"

UINT32 auiGammaLut[3 * 1026 + 1] = { 0 };
USHORT16 ausColorSpaceData[18];

static UINT32 s_uiGammaEnableOri = 0;
static UINT32 s_uiWCGBypassOri = 0;
static UINT32 s_uiLdgBypassOri = 0;
static UINT32 s_uiLdgHdrPassOri = 0;

/**
 * @brief Calculate the CRC of hisense factory ddcci message. 
 * @param[in] VOID.
 * @return UCHAR8  CRC value.
 */
static UCHAR8 Hv_App_Ddcci_GenFactoryChecksum(UCHAR8 *pucData)
{
    UINT32 uiCount = 0;
    UINT32 uiCheckLen = 0;
    UCHAR8 ucSum = DDCCI_VIRTUAL_HOST_ADDRESS;

    uiCheckLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) + DDCCI_FAC_DDC_HEADER_LEN - 1;

    for (uiCount = 0; uiCount < uiCheckLen; uiCount++)
    {
        ucSum = ucSum ^ pucData[uiCount];
    }

    return ucSum;
}


/**
 * @brief Verify the CRC of incoming hisense factory ddcci message.
 * @param[in] VOID.
 * @return UCHAR8  CRC value.
 */
UCHAR8 Hv_App_Ddcci_VerifyFactoryCheckSum(UCHAR8 *pucData)
{
    UINT32 uiCount = 0;
    UINT32 uiCheckLen = 0;
    UCHAR8 ucSum = DDCCI_DEST_ADDRESS;

    uiCheckLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) + DDCCI_FAC_DDC_HEADER_LEN - 1;

    for (uiCount = 0; uiCount < uiCheckLen; uiCount++)
    {
        ucSum = ucSum ^ pucData[uiCount];
    }

    return ucSum;
}


static UINT32 Hv_App_Ddcci_ReadRegister(UINT32 uiAddr, UCHAR8 ucStartBit, UCHAR8 ucStopBit)
{
    UINT64 mask;
    UINT32 data;

    // 读取寄存器的值
    data = HV_R32(uiAddr);

    // 创建一个掩码，用于选择我们感兴趣的位
    mask = (((UINT64)1 << (ucStopBit - ucStartBit + 1)) - 1) << ucStartBit;

    // 使用掩码选择我们感兴趣的位，并将它们移动到最低位
    data = (data & mask) >> ucStartBit;

    return data;
}


static VOID Hv_App_Ddcci_WriteRegister(UINT32 uiAddr, UCHAR8 ucStartBit, UCHAR8 ucStopBit, UINT32 uiValue)
{
    UINT64 mask;
    UINT32 data;

    // 读取寄存器的值
    data = HV_R32(uiAddr);

    // 创建一个掩码，用于选择我们要修改的位
    mask = (((UINT64)1 << (ucStopBit - ucStartBit + 1)) - 1) << ucStartBit;

    // 清除我们要修改的位
    data &= ~mask;

    // 将新的值移动到正确的位置，并使用掩码将其添加到数据中
    data |= (uiValue << ucStartBit) & mask;

    // 写回寄存器的值
    HV_W32(uiAddr, data);
}


static VOID Hv_App_Ddcci_PQWriteCmdRsp(UCHAR8 ucSource, UCHAR8 *pucData)
{
    UCHAR8 ucRspData[DDCCI_FAC_WRITE_PQ_CMD_RSP_LEN] = { 0 };
    USHORT16 usRspLen = 0;
    USHORT16 usProtocolLen = 0;
    
    usRspLen = DDCCI_FAC_WRITE_PQ_CMD_RSP_LEN;
    usProtocolLen = usRspLen - DDCCI_FAC_DDC_HEADER_LEN;
    
    HV_MEMCPY(ucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
    
    ucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
    ucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
    ucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;
    ucRspData[DDCCI_FAC_OFFSET_PQ_CMD_RC] = DDCCI_FAC_RC_SUCCESS;
    ucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(ucRspData);
    Hv_App_Ddcci_SendData(ucSource, ucRspData, usRspLen);

    return;
}


static VOID Hv_App_Ddcci_PQGammaPrepare(VOID)
{
    Hv_Drv_PQ_DdcciGammaPrepare();
    return;
}

static VOID Hv_App_Ddcci_PQGammaFinish(VOID)
{
    Hv_Drv_PQ_DdcciGammaFinish();
    //HV_W32_FIELD(DISP_TOP_SUB_LDG_04, reg_main_csc_en, 1);

    return;
}


static VOID Hv_App_Ddcci_PQColorSpacePrepare(VOID)
{
    Hv_Drv_PQ_DdcciColorSpacePrepare(); 
    return;
}


static VOID Hv_App_Ddcci_PQWCGEnable(BOOL bEn)
{
    Hv_Drv_PQ_DdcciWcgEnable(bEn); 
    return;
}


static VOID Hv_App_Ddcci_PQWriteColorSpaceData(USHORT16 *pusData)
{
    Hv_Drv_PQ_DdcciWriteColorSpaceData(pusData);
    return;
}


static VOID Hv_App_Ddcci_PQColorSpaceFinish(VOID)
{
    Hv_Drv_PQ_DdcciColorSpaceFinish();
    return;
}

static VOID Hv_App_Ddcci_PQColorTempPrepare(VOID)
{
    Hv_Drv_PQ_DdcciColorTempPrepare();
    return;
}


static VOID Hv_App_Ddcci_PQColorTempFinish(VOID)
{
    Hv_Drv_PQ_DdcciColorTempFinish();
    return;
}

static VOID Hv_App_Ddcci_PQPatternPrepare(VOID)
{
   
    Hv_Drv_PQ_DdcciPatternPrepare();
    return;
}

static VOID Hv_App_Ddcci_PQPatternFinish(VOID)
{
    Hv_Drv_PQ_DdcciPatternFinish(); 
    return;
}

static VOID Hv_App_Ddcci_PQTrainingStart(VOID)
{
    Hv_Mw_System_SetDatabaseSyncTimerEnable(HV_FALSE);

    Hv_Drv_PQ_DdcciTrainingStart();
    HV_W32_FIELD(RX_HSRX_CH_00_00, reg_00_hsrx_patt_apb_clk_en, 1);
    HV_W32_FIELD(RX_HSRX_CH_01_00, reg_01_hsrx_patt_apb_clk_en, 1);
    
    Hv_App_PQ_SetBrightness(100);

    Hv_Common_Db_GetSystemDataDBRegionPtr()->bBurnInEnable = 0;

    HV_W32_FIELD(STANDBY_HDMI21_RX_EDDC_00_00, reg_00_slv_en_edid, 0);
    HV_W32_FIELD(STANDBY_HDMI21_RX_EDDC_00_00, reg_00_slv_en_segment, 0);
    HV_W32_FIELD(RX_HDMI21_RX_SCDC_00_A4, reg_00_hdcp_ddc_enable, 0);

    return;
}

// 命令开始前的准备工作
static VOID Hv_App_Ddcci_CmdStart(VOID)
{
    HV_R32_DECL_VAR();

    // 禁止数据库同步
    Hv_Mw_System_SetDatabaseSyncTimerEnable(HV_FALSE);
    
    // 关闭HDCP
    HV_W32_FIELD(STANDBY_HDMI21_RX_EDDC_00_00, reg_00_slv_en_edid, 0);
    HV_W32_FIELD(STANDBY_HDMI21_RX_EDDC_00_00, reg_00_slv_en_segment, 0);
    HV_W32_FIELD(RX_HDMI21_RX_SCDC_00_A4, reg_00_hdcp_ddc_enable, 0);

    // 保存相关寄存器的值
    s_uiGammaEnableOri = Hv_Drv_PQ_DdcciGetGamma();
    s_uiWCGBypassOri = Hv_Drv_PQ_DdcciGetWcg();
    s_uiLdgBypassOri = Hv_Drv_PQ_DdcciGetLdg();
    s_uiLdgHdrPassOri = Hv_Drv_PQ_DdcciGetHdr();

    // 关闭OSD菜单
    Hv_App_Ddcci_SendEventToOsd(OSD_EVENT_HIDE_ALL, 0);
}

// 命令退出后的恢复工作
static VOID Hv_App_Ddcci_CmdEnd(VOID)
{
    // 恢复相关寄存器的值
    //HV_W32_FIELD(TX_GAMMA_00, reg_gamma_en, s_uiGammaEnableOri);
    //HV_W32_FIELD(DISP_TOP_LD_WCG_REG_1_1C, wcg_bypass, s_uiWCGBypassOri);
    //HV_W32_FIELD(DISP_TOP_SUB_LDG_00, reg_ldg_top_bypass, s_uiLdgBypassOri);
    //HV_W32_FIELD(DISP_TOP_LDG_HDR_REG_00_00, reg_00_ct_ldg_hdr_passthrough, s_uiLdgHdrPassOri);
    Hv_Drv_PQ_DdcciSetGamma(s_uiGammaEnableOri);
    Hv_Drv_PQ_DdcciSetWcg(s_uiWCGBypassOri);
    Hv_Drv_PQ_DdcciSetLdg(s_uiLdgBypassOri);
    Hv_Drv_PQ_DdcciSetHdr(s_uiLdgHdrPassOri);

    //打开HDCP
    HV_W32_FIELD(STANDBY_HDMI21_RX_EDDC_00_00, reg_00_slv_en_edid, 1);
    HV_W32_FIELD(STANDBY_HDMI21_RX_EDDC_00_00, reg_00_slv_en_segment, 1);
    HV_W32_FIELD(RX_HDMI21_RX_SCDC_00_A4, reg_00_hdcp_ddc_enable, 1);

    //以设置OSD开为PQ Tool结束标志，打开数据库同步
    Hv_Mw_System_SetDatabaseSyncTimerEnable(HV_TRUE);
}

static VOID Hv_App_Ddcci_ProcHisFactorySet(UCHAR8 ucSource, UCHAR8 *pucData, USHORT16 usLen)
{
    USHORT16 usCmd = (pucData[DDCCI_FAC_OFFSET_CMD_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_CMD_LOW];
    UCHAR8 *pucRspData = NULL;
    USHORT16 usRspLen = 0;
    USHORT16 usProtocolLen = 0;
    UCHAR8 *pucValidData = NULL;
    UINT32 uiDataLen = 0;
    UINT32 uiOpsAddr = 0;

    if (Hv_App_Ddcci_VerifyFactoryCheckSum(pucData) != pucData[usLen - 1])
    {
        DDC_PRINT("CRC Fail! Got:%x, Cal:%x", pucData[usLen - 1], Hv_App_Ddcci_VerifyFactoryCheckSum(pucData));
        return;
    }

    uiOpsAddr = (pucData[DDCCI_FAC_OFFSET_ADDR_LSB] | 
        (pucData[DDCCI_FAC_OFFSET_ADDR_3RD] << 8) | 
        (pucData[DDCCI_FAC_OFFSET_ADDR_2ND] << 16) | 
        (pucData[DDCCI_FAC_OFFSET_ADDR_MSB] << 24));

    switch(usCmd)
    {
        case DDCCI_FAC_CMD_START_OR_END:
        {
            // 1表示开始，2表示结束
            UCHAR8 ucEn = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            
            if (1 == ucEn)
            {
                Hv_App_Ddcci_CmdStart();
                DDC_PRINT("ddc start");
            }
            else
            {
                Hv_App_Ddcci_CmdEnd();
                DDC_PRINT("ddc end");
            }
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            
            break;
        }
        case DDCCI_FAC_CMD_REGISTER:
        {
            UINT32 uiValue = (pucData[DDCCI_FAC_OFFSET_REG_VALUE_LSB] | 
                (pucData[DDCCI_FAC_OFFSET_REG_VALUE_3RD] << 8) | 
                (pucData[DDCCI_FAC_OFFSET_REG_VALUE_2ND] << 16) | 
                (pucData[DDCCI_FAC_OFFSET_REG_VALUE_MSB] << 24));
            UCHAR8 ucStartBit = pucData[DDCCI_FAC_OFFSET_REG_START_BIT];
            UCHAR8 ucStopBit = pucData[DDCCI_FAC_OFFSET_REG_STOP_BIT];

            Hv_App_Ddcci_WriteRegister(uiOpsAddr, ucStartBit, ucStopBit, uiValue);
            // DDC_PRINT("Reg Write, Val:0x%x, uiOpsAddr:0x%08x", uiValue, uiOpsAddr);

            usRspLen = DDCCI_FAC_WRITE_REG_RSP_LEN;
            usProtocolLen = usRspLen - DDCCI_FAC_DDC_HEADER_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_REG_VALUE_MSB);

            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;
            pucRspData[usRspLen - 2] = DDCCI_FAC_RC_SUCCESS;
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            break;
        }
        case DDCCI_FAC_CMD_DDR:
        {
            USHORT16 usCmdLen = (pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW];
            uiDataLen = usCmdLen - DDCCI_FAC_DDC_CMD_FIX_LEN;

            usRspLen = DDCCI_FAC_WRITE_DDR_RSP_LEN;
            usProtocolLen = usRspLen - DDCCI_FAC_DDC_HEADER_LEN;
            // DDC_PRINT("DDR Write, Len:0x%x, uiOpsAddr:0x%08x", uiDataLen, uiOpsAddr);
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_W_DDR_DATA_START);
            
            for (UINT32 uiLoop = 0; uiLoop < uiDataLen; uiLoop++) 
            {
                HV_W8(uiOpsAddr + uiLoop, pucData[DDCCI_FAC_OFFSET_W_DDR_DATA_START + uiLoop]);
            }

            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;
            pucRspData[usRspLen - 2] = DDCCI_FAC_RC_SUCCESS;
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);

            break;
        }
        case DDCCI_FAC_CMD_GAMMA_LUT:
        {
            usRspLen = 8;
            usProtocolLen = usRspLen - DDCCI_FAC_DDC_HEADER_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMCPY(pucRspData, pucData, 6);

            //使用16bit传参数
            for (UINT32 uiId = 0; uiId < 3 * 1025; uiId++)
            {
                auiGammaLut[uiId] = pucData[7 + 2 * uiId] << 8 | pucData[6 + 2 * uiId];
            }

            Hv_Drv_Gamma_WriteLut(auiGammaLut, GAMMA_RGB);
            pucRspData[usRspLen - 2] = DDCCI_FAC_RC_SUCCESS;

            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("Write gamma lut");
            break;
        }

        case DDCCI_FAC_CMD_GAMMA_UNIT_WRITE:
        {
            //6-7-8-9:Data, 10:Col, 11-12:Row
            UINT32 uiCol = pucData[10];
            UINT32 uiRow = pucData[11] | (pucData[12] << 8);
            UINT32 uiData = (pucData[9] << 24) | (pucData[8] << 16) | 
                (pucData[7] << 8) | (pucData[6] << 0);
            DDC_PRINT("GAMMA_UNIT_WRITE - Col: %u, Row: %u, Data: %u");
            Hv_Drv_Gamma_WriteUnit(uiRow, uiCol, uiData);

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            break;
        }

        case DDCCI_FAC_CMD_DYNAMICPANEL:
        {
            UCHAR8 ucPanelEn = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_LSB];
            UCHAR8 ucPanelId = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            
            if (ucPanelEn)
            {
                Hv_Mw_Factory_SetDynamicPanelIndex(ucPanelId);
                Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucDynamicPanelIndex = ucPanelId;
            }
            Hv_Mw_Factory_SetDynamicPanelEn(ucPanelEn);
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->bDynamicPanelEn = ucPanelEn;

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set dynamic panel");
            break;
        }
        case DDCCI_FAC_CMD_GAMMAT:
        {
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set gammat");
            break;
        }
        case DDCCI_FAC_CMD_COLORTEMP_COOL:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stColTempCool, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set colortemp cool");
            break;
        }
        case DDCCI_FAC_CMD_COLORTEMP_WARM:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stColTempWarm, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set colortemp warm");
            break;
        }
        case DDCCI_FAC_CMD_COLORTEMP_STANDARD:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stColTempStandard, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set colortemp std");
            break;
        }
        case DDCCI_FAC_CMD_COLORTEMP_P3:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stColTempP3, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set colortemp p3");
            break;
        }
        case DDCCI_FAC_CMD_COLORTEMP_SRGB:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stColTempSrgb, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set colortemp srgb");
            break;
        }
        case DDCCI_FAC_CMD_COLORTEMP_EYECARE:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stColTempEyeCare, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set colortemp eyecare");
            break;
        }
        case DDCCI_FAC_CMD_FACWEEK:
        {
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucFactWeek = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set fac week: 0x%x", pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB]);
            break;
        }
        case DDCCI_FAC_CMD_FACYEAR:
        {
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucFactYear = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set fac year: 0x%x", pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB]);
            break;
        }
        case DDCCI_FAC_CMD_DEFAULT_LANG:
        {
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucDefaultLanguage = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            // Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->bDefaultLanguageChanged = HV_TRUE;

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set default lang %d", pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB]);
            break;
        }
        case DDCCI_FAC_CMD_FACBRIGHTNESS:
        {
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucFactoryBrightness = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set fac brightness %d", pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB]);
            break;
        }
        case DDCCI_FAC_CMD_FACCONTRAST:
        {
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucFactoryContrast = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set fac contrast %d", pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB]);
            break;
        }
        case DDCCI_FAC_CMD_GAMUT_NATIVE:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stGamutNative, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set gamut native");
            break;
        }
        case DDCCI_FAC_CMD_GAMUT_SRGB:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stGamutSrgb, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set gamut srgb");
            break;
        }
        case DDCCI_FAC_CMD_GAMUT_709:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stGamut709, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set gamut 709");
            break;
        }
        case DDCCI_FAC_CMD_GAMUT_P3:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stGamutP3, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set gamut p3");
            break;
        }
        case DDCCI_FAC_CMD_GAMUT_HDR:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stGamutHdr, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set gamut hdr");
            break;
        }
        case DDCCI_FAC_CMD_GAMUT_ADOBE:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - 3;

            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->stGamutAdobe, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set gamut adobe");
            break;
        }
        case DDCCI_FAC_CMD_SN:
        {
            // 先保存下来，等待DATABASE_SYNC命令后再写入
            CHAR8 *pcProductSn = (CHAR8 *)Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->acProductSn;
            USHORT16 usProductSNLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - DDCCI_FAC_DDC_CMD_LEN;

            if (usProductSNLen >= PRODUCT_SN_LENTH)
            {
                // product sn长度最大24，最后一字节补0
                usProductSNLen = PRODUCT_SN_LENTH - 1;
            }

            HV_MEMSET(pcProductSn, 0, PRODUCT_SN_LENTH);
            HV_MEMCPY(pcProductSn, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usProductSNLen);
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set product sn");
            break;
        }
        case DDCCI_FAC_CMD_SETEDIDSN:
        {
            // 先保存下来，等待DATABASE_SYNC命令后再写入
            CHAR8 *pcEdidSn = (CHAR8 *)Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->acDescSn;
            USHORT16 usEdidSNLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - DDCCI_FAC_DDC_CMD_LEN;

            if (usEdidSNLen > EDID_DESC_SN_LENTH)
            {
                // edid sn长度最大13，不够的后面补0x0A 0x20 0x20 ...
                usEdidSNLen = EDID_DESC_SN_LENTH;
            }

            HV_MEMSET(pcEdidSn, 0x20, EDID_DESC_SN_LENTH);
            HV_MEMCPY(pcEdidSn, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usEdidSNLen);
            if (usEdidSNLen < EDID_DESC_SN_LENTH)
            {
                pcEdidSn[usEdidSNLen] = 0x0A;
            }
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set edid sn");
            break;
        }
        case DDCCI_FAC_CMD_HDCP:
        {
            USHORT16 usHdcpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - DDCCI_FAC_DDC_CMD_LEN;
            
            Hv_Vos_Memcpy((VOID *)&Hv_Common_Db_GetHDCPDataDBRegionPtr()->stKey, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usHdcpLen);
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set hdcp");
            break;
        }
        case DDCCI_FAC_CMD_HDCP_ALL:
        {
            USHORT16 usHdcpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]) - DDCCI_FAC_DDC_CMD_LEN;
            if (usHdcpLen != sizeof(HDCPDataDBRegion))
            {
                HV_LOG_ERROR(DDCCI, "set hdcp-all len error, %u, should be %u", usHdcpLen, sizeof(HDCPDataDBRegion));
                break;
            }
            
            Hv_Vos_Memcpy(Hv_Common_Db_GetHDCPDataDBRegionPtr(), pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usHdcpLen);
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set hdcp all");
            break;
        }
        case DDCCI_FAC_CMD_HDMIEDID:
        {
            // 工具会先发edid数据，再发edid个数
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]);
            if (usTmpLen == DDCCI_FAC_DDC_CMD_FIX_LEN)
            {
                Hv_Common_Db_GetHdmiEdidDBRegionPtr()->ucNumber = pucData[DDCCI_FAC_OFFSET_ADDR_MSB];
                DDC_PRINT("set hdmi0 edid len: %u", Hv_Common_Db_GetHdmiEdidDBRegionPtr()->ucNumber);
            }
            else
            {
                usTmpLen -= DDCCI_FAC_DDC_CMD_LEN;
                Hv_Vos_Memcpy(Hv_Common_Db_GetHdmiEdidDBRegionPtr()->astHdmiEdid, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
                
                Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
                DDC_PRINT("set hdmi0 edid data");
            }
            break;
        }
        case DDCCI_FAC_CMD_HDMI1EDID:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]);
            if (usTmpLen == DDCCI_FAC_DDC_CMD_FIX_LEN)
            {
                Hv_Common_Db_GetHdmi1EdidDBRegionPtr()->ucNumber = pucData[DDCCI_FAC_OFFSET_ADDR_MSB];
                DDC_PRINT("set hdmi1 edid len: %u", Hv_Common_Db_GetHdmi1EdidDBRegionPtr()->ucNumber);
            }
            else
            {
                usTmpLen -= DDCCI_FAC_DDC_CMD_LEN;
                Hv_Vos_Memcpy(Hv_Common_Db_GetHdmi1EdidDBRegionPtr()->astHdmiEdid, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
                Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
                DDC_PRINT("set hdmi1 edid data");
            }
            break;
        }
        case DDCCI_FAC_CMD_DPEDID:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]);
            if (usTmpLen == DDCCI_FAC_DDC_CMD_FIX_LEN)
            {
                Hv_Common_Db_GetDpEdidDBRegionPtr()->ucNumber = pucData[DDCCI_FAC_OFFSET_ADDR_MSB];
                DDC_PRINT("set dp0 edid len: %u", Hv_Common_Db_GetDpEdidDBRegionPtr()->ucNumber);
            }
            else
            {
                usTmpLen -= DDCCI_FAC_DDC_CMD_LEN;
                Hv_Vos_Memcpy(Hv_Common_Db_GetDpEdidDBRegionPtr()->astDpEdid, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
                Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
                DDC_PRINT("set dp0 edid data");
            }
            break;
        }
        case DDCCI_FAC_CMD_DP1EDID:
        {
            USHORT16 usTmpLen = ((pucData[DDCCI_FAC_OFFSET_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_LEN_LOW]);
            if (usTmpLen == DDCCI_FAC_DDC_CMD_FIX_LEN)
            {
                Hv_Common_Db_GetDp1EdidDBRegionPtr()->ucNumber = pucData[DDCCI_FAC_OFFSET_ADDR_MSB];
                DDC_PRINT("set dp1 edid len: %u", Hv_Common_Db_GetDp1EdidDBRegionPtr()->ucNumber);
            }
            else
            {
                usTmpLen -= DDCCI_FAC_DDC_CMD_LEN;
                Hv_Vos_Memcpy(Hv_Common_Db_GetDp1EdidDBRegionPtr()->astDpEdid, pucData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, usTmpLen);
        
                Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
                DDC_PRINT("set dp1 edid data");
            }
            break;
        }
        case DDCCI_FAC_CMD_SETBURNOSD:
        {
            UCHAR8 ucMode = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];

            Hv_Common_Db_GetSystemDataDBRegionPtr()->bBurnInEnable = ucMode;

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set burn osd");
            break;
        }
        case DDCCI_FAC_CMD_BRIGHTNESS:
        {
            UCHAR8 ucBrightness = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            Hv_App_PQ_SetBrightness(ucBrightness);
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set brightness");
            break;
        }
        case DDCCI_FAC_CMD_CONTRAST:
        {
            UCHAR8 ucValue = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            Hv_App_PQ_SetContrast(ucValue);
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set contrast");
            break;
        }
        case DDCCI_FAC_CMD_BRIGHTNESS_NIT:
        {
#if 0
            UCHAR8 ucBrightness = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            
            Hv_App_PQ_SetBrightness(ucBrightness);
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->usFactoryDefaultNits = HV_PQ_DATABASE_GET(DiagData, usDBBrightness);
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set brightness nit");
#endif
            break;
        }
        case DDCCI_FAC_CMD_GAMMA_ACTION:
        {
            UCHAR8 ucVal = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            if (DDCCI_FAC_CMD_PQ_PREPARE == ucVal)
            {
                DDC_PRINT("gamma prepare");
                Hv_App_Ddcci_PQGammaPrepare();
            }
            else
            {
                DDC_PRINT("gamma finish");
                Hv_App_Ddcci_PQGammaFinish();
            }
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            break;
        }
        case DDCCI_FAC_CMD_COLORSPACE_ACTION:
        {
            UCHAR8 ucVal = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            if (DDCCI_FAC_CMD_PQ_PREPARE == ucVal)
            {
                DDC_PRINT("color space prepare");
                Hv_App_Ddcci_PQColorSpacePrepare();
            }
            else
            {
                DDC_PRINT("color space finish");
                Hv_App_Ddcci_PQColorSpaceFinish();
            }
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            break;
        }
        case DDCCI_FAC_CMD_WCG_ACTION:
        {
            UCHAR8 ucVal = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            if (1 == ucVal)
            {
                DDC_PRINT("WCG On");
                Hv_App_Ddcci_PQWCGEnable(HV_TRUE);
            }
            else
            {
                DDC_PRINT("WCG Off");
                Hv_App_Ddcci_PQWCGEnable(HV_FALSE);
            }
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            break;
        }
        case DDCCI_FAC_CMD_COLORSPACE_DATA1:
        case DDCCI_FAC_CMD_COLORSPACE_DATA2:
        case DDCCI_FAC_CMD_COLORSPACE_DATA3:
        case DDCCI_FAC_CMD_COLORSPACE_DATA4:
        case DDCCI_FAC_CMD_COLORSPACE_DATA5:
        {
            UCHAR8 ucIndex = 0;
            for (ucIndex = 0; ucIndex < 18; ucIndex++)
            {
                ausColorSpaceData[ucIndex] = pucData[6 + (2 * ucIndex)] << 8 | pucData[6 + (2 * ucIndex) + 1];
            }
            
            Hv_App_Ddcci_PQWriteColorSpaceData(ausColorSpaceData);
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_BUF_PRINT("[debug] Write color space data", pucData, usLen);
            break;
        }
        case DDCCI_FAC_CMD_COLORTEMP_ACTION:
        {
            UCHAR8 ucVal = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            if (DDCCI_FAC_CMD_PQ_PREPARE == ucVal)
            {
                DDC_PRINT("colortemp prepare");
                Hv_App_Ddcci_PQColorTempPrepare();
            }
            else
            {
                DDC_PRINT("colortemp finish");
                Hv_App_Ddcci_PQColorTempFinish();
            }
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            break;
        }
        case DDCCI_FAC_CMD_PATTERN_ACTION:
        {
            UCHAR8 ucVal = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            if (DDCCI_FAC_CMD_PQ_PREPARE == ucVal)
            {
                DDC_PRINT("pattern prepare");
                Hv_App_Ddcci_PQPatternPrepare();
            }
            else
            {
                DDC_PRINT("pattern finish");
                Hv_App_Ddcci_PQPatternFinish();
            }
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            break;
        }
        case DDCCI_FAC_CMD_PQ_TRAINING_START:
        {
            UCHAR8 ucVal = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            if (DDCCI_FAC_CMD_PQ_PREPARE == ucVal)
            {
                DDC_PRINT("pq traing start");
                Hv_App_Ddcci_PQTrainingStart();
            }
            else
            {
                DDC_PRINT("pq traing stop");
                
            }
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            break;
        }
        case DDCCI_FAC_CMD_ENERGY:
        {
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucFactoryEnergy = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("energy");
            break;
        }

        case DDCCI_FAC_CMD_SHARPNESS:
        {
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucFactorySharpness = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("Set Sharpness");
            break;
        }
        case DDCCI_FAC_CMD_PQ_RGB_COEF:
        {
            USHORT16 usR = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB] << 8 | pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_2ND];
            USHORT16 usG = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_3RD] << 8 | pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_LSB];
            USHORT16 usB = pucData[10] << 8 | pucData[11];

            HV_W32_FIELD(DISP_TOP_SUB_LDG_0C, reg_main_csc_cr_r_coef, usR);
            HV_W32_FIELD(DISP_TOP_SUB_LDG_24, reg_main_csc_y_g_coef, usG);
            HV_W32_FIELD(DISP_TOP_SUB_LDG_30, reg_main_csc_cb_b_coef, usB);
            
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("Set RGB Coef, 0x%04x, 0x%04x, 0x%04x", usR, usG, usB);
            break;
        }
        case DDCCI_FAC_CMD_PQ_WEEK_YEAR:
        {
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucFactWeek = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];
            Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucFactYear = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_2ND];

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("set fac week: %d, year: %d", pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB], pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_2ND]);
            break;
        }
        case DDCCI_FAC_CMD_FACTORYMODE:
        {
            UCHAR8 ucVal = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];

            Hv_Mw_Factory_SetFactoryModeEnable(!!ucVal);
            Hv_Common_Db_GetSystemDataDBRegionPtr()->bFactoryMode = !!ucVal;

            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("write factory mode");
            break;
        }
        case DDCCI_FAC_CMD_DATABASE_SYNC:
        {
            UCHAR8 ucRet = 0;
            UINT32 uiVal = (pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_LSB] | 
                (pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_3RD] << 8) | 
                (pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_2ND] << 16) | 
                (pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB] << 24));

            DDC_PRINT("set SYNC flag 0x%x", uiVal);
            
            /* HDCP modified */
            if (uiVal & PQTOOL_MODIFYFLAG_HDCP1X)
            {
                Hv_Common_Db_GetHDCPDataDBRegionPtr()->bModifyFlag = HV_TRUE;
                Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucUseSeperatorHDCPKey = HV_TRUE;
                Hv_Common_Db_GetHDCPDataDBRegionPtr()->bHdcp1XValid = HV_TRUE;
                ucRet |= Hv_Mw_DataBase_DdcSyncHdcp();
                DDC_PRINT("sync hdcp1x %d", ucRet);
            }
            if (uiVal & PQTOOL_MODIFYFLAG_HDCP2X)
            {
                Hv_Common_Db_GetHDCPDataDBRegionPtr()->bModifyFlag = HV_TRUE;
                Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->ucUseSeperatorHDCPKey = HV_TRUE;
                Hv_Common_Db_GetHDCPDataDBRegionPtr()->bHdcp2XValid = HV_TRUE;
                ucRet |= Hv_Mw_DataBase_DdcSyncHdcp();
                DDC_PRINT("sync hdcp2x %d", ucRet);
            }

            if (uiVal & PQTOOL_MODIFYFLAG_HDMIEDID)
            {
                Hv_Common_Db_GetHdmiEdidDBRegionPtr()->bModifyFlag = HV_TRUE;
                ucRet |= Hv_Mw_DataBase_DdcSyncHdmiEdid();
                DDC_PRINT("sync hdmi0 %d", ucRet);
            }
            if (uiVal & PQTOOL_MODIFYFLAG_HDMI1EDID)
            {
                Hv_Common_Db_GetHdmi1EdidDBRegionPtr()->bModifyFlag = HV_TRUE;
                ucRet |= Hv_Mw_DataBase_DdcSyncHdmi1Edid();
                DDC_PRINT("sync hdmi1 %d", ucRet);
            }
            if (uiVal & PQTOOL_MODIFYFLAG_DPEDID)
            {
                Hv_Common_Db_GetDpEdidDBRegionPtr()->bModifyFlag = HV_TRUE;
                ucRet |= Hv_Mw_DataBase_DdcSyncDPEdid();
                DDC_PRINT("sync dp0 %d", ucRet);
            }
            if (uiVal & PQTOOL_MODIFYFLAG_DP1EDID)
            {
                Hv_Common_Db_GetDp1EdidDBRegionPtr()->bModifyFlag = HV_TRUE;
                ucRet |= Hv_Mw_DataBase_DdcSyncDP1Edid();
                DDC_PRINT("sync dp1 %d", ucRet);
            }

            if(uiVal & PQTOOL_MODIFYFLAG_GAMMA)
            {
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_GAMMACOMPRESS)
                Hv_App_GmaCompress(auiGammaLut, (UCHAR8 *)Hv_Common_Db_GetGammaDataDBRegionPtr()->auiGamma);
#else
                HV_MEMCPY(Hv_Common_Db_GetGammaDataDBRegionPtr()->auiGamma, auiGammaLut, sizeof(Hv_Common_Db_GetGammaDataDBRegionPtr()->auiGamma));
#endif
                Hv_Common_Db_GetGammaDataDBRegionPtr()->bModifyFlag = HV_TRUE;
                ucRet |= Hv_Mw_DataBase_DdcSyncGamma();
                DDC_PRINT("sync gamma %d", ucRet);
            }

            /* Factory Data Update Without Any Flag. It is a mandantory selection */
            // if ((uiVal & PQTOOL_MODIFYFLAG_COLORTEMP) || (uiVal & PQTOOL_MODIFYFLAG_GAMUT))
            {
                Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()->bModifyFlag = HV_TRUE;
                Hv_Vos_Memcpy(Hv_Common_Db_GetFactoryDataDBRegionPtr(),
                    (FactoryDataDBRegion *)Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr(), sizeof(FactoryDataDBRegion));
                ucRet |= Hv_Mw_DataBase_SyncFactory();
                DDC_PRINT("sync factory %d", ucRet);
            }

            if (uiVal & PQTOOL_MODIFYFLAG_USERDATA)
            {
                Hv_Common_Db_GetUserDataDBRegionPtr()->bModifyFlag = HV_TRUE;
                ucRet |= Hv_Mw_DataBase_DdcSync();
                DDC_PRINT("sync user data %d", ucRet);
            }

            usRspLen = DDCCI_FAC_WRITE_PQ_CMD_RSP_LEN;
            usProtocolLen = usRspLen - DDCCI_FAC_DDC_HEADER_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);

            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;
            if (ucRet != 0)
            {
                pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_RC] = DDCCI_FAC_RC_FAIL;
            }
            else
            {
                pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_RC] = DDCCI_FAC_RC_SUCCESS;
            }
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);

            break;
        }
        case DDCCI_FAC_CMD_SWITCH_GAMMA:
        {
            UCHAR8 ucGammaId = pucData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB];

            Hv_Mw_PQ_SetGamma(ucGammaId);
            Hv_App_Ddcci_PQWriteCmdRsp(ucSource, pucData);
            DDC_PRINT("switch gamma: %u", ucGammaId);
            break;
        }
        case DDCCI_FAC_CMD_CM64:
        {
            break;
        }
        case DDCCI_FAC_CMD_GMACOMPRESS:
        {
            break;
        }
        case DDCCI_FAC_CMD_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_SATURATION:
        {
            break;
        }
        case DDCCI_FAC_CMD_DLC:
        {
            break;
        }
        case DDCCI_FAC_CMD_DCR:
        {
            break;
        }
        case DDCCI_FAC_CMD_COLORSPACE:
        {
            break;
        }
        case DDCCI_FAC_CMD_RGAIN:
        {
            break;
        }
        case DDCCI_FAC_CMD_GGAIN:
        {
            break;
        }
        case DDCCI_FAC_CMD_BGAIN:
        {
            break;
        }
        case DDCCI_FAC_CMD_ROFFSET:
        {
            break;
        }
        case DDCCI_FAC_CMD_GOFFSET:
        {
            break;
        }
        case DDCCI_FAC_CMD_BOFFSET:
        {
            break;
        }
        case DDCCI_FAC_CMD_RED_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_RED_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_RED_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_GREEN_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_GREEN_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_GREEN_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_BLUE_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_BLUE_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_BLUE_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_CYAN_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_CYAN_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_CYAN_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_YELLOW_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_YELLOW_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_YELLOW_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_MAGENTA_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_MAGENTA_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_MAGENTA_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_PWM:
        {
            break;
        }
        case DDCCI_FAC_CMD_SET_FR:
        {
            break;
        }
        case DDCCI_FAC_CMD_SIMKEY0:
        {
            break;
        }
        case DDCCI_FAC_CMD_SIMKEY1:
        {
            break;
        }
        case DDCCI_FAC_CMD_SIMKEY2:
        {
            break;
        }
        case DDCCI_FAC_CMD_SIMKEY3:
        {
            break;
        }
        case DDCCI_FAC_CMD_SIMKEY4:
        {
            break;
        }
        case DDCCI_FAC_CMD_GAMMA_MEA:
        {
            break;
        }
        case DDCCI_FAC_CMD_DELTAE_MEA:
        {
            break;
        }
        case DDCCI_FAC_CMD_LUTINIT:
        {
            break;
        }
        case DDCCI_FAC_CMD_WCG_3D_LUT:
        {
            break;
        }
        default:
        {
            break;
        }
    }

    if (NULL != pucValidData)
    {
        HV_FREE(pucValidData);
    }
    if (NULL != pucRspData)
    {
        HV_FREE(pucRspData);
    }
    return;
}

static VOID Hv_App_Ddcci_ProcHisFactoryGet(UCHAR8 ucSource, UCHAR8 *pucData, USHORT16 usLen)
{
    USHORT16 usCmd = (pucData[DDCCI_FAC_OFFSET_CMD_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_CMD_LOW];
    UCHAR8 *pucRspData = NULL;
    USHORT16 usRspLen = 0;
    USHORT16 usProtocolLen = 0;
    UCHAR8 *pucValidData = NULL;
    UINT32 uiDataLen = 0;
    UINT32 uiOpsAddr = 0;
    UINT32 uiDbAddr = 0;

    if (Hv_App_Ddcci_VerifyFactoryCheckSum(pucData) != pucData[usLen - 1])
    {
        DDC_PRINT("CRC Fail!! Got:%x, Cal:%x", pucData[usLen - 1], Hv_App_Ddcci_VerifyFactoryCheckSum(pucData));
        return;
    }

    uiOpsAddr = (pucData[DDCCI_FAC_OFFSET_ADDR_LSB] | 
        (pucData[DDCCI_FAC_OFFSET_ADDR_3RD] << 8) | 
        (pucData[DDCCI_FAC_OFFSET_ADDR_2ND] << 16) | 
        (pucData[DDCCI_FAC_OFFSET_ADDR_MSB] << 24));

    switch (usCmd)
    {
        case DDCCI_FAC_CMD_REGISTER:
        {
            UCHAR8 ucStartBit = pucData[DDCCI_FAC_OFFSET_REG_START_BIT];
            UCHAR8 ucStopBit = pucData[DDCCI_FAC_OFFSET_REG_STOP_BIT];
            UINT32 uiReadVal = Hv_App_Ddcci_ReadRegister(uiOpsAddr, ucStartBit, ucStopBit);

            usRspLen = DDCCI_FAC_READ_REG_RSP_LEN;
            usProtocolLen = usRspLen - DDCCI_FAC_DDC_HEADER_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_REG_VALUE_MSB);

            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;
            pucRspData[DDCCI_FAC_OFFSET_REG_VALUE_MSB] = (uiReadVal >> 24) & 0xFF;
            pucRspData[DDCCI_FAC_OFFSET_REG_VALUE_2ND] = (uiReadVal >> 16) & 0xFF;
            pucRspData[DDCCI_FAC_OFFSET_REG_VALUE_3RD] = (uiReadVal >> 8) & 0xFF;
            pucRspData[DDCCI_FAC_OFFSET_REG_VALUE_LSB] = uiReadVal & 0xFF;
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            // DDC_PRINT("Reg Read, ReadVal: %d, uiOpsAddr: 0x%08x", uiReadVal, uiOpsAddr);
            break;
        }
        case DDCCI_FAC_CMD_DDR:
        {
            UINT32 uiData;
            
            uiDataLen = (pucData[DDCCI_FAC_OFFSET_READ_DDR_LEN_HIGH] << 8) | pucData[DDCCI_FAC_OFFSET_READ_DDR_LEN_LOW];

            usRspLen = uiDataLen + DDCCI_FAC_DDC_CMD_FIX_LEN + DDCCI_FAC_DDC_HEADER_LEN;
            usProtocolLen = usRspLen - DDCCI_FAC_DDC_HEADER_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_R_DDR_RSP_DATA_START);
            
            pucValidData = HV_MALLOC(uiDataLen);
            if (NULL == pucValidData)
            {
                break;
            }
            
            for (UINT32 uiId = 0; uiId < uiDataLen; uiId++) 
            {
                // 如果地址是4字节对齐的，且剩余长度大于等于4字节，则按照32bit读取
                if (((uiOpsAddr + uiId) % 4 == 0) && (uiDataLen - uiId >= 4))
                {
                    uiData = HV_R32(uiOpsAddr + uiId);
                    pucValidData[uiId + 3] = (uiData >> 24) & 0xFF;
                    pucValidData[uiId + 2] = (uiData >> 16) & 0xFF;
                    pucValidData[uiId + 1] = (uiData >> 8) & 0xFF;
                    pucValidData[uiId] = uiData & 0xFF;
                    uiId += 3; // 因为已经读取了4字节，所以增加3
                } 
                else 
                {
                    // 否则，按照1字节读取
                    uiData = HV_R8(uiOpsAddr + uiId);
                    pucValidData[uiId] = uiData & 0xFF;
                }
            }

            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_R_DDR_RSP_DATA_START, pucValidData, uiDataLen);

            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            // DDC_PRINT("DDR Read, Len: %d, uiOpsAddr: 0x%08x", uiDataLen, uiOpsAddr);
            break;
        }
        case DDCCI_FAC_CMD_DYNAMICPANEL:
        {
            UCHAR8 ucPanelEn = 0;
            UCHAR8 ucPanelNum = 0;
            UCHAR8 ucPanelId = 0;
            
            Hv_Mw_Factory_GetDynamicPanelInfo(&ucPanelEn, &ucPanelId, &ucPanelNum);

            usRspLen = DDCCI_FAC_READ_PQ_CMD_RSP_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;
            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB] = ucPanelEn;
            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_2ND] = ucPanelNum;
            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_3RD] = ucPanelId;
            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_LSB] = 0x00;
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read dynamci panel");
            break;
        }
        case DDCCI_FAC_CMD_HDCP:
        {
            uiDbAddr = ((UINT32)(Hv_Common_Db_GetHDCPDataDBRegionPtr())) + OFFSET_OF(HDCPDataDBRegion, stKey);

            // HDCPKeyDataDBRegion，长度1152
            uiDataLen = sizeof(HDCPKeyDataDBRegion);
            usRspLen = uiDataLen + DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_LEN;
            usProtocolLen = uiDataLen + DDCCI_FAC_DDC_CMD_LEN;

            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); //拷贝1152个hdcp结构体数据，HDCPKeyDataDBRegion
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read hdcp");
            break;
        }
        case DDCCI_FAC_CMD_GAMMAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_COLORTEMP_COOL:
        case DDCCI_FAC_CMD_COLORTEMP_WARM:
        case DDCCI_FAC_CMD_COLORTEMP_STANDARD:
        case DDCCI_FAC_CMD_COLORTEMP_P3:
        case DDCCI_FAC_CMD_COLORTEMP_SRGB:
        case DDCCI_FAC_CMD_COLORTEMP_EYECARE:
        {
            uiDbAddr = ((UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()));
            if (DDCCI_FAC_CMD_COLORTEMP_COOL == usCmd)
            {
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stColTempCool);
            }
            else if (DDCCI_FAC_CMD_COLORTEMP_WARM == usCmd)
            {
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stColTempWarm);
            }
            else if (DDCCI_FAC_CMD_COLORTEMP_STANDARD == usCmd)
            {
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stColTempStandard);
            }
            else if (DDCCI_FAC_CMD_COLORTEMP_P3 == usCmd)
            {
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stColTempP3);
            }
            else if (DDCCI_FAC_CMD_COLORTEMP_SRGB == usCmd)
            {
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stColTempSrgb);
            }
            else // if (DDCCI_FAC_CMD_COLORTEMP_EYECARE == usCmd)
            {
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stColTempEyeCare);
            }

            // 色温3个值，rgb gain 
            uiDataLen = 3;
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read colortemp %d", usCmd);
        
            break;
        }
        case DDCCI_FAC_CMD_FACWEEK:
        case DDCCI_FAC_CMD_FACYEAR:
        {
            // 1个字节 
            uiDataLen = 1;
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            if (DDCCI_FAC_CMD_FACWEEK == usCmd)
            {
                uiDbAddr = (UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()) + OFFSET_OF(FactoryDataDBRegion, ucFactWeek);
            }
            else // if (DDCCI_FAC_CMD_FACYEAR == usCmd)
            {
                uiDbAddr = (UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()) + OFFSET_OF(FactoryDataDBRegion, ucFactYear);
            }
            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read factory week&year %d", usCmd);
        
            break;
        }
        case DDCCI_FAC_CMD_FACBRIGHTNESS:
        {
            // 1个字节 
            uiDataLen = 1;
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if(NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            uiDbAddr = (UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()) + OFFSET_OF(FactoryDataDBRegion, ucFactoryBrightness);
            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read factory brightness");
            break;
        }
        case DDCCI_FAC_CMD_DEFAULT_LANG:
        {
            // 1个字节 
            uiDataLen = 1;
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            uiDbAddr = (UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()) + OFFSET_OF(FactoryDataDBRegion, ucDefaultLanguage);
            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read default lang");
        
            break;
        }
        case DDCCI_FAC_CMD_FACCONTRAST:
        {
            // 1个字节 
            uiDataLen = 1;
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            uiDbAddr = (UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()) + OFFSET_OF(FactoryDataDBRegion, ucFactoryContrast);
            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read default lang");
        
            break;
        }
        case DDCCI_FAC_CMD_GAMUT_NATIVE:
        case DDCCI_FAC_CMD_GAMUT_SRGB:
        case DDCCI_FAC_CMD_GAMUT_709:
        case DDCCI_FAC_CMD_GAMUT_P3:
        case DDCCI_FAC_CMD_GAMUT_HDR:
        case DDCCI_FAC_CMD_GAMUT_ADOBE:
        {
            uiDbAddr = (UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr());
            if (DDCCI_FAC_CMD_GAMUT_NATIVE == usCmd)
            {
                DDC_PRINT("read gam native");
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stGamutNative);
            }
            else if (DDCCI_FAC_CMD_GAMUT_SRGB == usCmd)
            {
                DDC_PRINT("read gam srgb");
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stGamutSrgb);
            }
            else if (DDCCI_FAC_CMD_GAMUT_709 == usCmd)
            {
                DDC_PRINT("read gam 709");
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stGamut709);
            }
            else if (DDCCI_FAC_CMD_GAMUT_P3 == usCmd)
            {
                DDC_PRINT("read gam p3");
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stGamutP3);
            }
            else if (DDCCI_FAC_CMD_GAMUT_HDR == usCmd)
            {
                DDC_PRINT("read gam hdr");
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stGamutHdr);
            }
            else // if (DDCCI_FAC_CMD_GAMUT_ADOBE == usCmd)
            {
                DDC_PRINT("read gam adobe");
                uiDbAddr += OFFSET_OF(FactoryDataDBRegion, stGamutAdobe);
            }

            uiDataLen = sizeof(GamutSet);
            usRspLen = uiDataLen + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = uiDataLen + DDCCI_FAC_DDC_CMD_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            
            break;
        }
        case DDCCI_FAC_CMD_HDMIEDID:
        {
            uiDbAddr = (UINT32)(Hv_Common_Db_GetHdmiEdidDBRegionPtr()) + OFFSET_OF(HdmiEdidDBRegion, astHdmiEdid);
            
            uiDataLen = sizeof(EdidDataDBRegion) * HDMI_EDID_MAX_NUMBER;
            usRspLen = uiDataLen + DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_LEN;
            usProtocolLen = uiDataLen + DDCCI_FAC_DDC_CMD_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read hdmi edid");
        
            break;
        }
        case DDCCI_FAC_CMD_HDMI1EDID:
        {
            uiDbAddr = (UINT32)(Hv_Common_Db_GetHdmi1EdidDBRegionPtr()) + OFFSET_OF(HdmiEdidDBRegion, astHdmiEdid);
            
            uiDataLen = sizeof(EdidDataDBRegion) * HDMI_EDID_MAX_NUMBER;
            usRspLen = uiDataLen + DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_LEN;
            usProtocolLen = uiDataLen + DDCCI_FAC_DDC_CMD_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read hdmi1 edid");
        
            break;
        }
        case DDCCI_FAC_CMD_DPEDID:
        {
            uiDbAddr = (UINT32)(Hv_Common_Db_GetDpEdidDBRegionPtr()) + OFFSET_OF(DpEdidDBRegion, astDpEdid);
            
            uiDataLen = sizeof(EdidDataDBRegion) * DP_EDID_MAX_NUMBER;
            usRspLen = uiDataLen + DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_LEN;
            usProtocolLen = uiDataLen + DDCCI_FAC_DDC_CMD_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read dp edid");
        
            break;
        }
        case DDCCI_FAC_CMD_DP1EDID:
        {
            uiDbAddr = (UINT32)(Hv_Common_Db_GetDp1EdidDBRegionPtr()) + OFFSET_OF(DpEdidDBRegion, astDpEdid);
            
            uiDataLen = sizeof(EdidDataDBRegion) * DP_EDID_MAX_NUMBER;
            usRspLen = uiDataLen + DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_LEN;
            usProtocolLen = uiDataLen + DDCCI_FAC_DDC_CMD_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read dp1 edid");
        
            break;
        }
        case DDCCI_FAC_CMD_GMACOMPRESS:
        {
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB] = HV_PQ_DATABASE_GET(GammaData, ucGammaCompress);
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read gam compress");
            break;
        }
        case DDCCI_FAC_CMD_SETBURNOSD:
        {
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB] = HV_COMMON_DATABASE_GET(SystemData, bBurnInEnable);
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read burnin enable");
        
            break;
        }
        case DDCCI_FAC_CMD_BRIGHTNESS:
        {
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB] = Hv_App_PQ_GetBrightness();
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read brightness");
            break;
        }
        case DDCCI_FAC_CMD_BRIGHTNESS_NIT:
        {
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB] = Hv_App_PQ_GetBrightness();
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read brightness nit");
            break;
        }
        case DDCCI_FAC_CMD_ENERGY:
        {
            uiDataLen = 1;
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            uiDbAddr = (UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()) + OFFSET_OF(FactoryDataDBRegion, ucFactoryEnergy);
            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read energy");
            break;
        }

        case DDCCI_FAC_CMD_SHARPNESS:
        {
            uiDataLen = 1;
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            uiDbAddr = (UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()) + OFFSET_OF(FactoryDataDBRegion, ucFactorySharpness);
            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), uiDataLen); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read sharpness");
            break;
        }
        
        case DDCCI_FAC_CMD_PQ_RGB_COEF:
        {
            HV_R32_DECL_VAR();
            USHORT16 usR = HV_R32_FIELD(DISP_TOP_SUB_LDG_0C, reg_main_csc_cr_r_coef);
            USHORT16 usG = HV_R32_FIELD(DISP_TOP_SUB_LDG_24, reg_main_csc_y_g_coef);
            USHORT16 usB = HV_R32_FIELD(DISP_TOP_SUB_LDG_30, reg_main_csc_cb_b_coef);

            uiDataLen = 6;
            usRspLen = uiDataLen + DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_LEN;
            usProtocolLen = uiDataLen + DDCCI_FAC_DDC_CMD_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB] = usR >> 8;
            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_2ND] = usR & 0xFF;
            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_3RD] = usG >> 8;
            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_LSB] = usG & 0xFF;
            pucRspData[10] = usB >> 8;
            pucRspData[11] = usB & 0xFF;
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read RGB Coef, 0x%04x, 0x%04x, 0x%04x", usR, usG, usB);
            break;
        }
        case DDCCI_FAC_CMD_PQ_WEEK_YEAR:
        {
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            HV_MEMCPY(pucRspData, pucData, DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;

            uiDbAddr = (UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()) + OFFSET_OF(FactoryDataDBRegion, ucFactWeek);
            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB, (void *)(uiDbAddr), 1); 
            uiDbAddr = (UINT32)(Hv_Common_Db_GetDefaultFactoryDataDBRegionPtr()) + OFFSET_OF(FactoryDataDBRegion, ucFactYear);
            HV_MEMCPY(pucRspData + DDCCI_FAC_OFFSET_PQ_CMD_VALUE_2ND, (void *)(uiDbAddr), 1); 
            
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT("read factory week:%d, year:%d", pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB], pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_2ND]);
        
            break;
        }
        case DDCCI_FAC_CMD_CM64:
        {
            break;
        }
        case DDCCI_FAC_CMD_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_SATURATION:
        {
            break;
        }
        case DDCCI_FAC_CMD_DLC:
        {
            break;
        }
        case DDCCI_FAC_CMD_DCR:
        {
            break;
        }
        case DDCCI_FAC_CMD_COLORSPACE:
        {
            break;
        }
        case DDCCI_FAC_CMD_RGAIN:
        {
            break;
        }
        case DDCCI_FAC_CMD_GGAIN:
        {
            break;
        }
        case DDCCI_FAC_CMD_BGAIN:
        {
            break;
        }
        case DDCCI_FAC_CMD_ROFFSET:
        {
            break;
        }
        case DDCCI_FAC_CMD_GOFFSET:
        {
            break;
        }
        case DDCCI_FAC_CMD_BOFFSET:
        {
            break;
        }
        case DDCCI_FAC_CMD_RED_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_RED_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_RED_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_GREEN_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_GREEN_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_GREEN_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_BLUE_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_BLUE_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_BLUE_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_CYAN_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_CYAN_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_CYAN_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_YELLOW_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_YELLOW_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_YELLOW_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_MAGENTA_HUE:
        {
            break;
        }
        case DDCCI_FAC_CMD_MAGENTA_SAT:
        {
            break;
        }
        case DDCCI_FAC_CMD_MAGENTA_LUM:
        {
            break;
        }
        case DDCCI_FAC_CMD_PWM:
        {
            break;
        }
        case DDCCI_FAC_CMD_SET_FR:
        {
            break;
        }
        case DDCCI_FAC_CMD_SIMKEY0:
        {
            break;
        }
        case DDCCI_FAC_CMD_SIMKEY1:
        {
            break;
        }
        case DDCCI_FAC_CMD_SIMKEY2:
        {
            break;
        }
        case DDCCI_FAC_CMD_SIMKEY3:
        {
            break;
        }
        case DDCCI_FAC_CMD_SIMKEY4:
        {
            break;
        }
        case DDCCI_FAC_CMD_GAMMA_MEA:
        {
            break;
        }
        case DDCCI_FAC_CMD_DELTAE_MEA:
        {
            break;
        }
        case DDCCI_FAC_CMD_FACTORYMODE:
        {
            UCHAR8 ucVal = Hv_Mw_Factory_GetFactoryModeEnable();
            usRspLen = DDCCI_FAC_DDC_HEADER_LEN + DDCCI_FAC_DDC_CMD_FIX_LEN;
            usProtocolLen = DDCCI_FAC_DDC_CMD_FIX_LEN;
            pucRspData = HV_MALLOC(usRspLen);
            if (NULL == pucRspData)
            {
                break;
            }
            HV_MEMSET(pucRspData, 0x00, usRspLen);
            
            pucRspData[DDCCI_FAC_OFFSET_SRC] = DDCCI_DEST_ADDRESS;
            pucRspData[DDCCI_FAC_OFFSET_LEN_HIGH] = usProtocolLen >> 8;
            pucRspData[DDCCI_FAC_OFFSET_LEN_LOW] = usProtocolLen & 0xFF;
            pucRspData[DDCCI_FAC_OFFSET_PQ_CMD_VALUE_MSB] = !!ucVal;
            pucRspData[usRspLen - 1] = Hv_App_Ddcci_GenFactoryChecksum(pucRspData);
            
            Hv_App_Ddcci_SendData(ucSource, pucRspData, usRspLen);
            DDC_PRINT( "read factory mode");
            
            break;
        }
        case DDCCI_FAC_CMD_LUTINIT:
        {
            break;
        }
        case DDCCI_FAC_CMD_WCG_3D_LUT:
        {
            break;
        }
        
        default:
        {
            break;
        }
    }
    
    if (NULL != pucValidData)
    {
        HV_FREE(pucValidData);
    }
    if (NULL != pucRspData)
    {
        HV_FREE(pucRspData);
    }
    return;
}

VOID Hv_App_Ddcci_ProcFactoryMsg(UCHAR8 ucSource, UCHAR8 *pucData, USHORT16 usLen)
{
    if (DDCCI_FAC_CMD_TYPE_WRITE == pucData[DDCCI_FAC_OFFSET_CMD_TYPE])
    {
        Hv_App_Ddcci_ProcHisFactorySet(ucSource, pucData, usLen);
    }
    else
    {
        Hv_App_Ddcci_ProcHisFactoryGet(ucSource, pucData, usLen);
    }
    return;
}

VOID deltaCompress(UINT32 *puiInputArray, UINT32 uiArraySize, UCHAR8 *pucCompressedArray) 
{
    INT32 iPrevValue = 0;
    INT32 iDelta;
    UINT32 uiId = 0;

    for (uiId = 0; uiId < uiArraySize; uiId++)
    {
        iDelta = puiInputArray[uiId] - iPrevValue;
        if (iDelta > 16) 
        {
            iDelta = 16;
        }
        
        if(iDelta < 0)
        {
            iDelta = 0;
        }
        
        if (uiId % 2 == 0) 
        {
            pucCompressedArray[uiId / 2] = (iDelta & 0xf) << 4; // 存储高4位
        } 
        else 
        {
            pucCompressedArray[uiId / 2] |= (iDelta & 0xf); // 存储低4位
        }
        
        iPrevValue = puiInputArray[uiId];
    }
}

// Input 1025 * 3 * 4 Bytes; output 514 * 3 Bytes
VOID Hv_App_GmaCompress(UINT32 *puiInput, UCHAR8 *pucOut)
{
    deltaCompress(puiInput, 1026, pucOut);
    deltaCompress(&puiInput[1025], 1026, &pucOut[513]);
    deltaCompress(&puiInput[1025 * 2], 1026, &pucOut[513 * 2]);
    return;
}


