Hardware/ATI/ADL.cs
author moel.mich
Sat, 27 Oct 2012 11:40:28 +0000
changeset 384 76f859f4aea1
parent 344 3145aadca3d2
permissions -rw-r--r--
Reduced the amount of dynamic memory allocation when reading from the T-Balancer or creating tray icons.
     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 }