Hardware/ATI/ADL.cs
author StephaneLenclud
Sun, 03 Feb 2013 18:01:50 +0100
branchMiniDisplay
changeset 433 090259cfd699
parent 344 3145aadca3d2
permissions -rw-r--r--
Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
     1 /*
     2  
     3   This Source Code Form is subject to the terms of the Mozilla Public
     4   License, v. 2.0. If a copy of the MPL was not distributed with this
     5   file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7   Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
     8 	
     9 */
    10 
    11 using System;
    12 using System.Runtime.InteropServices;
    13 using System.Text.RegularExpressions;
    14 
    15 namespace OpenHardwareMonitor.Hardware.ATI {
    16   
    17   [StructLayout(LayoutKind.Sequential)]
    18   internal struct ADLAdapterInfo {
    19     public int Size;
    20     public int AdapterIndex;
    21     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    22     public string UDID;
    23     public int BusNumber;
    24     public int DeviceNumber;
    25     public int FunctionNumber;
    26     public int VendorID;
    27     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    28     public string AdapterName;
    29     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    30     public string DisplayName;
    31     public int Present;
    32     public int Exist;
    33     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    34     public string DriverPath;
    35     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    36     public string DriverPathExt;
    37     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    38     public string PNPString;
    39     public int OSDisplayIndex;
    40   }
    41 
    42   [StructLayout(LayoutKind.Sequential)]
    43   internal struct ADLPMActivity {
    44     public int Size;
    45     public int EngineClock;
    46     public int MemoryClock;
    47     public int Vddc;
    48     public int ActivityPercent;
    49     public int CurrentPerformanceLevel;
    50     public int CurrentBusSpeed;
    51     public int CurrentBusLanes;
    52     public int MaximumBusLanes;
    53     public int Reserved;
    54   }
    55 
    56   [StructLayout(LayoutKind.Sequential)]
    57   internal struct ADLTemperature {
    58     public int Size;
    59     public int Temperature;
    60   }
    61 
    62   [StructLayout(LayoutKind.Sequential)]
    63   internal struct ADLFanSpeedValue {
    64     public int Size;
    65     public int SpeedType;
    66     public int FanSpeed;
    67     public int Flags;
    68   }
    69 
    70   [StructLayout(LayoutKind.Sequential)]
    71   internal struct ADLFanSpeedInfo {
    72     public int Size;
    73     public int Flags;
    74     public int MinPercent;
    75     public int MaxPercent;
    76     public int MinRPM;
    77     public int MaxRPM;
    78   }
    79 
    80   internal class ADL {
    81     public const int ADL_MAX_PATH = 256;
    82     public const int ADL_MAX_ADAPTERS = 40;
    83     public const int ADL_MAX_DISPLAYS = 40;
    84     public const int ADL_MAX_DEVICENAME = 32;
    85     public const int ADL_OK = 0;
    86     public const int ADL_ERR = -1;
    87     public const int ADL_DRIVER_OK = 0;
    88     public const int ADL_MAX_GLSYNC_PORTS = 8;
    89     public const int ADL_MAX_GLSYNC_PORT_LEDS = 8;
    90     public const int ADL_MAX_NUM_DISPLAYMODES = 1024;
    91 
    92     public const int ADL_DL_FANCTRL_SPEED_TYPE_PERCENT = 1;
    93     public const int ADL_DL_FANCTRL_SPEED_TYPE_RPM = 2;
    94 
    95     public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_READ = 1;
    96     public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_WRITE = 2;
    97     public const int ADL_DL_FANCTRL_SUPPORTS_RPM_READ = 4;
    98     public const int ADL_DL_FANCTRL_SUPPORTS_RPM_WRITE = 8;
    99     public const int ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED = 1;
   100 
   101     public const int ATI_VENDOR_ID = 0x1002;
   102 
   103     private delegate int ADL_Main_Control_CreateDelegate(
   104       ADL_Main_Memory_AllocDelegate callback, int enumConnectedAdapters);
   105     private delegate int ADL_Adapter_AdapterInfo_GetDelegate(IntPtr info,
   106       int size);
   107 
   108     public delegate int ADL_Main_Control_DestroyDelegate();
   109     public delegate int ADL_Adapter_NumberOfAdapters_GetDelegate(
   110       ref int numAdapters);    
   111     public delegate int ADL_Adapter_ID_GetDelegate(int adapterIndex,
   112       out int adapterID);
   113     public delegate int ADL_Display_AdapterID_GetDelegate(int adapterIndex,
   114       out int adapterID);      	
   115     public delegate int ADL_Adapter_Active_GetDelegate(int adapterIndex,
   116       out int status);
   117     public delegate int ADL_Overdrive5_CurrentActivity_GetDelegate(
   118       int iAdapterIndex, ref ADLPMActivity activity);
   119     public delegate int ADL_Overdrive5_Temperature_GetDelegate(int adapterIndex,
   120         int thermalControllerIndex, ref ADLTemperature temperature);
   121     public delegate int ADL_Overdrive5_FanSpeed_GetDelegate(int adapterIndex,
   122         int thermalControllerIndex, ref	ADLFanSpeedValue fanSpeedValue);
   123     public delegate int ADL_Overdrive5_FanSpeedInfo_GetDelegate(
   124       int adapterIndex, int thermalControllerIndex,
   125       ref ADLFanSpeedInfo fanSpeedInfo);
   126     public delegate int ADL_Overdrive5_FanSpeedToDefault_SetDelegate(
   127       int adapterIndex, int thermalControllerIndex);
   128     public delegate int ADL_Overdrive5_FanSpeed_SetDelegate(int adapterIndex,
   129       int thermalControllerIndex, ref	ADLFanSpeedValue fanSpeedValue);
   130 
   131     private static ADL_Main_Control_CreateDelegate
   132       _ADL_Main_Control_Create;
   133     private static ADL_Adapter_AdapterInfo_GetDelegate
   134       _ADL_Adapter_AdapterInfo_Get;
   135 
   136     public static ADL_Main_Control_DestroyDelegate
   137       ADL_Main_Control_Destroy;
   138     public static ADL_Adapter_NumberOfAdapters_GetDelegate
   139       ADL_Adapter_NumberOfAdapters_Get;
   140     public static ADL_Adapter_ID_GetDelegate 
   141       _ADL_Adapter_ID_Get;
   142     public static ADL_Display_AdapterID_GetDelegate 
   143       _ADL_Display_AdapterID_Get;
   144     public static ADL_Adapter_Active_GetDelegate 
   145       ADL_Adapter_Active_Get;
   146     public static ADL_Overdrive5_CurrentActivity_GetDelegate
   147       ADL_Overdrive5_CurrentActivity_Get;
   148     public static ADL_Overdrive5_Temperature_GetDelegate
   149       ADL_Overdrive5_Temperature_Get;
   150     public static ADL_Overdrive5_FanSpeed_GetDelegate
   151       ADL_Overdrive5_FanSpeed_Get;
   152     public static ADL_Overdrive5_FanSpeedInfo_GetDelegate
   153       ADL_Overdrive5_FanSpeedInfo_Get;
   154     public static ADL_Overdrive5_FanSpeedToDefault_SetDelegate
   155       ADL_Overdrive5_FanSpeedToDefault_Set;
   156     public static ADL_Overdrive5_FanSpeed_SetDelegate
   157       ADL_Overdrive5_FanSpeed_Set;
   158 
   159     private static string dllName;
   160 
   161     private static void GetDelegate<T>(string entryPoint, out T newDelegate)
   162       where T : class 
   163     {
   164       DllImportAttribute attribute = new DllImportAttribute(dllName);
   165       attribute.CallingConvention = CallingConvention.Cdecl;
   166       attribute.PreserveSig = true;
   167       attribute.EntryPoint = entryPoint;
   168       PInvokeDelegateFactory.CreateDelegate(attribute, out newDelegate);
   169     }
   170 
   171     private static void CreateDelegates(string name) {
   172       int p = (int)Environment.OSVersion.Platform;
   173       if ((p == 4) || (p == 128))
   174         dllName = name + ".so";
   175       else
   176         dllName = name + ".dll";
   177 
   178       GetDelegate("ADL_Main_Control_Create",
   179         out _ADL_Main_Control_Create);
   180       GetDelegate("ADL_Adapter_AdapterInfo_Get",
   181         out _ADL_Adapter_AdapterInfo_Get);
   182       GetDelegate("ADL_Main_Control_Destroy",
   183         out ADL_Main_Control_Destroy);
   184       GetDelegate("ADL_Adapter_NumberOfAdapters_Get",
   185         out ADL_Adapter_NumberOfAdapters_Get);
   186       GetDelegate("ADL_Adapter_ID_Get",
   187         out _ADL_Adapter_ID_Get);
   188       GetDelegate("ADL_Display_AdapterID_Get", 
   189         out _ADL_Display_AdapterID_Get);
   190       GetDelegate("ADL_Adapter_Active_Get",
   191         out ADL_Adapter_Active_Get);
   192       GetDelegate("ADL_Overdrive5_CurrentActivity_Get",
   193         out ADL_Overdrive5_CurrentActivity_Get);
   194       GetDelegate("ADL_Overdrive5_Temperature_Get",
   195         out ADL_Overdrive5_Temperature_Get);
   196       GetDelegate("ADL_Overdrive5_FanSpeed_Get",
   197         out ADL_Overdrive5_FanSpeed_Get);
   198       GetDelegate("ADL_Overdrive5_FanSpeedInfo_Get",
   199         out ADL_Overdrive5_FanSpeedInfo_Get);
   200       GetDelegate("ADL_Overdrive5_FanSpeedToDefault_Set",
   201         out ADL_Overdrive5_FanSpeedToDefault_Set);
   202       GetDelegate("ADL_Overdrive5_FanSpeed_Set",
   203         out ADL_Overdrive5_FanSpeed_Set);
   204     }
   205 
   206     static ADL() {
   207       CreateDelegates("atiadlxx");
   208     }
   209 
   210     private ADL() { }
   211 
   212     public static int ADL_Main_Control_Create(int enumConnectedAdapters) {
   213       try {
   214         try {
   215           return _ADL_Main_Control_Create(Main_Memory_Alloc,
   216             enumConnectedAdapters);
   217         } catch {
   218           CreateDelegates("atiadlxy");
   219           return _ADL_Main_Control_Create(Main_Memory_Alloc,
   220             enumConnectedAdapters);
   221         }
   222       } catch {
   223         return ADL_ERR;
   224       }
   225     }
   226 
   227     public static int ADL_Adapter_AdapterInfo_Get(ADLAdapterInfo[] info) {
   228       int elementSize = Marshal.SizeOf(typeof(ADLAdapterInfo));
   229       int size = info.Length * elementSize;
   230       IntPtr ptr = Marshal.AllocHGlobal(size);
   231       int result = _ADL_Adapter_AdapterInfo_Get(ptr, size);
   232       for (int i = 0; i < info.Length; i++)
   233         info[i] = (ADLAdapterInfo)
   234           Marshal.PtrToStructure((IntPtr)((long)ptr + i * elementSize),
   235           typeof(ADLAdapterInfo));
   236       Marshal.FreeHGlobal(ptr);
   237 
   238       // the ADLAdapterInfo.VendorID field reported by ADL is wrong on 
   239       // Windows systems (parse error), so we fix this here
   240       for (int i = 0; i < info.Length; i++) {
   241         // try Windows UDID format
   242         Match m = Regex.Match(info[i].UDID, "PCI_VEN_([A-Fa-f0-9]{1,4})&.*");
   243         if (m.Success && m.Groups.Count == 2) {
   244           info[i].VendorID = Convert.ToInt32(m.Groups[1].Value, 16);
   245           continue;
   246         }
   247         // if above failed, try Unix UDID format
   248         m = Regex.Match(info[i].UDID, "[0-9]+:[0-9]+:([0-9]+):[0-9]+:[0-9]+");
   249         if (m.Success && m.Groups.Count == 2) {
   250           info[i].VendorID = Convert.ToInt32(m.Groups[1].Value, 10);
   251         }
   252       }
   253 
   254       return result;
   255     }
   256 
   257     public static int ADL_Adapter_ID_Get(int adapterIndex,
   258       out int adapterID) {
   259       try {
   260         return _ADL_Adapter_ID_Get(adapterIndex, out adapterID);
   261       } catch (EntryPointNotFoundException) {
   262         try {
   263           return _ADL_Display_AdapterID_Get(adapterIndex, out adapterID);
   264         } catch (EntryPointNotFoundException) {
   265           adapterID = 1;
   266           return ADL_OK;
   267         }
   268       }
   269     }
   270 
   271     private delegate IntPtr ADL_Main_Memory_AllocDelegate(int size);
   272 
   273     // create a Main_Memory_Alloc delegate and keep it alive
   274     private static ADL_Main_Memory_AllocDelegate Main_Memory_Alloc =
   275       delegate(int size) {
   276         return Marshal.AllocHGlobal(size);
   277       };
   278 
   279     private static void Main_Memory_Free(IntPtr buffer) {
   280       if (IntPtr.Zero != buffer)
   281         Marshal.FreeHGlobal(buffer);
   282     }
   283   }
   284 }