Fixed Issue 651.
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/.
7 Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Runtime.InteropServices;
13 using System.Text.RegularExpressions;
15 namespace OpenHardwareMonitor.Hardware.ATI {
17 [StructLayout(LayoutKind.Sequential)]
18 internal struct ADLAdapterInfo {
20 public int AdapterIndex;
21 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
24 public int DeviceNumber;
25 public int FunctionNumber;
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;
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;
42 [StructLayout(LayoutKind.Sequential)]
43 internal struct ADLPMActivity {
45 public int EngineClock;
46 public int MemoryClock;
48 public int ActivityPercent;
49 public int CurrentPerformanceLevel;
50 public int CurrentBusSpeed;
51 public int CurrentBusLanes;
52 public int MaximumBusLanes;
56 [StructLayout(LayoutKind.Sequential)]
57 internal struct ADLTemperature {
59 public int Temperature;
62 [StructLayout(LayoutKind.Sequential)]
63 internal struct ADLFanSpeedValue {
70 [StructLayout(LayoutKind.Sequential)]
71 internal struct ADLFanSpeedInfo {
74 public int MinPercent;
75 public int MaxPercent;
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;
92 public const int ADL_DL_FANCTRL_SPEED_TYPE_PERCENT = 1;
93 public const int ADL_DL_FANCTRL_SPEED_TYPE_RPM = 2;
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;
101 public const int ATI_VENDOR_ID = 0x1002;
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,
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,
113 public delegate int ADL_Display_AdapterID_GetDelegate(int adapterIndex,
115 public delegate int ADL_Adapter_Active_GetDelegate(int adapterIndex,
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);
131 private static ADL_Main_Control_CreateDelegate
132 _ADL_Main_Control_Create;
133 private static ADL_Adapter_AdapterInfo_GetDelegate
134 _ADL_Adapter_AdapterInfo_Get;
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
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;
159 private static string dllName;
161 private static void GetDelegate<T>(string entryPoint, out T newDelegate)
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);
171 private static void CreateDelegates(string name) {
172 int p = (int)Environment.OSVersion.Platform;
173 if ((p == 4) || (p == 128))
174 dllName = name + ".so";
176 dllName = name + ".dll";
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);
207 CreateDelegates("atiadlxx");
212 public static int ADL_Main_Control_Create(int enumConnectedAdapters) {
215 return _ADL_Main_Control_Create(Main_Memory_Alloc,
216 enumConnectedAdapters);
218 CreateDelegates("atiadlxy");
219 return _ADL_Main_Control_Create(Main_Memory_Alloc,
220 enumConnectedAdapters);
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);
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);
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);
257 public static int ADL_Adapter_ID_Get(int adapterIndex,
260 return _ADL_Adapter_ID_Get(adapterIndex, out adapterID);
261 } catch (EntryPointNotFoundException) {
263 return _ADL_Display_AdapterID_Get(adapterIndex, out adapterID);
264 } catch (EntryPointNotFoundException) {
271 private delegate IntPtr ADL_Main_Memory_AllocDelegate(int size);
273 // create a Main_Memory_Alloc delegate and keep it alive
274 private static ADL_Main_Memory_AllocDelegate Main_Memory_Alloc =
276 return Marshal.AllocHGlobal(size);
279 private static void Main_Memory_Free(IntPtr buffer) {
280 if (IntPtr.Zero != buffer)
281 Marshal.FreeHGlobal(buffer);