//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <BSP.h>
#include <iic.h>

#if __cplusplus
extern "C"
{
#endif


#define RETRY_COUNT     1
#define FAST_CALL       FALSE
#define DEBUG_MSG_ON    TRUE

static I2C_FASTCALL FastCall;

HANDLE
Open_HDMI_I2C(LPWSTR lpGroupName)
{
        HANDLE hI2C;

        hI2C = CreateFile(lpGroupName,
                        GENERIC_READ|GENERIC_WRITE,
                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                        NULL, OPEN_EXISTING, 0, 0);

        if(hI2C == INVALID_HANDLE_VALUE) 
        {
                ERRMSG((L"[Open_HDMI_I2C] I2C OPEN : %s ERROR(%d) \r\n", lpGroupName, GetLastError()));
                hI2C = NULL;
        }
        else
        {
                DBGMSG(DEBUG_MSG_ON, (L"[Open_HDMI_I2C] I2C OPEN : %s SUCCESS\r\n", lpGroupName));
        }

        return hI2C;
}

BOOL
Init_HDMI_I2C(HANDLE hI2C, WORD wSlaveAddr, DWORD dwSpead)
{
        I2C_INIT_DESC I2CInitDesc;

        I2CInitDesc.IN_wSlaveAddr           = wSlaveAddr; 
        I2CInitDesc.IN_dwClockSpeed     = dwSpead;
        I2CInitDesc.OUT_dwActualSpeed   = 0;

        if(!DeviceIoControl(hI2C,
                                IOCTL_I2C_INIT, 
                                &I2CInitDesc, sizeof(I2CInitDesc), 
                                NULL, 0,
                                NULL, NULL) ) 
        {
                ERRMSG((L"[Init_HDMI_I2C] IOCTL_I2C_INIT is failed(Error %d) \r\n", GetLastError()));
                return FALSE;
        } 

        DBGMSG(DEBUG_MSG_ON, (L"[Init_HDMI_I2C] ACTUAL I2C CLCOK SPEAD : %d Khz\r\n", I2CInitDesc.OUT_dwActualSpeed));

#if FAST_CALL
        if (!DeviceIoControl(hI2C,
                                IOCTL_I2C_GET_FASTCALL, 
                                NULL, 0, 
                                &FastCall, sizeof(I2C_FASTCALL),
                                NULL, NULL) ) 
        {
                ERRMSG((L"[Init_HDMI_I2C] IOCTL_I2C_GET_FASTCALL is failed(Error %d) \r\n", GetLastError()));
                return FALSE;
        } 

        DBGMSG(DEBUG_MSG_ON, (L"[Init_HDMI_I2C] FastCall : Context : %X, Read Function :  %X Write Function : %X\r\n", FastCall.Context, FastCall.I2CRead, FastCall.I2CWrite));
#endif

        return TRUE;
}

BOOL
Write_HDMI_Seg_I2C(HANDLE hI2C, PBYTE pWSegData,  DWORD dwWSegDatas, 
                                        PBYTE pWIndexData, DWORD dwWIndexDatas, 
                                        PBYTE pRData,      DWORD dwRDatas)
{
        BOOL bResult = TRUE;
        DWORD dwTry;
        I2C_WRITE_DESC I2CWriteDesc;
        I2C_READ_DESC I2CReadDesc;

        I2CWriteDesc.IO_pbtData = pWSegData;
        I2CWriteDesc.IN_dwData  = dwWSegDatas;
	    I2CWriteDesc.IN_bStop   = FALSE;

        for(dwTry=0; dwTry<RETRY_COUNT; ++dwTry)
        {
                if(!DeviceIoControl(hI2C,
                                        IOCTL_I2C_EDIDSEGMENT_WRITE, 
                                        &I2CWriteDesc, sizeof(I2C_WRITE_DESC), 
                                        NULL, 0,
                                        NULL, NULL)) 
                {
                        ERRMSG((L"[Write_HDMI_I2C] IOCTL_I2C_EDIDSEGMENT_WRITE ERROR: %u \r\n", GetLastError()));
                        if(dwTry == (RETRY_COUNT-1)) bResult = FALSE;
                        continue;
                }

                break;
        }
		
        I2CWriteDesc.IO_pbtData = pWIndexData;
        I2CWriteDesc.IN_dwData  = dwWIndexDatas;
        I2CWriteDesc.IN_bStop   = FALSE;

        for(dwTry=0; dwTry<RETRY_COUNT; ++dwTry)
                {
                if(!DeviceIoControl(hI2C,
                                        IOCTL_I2C_GENERAL_WRITE, 
                                        &I2CWriteDesc, sizeof(I2C_WRITE_DESC), 
                                        NULL, 0,
                                        NULL, NULL)) 

                {
                        ERRMSG((L"[Read_HDMI_I2C] IOCTL_I2C_GENERAL_WRITE ERROR: %u \r\n", GetLastError()));
                        if(dwTry == (RETRY_COUNT-1)) bResult = FALSE;
                        continue;
                }
                else 
                {
                        I2CReadDesc.IO_pbtData          = pRData;
                        I2CReadDesc.IN_dwData           = dwRDatas;
                        I2CReadDesc.IN_bStop            = TRUE;

                        if (!DeviceIoControl(hI2C,
                                                IOCTL_I2C_GENERAL_READ, 
                                                &I2CReadDesc, sizeof(I2C_READ_DESC), 
                                                NULL, 0,
                                                NULL, NULL))

                        {
                                ERRMSG((L"[Read_HDMI_I2C] IOCTL_I2C_GENERAL_READ ERROR: %u \r\n", GetLastError()));
                                if(dwTry == (RETRY_COUNT-1)) bResult = FALSE;
                                continue;
                        }               
                }

                break;
        }


        return bResult;
}

BOOL
Write_HDMI_I2C(HANDLE hI2C, PBYTE pWData, DWORD dwWDatas, BOOL bStop)
{
        BOOL bWrite = TRUE;
        DWORD dwTry;
        I2C_WRITE_DESC I2CWriteDesc;

        I2CWriteDesc.IO_pbtData = pWData;
        I2CWriteDesc.IN_dwData  = dwWDatas;
	I2CWriteDesc.IN_bStop   = bStop;

        for(dwTry=0; dwTry<RETRY_COUNT; ++dwTry)
        {
                if(!DeviceIoControl(hI2C,
                                        IOCTL_I2C_GENERAL_WRITE, 
                                        &I2CWriteDesc, sizeof(I2C_WRITE_DESC), 
                                        NULL, 0,
                                        NULL, NULL)) 

                {
                        ERRMSG((L"[Write_HDMI_I2C] IOCTL_I2C_GENERAL_WRITE ERROR: %u \r\n", GetLastError()));
                        if(dwTry == (RETRY_COUNT-1)) bWrite = FALSE;
                        continue;
                }

                break;
        }


        return bWrite;
}

BOOL
Read_HDMI_I2C(HANDLE hI2C, PBYTE pWData, DWORD dwWDatas, BOOL bStop, PBYTE pRData, DWORD dwRDatas)
{
        BOOL bRead = TRUE;
        DWORD dwTry;
        I2C_WRITE_DESC I2CWriteDesc;    
        I2C_READ_DESC I2CReadDesc;


        I2CWriteDesc.IO_pbtData = pWData;
        I2CWriteDesc.IN_dwData  = dwWDatas;
        I2CWriteDesc.IN_bStop   = bStop;

        for(dwTry=0; dwTry<RETRY_COUNT; ++dwTry)
        {
                if(!DeviceIoControl(hI2C,
                                        IOCTL_I2C_GENERAL_WRITE, 
                                        &I2CWriteDesc, sizeof(I2C_WRITE_DESC), 
                                        NULL, 0,
                                        NULL, NULL)) 

                {
                        ERRMSG((L"[Read_HDMI_I2C] IOCTL_I2C_GENERAL_WRITE ERROR: %u \r\n", GetLastError()));
                        if(dwTry == (RETRY_COUNT-1)) bRead = FALSE;
                        continue;
                } 
                else 
                {
                        I2CReadDesc.IO_pbtData          = pRData;
                        I2CReadDesc.IN_dwData           = dwRDatas;
                        I2CReadDesc.IN_bStop            = TRUE;

                        if (!DeviceIoControl(hI2C,
                                                IOCTL_I2C_GENERAL_READ, 
                                                &I2CReadDesc, sizeof(I2C_READ_DESC), 
                                                NULL, 0,
                                                NULL, NULL))

                        {
                                ERRMSG((L"[Read_HDMI_I2C] IOCTL_I2C_GENERAL_READ ERROR: %u \r\n", GetLastError()));
                                if(dwTry == (RETRY_COUNT-1)) bRead = FALSE;
                                continue;
                        }               
                }

                break;
        }

        return bRead;
}

BOOL
EDIDRead_HDMI_I2C(HANDLE hI2C, PBYTE pWData, DWORD dwWDatas, BOOL bStop, PBYTE pRData, DWORD dwRDatas)
{
        BOOL bRead = TRUE;
    
        I2C_READ_DESC  I2CReadDesc;


        I2CReadDesc.IO_pbtData = pRData;
        I2CReadDesc.IN_dwData  = dwRDatas;
        I2CReadDesc.IN_bStop   = TRUE;

        if (!DeviceIoControl(hI2C,
                                IOCTL_I2C_GENERAL_READ, 
                                &I2CReadDesc, sizeof(I2C_READ_DESC), 
                                NULL, 0,
                                NULL, NULL))

        {
                ERRMSG((L"[Read_HDMI_I2C] IOCTL_I2C_EDID_READ ERROR: %u \r\n", GetLastError()));
                bRead = FALSE;
        }               

        return bRead;
}

#if __cplusplus
}
#endif



