Added a minimal control interface to allow manual fan control and implemented the interface for ATI GPUs.
authormoel.mich
Thu, 20 Jan 2011 21:31:54 +0000
changeset 2476dc755f1970e
parent 246 59024371cd50
child 248 045eb5c1ec32
Added a minimal control interface to allow manual fan control and implemented the interface for ATI GPUs.
GUI/MainForm.cs
Hardware/ATI/ADL.cs
Hardware/ATI/ATIGPU.cs
Hardware/ATI/ATIGroup.cs
Hardware/Control.cs
Hardware/Hardware.cs
Hardware/IControl.cs
Hardware/ISensor.cs
Hardware/LPC/IT87XX.cs
Hardware/Sensor.cs
OpenHardwareMonitorLib.csproj
     1.1 --- a/GUI/MainForm.cs	Wed Dec 08 19:23:13 2010 +0000
     1.2 +++ b/GUI/MainForm.cs	Thu Jan 20 21:31:54 2011 +0000
     1.3 @@ -461,6 +461,34 @@
     1.4              };
     1.5              sensorContextMenu.MenuItems.Add(item);
     1.6            }
     1.7 +          if (node.Sensor.Control != null) {
     1.8 +            IControl control = node.Sensor.Control;
     1.9 +            MenuItem controlItem = new MenuItem("Control");
    1.10 +            MenuItem defaultItem = new MenuItem("Default");
    1.11 +            defaultItem.Checked = control.ControlMode == ControlMode.Default;
    1.12 +            controlItem.MenuItems.Add(defaultItem);
    1.13 +            defaultItem.Click += delegate(object obj, EventArgs args) {
    1.14 +              control.SetDefault();
    1.15 +            };
    1.16 +            MenuItem manualItem = new MenuItem("Manual");            
    1.17 +            controlItem.MenuItems.Add(manualItem);
    1.18 +            manualItem.Checked = control.ControlMode == ControlMode.Software;
    1.19 +            for (int i = 0; i <= 100; i += 5) {
    1.20 +              if (i <= control.MaxSoftwareValue &&
    1.21 +                  i >= control.MinSoftwareValue) 
    1.22 +              {
    1.23 +                MenuItem item = new MenuItem(i + " %");
    1.24 +                manualItem.MenuItems.Add(item);
    1.25 +                item.Checked = control.ControlMode == ControlMode.Software &&
    1.26 +                  Math.Round(control.SoftwareValue) == i;
    1.27 +                int softwareValue = i;
    1.28 +                item.Click += delegate(object obj, EventArgs args) {
    1.29 +                  control.SetSoftware(softwareValue);
    1.30 +                };
    1.31 +              }
    1.32 +            }
    1.33 +            sensorContextMenu.MenuItems.Add(controlItem);
    1.34 +          }
    1.35  
    1.36            sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
    1.37          }
     2.1 --- a/Hardware/ATI/ADL.cs	Wed Dec 08 19:23:13 2010 +0000
     2.2 +++ b/Hardware/ATI/ADL.cs	Thu Jan 20 21:31:54 2011 +0000
     2.3 @@ -122,6 +122,7 @@
     2.4      public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_WRITE = 2;
     2.5      public const int ADL_DL_FANCTRL_SUPPORTS_RPM_READ = 4;
     2.6      public const int ADL_DL_FANCTRL_SUPPORTS_RPM_WRITE = 8;
     2.7 +    public const int ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED = 1;
     2.8  
     2.9      public const int ATI_VENDOR_ID1 = 1002;
    2.10      public const int ATI_VENDOR_ID2 = 0x1002;
    2.11 @@ -149,6 +150,10 @@
    2.12      public delegate int ADL_Overdrive5_FanSpeedInfo_GetDelegate(
    2.13        int adapterIndex, int thermalControllerIndex,
    2.14        ref ADLFanSpeedInfo fanSpeedInfo);
    2.15 +    public delegate int ADL_Overdrive5_FanSpeedToDefault_SetDelegate(
    2.16 +      int adapterIndex, int thermalControllerIndex);
    2.17 +    public delegate int ADL_Overdrive5_FanSpeed_SetDelegate(int adapterIndex,
    2.18 +      int thermalControllerIndex, ref	ADLFanSpeedValue fanSpeedValue);
    2.19  
    2.20      private static ADL_Main_Control_CreateDelegate
    2.21        _ADL_Main_Control_Create;
    2.22 @@ -173,6 +178,10 @@
    2.23        ADL_Overdrive5_FanSpeed_Get;
    2.24      public static ADL_Overdrive5_FanSpeedInfo_GetDelegate
    2.25        ADL_Overdrive5_FanSpeedInfo_Get;
    2.26 +    public static ADL_Overdrive5_FanSpeedToDefault_SetDelegate
    2.27 +      ADL_Overdrive5_FanSpeedToDefault_Set;
    2.28 +    public static ADL_Overdrive5_FanSpeed_SetDelegate
    2.29 +      ADL_Overdrive5_FanSpeed_Set;
    2.30  
    2.31      private static string dllName;
    2.32  
    2.33 @@ -215,6 +224,10 @@
    2.34          out ADL_Overdrive5_FanSpeed_Get);
    2.35        GetDelegate("ADL_Overdrive5_FanSpeedInfo_Get",
    2.36          out ADL_Overdrive5_FanSpeedInfo_Get);
    2.37 +      GetDelegate("ADL_Overdrive5_FanSpeedToDefault_Set",
    2.38 +        out ADL_Overdrive5_FanSpeedToDefault_Set);
    2.39 +      GetDelegate("ADL_Overdrive5_FanSpeed_Set",
    2.40 +        out ADL_Overdrive5_FanSpeed_Set);
    2.41      }
    2.42  
    2.43      static ADL() {
     3.1 --- a/Hardware/ATI/ATIGPU.cs	Wed Dec 08 19:23:13 2010 +0000
     3.2 +++ b/Hardware/ATI/ATIGPU.cs	Thu Jan 20 21:31:54 2011 +0000
     3.3 @@ -51,7 +51,10 @@
     3.4      private readonly Sensor memoryClock;
     3.5      private readonly Sensor coreVoltage;
     3.6      private readonly Sensor coreLoad;
     3.7 -    private readonly Sensor fanControl;
     3.8 +    private readonly Sensor controlSensor;
     3.9 +    private readonly Control fanControl;
    3.10 +
    3.11 +    private ADLFanSpeedValue initialFanSpeedValue;
    3.12  
    3.13      public ATIGPU(string name, int adapterIndex, int busNumber, 
    3.14        int deviceNumber, ISettings settings) 
    3.15 @@ -61,16 +64,61 @@
    3.16        this.busNumber = busNumber;
    3.17        this.deviceNumber = deviceNumber;
    3.18  
    3.19 +      this.initialFanSpeedValue = new ADLFanSpeedValue();
    3.20 +      this.initialFanSpeedValue.SpeedType = 
    3.21 +        ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
    3.22 +      ADL.ADL_Overdrive5_FanSpeed_Get(adapterIndex, 0, 
    3.23 +        ref this.initialFanSpeedValue);
    3.24 +
    3.25        this.temperature = new Sensor("GPU Core", 0, SensorType.Temperature, this, settings);
    3.26        this.fan = new Sensor("GPU Fan", 0, SensorType.Fan, this, settings);
    3.27        this.coreClock = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
    3.28        this.memoryClock = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
    3.29        this.coreVoltage = new Sensor("GPU Core", 0, SensorType.Voltage, this, settings);
    3.30        this.coreLoad = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
    3.31 -      this.fanControl = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
    3.32 +      this.controlSensor = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
    3.33 +
    3.34 +      ADLFanSpeedInfo afsi = new ADLFanSpeedInfo();
    3.35 +      if (ADL.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref afsi)
    3.36 +        != ADL.ADL_OK) 
    3.37 +      {
    3.38 +        afsi.MaxPercent = 100;
    3.39 +        afsi.MinPercent = 0;
    3.40 +      }
    3.41 +
    3.42 +      this.fanControl = new Control(controlSensor, settings, afsi.MinPercent, 
    3.43 +        afsi.MaxPercent);
    3.44 +      this.fanControl.ControlModeChanged += ControlModeChanged;
    3.45 +      this.fanControl.SoftwareControlValueChanged += 
    3.46 +        SoftwareControlValueChanged;
    3.47 +      ControlModeChanged(fanControl);
    3.48 +      this.controlSensor.Control = fanControl;
    3.49        Update();                   
    3.50      }
    3.51  
    3.52 +    private void SoftwareControlValueChanged(IControl control) {
    3.53 +      if (control.ControlMode == ControlMode.Software) {
    3.54 +        ADLFanSpeedValue adlf = new ADLFanSpeedValue();
    3.55 +        adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
    3.56 +        adlf.Flags = ADL.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
    3.57 +        adlf.FanSpeed = (int)control.SoftwareValue;
    3.58 +        ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0, ref adlf);
    3.59 +      }
    3.60 +    }
    3.61 +
    3.62 +    private void ControlModeChanged(IControl control) {
    3.63 +      if (control.ControlMode == ControlMode.Default) {
    3.64 +        ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0,
    3.65 +          ref this.initialFanSpeedValue);
    3.66 +      } else {
    3.67 +        ADLFanSpeedValue adlf = new ADLFanSpeedValue();
    3.68 +        adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
    3.69 +        adlf.Flags = ADL.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
    3.70 +        adlf.FanSpeed = (int)control.SoftwareValue;
    3.71 +        ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0, ref adlf);
    3.72 +      }
    3.73 +    }
    3.74 +
    3.75      public int BusNumber { get { return busNumber; } }
    3.76  
    3.77      public int DeviceNumber { get { return deviceNumber; } }
    3.78 @@ -116,10 +164,10 @@
    3.79        adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
    3.80        if (ADL.ADL_Overdrive5_FanSpeed_Get(adapterIndex, 0, ref adlf)
    3.81          == ADL.ADL_OK) {
    3.82 -        fanControl.Value = adlf.FanSpeed;
    3.83 -        ActivateSensor(fanControl);
    3.84 +        controlSensor.Value = adlf.FanSpeed;
    3.85 +        ActivateSensor(controlSensor);
    3.86        } else {
    3.87 -        fanControl.Value = null;
    3.88 +        controlSensor.Value = null;
    3.89        }
    3.90  
    3.91        ADLPMActivity adlp = new ADLPMActivity();
    3.92 @@ -150,5 +198,14 @@
    3.93          coreLoad.Value = null;
    3.94        }
    3.95      }
    3.96 +
    3.97 +    public void Close() {
    3.98 +      this.fanControl.ControlModeChanged -= ControlModeChanged;
    3.99 +      this.fanControl.SoftwareControlValueChanged -=
   3.100 +        SoftwareControlValueChanged;
   3.101 +
   3.102 +      ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0,
   3.103 +        ref this.initialFanSpeedValue);
   3.104 +    }
   3.105    }
   3.106  }
     4.1 --- a/Hardware/ATI/ATIGroup.cs	Wed Dec 08 19:23:13 2010 +0000
     4.2 +++ b/Hardware/ATI/ATIGroup.cs	Thu Jan 20 21:31:54 2011 +0000
     4.3 @@ -144,6 +144,8 @@
     4.4  
     4.5      public void Close() {
     4.6        try {
     4.7 +        foreach (ATIGPU gpu in hardware)
     4.8 +          gpu.Close();
     4.9          ADL.ADL_Main_Control_Destroy();
    4.10        } catch (Exception) { }
    4.11      }
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/Hardware/Control.cs	Thu Jan 20 21:31:54 2011 +0000
     5.3 @@ -0,0 +1,143 @@
     5.4 +/*
     5.5 +  
     5.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     5.7 +
     5.8 +  The contents of this file are subject to the Mozilla Public License Version
     5.9 +  1.1 (the "License"); you may not use this file except in compliance with
    5.10 +  the License. You may obtain a copy of the License at
    5.11 + 
    5.12 +  http://www.mozilla.org/MPL/
    5.13 +
    5.14 +  Software distributed under the License is distributed on an "AS IS" basis,
    5.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    5.16 +  for the specific language governing rights and limitations under the License.
    5.17 +
    5.18 +  The Original Code is the Open Hardware Monitor code.
    5.19 +
    5.20 +  The Initial Developer of the Original Code is 
    5.21 +  Michael Möller <m.moeller@gmx.ch>.
    5.22 +  Portions created by the Initial Developer are Copyright (C) 2010
    5.23 +  the Initial Developer. All Rights Reserved.
    5.24 +
    5.25 +  Contributor(s):
    5.26 +
    5.27 +  Alternatively, the contents of this file may be used under the terms of
    5.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
    5.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    5.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
    5.31 +  of those above. If you wish to allow use of your version of this file only
    5.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
    5.33 +  use your version of this file under the terms of the MPL, indicate your
    5.34 +  decision by deleting the provisions above and replace them with the notice
    5.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
    5.36 +  the provisions above, a recipient may use your version of this file under
    5.37 +  the terms of any one of the MPL, the GPL or the LGPL.
    5.38 + 
    5.39 +*/
    5.40 +
    5.41 +using System;
    5.42 +using System.Globalization;
    5.43 +
    5.44 +namespace OpenHardwareMonitor.Hardware {
    5.45 +
    5.46 +  internal delegate void ControlEventHandler(Control control);
    5.47 +
    5.48 +  internal class Control : IControl {
    5.49 +
    5.50 +    private readonly Identifier identifier;
    5.51 +    private readonly ISettings settings;
    5.52 +    private ControlMode mode;
    5.53 +    private float softwareValue;
    5.54 +    private float minSoftwareValue;
    5.55 +    private float maxSoftwareValue;
    5.56 +
    5.57 +    public Control(ISensor sensor, ISettings settings, float minSoftwareValue,
    5.58 +      float maxSoftwareValue) 
    5.59 +    {
    5.60 +      this.identifier = new Identifier(sensor.Identifier, "control");
    5.61 +      this.settings = settings;
    5.62 +      this.minSoftwareValue = minSoftwareValue;
    5.63 +      this.maxSoftwareValue = maxSoftwareValue;
    5.64 +
    5.65 +      if (!float.TryParse(settings.GetValue(
    5.66 +          new Identifier(identifier, "value").ToString(), "0"),
    5.67 +        NumberStyles.Float, CultureInfo.InvariantCulture,
    5.68 +        out this.softwareValue)) 
    5.69 +      {
    5.70 +        this.softwareValue = 0;
    5.71 +      }
    5.72 +      int mode;
    5.73 +      if (!int.TryParse(settings.GetValue(
    5.74 +          new Identifier(identifier, "mode").ToString(),
    5.75 +          ((int)ControlMode.Default).ToString(CultureInfo.InvariantCulture)),
    5.76 +        NumberStyles.Integer, CultureInfo.InvariantCulture,
    5.77 +        out mode)) 
    5.78 +      {
    5.79 +        this.mode = ControlMode.Default;
    5.80 +      } else {
    5.81 +        this.mode = (ControlMode)mode;
    5.82 +      }
    5.83 +    }
    5.84 +
    5.85 +    public Identifier Identifier {
    5.86 +      get {
    5.87 +        return identifier;
    5.88 +      }
    5.89 +    }
    5.90 +
    5.91 +    public ControlMode ControlMode {
    5.92 +      get {
    5.93 +        return mode;
    5.94 +      }
    5.95 +      private set {
    5.96 +        if (mode != value) {
    5.97 +          mode = value;
    5.98 +          if (ControlModeChanged != null)
    5.99 +            ControlModeChanged(this);
   5.100 +          this.settings.SetValue(new Identifier(identifier, "mode").ToString(),
   5.101 +            ((int)mode).ToString(CultureInfo.InvariantCulture));
   5.102 +        }
   5.103 +      }
   5.104 +    }
   5.105 +
   5.106 +    public float SoftwareValue {
   5.107 +      get {
   5.108 +        return softwareValue;
   5.109 +      }
   5.110 +      private set {
   5.111 +        if (softwareValue != value) {
   5.112 +          softwareValue = value;
   5.113 +          if (SoftwareControlValueChanged != null)
   5.114 +            SoftwareControlValueChanged(this);
   5.115 +          this.settings.SetValue(new Identifier(identifier,
   5.116 +            "value").ToString(),
   5.117 +            value.ToString(CultureInfo.InvariantCulture));
   5.118 +        }
   5.119 +      }
   5.120 +    }
   5.121 +
   5.122 +    public void SetDefault() {
   5.123 +      ControlMode = ControlMode.Default;
   5.124 +    }
   5.125 +
   5.126 +    public float MinSoftwareValue {
   5.127 +      get {
   5.128 +        return minSoftwareValue;
   5.129 +      }
   5.130 +    }
   5.131 +
   5.132 +    public float MaxSoftwareValue {
   5.133 +      get {
   5.134 +        return maxSoftwareValue;
   5.135 +      }
   5.136 +    }
   5.137 +
   5.138 +    public void SetSoftware(float value) {
   5.139 +      ControlMode = ControlMode.Software;
   5.140 +      SoftwareValue = value;
   5.141 +    }
   5.142 +
   5.143 +    internal event ControlEventHandler ControlModeChanged;
   5.144 +    internal event ControlEventHandler SoftwareControlValueChanged;
   5.145 +  }
   5.146 +}
     6.1 --- a/Hardware/Hardware.cs	Wed Dec 08 19:23:13 2010 +0000
     6.2 +++ b/Hardware/Hardware.cs	Thu Jan 20 21:31:54 2011 +0000
     6.3 @@ -55,13 +55,13 @@
     6.4        get { return active.ToArray(); }
     6.5      }
     6.6  
     6.7 -    protected void ActivateSensor(Sensor sensor) {
     6.8 +    protected void ActivateSensor(ISensor sensor) {
     6.9        if (active.Add(sensor)) 
    6.10          if (SensorAdded != null)
    6.11            SensorAdded(sensor);
    6.12      }
    6.13  
    6.14 -    protected void DeactivateSensor(Sensor sensor) {
    6.15 +    protected void DeactivateSensor(ISensor sensor) {
    6.16        if (active.Remove(sensor))
    6.17          if (SensorRemoved != null)
    6.18            SensorRemoved(sensor);     
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/Hardware/IControl.cs	Thu Jan 20 21:31:54 2011 +0000
     7.3 @@ -0,0 +1,61 @@
     7.4 +/*
     7.5 +  
     7.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     7.7 +
     7.8 +  The contents of this file are subject to the Mozilla Public License Version
     7.9 +  1.1 (the "License"); you may not use this file except in compliance with
    7.10 +  the License. You may obtain a copy of the License at
    7.11 + 
    7.12 +  http://www.mozilla.org/MPL/
    7.13 +
    7.14 +  Software distributed under the License is distributed on an "AS IS" basis,
    7.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    7.16 +  for the specific language governing rights and limitations under the License.
    7.17 +
    7.18 +  The Original Code is the Open Hardware Monitor code.
    7.19 +
    7.20 +  The Initial Developer of the Original Code is 
    7.21 +  Michael Möller <m.moeller@gmx.ch>.
    7.22 +  Portions created by the Initial Developer are Copyright (C) 2010
    7.23 +  the Initial Developer. All Rights Reserved.
    7.24 +
    7.25 +  Contributor(s):
    7.26 +
    7.27 +  Alternatively, the contents of this file may be used under the terms of
    7.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
    7.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    7.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
    7.31 +  of those above. If you wish to allow use of your version of this file only
    7.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
    7.33 +  use your version of this file under the terms of the MPL, indicate your
    7.34 +  decision by deleting the provisions above and replace them with the notice
    7.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
    7.36 +  the provisions above, a recipient may use your version of this file under
    7.37 +  the terms of any one of the MPL, the GPL or the LGPL.
    7.38 + 
    7.39 +*/
    7.40 +
    7.41 +namespace OpenHardwareMonitor.Hardware {
    7.42 +
    7.43 +  public enum ControlMode {
    7.44 +    Default,
    7.45 +    Software
    7.46 +  }
    7.47 +
    7.48 +  public interface IControl {
    7.49 +
    7.50 +    Identifier Identifier { get; }
    7.51 +
    7.52 +    ControlMode ControlMode { get; }
    7.53 +
    7.54 +    float SoftwareValue { get; }
    7.55 +
    7.56 +    void SetDefault();
    7.57 +
    7.58 +    float MinSoftwareValue { get; }
    7.59 +    float MaxSoftwareValue { get; }
    7.60 +
    7.61 +    void SetSoftware(float value);
    7.62 +
    7.63 +  }
    7.64 +}
     8.1 --- a/Hardware/ISensor.cs	Wed Dec 08 19:23:13 2010 +0000
     8.2 +++ b/Hardware/ISensor.cs	Thu Jan 20 21:31:54 2011 +0000
     8.3 @@ -87,6 +87,8 @@
     8.4      void ResetMax();
     8.5  
     8.6      IEnumerable<SensorValue> Values { get; }
     8.7 +
     8.8 +    IControl Control { get; }
     8.9    }
    8.10  
    8.11  }
     9.1 --- a/Hardware/LPC/IT87XX.cs	Wed Dec 08 19:23:13 2010 +0000
     9.2 +++ b/Hardware/LPC/IT87XX.cs	Thu Jan 20 21:31:54 2011 +0000
     9.3 @@ -82,6 +82,12 @@
     9.4        return value;
     9.5      }
     9.6  
     9.7 +    private bool WriteByte(byte register, byte value) {
     9.8 +      Ring0.WriteIoPort(addressReg, register);
     9.9 +      Ring0.WriteIoPort(dataReg, value);
    9.10 +      return register == Ring0.ReadIoPort(addressReg);
    9.11 +    }
    9.12 +
    9.13      public byte? ReadGPIO(int index) {
    9.14        if (index >= gpioCount)
    9.15          return null;
    10.1 --- a/Hardware/Sensor.cs	Wed Dec 08 19:23:13 2010 +0000
    10.2 +++ b/Hardware/Sensor.cs	Thu Jan 20 21:31:54 2011 +0000
    10.3 @@ -57,6 +57,7 @@
    10.4      private readonly Queue<SensorValue> values =
    10.5        new Queue<SensorValue>(MAX_MINUTES * 15);
    10.6      private readonly ISettings settings;
    10.7 +    private IControl control;
    10.8      
    10.9      private float sum;
   10.10      private int count;
   10.11 @@ -186,5 +187,14 @@
   10.12        foreach (IParameter parameter in parameters)
   10.13          parameter.Accept(visitor);
   10.14      }
   10.15 +
   10.16 +    public IControl Control {
   10.17 +      get {
   10.18 +        return control;
   10.19 +      }
   10.20 +      internal set {
   10.21 +        this.control = value;
   10.22 +      }
   10.23 +    }
   10.24    }
   10.25  }
    11.1 --- a/OpenHardwareMonitorLib.csproj	Wed Dec 08 19:23:13 2010 +0000
    11.2 +++ b/OpenHardwareMonitorLib.csproj	Thu Jan 20 21:31:54 2011 +0000
    11.3 @@ -59,6 +59,8 @@
    11.4      <Compile Include="Hardware\ATI\ADL.cs" />
    11.5      <Compile Include="Hardware\ATI\ATIGPU.cs" />
    11.6      <Compile Include="Hardware\ATI\ATIGroup.cs" />
    11.7 +    <Compile Include="Hardware\Control.cs" />
    11.8 +    <Compile Include="Hardware\IControl.cs" />
    11.9      <Compile Include="Hardware\IOControlCode.cs" />
   11.10      <Compile Include="Hardware\Computer.cs" />
   11.11      <Compile Include="Hardware\CPU\AMDCPU.cs" />