DDCBlockAccess/DDCBlockAccessDlg.cpp

A C/C++ Sample Application for Windows (XP, Vista and above); 32bit and 64bit
Visual Studio 2005 solution file "DDCBlockAccess.sln" is included in ADL SDK

// DDCBlockAccessDlg.cpp : implementation file
//

#include "stdafx.h"
#include <codecvt>
#include "..\..\include\adl_sdk.h"
#include "DDCBlockAccess.h"
#include "DDCBlockAccessDlg.h"
#include "mccs.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


//********************************
// Prototypes
//********************************
void    vGetVcpCommand(UCHAR ucVcp, UINT * ulMaxVal, UINT * ulCurVal, int iAdapterIndex, int iDisplayIndex);
void    vSetVcpCommand(UCHAR ucVcp, UINT ulVal, int iAdapterIndex, int iDisplayIndex);
bool    vGetCapabilitiesCommand(UCHAR ucVcp, int iAdapterIndex, int iDisplayIndex);
int             vWriteI2c(char * lpucSendMsgBuf, int iSendMsgLen, int iAdapterIndex, int iDisplayIndex);
int             vWriteAndReadI2c(char *lpucSendMsgBuf, int iSendMsgLen, char * lpucRecvMsgBuf, int iRecvMsgLen,  int iAdapterIndex, int iDisplayIndex);
bool    InitADL();
void    FreeADL();


void* __stdcall ADL_Main_Memory_Alloc ( int iSize )
{
    void* lpBuffer = malloc ( iSize );
    return lpBuffer;
}

void __stdcall ADL_Main_Memory_Free ( void** lpBuffer )
{
    if ( NULL != *lpBuffer )
    {
        free ( *lpBuffer );
        *lpBuffer = NULL;
    }
}

//********************************
// Globals
//********************************
UINT aAllConnectedDisplays[MAX_NUM_DISPLAY_DEVICES]; //int array of connected displays for each of the ATI devices (aligned with sDriverNames)
ADLPROCS adlprocs = {0,0,0,0};
UCHAR ucSetCommandWrite[SETWRITESIZE]           =                                               {0x6e,0x51,0x84,0x03,0x00,0x00,0x00,0x00};
UCHAR ucGetCommandRequestWrite[GETRQWRITESIZE]  =               {0x6e,0x51,0x82,0x01,0x00,0x00};
UCHAR ucGetCommandCapabilitiesWrite[GETCAPWRITESIZE]={0x6e,0x51,0x83,0xf3,0x00,0x00,0x00};
UCHAR ucGetCommandReplyWrite[GETREPLYWRITESIZE] =               {0x6f};
UCHAR ucGetCommandReplyRead[MAXREADSIZE];
UCHAR ucGlobalVcp = VCP_CODE_BRIGHTNESS;

LPAdapterInfo                   lpAdapterInfo = NULL;
LPADLDisplayInfo        lpAdlDisplayInfo = NULL;
char                                                    MonitorNames[MAX_NUM_DISPLAY_DEVICES] [128];            // Array of Monitor names


//********************************
// Helper Functions
//********************************

//****************************************************************************
//
//  int iInitDisplayNames()
//
//  This function initializes the display name buffers passed in the 
//  parameter list as an array of CStrings 
//
//  Returns: The function will return the number of connected adapters.
//           So if only one adapter/driver is loaded, this will return 1.
//
//****************************************************************************/
int iInitDisplayNames(CString *aDriverNames)
{
  int                   iNumberAdapters = 0;
  int                   iAdapterIndex;
  int                   iDisplayIndex;
  int                   iNumDisplays;
  int                   ADL_Err = ADL_ERR;

                adlprocs.ADL_Adapter_NumberOfAdapters_Get ( &iNumberAdapters );

        if ( 0 >=  iNumberAdapters )            // No adapters found!!!
                        return 0;

        lpAdapterInfo = (LPAdapterInfo)malloc ( sizeof (AdapterInfo) * iNumberAdapters );
        memset ( lpAdapterInfo,'\0', sizeof (AdapterInfo) * iNumberAdapters );

        // Get the AdapterInfo structure for all adapters in the system
        adlprocs.ADL_Adapter_AdapterInfo_Get (lpAdapterInfo, sizeof (AdapterInfo) * iNumberAdapters);

                // Repeat for all available adapters in the system
                for ( int i = 0; i < iNumberAdapters; i++ )
                {
                        iAdapterIndex = lpAdapterInfo[ i ].iAdapterIndex;
                        ADL_Main_Memory_Free ( (void **) &lpAdlDisplayInfo );

                        ADL_Err = adlprocs.ADL_Display_DisplayInfo_Get (lpAdapterInfo[i].iAdapterIndex, &iNumDisplays, &lpAdlDisplayInfo, 0);

                        for ( int j = 0; j < iNumDisplays; j++ )
                        {
                                // For each display, check its status. Use the display only if it's connected AND mapped (iDisplayInfoValue: bit 0 and 1 )
                if (  ( ADL_DISPLAY_DISPLAYINFO_DISPLAYCONNECTED | ADL_DISPLAY_DISPLAYINFO_DISPLAYMAPPED ) != 
                                        ( ADL_DISPLAY_DISPLAYINFO_DISPLAYCONNECTED | ADL_DISPLAY_DISPLAYINFO_DISPLAYMAPPED      & lpAdlDisplayInfo[ j ].iDisplayInfoValue ) )
                                        continue;   // Skip the not connected or non-active displays

                                // Is the display mapped to this adapter?
//                              if ( iAdapterIndex != lpAdlDisplayInfo[ j ].displayID.iDisplayLogicalAdapterIndex )
//                                      continue;
                                
                                // Preserve the Connected displays in PDL style :-)
                                iDisplayIndex = lpAdlDisplayInfo[ j ].displayID.iDisplayLogicalIndex;
                                aAllConnectedDisplays[ iAdapterIndex ] |= 1 << iDisplayIndex;

                                strncpy_s( MonitorNames[ j ], lpAdlDisplayInfo[ j ].strDisplayName, 127 );
                        }
                        char tmp[4];
                        sprintf_s( tmp, "%d", lpAdapterInfo[ i ].iAdapterIndex );
                        aDriverNames[i] = tmp;
                }
                return iNumberAdapters;
}

// Function:
// void vGetCapabilitiesCommand
// Purpose:
// Get the MCCS capabilities
// Input: UCHAR ucVcp, VCP code (CONTRAST, BRIGHTNESS, etc)
//        int iDisplayIndex, display index
// Output: VOID
bool vGetCapabilitiesCommand(UCHAR ucVcp, int iAdapterIndex, int iDisplayIndex)
{
  unsigned int i;
  unsigned char chk=0;
  int val=0;
  int read_val=0;
  int temp_val=1;
  int replySize=0;
  bool ret=TRUE;

  ucGetCommandCapabilitiesWrite[CAP_LOW_OFFSET]=0;

  if (ucVcp == VCP_CODE_CAPABILITIES)
    replySize = GETREPLYCAPSIZEFIXED;
  else
    replySize = GETREPLYCAPSIZEVARIABLE;

  while(temp_val!=0)
  {
    // set the offset
    ucGetCommandCapabilitiesWrite[CAP_LOW_OFFSET]+=(UCHAR)val;
    // get checksum
    for ( i = 0; i < CAP_CHK_OFFSET; i++)
      chk=chk^ucGetCommandCapabilitiesWrite[i];

    ucGetCommandCapabilitiesWrite[CAP_CHK_OFFSET] = chk;

    // write get capability with offset
    vWriteI2c((char*)&ucGetCommandCapabilitiesWrite[0], GETCAPWRITESIZE, iAdapterIndex, iDisplayIndex);
    Sleep(40);
    // initial read to get the length to determine actual read length
    vWriteAndReadI2c((char*)&ucGetCommandReplyWrite[0], GETREPLYWRITESIZE, (char*)&ucGetCommandReplyRead[0], replySize,
                     iAdapterIndex, iDisplayIndex);

    if (ucVcp == VCP_CODE_CAPABILITIES_NEW)
    {
      // compute read length
      read_val= (int)ucGetCommandReplyRead[GETRP_LENGHTH_OFFSET] & 0x7F;
      read_val += 0x3;
      // re-write get capability with offset

      vWriteI2c((char*)&ucGetCommandCapabilitiesWrite[0],GETCAPWRITESIZE, iAdapterIndex, iDisplayIndex);
      Sleep(40);
      // read with actual read length computed from above
      vWriteAndReadI2c((char*)&ucGetCommandReplyWrite[0],GETREPLYWRITESIZE,(char*)&ucGetCommandReplyRead[0],read_val,
                       iAdapterIndex, iDisplayIndex);
    }
    if ((int)ucGetCommandReplyRead[GETRP_LENGHTH_OFFSET] == 0)
    {
      ret=FALSE;
      break;
    }
    // compute new offset
    val=(int)ucGetCommandReplyRead[GETRP_LENGHTH_OFFSET]-0x83;
    temp_val=val;
    chk=0;
  }

  return ret;
}



// Function:
// void vGetVcpCommand
// Purpose:
// Get the values from display based on which VCP code
// Input: UCHAR ucVcp, VCP code (CONTRAST, BRIGHTNESS, etc)
//        int*ulMaxVal, return value of the max possible value to can be set
//        int*ulCurVal, return value of current set
//        int iDisplayIndex, display index
// Output: VOID

void vGetVcpCommand(UCHAR ucVcp, UINT * ulMaxVal, UINT * ulCurVal, int iAdapterIndex, int iDisplayIndex)
{
  unsigned int i;
  unsigned char chk=0;
  int ADL_Err = ADL_ERR;

  ucGetCommandRequestWrite[GETRQ_VCPCODE_OFFSET]=ucVcp;

  for( i = 0; i < GETRQ_CHK_OFFSET; i++)
                chk = chk ^ ucGetCommandRequestWrite[ i ];

  ucGetCommandRequestWrite[GETRQ_CHK_OFFSET] = chk;

  ADL_Err = vWriteI2c( (char*) &ucGetCommandRequestWrite[0], GETRQWRITESIZE, iAdapterIndex, iDisplayIndex);
  Sleep(40);
  ADL_Err = vWriteAndReadI2c( (char*)&ucGetCommandReplyWrite[0], GETREPLYWRITESIZE, (char*) &ucGetCommandReplyRead[0],
                                                                                GETREPLYREADSIZE, iAdapterIndex, iDisplayIndex);

  *(ulMaxVal) = (ucGetCommandReplyRead[GETRP_MAXHIGH_OFFSET] << 8 |ucGetCommandReplyRead[GETRP_MAXLOW_OFFSET]);
  *(ulCurVal) = (ucGetCommandReplyRead[GETRP_CURHIGH_OFFSET] << 8 |ucGetCommandReplyRead[GETRP_CURLOW_OFFSET]);
}


//
// Function:
//  void vSetVcpCommand
// Purpose:
// Set the values from display based on which VCP code
// Input: UCHAR ucVcp, VCP code (CONTRAST, BRIGHTNESS, etc)
//       int ulVal, which value to set
//       int iDisplayIndex, display index
// Output: VOID
//
void vSetVcpCommand(UCHAR ucVcp, UINT ulVal, int iAdapterIndex, int iDisplayIndex)
{
  unsigned int i;
  unsigned char chk=0;
  int ADL_Err = ADL_ERR;

  ucSetCommandWrite[SET_VCPCODE_OFFSET] = ucVcp;
  ucSetCommandWrite[SET_LOW_OFFSET] = (char)(ulVal & 0x0ff);
  ucSetCommandWrite[SET_HIGH_OFFSET] = (char)((ulVal>>8) & 0x0ff);

  for( i = 0; i < SET_CHK_OFFSET; i++)
    chk=chk ^ ucSetCommandWrite[i];

  ucSetCommandWrite[SET_CHK_OFFSET] = chk;
  ADL_Err = vWriteI2c( (char*)&ucSetCommandWrite[0], SETWRITESIZE, iAdapterIndex, iDisplayIndex);
  Sleep(50);
}


// Function:
//      void vWriteI2c
// Purpose:
// Write to and read from an i2s address 
// Input: char * lpucSendMsgBuf                 Data to write
//                      int iSendMsgLen                                 Length of data
//                      int iAdapterIndex, int iDisplayIndex
//      Output: result code
//
int vWriteI2c(char * lpucSendMsgBuf, int iSendMsgLen, int iAdapterIndex, int iDisplayIndex)
{
    int iRev = 0;
        return adlprocs.ADL_Display_DDCBlockAccess_Get( iAdapterIndex, iDisplayIndex, NULL, NULL, iSendMsgLen, lpucSendMsgBuf, &iRev, NULL);
}

// Function:
// void vWriteAndReadI2c
// Purpose:
// Write to and read from an i2s address 
// Input: char * lpucSendMsgBuf                 Data to write
//                      int iSendMsgLen                                 Length of data
//                      char * lpucRecvMsgBuf                   Read buffer
//                      int iRecvMsgLen                                         Read buffer size
//                      int iAdapterIndex, int iDisplayIndex
//      Output: result code
//
int vWriteAndReadI2c(char * lpucSendMsgBuf, int iSendMsgLen, char * lpucRecvMsgBuf, int iRecvMsgLen,  int iAdapterIndex, int iDisplayIndex)
{
        return adlprocs.ADL_Display_DDCBlockAccess_Get( iAdapterIndex, iDisplayIndex, NULL, NULL,
                                                                                                                                                        iSendMsgLen, lpucSendMsgBuf, &iRecvMsgLen, lpucRecvMsgBuf);
}

//******************************
// CDDCBlockAccessDlg dialog
//******************************
CDDCBlockAccessDlg::CDDCBlockAccessDlg(CWnd* pParent /*=NULL*/)
        : CDialog(CDDCBlockAccessDlg::IDD, pParent)
{
        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDDCBlockAccessDlg::DoDataExchange(CDataExchange* pDX)
{
        CDialog::DoDataExchange(pDX);
  DDX_Control(pDX, IDC_COMBO_VCPCODE, cb_VCPCode);
  DDX_Control(pDX, IDC_COMBO_DISPLAYINDEX, m_indexList);
  DDX_Control(pDX, IDC_COMBO_DRIVERINDEX, m_deviceList);
}

BEGIN_MESSAGE_MAP(CDDCBlockAccessDlg, CDialog)
        ON_WM_PAINT()
        ON_WM_QUERYDRAGICON()
        //}}AFX_MSG_MAP
  ON_BN_CLICKED(IDOK, &CDDCBlockAccessDlg::OnBnClickedOk)
  ON_BN_CLICKED(IDC_BUTTON_GET, &CDDCBlockAccessDlg::OnBnClickedButtonGet)
  ON_BN_CLICKED(IDC_BUTTON_SET, &CDDCBlockAccessDlg::OnBnClickedButtonSet)
  ON_WM_DESTROY()
  ON_CBN_SELCHANGE(IDC_COMBO_VCPCODE, &CDDCBlockAccessDlg::OnCbnSelchangeComboVcpcode)
  ON_CBN_SELCHANGE(IDC_COMBO_DISPLAYINDEX, &CDDCBlockAccessDlg::OnCbnSelchangeComboDisplayindex)
  ON_CBN_SELCHANGE(IDC_COMBO_DRIVERINDEX, &CDDCBlockAccessDlg::OnCbnSelchangeComboDriverindex)
END_MESSAGE_MAP()


// CDDCBlockAccessDlg message handlers

BOOL CDDCBlockAccessDlg::OnInitDialog()
{
        CDialog::OnInitDialog();

        // Set the icon for this dialog.  The framework does this automatically
        // when the application's main window is not a dialog
        SetIcon(m_hIcon, TRUE);                 // Set big icon
        SetIcon(m_hIcon, FALSE);                // Set small icon

// Initialize ADL
  if ( !InitADL() )
                exit (1);

        memset( &aAllConnectedDisplays[0], 0, sizeof (aAllConnectedDisplays) );
  m_deviceList.ResetContent();
  CString sDriverNames[MAX_NUM_DISPLAY_DEVICES];        //String array of all ATI device names (aligned with aAllConnectedDisplays)

  // Enumerate all AMD desktops
  int numberOfATIDevices = iInitDisplayNames( sDriverNames );

  for (int i = 0; i < MAX_NUM_DISPLAY_DEVICES ; i++)
  {
    if (sDriverNames[i].GetLength( ) != 0 )
    {
      //Add the name to the Driver ID combo box (AddString)
      //At the same time set that entry to have i (SetItemData)
      //i will be saved as the driver ID corresponding to this device name
      m_deviceList.SetItemData (m_deviceList.AddString(sDriverNames[i]), i);

      // No need to call ATIDL_GetConnectedDisplays(i, &aAllConnectedDisplays[i])  (Very expensive call).
          // The connected and mapped displays are already recorded.
    }
  }
  m_deviceList.SetCurSel(0);

  //Refresh the display index for the first ATI device
  RefreshDisplayIndices ();

  // Init VCP combo box
  cb_VCPCode.AddString(_T("Luminance"));
  cb_VCPCode.AddString(_T("Contrast"));
  cb_VCPCode.AddString(_T("Color Temperature"));
  cb_VCPCode.AddString(_T("Get Capabilities (Fixed)"));
  cb_VCPCode.AddString(_T("Get Capabilities (Variable)"));
  cb_VCPCode.SetCurSel(0);

        return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CDDCBlockAccessDlg::OnPaint()
{
        if (IsIconic())
        {
                CPaintDC dc(this); // device context for painting

                SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

                // Center icon in client rectangle
                int cxIcon = GetSystemMetrics(SM_CXICON);
                int cyIcon = GetSystemMetrics(SM_CYICON);
                CRect rect;
                GetClientRect(&rect);
                int x = (rect.Width() - cxIcon + 1) / 2;
                int y = (rect.Height() - cyIcon + 1) / 2;

                // Draw the icon
                dc.DrawIcon(x, y, m_hIcon);
        }
        else
        {
                CDialog::OnPaint();
        }
}

//This function is to refresh the Display index combo box
void CDDCBlockAccessDlg::RefreshDisplayIndices ()
{
  int iAdapterIndex = (int) m_deviceList.GetItemData ( m_deviceList.GetCurSel() );
  int ulDisplaysConnected = aAllConnectedDisplays[iAdapterIndex];

  //Clear the list
  m_indexList.ResetContent();

  // ulDisplayIndices is a bit vector of connected displays
  // for example, if ulDisplaysConnected == 0x9, i.e binary 1001, this means
  // you have two display devices connected - one has index 0, and another has index 3
  // another example: ulDisplaysConnected = 0x7, i.e. binary 0111, means
  // you have 3 displays connected - one has index 0, another has index 1, and another has index 2  
  for (int j = 0 ; ulDisplaysConnected != 0 ; j++ )
  {
    if (ulDisplaysConnected & 0x1)
    {
      TCHAR ucTemp[5];
      wsprintf(ucTemp,_T("%d"),j);

      //Add the display index to the combo box (AddString)
      //At the same time save the j into that entry (SetItemData)
      //j will be the display index corresponding to this entry
      m_indexList.SetItemData (m_indexList.AddString(ucTemp), j);
    }
    ulDisplaysConnected = ulDisplaysConnected>>1;
  }
  
  m_indexList.SetCurSel(0);
  int iDisplayIndex = (int)m_indexList.GetItemData ( m_indexList.GetCurSel() );

//  SetDlgItemText(IDC_EDIT_MONNAME, MonitorNames[ iDisplayIndex ] );
  std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
  std::wstring wideAdapterName = conv.from_bytes(lpAdapterInfo[iAdapterIndex].strAdapterName);
  std::wstring wideDisplayName = conv.from_bytes(lpAdapterInfo[iAdapterIndex].strDisplayName);
  SetDlgItemText(IDC_EDIT_ANAME, wideAdapterName.c_str());
  SetDlgItemText(IDC_EDIT_DNAME, wideDisplayName.c_str());

  // Read the EDID of the first display
  OnCbnSelchangeComboDisplayindex();
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CDDCBlockAccessDlg::OnQueryDragIcon()
{
        return static_cast<HCURSOR>(m_hIcon);
}

void CDDCBlockAccessDlg::OnBnClickedOk()
{
  OnOK();
}

void CDDCBlockAccessDlg::OnBnClickedButtonGet()
{
  UINT ulMax=0, ulCur=0;
  TCHAR ucBuffer [16];
  int iAdapterIndex = (int) m_deviceList.GetItemData ( m_deviceList.GetCurSel() );
  int iDisplayIndex = (int) m_indexList.GetItemData ( m_indexList.GetCurSel() );

  if (ucGlobalVcp == VCP_CODE_CAPABILITIES || ucGlobalVcp == VCP_CODE_CAPABILITIES_NEW)
  {
    if (vGetCapabilitiesCommand(ucGlobalVcp, iAdapterIndex, iDisplayIndex))
    {
      SetDlgItemText(IDC_EDIT_MAX,_T("PASS"));
      SetDlgItemText(IDC_EDIT_CURRENT,_T("PASS"));
    }
    else
    {
      SetDlgItemText(IDC_EDIT_MAX,_T("FAIL"));
      SetDlgItemText(IDC_EDIT_CURRENT,_T("FAIL"));
    }
  }
  else
  {
    vGetVcpCommand( ucGlobalVcp, &ulMax, &ulCur, iAdapterIndex, iDisplayIndex );

    ulMax &= 0x0ffff;
    ulCur &= 0x0ffff;
    wsprintf(ucBuffer,_T("0x%x"),ulMax);
    SetDlgItemText(IDC_EDIT_MAX,ucBuffer);
    wsprintf(ucBuffer,_T("0x%x"),ulCur);
    SetDlgItemText(IDC_EDIT_CURRENT,ucBuffer);
  }
}

void CDDCBlockAccessDlg::OnBnClickedButtonSet()
{
  UINT ulCur=0;
  TCHAR ucBuffer[255];
  int iAdapterIndex = (int) m_deviceList.GetItemData ( m_deviceList.GetCurSel() );
  int iDisplayIndex = (int) m_indexList.GetItemData ( m_indexList.GetCurSel() );

  if( GetDlgItemText(IDC_EDIT_CURRENT,ucBuffer,10) > 0 )
  {
      if (_stscanf_s(ucBuffer, _T("%x"), &(ulCur)) > 0)
    {
      vSetVcpCommand(ucGlobalVcp,ulCur, iAdapterIndex, iDisplayIndex);
    }
  }
}

void CDDCBlockAccessDlg::OnDestroy()
{
  CDialog::OnDestroy();
  FreeADL();
}

void CDDCBlockAccessDlg::OnCbnSelchangeComboVcpcode()
{
  int sel = cb_VCPCode.GetCurSel();
  GetDlgItem(IDC_BUTTON_SET)->EnableWindow(TRUE);

  /***********************************
  / 0 - "Luminance"
  / 1 - "Contrast"
  / 2 - "Color Temperature"
  / 3 - "Get Capabilities (Fixed)"
  / 4 - "Get Capabilities (Variable)"
  /***********************************/
  switch (sel)
  {
  case 0:
    ucGlobalVcp = VCP_CODE_BRIGHTNESS;
    break;

  case 1: // contrast
    ucGlobalVcp = VCP_CODE_CONTRAST;
    break;

  case 2: // color temperature
    ucGlobalVcp = VCP_CODE_COLORTEMP;
    break;

  case 3: // get capabilities 38 read
    ucGlobalVcp = VCP_CODE_CAPABILITIES;
    GetDlgItem(IDC_BUTTON_SET)->EnableWindow(FALSE);
    break;

  case 4: // get capabilities new
    ucGlobalVcp = VCP_CODE_CAPABILITIES_NEW;
    GetDlgItem(IDC_BUTTON_SET)->EnableWindow(FALSE);
    break;
  }
}

void CDDCBlockAccessDlg::OnCbnSelchangeComboDisplayindex()
{
  TCHAR hexBuffer[1000*2];
  TCHAR tBuffer[1000*2];
  TCHAR cTemp[4*2];
  unsigned char ucSymbol;
  int iAdapterIndex = (int) m_deviceList.GetItemData ( m_deviceList.GetCurSel() );
  int iDisplayIndex = (int) m_indexList.GetItemData ( m_indexList.GetCurSel() );
  
  //Setup structures for the ADL call
  ADLDisplayEDIDData  aBlockOutput;
  ZeroMemory(&aBlockOutput, sizeof(ADLDisplayEDIDData));
  aBlockOutput.iSize   = sizeof(ADLDisplayEDIDData);
  aBlockOutput.iBlockIndex = 0; //First block
  
  std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
  std::wstring wideChar = conv.from_bytes(MonitorNames[iDisplayIndex]);
  SetDlgItemText(IDC_EDIT_MONNAME, wideChar.c_str());

  //Call ADL to get the EDID
  adlprocs.ADL_Display_EdidData_Get(iAdapterIndex, iDisplayIndex, &aBlockOutput);

  //Printout
  _tcscpy_s(hexBuffer, _T(""));
  _tcscpy_s(tBuffer, _T(""));
  for (int i = 0; i < aBlockOutput.iEDIDSize ; i++)
  {
    //Newline every 8 bytes
    if (i != 0 && i% 8 == 0)
        {
        _tcscat_s(hexBuffer, _T("\r\n"));
        _tcscat_s(tBuffer, _T("\r\n"));
        }

    //add the byte to the buffer string
        ucSymbol = (unsigned char)aBlockOutput.cEDIDData[i];
    wsprintf( cTemp,_T(" %.2x"), ucSymbol );
    _tcscat_s(hexBuffer, cTemp);

    if ( ucSymbol < 0x20 )                      // Mask control characters
                ucSymbol |= 0x20;

    wsprintf(cTemp, _T(" %c"), ucSymbol);
    _tcscat_s(tBuffer, cTemp);
  }

  //Print to Edit box  
  SetDlgItemText(IDC_EDIT_RAWEDID, hexBuffer);
  SetDlgItemText(IDC_EDIT_TEXTEDID, tBuffer);
}

void CDDCBlockAccessDlg::OnCbnSelchangeComboDriverindex()
{
  RefreshDisplayIndices ();
}


// Function:
// void InitADL
// Purpose:
// Initialize ADL functions
// Input: NONE
// Output: bool, Function successful or not
bool InitADL()
{
        int     ADL_Err = ADL_ERR;
  if (!adlprocs.hModule)
  {
    adlprocs.hModule = LoadLibrary(_T("atiadlxx.dll"));
    // A 32 bit calling application on 64 bit OS will fail to LoadLIbrary.
    // Try to load the 32 bit library (atiadlxy.dll) instead
    if (adlprocs.hModule == NULL)
      adlprocs.hModule = LoadLibrary(_T("atiadlxy.dll"));

    if(adlprocs.hModule)
    {
      adlprocs.ADL_Main_Control_Create       = (ADL_MAIN_CONTROL_CREATE) GetProcAddress(adlprocs.hModule, "ADL_Main_Control_Create");
      adlprocs.ADL_Main_Control_Destroy      = (ADL_MAIN_CONTROL_DESTROY) GetProcAddress(adlprocs.hModule, "ADL_Main_Control_Destroy");
      adlprocs.ADL_Adapter_NumberOfAdapters_Get   = (ADL_ADAPTER_NUMBEROFADAPTERS_GET) GetProcAddress(adlprocs.hModule, "ADL_Adapter_NumberOfAdapters_Get");
      adlprocs.ADL_Adapter_AdapterInfo_Get   = (ADL_ADAPTER_ADAPTERINFO_GET) GetProcAddress(adlprocs.hModule, "ADL_Adapter_AdapterInfo_Get");
      adlprocs.ADL_Display_DisplayInfo_Get   = (ADL_DISPLAY_DISPLAYINFO_GET) GetProcAddress(adlprocs.hModule, "ADL_Display_DisplayInfo_Get");
      adlprocs.ADL_Display_DDCBlockAccess_Get   = (ADL_DISPLAY_DDCBLOCKACCESSGET) GetProcAddress(adlprocs.hModule, "ADL_Display_DDCBlockAccess_Get");
      adlprocs.ADL_Display_EdidData_Get   = (ADL_DISPLAY_EDIDDATA_GET) GetProcAddress(adlprocs.hModule, "ADL_Display_EdidData_Get");
    }
    
    if(adlprocs.hModule == NULL              ||
                adlprocs.ADL_Main_Control_Create == NULL ||
                adlprocs.ADL_Main_Control_Destroy == NULL ||
                adlprocs.ADL_Adapter_NumberOfAdapters_Get == NULL ||
                adlprocs.ADL_Adapter_AdapterInfo_Get == NULL ||
                adlprocs.ADL_Display_DisplayInfo_Get == NULL ||
                adlprocs.ADL_Display_DDCBlockAccess_Get   == NULL || 
                adlprocs.ADL_Display_EdidData_Get   == NULL ) 
    {
      AfxMessageBox(_T("Error: ADL initialization failed! This app will NOT work!"), MB_OK, 0);
      return false;
    }
        // Initialize ADL with second parameter = 1, which means: Get the info for only currently active adapters!
    ADL_Err = adlprocs.ADL_Main_Control_Create (ADL_Main_Memory_Alloc, 1);

  }
  return (ADL_OK == ADL_Err) ?  true : false;
          
}

// Function:
// void FreeADL
// Purpose:
// free the ADL Module
// Input: NONE
// Output: VOID
void FreeADL()
{

  ADL_Main_Memory_Free ( (void **)&lpAdapterInfo );
  ADL_Main_Memory_Free ( (void **)&lpAdlDisplayInfo );

  adlprocs.ADL_Main_Control_Destroy ();
  FreeLibrary (adlprocs.hModule);
  adlprocs.hModule = NULL;
}


Copyright © 2009-2016 Advanced Micro Devices, Inc. All rights reserved.