⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dalddc.c

📁 此代码为WCE5.0下显示器的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
  if (lpDisplay->lpHWED->ulFunctionHooks2 
      & GDO_HOOK2_DDCPOSTDDCQUERY)
  {
    lpDisplay->
        lpHWED->pfnDDC_I2C_PostDDCQuery(lpDisplay->hGDO, bRetCode);
  }

  if (FALSE == bRetCode)
  {
	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQuery- Exit"));
    return FALSE;
  }
  else if(lpDisplay ->lpHWED ->ulDisplayType & HW_DISPLAY_TYPE_CV)
  { 
	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQuery- Exit"));
	return TRUE; 
  }
  // Verify that the data obtained is valid
  //
  lpEDIDBuf->ulSize = GetStandardEdidLength(lpEDIDBuf->aucEdidDataBuffer);
  if(sizeof(lpEDIDBuf->aucEdidDataBuffer) < lpEDIDBuf->ulSize)
  {
    DALASSERT(FALSE, "Available Edid buffer is too small for this EDID version!");
	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQuery- Exit"));
    return FALSE;
  }
  
  if (EDID_VER_1_STDLEN == lpEDIDBuf->ulSize)
  {   // Version 1
    
    // Was bug (DFP): ulFormatId = EDID_VERSION_11 (0x101)
    lpEDIDBuf->ulFormatId = (lpEDIDBuf->aucEdidDataBuffer[0x12] << 8) 
                              | lpEDIDBuf->aucEdidDataBuffer[0x13];
    //lpEDIDBuf->ulSize = EDID_VERSION_1_STDLEN;  // Was bug (CRT): set only if 0x101
  }
  else if (EDID_VER_2_STDLEN == lpEDIDBuf->ulSize)
  {   // Version 2
    
    lpEDIDBuf->ulFormatId = EDID_VER_20;

      // Do not support Version 2 for CRTs (Why??)
      //
    if(lpDisplay->lpHWED->ulDisplayType & HW_DISPLAY_TYPES_CRT_MASK)       
    {
	  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQuery- Exit"));
      return FALSE;
    }
  }
  else
  {   // Unknown
    
    DALDEBUG((DALDBG_NORMAL, "Unknown EDID version"));
	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQuery- Exit"));
    return FALSE;
  }
  
  // ulDFPSupportsDDC in DFP GDO is no longer used
  
  // Return TRUE *only* if DDC-reported display type is expected
  //
  if (!(lpDisplay->lpHWED->ulDisplayType 
        & GetDisplayTypeFromEdid(lpEDIDBuf)))
  {
	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQuery- Exit"));
    return FALSE;
  }

  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQuery- Exit"));
  return TRUE;
} // DDCQuery()

/******************************Private*Routine*****************************\
* BOOL DDCQueryCallback(LPDALDDC_DDCCONTEXT lpddcContext)
*
* Synchronized callback used by DDCQuery()
*
\**************************************************************************/

static BOOL 
DDCQueryCallback(
  LPDALDDC_DDCCONTEXT lpddcContext) // Contains all DDCQuery() parameters
{
  ULONG       ulChecksum;         // EDID checksum
  ULONG       ulScratch;          // Temp variable
  ULONG       ulAddr, ulStartAddr;
  BOOL        bRes = FALSE;
  PFNDDCREADLINE    pfnReadLine = 
    lpddcContext->lpDisplay->lpHWED->pfnDDC_I2C_ReadLine;
  PFNDDCWRITELINE   pfnWriteLine = 
    lpddcContext->lpDisplay->lpHWED->pfnDDC_I2C_WriteLine;
  HGDO      hGDO            = lpddcContext->lpDisplay->hGDO;
  LPUCHAR   lpucQueryBuffer = lpddcContext->lpucQueryBuffer;
  ULONG     ulLength        = lpddcContext->ulLength;


  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQueryCallback- Entry"));
  
  DALASSERT(NULL != lpddcContext, "lpddcContext is NULL!");
  
  // This is a little fix that gets some older DDC monitors to respond
  // properly to DDC queries.  Set the clock line low, wait 15 ms then set
  // the clock line high.
  //
  pfnWriteLine(hGDO, 0, DAL_DDC_I2C_LINE_SCL);
  DDC_DELAY_MILLISECONDS(15);
  pfnWriteLine(hGDO, 1, DAL_DDC_I2C_LINE_SCL);

    // Initialize SDA and SCL lines to default state of released high (input).
    // Drive SCL low for 15ms to switch DDC2-capable monitor to DDC2 mode.
    //
  pfnWriteLine(hGDO, 1, DAL_DDC_I2C_LINE_SDA);
  pfnWriteLine(hGDO, 0, DAL_DDC_I2C_LINE_SCL);
  DDC_DELAY_MILLISECONDS(15);
  pfnWriteLine(hGDO, 1, DAL_DDC_I2C_LINE_SCL);
  
  if (DDCWaitForClockLineHigh(lpddcContext->lpDisplay) == FALSE)
  {
    DALDEBUG((DALDBG_DETAIL, "DDCQueryCallback: Can't switch to DDC2"));
    DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQueryCallback- Exit"));
    return FALSE;
  }
  
    // Tell the monitor that we want to talk to it and give the

    // address we want to start with. If DFP then try different addresses 
    // starting from high.
    //
  ulAddr = (lpddcContext->lpDisplay->lpHWED->ulDisplayType & HW_DISPLAY_TYPES_DFP_MASK) ? 
            DDC_I2C_MONITOR_ADDRESS_WRITE_A2 : DDC_I2C_MONITOR_ADDRESS_WRITE_A0;

  if(lpddcContext->lpDisplay->lpHWED->ulDisplayType & HW_DISPLAY_TYPE_CV)
  {
    //We might use other chips, add more check later.
     ulAddr                 = lpddcContext->lpDisplay->lpHWED->usI2CWriteLastAddr;
                          
     ulStartAddr            = lpddcContext->lpDisplay->lpHWED->usI2CWriteStartAddr;
     lpddcContext->ulLength = 2;   //Write 2 bytes
     ulLength               = 1;   //Only query 1 byte.
    
  }
  else
    ulStartAddr = DDC_I2C_MONITOR_ADDRESS_WRITE_A0 ;

  for(; ulAddr >= ulStartAddr; ulAddr -=2)
  {
    ULONG ulRetryCounter = lpddcContext->lpHDE->ulRetryDDCWriteTimes;
    lpucQueryBuffer[0] = (UCHAR)ulAddr;
    lpucQueryBuffer[1] = (UCHAR)DDC_I2C_EDID_START_ADDRESS;
    while (FALSE == (bRes = DDCWrite(lpddcContext->lpDisplay, 
                    lpucQueryBuffer, 2))
           && ulRetryCounter--);

    if (FALSE == bRes)
      continue;
 

      // Read EDID from the monitor. The read address is always write address + 1
      //
    ZEROMEMORY(lpucQueryBuffer, ulLength);
    if (FALSE == DDCRead(lpddcContext->lpDisplay, 
      lpucQueryBuffer, ulLength, (UCHAR)(ulAddr + 1)))
    { 
      DALDEBUG((DALDBG_DETAIL, "DDCQueryCallback: Can't read - DDC2 not supported"));
	  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQueryCallback- Exit"));
      return FALSE;
    }
  
    break;
  }

  if (FALSE == bRes)
  {
    DALDEBUG((DALDBG_DETAIL, "DDCQueryCallback: Can't write - DDC2 not supported"));
	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQueryCallback- Exit"));
    return FALSE;
  }
  
  if(lpddcContext->lpDisplay->lpHWED->ulDisplayType & HW_DISPLAY_TYPE_CV)
  {
    //Inform GDO about I2C addr update for later set Mode ID use.
    if (GDO_HOOK2_I2C_SUPPORT & lpddcContext->lpDisplay->lpHWED->ulFunctionHooks2)
    {
      UCHAR ucAddr = (UCHAR)(ulAddr);
     (*lpddcContext->lpDisplay->lpHWED->pfnGetSetI2CData)
       (lpddcContext->lpDisplay->hGDO, &ucAddr, 1, DAL_I2C_SET_ADDR_TO_GDO);

     (*lpddcContext->lpDisplay->lpHWED->pfnGetSetI2CData)
       (lpddcContext->lpDisplay->hGDO, lpucQueryBuffer, 1, DAL_I2C_SET_DATA_TO_GDO);
   
    }
	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQueryCallback- Exit"));
    return TRUE; 
  }
    // Calculate the EDID checksum. We should have 0x00 in LSB for 
    // proper EDID.  
    // There are two versions of the EDID buffer structure.  Version
    // 1 has a buffer size of 128 bytes while version 2 has a buffer
    // size of 256 bytes.
    // Note: we don't have to preset EDID buffer since we know we 
    // can talk to the monitor.
    //
  ulChecksum = 0x00;
  
    // Identify EDID Version
    // Using the first eight bytes of the EDID buffer, the version of
    // the EDID can be determine.  Version 1 has the first eight bytes
    // dedicated as a flag, 0x00FFFFFFFFFFFF00, while version 2 has
    // the first byte set aside as a revision field.
    //
    // BUGBUG: won't work on alpha (big indian) machine
    //
  //lpHeader = (LPULONG) lpucQueryBuffer;
  //if (*lpHeader++ == DDC_EDID_LSD_HEADER_VERSION_1)
  //{
  //  if (*lpHeader == DDC_EDID_MSD_HEADER_VERSION_1)
  //  {   // Version 1 - Buffer size is only 128 bytes
  //
  //    ulLength = 128;
  //  } 
  //}
  {
    ULONG ulStdLength = GetStandardEdidLength(lpucQueryBuffer);
  
      // Cannot proceed if supplied buffer was smaller (was a bug!)
      //
    if (ulLength < ulStdLength)
	{
	  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQueryCallback- Exit"));
      return FALSE;
	}

    ulLength = ulStdLength;
  }
  
    // Verify EDID Buffer
    // Do a simple checksum on the buffer the LSB should be zero.
    // 
  for (ulScratch = 0; ulScratch < ulLength; ulScratch++)
  {
    ulChecksum += lpucQueryBuffer[ulScratch];
  }
  
  DALDEBUG((DALDBG_DETAIL, 
    "DDCQueryCallback: EDID checksum = 0x%08X", ulChecksum));
  
    // We need to make sure that the LSB of the checksum is 0
    // AS WELL AS ensuring that the checksum does not equal the 
    // value that we inititally set it to (zero).  Since we zeroed
    // the buffer before we called the routine to get the DDC buffer,
    // if the monitor didn't respond at all but we thought it did then
    // the checksum would be zero and if we didn't check to make sure the
    // upper part of the dword was not 0 we could be passing back a bad
    // buffer.
    //
  if ((ulChecksum & 0xFF) || (ulChecksum == 0 ))
  {
    DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQueryCallback- Exit"));
    return FALSE;
  }

  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQueryCallback- Exit"));
  return TRUE;
} // DDCQueryCallback()


/******************************Private*Routine*****************************\
* BOOL DDCStart(LPDEVGDO lpDisplay)
*
* Start DDC communication.
*
\**************************************************************************/

static BOOL
DDCStart(
  LPDEVGDO  lpDisplay)  // Display structure
{
  ULONG ulRetry;
  PFNDDCREADLINE    pfnReadLine = lpDisplay->lpHWED->pfnDDC_I2C_ReadLine;
  PFNDDCWRITELINE   pfnWriteLine = lpDisplay->lpHWED->pfnDDC_I2C_WriteLine;
  
  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCStart- Entry"));

  //
  // The I2C communications start signal is a SDA high->low while the SCL is high.
  //
  // this is a little fix that gets some marginal DDC monitors to respond
  // properly to DDC queries.  Set the clock line low, wait 15 ms then set
  // the clock line high, wait, set clock low.
  //
  
  // Set SCL high
  //
  pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SCL);
  
  for (ulRetry = 0; ulRetry <= DDC_I2C_START_RETRIES; ulRetry++)
  {
    // Set SDA high
    //
    pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SDA);
    DDC_DELAY_MICROSECONDS(13);
    if (pfnReadLine(lpDisplay->hGDO, DAL_DDC_I2C_LINE_SDA) == FALSE)
      continue; // SDA didn't take - retry
    
    // Set SCL high
    //
    pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SCL);
    DDC_I2C_DELAY();
    if (DDCWaitForClockLineHigh(lpDisplay) == FALSE)
    {
      DALDEBUG((DALDBG_DETAIL, "DDCStart: SCL didn't take"));
      break;
    }
    
    // Set SDA low
    //
    pfnWriteLine(lpDisplay->hGDO, 0, DAL_DDC_I2C_LINE_SDA);
    DDC_I2C_DELAY();
    
    // Set SCL low
    //
    pfnWriteLine(lpDisplay->hGDO, 0, DAL_DDC_I2C_LINE_SCL);
    DDC_I2C_DELAY();
    
    // Set SDA high
    //
    pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SDA);
    DDC_I2C_DELAY();

	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCStart- Exit"));
    return TRUE;
  }
  
  DALDEBUG((DALDBG_DETAIL, "DDCStart: Failed"));
  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCStart- Exit"));
  return FALSE;
} // DDCStart()

/******************************Private*Routine*****************************\
* BOOL DDCStop(LPDEVGDO lpDisplay)
*
* Stop DDC communication.
*
\**************************************************************************/

static BOOL
DDCStop(
  LPDEVGDO  lpDisplay)  // Display structure
{
  PFNDDCREADLINE    pfnReadLine = lpDisplay->lpHWED->pfnDDC_I2C_ReadLine;
  PFNDDCWRITELINE   pfnWriteLine = lpDisplay->lpHWED->pfnDDC_I2C_WriteLine;
  
  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCStop- Entry"));

  //
  // The I2C communications stop signal is a SDA low->high while the SCL is high.
  //
  
  pfnWriteLine(lpDisplay->hGDO, 0, DAL_DDC_I2C_LINE_SCL);
  
  // Set SDA low
  //
  pfnWriteLine(lpDisplay->hGDO, 0, DAL_DDC_I2C_LINE_SDA);
  DDC_I2C_DELAY();
  
  // Set SCL high
  //
  pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SCL);
  DDC_I2C_DELAY();
  
  if (DDCWaitForClockLineHigh(lpDisplay) == FALSE)
  {
    DALDEBUG((DALDBG_DETAIL, "DDCStop: SCL didn't take"));
	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCStop- Exit"));
    return FALSE;
  }
  
  // Set SDA high
  //
  pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SDA);
  DDC_I2C_DELAY();
  if (pfnReadLine(lpDisplay->hGDO, DAL_DDC_I2C_LINE_SDA) == FALSE)
  {
    DALDEBUG((DALDBG_DETAIL, "DDCStop: SDA didn't take"));
	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCStop- Exit"));
    return FALSE;
  }
  
  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCStop- Exit"));
  return TRUE;
} // DDCStop()

/******************************Private*Routine*****************************\
* BOOL DDCRead(LPDEVGDO lpDisplay, LPUCHAR lpucBuf, ULONG ulLen, 
*               UCHAR ucReadAddr)
*
* Read byte block of EDID data.
*
\**************************************************************************/

static BOOL
DDCRead(
  LPDEVGDO  lpDisplay,  // Display structure
  LPUCHAR   lpucBuf,    // Buffer to read to
  ULONG     ulLen,      // Buffer length
  UCHAR     ucReadAddr)
{
  BOOL     bRet;
  ULONG    ulCount;
  
  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCRead- Entry"));
  DALASSERT(NULL != lpucBuf, "lpucBuf is NULL!");
  
    // Try to start I2C bus a number of times. Should succeed every time,
    // otherwise fail. Really paranoid.
    //
  bRet    = DDCStart(lpDisplay);
  ulCount = DDC_RETRIES;
  while ((bRet) && (ulCount > 0))
  {
    bRet = DDCStart(lpDisplay);
    ulCount--;
  }

  if (bRet == FALSE)
  {
    DALDEBUG((DALDBG_ENTRY_EXIT, "DDCRead- Exit"));
    return FALSE;
  }

    // Tell the monitor that we want to listen to it.
    //
  if (FALSE == DDCWriteByte(lpDisplay, ucReadAddr))
  {
    DDCStop(lpDisplay);
	DALDEBUG((DALDBG_ENTRY_EXIT, "DDCRead- Exit"));
    return FALSE;
  }

    // On all but the last byte, we must send an ACK in order to ensure that the sending device will
    // send subsequent data bytes. On the last byte, we must send a NAK so that it will shut up.
    //
  for (ulCount = 0; ulCount < ulLen; ulCount++)
  {
    if (FALSE == (bRet = DDCReadByte(lpDisplay, lpucBuf + ulCount, ulCount < ulLen - 1)))
      break;

      // Make sure we don't attempt to read beyond the standard EDID length.
      // Doing this may hang certain monitors.
      //
      // NOTE:
      // Should read EDID data in portions at high level (bGetEdidData())
      // if want to save the overhead of rereading/restarting:
      // 1. Read 8 first bytes
      // 2. Read EDID data of standard length less 8 bytes
      // 3. Read any optional data less read data
      // In such implementation Start() and Stop() are called at high level 
      // and this check is moved there as well.
      //
    if (EDID_VER_1_HDRLEN - 1 == ulCount)
    {
      ULONG ulStdLen = GetStandardEdidLength(lpucBuf);

      if (ulStdLen != 0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -