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