
#define USE_NEW_I2C_DRV 1

#include "libddc.h"

#ifdef USE_NEW_I2C_DRV

#include "i2c_hdmi_interface.h"
#include "i2c_hdcp_interface.h"

#define I2C_DRIVER_HDMI_PORT  _T("I2C1:")

#define EDID_ADDR       (0xa0)
#define EDID_SEGMENT_ADDR  (0x60)
#define HDCP_ADDR	(0x74)
#define DDC_CLK         80

HANDLE g_hI2C_Hdmi = NULL;
HANDLE g_hI2C_HdmiSegment = NULL;
HANDLE g_hI2C_Hdcp = NULL;
#endif


// device driver for DDC
#include "hdmi_iic.h"

//TODO: change the debug zone
#define DDC_ZONE	0

// buffer length for DDC Write
#define MAX_BUFFER_SIZE     1024

// handle for DDC
HANDLE hDDC = INVALID_HANDLE_VALUE;

BOOL DDCInit(VOID)
{
    BOOL bRet = FALSE;
//    DWORD dwErr;
	
    RETAILMSG(DDC_ZONE,(_T("[DDC: %s]:(FUNC) InitializeIIC_DRV ++ \n\r"),TEXT(__FUNCTION__)));

#ifdef USE_NEW_I2C_DRV
	g_hI2C_Hdmi = Open_HDMI_I2C(I2C_DRIVER_HDMI_PORT);
	Init_HDMI_I2C(g_hI2C_Hdmi, EDID_ADDR, DDC_CLK);

	g_hI2C_HdmiSegment = Open_HDMI_I2C(I2C_DRIVER_HDMI_PORT);
	Init_HDMI_I2C(g_hI2C_HdmiSegment, EDID_SEGMENT_ADDR, DDC_CLK);

    g_hI2C_Hdcp = Open_HDCP_I2C(I2C_DRIVER_HDMI_PORT);
    Init_HDCP_I2C(g_hI2C_Hdcp, HDCP_ADDR, DDC_CLK);
//    g_hI2C_Hdcp = Open_HDMI_I2C(I2C_DRIVER_HDMI_PORT);
//    Init_HDMI_I2C(g_hI2C_Hdcp, HDCP_ADDR, DDC_CLK);

	bRet = TRUE;
#else

    if( hDDC == INVALID_HANDLE_VALUE )
    {
        hDDC = CreateFile( L"HIC1:",
                            GENERIC_READ | GENERIC_WRITE,
                            FILE_SHARE_READ | FILE_SHARE_WRITE,
                            NULL, OPEN_EXISTING, 0, 0);

        if ( hDDC == INVALID_HANDLE_VALUE )
        {
            dwErr = GetLastError();
            RETAILMSG(DDC_ZONE,(_T("[DDC: %s]:(ERR) DDCInit() : IIC0: Device Open Failed = 0x%08x\n\r"),TEXT(__FUNCTION__), dwErr));
            bRet = FALSE;
            goto CleanUp;
        }
    }

    bRet = TRUE;
#endif

#ifdef USE_NEW_I2C_DRV
#else

CleanUp:

#endif

    return bRet;
}

// deinitialize DDC driver
BOOL DDCDeInit(VOID)
{
    BOOL ret = TRUE;

#ifdef USE_NEW_I2C_DRV

    if( g_hI2C_Hdmi != INVALID_HANDLE_VALUE )
    {
        ret = CloseHandle(g_hI2C_Hdmi);
        g_hI2C_Hdmi = INVALID_HANDLE_VALUE;
    }
	
    if( g_hI2C_Hdcp != INVALID_HANDLE_VALUE )
    {
        ret = CloseHandle(g_hI2C_Hdcp);
        g_hI2C_Hdcp = INVALID_HANDLE_VALUE;
    }

#else

    if( hDDC != INVALID_HANDLE_VALUE )
    {
        ret = CloseHandle(hDDC);
        hDDC = INVALID_HANDLE_VALUE;
    }

#endif

    return ret;    
}

// read data through DDC (fast read)
BOOL DDCRead(BYTE ucDevAddr,BYTE ucOffset, UINT32 uiSize, PBYTE pucData)
{

#ifdef USE_NEW_I2C_DRV
//    DWORD index;
	BOOL bReturn = TRUE;
	BYTE btWriteBuffer[2];
//    WORD dwData;
//    BYTE temp[2];

	if (pucData == NULL)
		return FALSE;

	RETAILMSG(DDC_ZONE, (TEXT("+%s\r\n"), _T(__FUNCTION__)));
    RETAILMSG(DDC_ZONE, (_T("[DDC: %s]:ucDevAddr = 0x%x,ucOffset = 0x%x, uiSize = 0x%x \n\r"),TEXT(__FUNCTION__),ucDevAddr, ucOffset, uiSize));

	btWriteBuffer[0] = (BYTE)ucOffset;

    if(Read_HDMI_I2C(g_hI2C_Hdcp, btWriteBuffer, 1, FALSE, (PBYTE)pucData, uiSize) == FALSE)    
//    if(Read_HDMI_I2C(g_hI2C_Hdmi, btWriteBuffer, 1, FALSE, (PBYTE)pucData, uiSize) == FALSE)
//    if(Read_HDMI_I2C(g_hI2C_Hdmi, (PUCHAR)&ucOffset, 1, FALSE, pucData, uiSize) == FALSE)
	{
		RETAILMSG(DDC_ZONE, (TEXT("Read 0x%X was failed, error code = %dr\n"), ucDevAddr, GetLastError()));
		bReturn = FALSE;
	}

	RETAILMSG(DDC_ZONE, (TEXT("-%s\r\n"), _T(__FUNCTION__)));
	return bReturn;

#else

    int i = 0;
    DWORD dwErr = 0;
    DWORD dwbytes = 0;
    IIC_IO_DESC IIC_AddressData;
    IIC_IO_DESC IIC_Data;
    BOOL bRet = FALSE;

    RETAILMSG(DDC_ZONE, (_T("[DDC: %s]:(FUNC) Receive addr = 0x%x, Size = %d\n\r"),TEXT(__FUNCTION__),ucDevAddr, uiSize));
    
    IIC_AddressData.SlaveAddress = ucDevAddr;
    IIC_AddressData.Data  = (PUCHAR)&ucOffset;
    IIC_AddressData.Count = 1;

    IIC_Data.SlaveAddress = ucDevAddr;
    IIC_Data.Data = pucData;
    IIC_Data.Count = uiSize;
    

    RETAILMSG(DDC_ZONE, (_T("[DDC: %s] addr = 0x%x, ucCount = %d\n\r"),TEXT(__FUNCTION__),IIC_AddressData.Data[0], IIC_Data.Count));                

	if (hDDC == INVALID_HANDLE_VALUE)
	{
	    RETAILMSG(DDC_ZONE, (_T("[DDC: %s]:(ERR): INVALID_HANDLE_VALUE \r\n"),TEXT(__FUNCTION__)));
	    return FALSE;
	}
    bRet = DeviceIoControl(hDDC,
        IOCTL_IIC_READ,
        &IIC_AddressData,  sizeof(IIC_IO_DESC),
        &IIC_Data,  sizeof(IIC_IO_DESC),
        &dwbytes, NULL);

    if (bRet == FALSE)
    {
        dwErr = GetLastError();
        RETAILMSG(DDC_ZONE, (_T("[DDC: %s]:(ERR) DDC_READ ERROR: %u \r\n"),TEXT(__FUNCTION__),dwErr));
        return FALSE;            
    }
    else
    {
        RETAILMSG(DDC_ZONE,(_T("[DDC: %s] DDC_READ Success\n\r"),TEXT(__FUNCTION__)));
        return TRUE;
    }
    
    return TRUE;
#endif

}

// write data through DDC
BOOL DDCWrite(BYTE ucDevAddr,BYTE ucOffset, UINT32 uiSize, PBYTE pucData)
{
#ifdef USE_NEW_I2C_DRV
    UINT32 i;
//    DWORD index;
	BOOL bReturn = TRUE;
	BYTE btWriteBuffer[2];
//    WORD dwData;
//    BYTE temp[2];
    BOOL bStop = TRUE;

	if (pucData == NULL)
		return FALSE;

	RETAILMSG(DDC_ZONE, (TEXT("+%s\r\n"), _T(__FUNCTION__)));

	btWriteBuffer[0] = (BYTE)ucOffset;

       for (i = 1; i <= uiSize; i++)
      {
            btWriteBuffer[i] = pucData[i - 1];
            RETAILMSG(DDC_ZONE, (_T("[DDC: %s]: btWriteBuffer[%d] = 0x%x\n"),TEXT(__FUNCTION__),i, btWriteBuffer[i]));            
      }

    if(Write_HDMI_I2C(g_hI2C_Hdcp, btWriteBuffer, uiSize,bStop) == FALSE)    
//    if(Write_HDMI_I2C(g_hI2C_Hdmi, btWriteBuffer, uiSize,bStop) == FALSE)
	{
		RETAILMSG(DDC_ZONE, (TEXT("Write 0x%X was failed, error code = %dr\n"), ucDevAddr, GetLastError()));
		bReturn = FALSE;
	}

	RETAILMSG(DDC_ZONE, (TEXT("-%s\r\n"), _T(__FUNCTION__)));
	return bReturn;

#else
	
    IIC_IO_DESC IIC_Data;
    BOOL bRet = FALSE;
    DWORD dwErr = 0;
    DWORD bytes;
    UINT32 i = 0;
    
    // TODO: check this!!! if size is more than 9?
    //UCHAR buff[9];
    UCHAR buff[MAX_BUFFER_SIZE+1];

    RETAILMSG(DDC_ZONE, (_T("[DDC: %s]:(FUNC) DDC WRITE\n\r"),TEXT(__FUNCTION__)));

    if (uiSize > MAX_BUFFER_SIZE)
    {
        RETAILMSG(DDC_ZONE, (_T("[DDC: %s]:(FUNC) Write SIZE Exceeds %d \n\r"),TEXT(__FUNCTION__),MAX_BUFFER_SIZE));
        return FALSE;
    }
    
    buff[0] = ucOffset;
    for (i = 1; i <= uiSize; i++)
    {
        buff[i] = pucData[i - 1];
        RETAILMSG(DDC_ZONE, (_T("[DDC: %s]: buff[%d] = 0x%x\n"),TEXT(__FUNCTION__),i, buff[i]));            
    }
    
    RETAILMSG(DDC_ZONE, (_T("[DDC: %s]: buff[0] = 0x%x\n"),TEXT(__FUNCTION__),buff[0]));
    IIC_Data.SlaveAddress = ucDevAddr;
    IIC_Data.Data = buff;
    IIC_Data.Count = uiSize;

    if (hDDC == INVALID_HANDLE_VALUE)
	{
	    RETAILMSG(DDC_ZONE, (_T("[DDC: %s]:(ERR) IOCTL_IIC_WRITE ERROR: INVALID_HANDLE_VALUE \r\n"),TEXT(__FUNCTION__)));
        return FALSE;
	}
    bRet = DeviceIoControl(hDDC,
            IOCTL_IIC_WRITE,
            &IIC_Data, sizeof(IIC_IO_DESC),
            NULL, 0,
            &bytes, NULL);

    if (bRet == FALSE)
    {
        dwErr = GetLastError();
        RETAILMSG(DDC_ZONE,(_T("[DDC: %s]:(ERR) IOCTL_IIC_WRITE ERROR: %u \r\n"),TEXT(__FUNCTION__), dwErr));
        return FALSE;            
    }
    else
    {
        RETAILMSG(DDC_ZONE,(_T("[DDC: %s] DDC_WRITE DONE\n\r"),TEXT(__FUNCTION__)));
    }
    
    return TRUE;
#endif	
}

// read data though DDC by using E-DDC protocol
BOOL EDDCReadEDID(BYTE ucSegNum, BYTE ucDevAddr,UINT32 uiOffset, BYTE ucSize, PBYTE pucData)
{
// I2C Drvier has a problem. for now, have to read by byte not burst. 
#ifdef USE_NEW_I2C_DRV

	DWORD index = uiOffset;
	BOOL bReturn = TRUE;
	BYTE btWriteSegBuffer[2];
	BYTE btWriteIndexBuffer[2];
	BOOL bStop = FALSE;

	if (pucData == NULL)
		return FALSE;

	RETAILMSG(DDC_ZONE, (TEXT("+%s\r\n"), _T(__FUNCTION__)));

	//It is nothing ...
	btWriteSegBuffer[0] = (BYTE)ucSegNum;

	//Real Segment Number...
	btWriteIndexBuffer[0] = (BYTE)ucSegNum;
	btWriteIndexBuffer[1] = (BYTE)index;	
	if(Write_HDMI_Seg_I2C(g_hI2C_Hdmi, btWriteSegBuffer, 1, 
		                                btWriteIndexBuffer, 1, 
		                                (PBYTE)(pucData + (index-uiOffset)), 128) == FALSE)
	{
		RETAILMSG(DDC_ZONE, (TEXT("Write 0x%X was failed, error code = %dr\n"), ucDevAddr, GetLastError()));
		bReturn = FALSE;
	}

	RETAILMSG(DDC_ZONE, (TEXT("-%s\r\n"), _T(__FUNCTION__)));
	return bReturn;

#else


#if 0
    DWORD dwErr = 0;
    DWORD dwbytes = 0;
    DWORD dwOffsetAddr = 0;
    IIC_IO_DESC IIC_AddressData;
    IIC_IO_DESC IIC_Data;
    BYTE temp[2];

    if (pucData == NULL)
        return FALSE;

    IIC_AddressData.SlaveAddress = ucDevAddr;
    IIC_AddressData.Count = 1;
    IIC_AddressData.Data  = temp;

    IIC_Data.SlaveAddress = ucDevAddr;
    IIC_Data.Count = ucSize;

    temp[0] = ucSegNum;
    temp[1] = uiOffset;

    IIC_Data.Data = pucData;

	RETAILMSG(DDC_ZONE, (_T("[DDC: %s]:(FUNC) Receive addr = 0x%x, Size = %d\n\r"),TEXT(__FUNCTION__),ucDevAddr, ucSize));

    if(!DeviceIoControl(hDDC,
                          IOCTL_IIC_EDID_READ,
                          &IIC_AddressData,  sizeof(IIC_IO_DESC),
                          &IIC_Data,  sizeof(IIC_IO_DESC),
                          &dwbytes, NULL))
    {
        dwErr = GetLastError();
        RETAILMSG(DDC_ZONE,(_T("[DDC: %s] IOCTL_IIC_EDID_READ ERROR: 0x%04x \r\n"),TEXT(__FUNCTION__), dwErr));
        return FALSE;
    }
    
    return TRUE;
#else
	DWORD index;
	DWORD dwErr = 0;
    DWORD dwbytes = 0;
    DWORD dwOffsetAddr = 0;
    IIC_IO_DESC IIC_AddressData;
    IIC_IO_DESC IIC_Data;
    BYTE temp[2];

    if (pucData == NULL)
        return FALSE;

    IIC_AddressData.SlaveAddress = ucDevAddr;
    IIC_AddressData.Count = 1;
    IIC_AddressData.Data  = temp;

    IIC_Data.SlaveAddress = ucDevAddr;
    IIC_Data.Count = 1;

    temp[0] = ucSegNum;

	RETAILMSG(DDC_ZONE, (_T("[DDC: %s]:(FUNC) Receive addr = 0x%x, Size = %d, Offset = %d,  Buffer = 0x%04X\n\r"),TEXT(__FUNCTION__),ucDevAddr, ucSize, uiOffset, pucData));

    
    for (index = uiOffset; index < (uiOffset + ucSize); index++)
    {
        temp[1]  = (UCHAR)index;

        IIC_Data.Data = (PBYTE)(pucData + (index-uiOffset));
        
        if(!DeviceIoControl(hDDC,
                              IOCTL_IIC_EDID_READ,
                              &IIC_AddressData,  sizeof(IIC_IO_DESC),
                              &IIC_Data,  sizeof(IIC_IO_DESC),
                              &dwbytes, NULL))
        {
            dwErr = GetLastError();
            RETAILMSG(DDC_ZONE,(_T("[DDC: %s] IOCTL_IIC_EDID_READ ERROR: 0x%04X \r\n"),TEXT(__FUNCTION__), dwErr));
            return 0;
        }
    }
    return TRUE;
#endif     

#endif
}
