Hardware/ATI/ADL.cs
author moel.mich
Sun, 15 Jan 2012 15:07:23 +0000
changeset 333 c34cbcc7df66
parent 247 6dc755f1970e
child 344 3145aadca3d2
permissions -rw-r--r--
Fixed Issue 213.
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     5   The contents of this file are subject to the Mozilla Public License Version
     6   1.1 (the "License"); you may not use this file except in compliance with
     7   the License. You may obtain a copy of the License at
     8  
     9   http://www.mozilla.org/MPL/
    10 
    11   Software distributed under the License is distributed on an "AS IS" basis,
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13   for the specific language governing rights and limitations under the License.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    17   The Initial Developer of the Original Code is 
    18   Michael Möller <m.moeller@gmx.ch>.
    19   Portions created by the Initial Developer are Copyright (C) 2009-2012
    20   the Initial Developer. All Rights Reserved.
    21 
    22   Contributor(s):
    23 
    24   Alternatively, the contents of this file may be used under the terms of
    25   either the GNU General Public License Version 2 or later (the "GPL"), or
    26   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    27   in which case the provisions of the GPL or the LGPL are applicable instead
    28   of those above. If you wish to allow use of your version of this file only
    29   under the terms of either the GPL or the LGPL, and not to allow others to
    30   use your version of this file under the terms of the MPL, indicate your
    31   decision by deleting the provisions above and replace them with the notice
    32   and other provisions required by the GPL or the LGPL. If you do not delete
    33   the provisions above, a recipient may use your version of this file under
    34   the terms of any one of the MPL, the GPL or the LGPL.
    35  
    36 */
    37 
    38 using System;
    39 using System.Runtime.InteropServices;
    40 using System.Text.RegularExpressions;
    41 
    42 namespace OpenHardwareMonitor.Hardware.ATI {
    43   
    44   [StructLayout(LayoutKind.Sequential)]
    45   internal struct ADLAdapterInfo {
    46     public int Size;
    47     public int AdapterIndex;
    48     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    49     public string UDID;
    50     public int BusNumber;
    51     public int DeviceNumber;
    52     public int FunctionNumber;
    53     public int VendorID;
    54     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    55     public string AdapterName;
    56     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    57     public string DisplayName;
    58     public int Present;
    59     public int Exist;
    60     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    61     public string DriverPath;
    62     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    63     public string DriverPathExt;
    64     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
    65     public string PNPString;
    66     public int OSDisplayIndex;
    67   }
    68 
    69   [StructLayout(LayoutKind.Sequential)]
    70   internal struct ADLPMActivity {
    71     public int Size;
    72     public int EngineClock;
    73     public int MemoryClock;
    74     public int Vddc;
    75     public int ActivityPercent;
    76     public int CurrentPerformanceLevel;
    77     public int CurrentBusSpeed;
    78     public int CurrentBusLanes;
    79     public int MaximumBusLanes;
    80     public int Reserved;
    81   }
    82 
    83   [StructLayout(LayoutKind.Sequential)]
    84   internal struct ADLTemperature {
    85     public int Size;
    86     public int Temperature;
    87   }
    88 
    89   [StructLayout(LayoutKind.Sequential)]
    90   internal struct ADLFanSpeedValue {
    91     public int Size;
    92     public int SpeedType;
    93     public int FanSpeed;
    94     public int Flags;
    95   }
    96 
    97   [StructLayout(LayoutKind.Sequential)]
    98   internal struct ADLFanSpeedInfo {
    99     public int Size;
   100     public int Flags;
   101     public int MinPercent;
   102     public int MaxPercent;
   103     public int MinRPM;
   104     public int MaxRPM;
   105   }
   106 
   107   internal class ADL {
   108     public const int ADL_MAX_PATH = 256;
   109     public const int ADL_MAX_ADAPTERS = 40;
   110     public const int ADL_MAX_DISPLAYS = 40;
   111     public const int ADL_MAX_DEVICENAME = 32;
   112     public const int ADL_OK = 0;
   113     public const int ADL_ERR = -1;
   114     public const int ADL_DRIVER_OK = 0;
   115     public const int ADL_MAX_GLSYNC_PORTS = 8;
   116     public const int ADL_MAX_GLSYNC_PORT_LEDS = 8;
   117     public const int ADL_MAX_NUM_DISPLAYMODES = 1024;
   118 
   119     public const int ADL_DL_FANCTRL_SPEED_TYPE_PERCENT = 1;
   120     public const int ADL_DL_FANCTRL_SPEED_TYPE_RPM = 2;
   121 
   122     public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_READ = 1;
   123     public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_WRITE = 2;
   124     public const int ADL_DL_FANCTRL_SUPPORTS_RPM_READ = 4;
   125     public const int ADL_DL_FANCTRL_SUPPORTS_RPM_WRITE = 8;
   126     public const int ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED = 1;
   127 
   128     public const int ATI_VENDOR_ID = 0x1002;
   129 
   130     private delegate int ADL_Main_Control_CreateDelegate(
   131       ADL_Main_Memory_AllocDelegate callback, int enumConnectedAdapters);
   132     private delegate int ADL_Adapter_AdapterInfo_GetDelegate(IntPtr info,
   133       int size);
   134 
   135     public delegate int ADL_Main_Control_DestroyDelegate();
   136     public delegate int ADL_Adapter_NumberOfAdapters_GetDelegate(
   137       ref int numAdapters);    
   138     public delegate int ADL_Adapter_ID_GetDelegate(int adapterIndex,
   139       out int adapterID);
   140     public delegate int ADL_Display_AdapterID_GetDelegate(int adapterIndex,
   141       out int adapterID);      	
   142     public delegate int ADL_Adapter_Active_GetDelegate(int adapterIndex,
   143       out int status);
   144     public delegate int ADL_Overdrive5_CurrentActivity_GetDelegate(
   145       int iAdapterIndex, ref ADLPMActivity activity);
   146     public delegate int ADL_Overdrive5_Temperature_GetDelegate(int adapterIndex,
   147         int thermalControllerIndex, ref ADLTemperature temperature);
   148     public delegate int ADL_Overdrive5_FanSpeed_GetDelegate(int adapterIndex,
   149         int thermalControllerIndex, ref	ADLFanSpeedValue fanSpeedValue);
   150     public delegate int ADL_Overdrive5_FanSpeedInfo_GetDelegate(
   151       int adapterIndex, int thermalControllerIndex,
   152       ref ADLFanSpeedInfo fanSpeedInfo);
   153     public delegate int ADL_Overdrive5_FanSpeedToDefault_SetDelegate(
   154       int adapterIndex, int thermalControllerIndex);
   155     public delegate int ADL_Overdrive5_FanSpeed_SetDelegate(int adapterIndex,
   156       int thermalControllerIndex, ref	ADLFanSpeedValue fanSpeedValue);
   157 
   158     private static ADL_Main_Control_CreateDelegate
   159       _ADL_Main_Control_Create;
   160     private static ADL_Adapter_AdapterInfo_GetDelegate
   161       _ADL_Adapter_AdapterInfo_Get;
   162 
   163     public static ADL_Main_Control_DestroyDelegate
   164       ADL_Main_Control_Destroy;
   165     public static ADL_Adapter_NumberOfAdapters_GetDelegate
   166       ADL_Adapter_NumberOfAdapters_Get;
   167     public static ADL_Adapter_ID_GetDelegate 
   168       _ADL_Adapter_ID_Get;
   169     public static ADL_Display_AdapterID_GetDelegate 
   170       _ADL_Display_AdapterID_Get;
   171     public static ADL_Adapter_Active_GetDelegate 
   172       ADL_Adapter_Active_Get;
   173     public static ADL_Overdrive5_CurrentActivity_GetDelegate
   174       ADL_Overdrive5_CurrentActivity_Get;
   175     public static ADL_Overdrive5_Temperature_GetDelegate
   176       ADL_Overdrive5_Temperature_Get;
   177     public static ADL_Overdrive5_FanSpeed_GetDelegate
   178       ADL_Overdrive5_FanSpeed_Get;
   179     public static ADL_Overdrive5_FanSpeedInfo_GetDelegate
   180       ADL_Overdrive5_FanSpeedInfo_Get;
   181     public static ADL_Overdrive5_FanSpeedToDefault_SetDelegate
   182       ADL_Overdrive5_FanSpeedToDefault_Set;
   183     public static ADL_Overdrive5_FanSpeed_SetDelegate
   184       ADL_Overdrive5_FanSpeed_Set;
   185 
   186     private static string dllName;
   187 
   188     private static void GetDelegate<T>(string entryPoint, out T newDelegate)
   189       where T : class 
   190     {
   191       DllImportAttribute attribute = new DllImportAttribute(dllName);
   192       attribute.CallingConvention = CallingConvention.StdCall;
   193       attribute.PreserveSig = true;
   194       attribute.EntryPoint = entryPoint;
   195       PInvokeDelegateFactory.CreateDelegate(attribute, out newDelegate);
   196     }
   197 
   198     private static void CreateDelegates(string name) {
   199       int p = (int)Environment.OSVersion.Platform;
   200       if ((p == 4) || (p == 128))
   201         dllName = name + ".so";
   202       else
   203         dllName = name + ".dll";
   204 
   205       GetDelegate("ADL_Main_Control_Create",
   206         out _ADL_Main_Control_Create);
   207       GetDelegate("ADL_Adapter_AdapterInfo_Get",
   208         out _ADL_Adapter_AdapterInfo_Get);
   209       GetDelegate("ADL_Main_Control_Destroy",
   210         out ADL_Main_Control_Destroy);
   211       GetDelegate("ADL_Adapter_NumberOfAdapters_Get",
   212         out ADL_Adapter_NumberOfAdapters_Get);
   213       GetDelegate("ADL_Adapter_ID_Get",
   214         out _ADL_Adapter_ID_Get);
   215       GetDelegate("ADL_Display_AdapterID_Get", 
   216         out _ADL_Display_AdapterID_Get);
   217       GetDelegate("ADL_Adapter_Active_Get",
   218         out ADL_Adapter_Active_Get);
   219       GetDelegate("ADL_Overdrive5_CurrentActivity_Get",
   220         out ADL_Overdrive5_CurrentActivity_Get);
   221       GetDelegate("ADL_Overdrive5_Temperature_Get",
   222         out ADL_Overdrive5_Temperature_Get);
   223       GetDelegate("ADL_Overdrive5_FanSpeed_Get",
   224         out ADL_Overdrive5_FanSpeed_Get);
   225       GetDelegate("ADL_Overdrive5_FanSpeedInfo_Get",
   226         out ADL_Overdrive5_FanSpeedInfo_Get);
   227       GetDelegate("ADL_Overdrive5_FanSpeedToDefault_Set",
   228         out ADL_Overdrive5_FanSpeedToDefault_Set);
   229       GetDelegate("ADL_Overdrive5_FanSpeed_Set",
   230         out ADL_Overdrive5_FanSpeed_Set);
   231     }
   232 
   233     static ADL() {
   234       CreateDelegates("atiadlxx");
   235     }
   236 
   237     private ADL() { }
   238 
   239     public static int ADL_Main_Control_Create(int enumConnectedAdapters) {
   240       try {
   241         try {
   242           return _ADL_Main_Control_Create(Main_Memory_Alloc,
   243             enumConnectedAdapters);
   244         } catch {
   245           CreateDelegates("atiadlxy");
   246           return _ADL_Main_Control_Create(Main_Memory_Alloc,
   247             enumConnectedAdapters);
   248         }
   249       } catch {
   250         return ADL_ERR;
   251       }
   252     }
   253 
   254     public static int ADL_Adapter_AdapterInfo_Get(ADLAdapterInfo[] info) {
   255       int elementSize = Marshal.SizeOf(typeof(ADLAdapterInfo));
   256       int size = info.Length * elementSize;
   257       IntPtr ptr = Marshal.AllocHGlobal(size);
   258       int result = _ADL_Adapter_AdapterInfo_Get(ptr, size);
   259       for (int i = 0; i < info.Length; i++)
   260         info[i] = (ADLAdapterInfo)
   261           Marshal.PtrToStructure((IntPtr)((long)ptr + i * elementSize),
   262           typeof(ADLAdapterInfo));
   263       Marshal.FreeHGlobal(ptr);
   264 
   265       // the ADLAdapterInfo.VendorID field reported by ADL is wrong on 
   266       // Windows systems (parse error), so we fix this here
   267       for (int i = 0; i < info.Length; i++) {
   268         // try Windows UDID format
   269         Match m = Regex.Match(info[i].UDID, "PCI_VEN_([A-Fa-f0-9]{1,4})&.*");
   270         if (m.Success && m.Groups.Count == 2) {
   271           info[i].VendorID = Convert.ToInt32(m.Groups[1].Value, 16);
   272           continue;
   273         }
   274         // if above failed, try Unix UDID format
   275         m = Regex.Match(info[i].UDID, "[0-9]+:[0-9]+:([0-9]+):[0-9]+:[0-9]+");
   276         if (m.Success && m.Groups.Count == 2) {
   277           info[i].VendorID = Convert.ToInt32(m.Groups[1].Value, 10);
   278         }
   279       }
   280 
   281       return result;
   282     }
   283 
   284     public static int ADL_Adapter_ID_Get(int adapterIndex,
   285       out int adapterID) {
   286       try {
   287         return _ADL_Adapter_ID_Get(adapterIndex, out adapterID);
   288       } catch (EntryPointNotFoundException) {
   289         try {
   290           return _ADL_Display_AdapterID_Get(adapterIndex, out adapterID);
   291         } catch (EntryPointNotFoundException) {
   292           adapterID = 1;
   293           return ADL_OK;
   294         }
   295       }
   296     }
   297 
   298     private delegate IntPtr ADL_Main_Memory_AllocDelegate(int size);
   299 
   300     // create a Main_Memory_Alloc delegate and keep it alive
   301     private static ADL_Main_Memory_AllocDelegate Main_Memory_Alloc =
   302       delegate(int size) {
   303         return Marshal.AllocHGlobal(size);
   304       };
   305 
   306     private static void Main_Memory_Free(IntPtr buffer) {
   307       if (IntPtr.Zero != buffer)
   308         Marshal.FreeHGlobal(buffer);
   309     }
   310   }
   311 }