# HG changeset patch
# User moel.mich
# Date 1343232216 0
# Node ID ea86cea126bcd52c86aad35a0a95a2d7094a7821
# Parent  3b8443edb0e6dc54ec02907f00730a17d38fd918
Added temperature offset parameters to all HDD temperature sensors. Fixed issue 271.

diff -r 3b8443edb0e6 -r ea86cea126bc Hardware/HDD/AbstractHarddrive.cs
--- a/Hardware/HDD/AbstractHarddrive.cs	Wed Jul 25 15:33:16 2012 +0000
+++ b/Hardware/HDD/AbstractHarddrive.cs	Wed Jul 25 16:03:36 2012 +0000
@@ -169,7 +169,8 @@
         if (!sensorTypeAndChannels.Contains(pair)) {
           Sensor sensor = new Sensor(attribute.Name, 
             attribute.SensorChannel, attribute.DefaultHiddenSensor, 
-            attribute.SensorType.Value, this, null, settings);
+            attribute.SensorType.Value, this, attribute.ParameterDescriptions, 
+            settings);
 
           sensors.Add(attribute, sensor);
           ActivateSensor(sensor);
@@ -199,7 +200,7 @@
           foreach (DriveAttributeValue value in values) {
             if (value.Identifier == attribute.Identifier) {
               Sensor sensor = keyValuePair.Value;
-              sensor.Value = attribute.ConvertValue(value);
+              sensor.Value = attribute.ConvertValue(value, sensor.Parameters);
             }
           }
         }
@@ -261,7 +262,7 @@
             if (a.Identifier == value.Identifier) {
               description = a.Name;
               if (a.HasRawValueConversion | a.SensorType.HasValue)
-                physical = a.ConvertValue(value);
+                physical = a.ConvertValue(value, null);
               else
                 physical = null;
             }
@@ -295,7 +296,9 @@
       return r.ToString();
     }
 
-    protected static float RawToInt(byte[] raw, byte value) {
+    protected static float RawToInt(byte[] raw, byte value,
+      IReadOnlyArray<IParameter> parameters) 
+    {
       return (raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0];
     }
 
diff -r 3b8443edb0e6 -r ea86cea126bc Hardware/HDD/HDDGeneric.cs
--- a/Hardware/HDD/HDDGeneric.cs	Wed Jul 25 15:33:16 2012 +0000
+++ b/Hardware/HDD/HDDGeneric.cs	Wed Jul 25 16:03:36 2012 +0000
@@ -13,6 +13,7 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using OpenHardwareMonitor.Collections;
 
 namespace OpenHardwareMonitor.Hardware.HDD {
 
@@ -82,9 +83,19 @@
       new SmartAttribute(0xFE, SmartNames.FreeFallProtection),
 
       new SmartAttribute(0xC2, SmartNames.Temperature, 
-        (byte[] r, byte v) => { return r[0]; }, SensorType.Temperature, 0),
+        (byte[] r, byte v, IReadOnlyArray<IParameter> p) 
+          => { return r[0] + (p == null ? 0 : p[0].Value); }, 
+          SensorType.Temperature, 0, false, 
+        new[] { new ParameterDescription("Offset [°C]", 
+                  "Temperature offset of the thermal sensor.\n" + 
+                  "Temperature = Value + Offset.", 0) }),
       new SmartAttribute(0xE7, SmartNames.Temperature, 
-        (byte[] r, byte v) => { return r[0]; }, SensorType.Temperature, 0),
+        (byte[] r, byte v, IReadOnlyArray<IParameter> p) 
+          => { return r[0] + (p == null ? 0 : p[0].Value); }, 
+          SensorType.Temperature, 0, false, 
+        new[] { new ParameterDescription("Offset [°C]", 
+                  "Temperature offset of the thermal sensor.\n" + 
+                  "Temperature = Value + Offset.", 0) }),
       new SmartAttribute(0xBE, SmartNames.TemperatureDifferenceFrom100, 
         null, SensorType.Temperature, 0)
     };
diff -r 3b8443edb0e6 -r ea86cea126bc Hardware/HDD/SSDIntel.cs
--- a/Hardware/HDD/SSDIntel.cs	Wed Jul 25 15:33:16 2012 +0000
+++ b/Hardware/HDD/SSDIntel.cs	Wed Jul 25 16:03:36 2012 +0000
@@ -10,9 +10,11 @@
 	
 */
 
+using System.Collections.Generic;
+using OpenHardwareMonitor.Collections;
+
 namespace OpenHardwareMonitor.Hardware.HDD {
-  using System.Collections.Generic;
-
+   
   [NamePrefix("INTEL SSD"), 
    RequireSmart(0xE1), RequireSmart(0xE8), RequireSmart(0xE9)]
   internal class SSDIntel : AbstractHarddrive {
@@ -32,16 +34,19 @@
       new SmartAttribute(0xB8, SmartNames.EndToEndError),
       new SmartAttribute(0xC0, SmartNames.UnsafeShutdownCount), 
       new SmartAttribute(0xE1, SmartNames.HostWrites, 
-        (byte[] r, byte v) => { return RawToInt(r, v) / 0x20; }, 
+        (byte[] r, byte v, IReadOnlyArray<IParameter> p) 
+          => { return RawToInt(r, v, p) / 0x20; }, 
         SensorType.Data, 0),
       new SmartAttribute(0xE8, SmartNames.RemainingLife, 
         null, SensorType.Level, 0),
       new SmartAttribute(0xE9, SmartNames.MediaWearOutIndicator),
       new SmartAttribute(0xF1, SmartNames.HostWrites,
-        (byte[] r, byte v) => { return RawToInt(r, v) / 0x20; }, 
+        (byte[] r, byte v, IReadOnlyArray<IParameter> p) 
+          => { return RawToInt(r, v, p) / 0x20; }, 
         SensorType.Data, 0),
       new SmartAttribute(0xF2, SmartNames.HostReads, 
-        (byte[] r, byte v) => { return RawToInt(r, v) / 0x20; }, 
+        (byte[] r, byte v, IReadOnlyArray<IParameter> p) 
+          => { return RawToInt(r, v, p) / 0x20; }, 
         SensorType.Data, 1),      
     };
 
diff -r 3b8443edb0e6 -r ea86cea126bc Hardware/HDD/SSDMicron.cs
--- a/Hardware/HDD/SSDMicron.cs	Wed Jul 25 15:33:16 2012 +0000
+++ b/Hardware/HDD/SSDMicron.cs	Wed Jul 25 16:03:36 2012 +0000
@@ -8,8 +8,10 @@
 	
 */
 
-namespace OpenHardwareMonitor.Hardware.HDD {
-  using System.Collections.Generic;
+using System.Collections.Generic;
+using OpenHardwareMonitor.Collections;
+
+namespace OpenHardwareMonitor.Hardware.HDD {  
 
   [NamePrefix(""), RequireSmart(0xAA), RequireSmart(0xAB), RequireSmart(0xAC), 
    RequireSmart(0xAD), RequireSmart(0xAE), RequireSmart(0xCA)]
@@ -28,7 +30,8 @@
       new SmartAttribute(0xAD, SmartNames.WearLevelingCount, RawToInt),
       new SmartAttribute(0xAE, SmartNames.UnexpectedPowerLossCount, RawToInt),
       new SmartAttribute(0xB5, SmartNames.Non4kAlignedAccess, 
-        (byte[] raw, byte value) => { return 6e4f * ((raw[5] << 8) | raw[4]); }),
+        (byte[] raw, byte value, IReadOnlyArray<IParameter> p) 
+          => { return 6e4f * ((raw[5] << 8) | raw[4]); }),
       new SmartAttribute(0xB7, SmartNames.SataDownshiftErrorCount, RawToInt),
       new SmartAttribute(0xBB, SmartNames.ReportedUncorrectableErrors, RawToInt),
       new SmartAttribute(0xBC, SmartNames.CommandTimeout, RawToInt),
@@ -38,10 +41,12 @@
       new SmartAttribute(0xC6, SmartNames.OffLineUncorrectableErrorCount, RawToInt),
       new SmartAttribute(0xC7, SmartNames.UltraDmaCrcErrorCount, RawToInt),
       new SmartAttribute(0xCA, SmartNames.RemainingLife, 
-        (byte[] raw, byte value) => { return 100 - RawToInt(raw, value); }, 
+        (byte[] raw, byte value, IReadOnlyArray<IParameter> p) 
+          => { return 100 - RawToInt(raw, value, p); }, 
         SensorType.Level, 0),
       new SmartAttribute(0xCE, SmartNames.WriteErrorRate, 
-         (byte[] raw, byte value) => { return 6e4f * ((raw[1] << 8) | raw[0]); }),
+         (byte[] raw, byte value, IReadOnlyArray<IParameter> p)
+           => { return 6e4f * ((raw[1] << 8) | raw[0]); }),
     };
 
     public SSDMicron(ISmart smart, string name, string firmwareRevision, 
diff -r 3b8443edb0e6 -r ea86cea126bc Hardware/HDD/SSDSandforce.cs
--- a/Hardware/HDD/SSDSandforce.cs	Wed Jul 25 15:33:16 2012 +0000
+++ b/Hardware/HDD/SSDSandforce.cs	Wed Jul 25 16:03:36 2012 +0000
@@ -9,8 +9,10 @@
 	
 */
 
+using System.Collections.Generic;
+using OpenHardwareMonitor.Collections;
+
 namespace OpenHardwareMonitor.Hardware.HDD {
-  using System.Collections.Generic;
 
   [NamePrefix(""), RequireSmart(0xAB), RequireSmart(0xB1)]
   internal class SSDSandforce : AbstractHarddrive {
@@ -28,8 +30,13 @@
       new SmartAttribute(0xB5, SmartNames.AlternativeProgramFailCount, RawToInt),
       new SmartAttribute(0xB6, SmartNames.AlternativeEraseFailCount, RawToInt),
       new SmartAttribute(0xBB, SmartNames.UncorrectableErrorCount, RawToInt),
-      new SmartAttribute(0xC2, SmartNames.Temperature, (byte[] raw, byte value) 
-        => { return value; }, SensorType.Temperature, 0, true), 
+      new SmartAttribute(0xC2, SmartNames.Temperature, 
+        (byte[] raw, byte value, IReadOnlyArray<IParameter> p) 
+          => { return value + (p == null ? 0 : p[0].Value); }, 
+        SensorType.Temperature, 0, true, 
+        new[] { new ParameterDescription("Offset [°C]", 
+                  "Temperature offset of the thermal sensor.\n" + 
+                  "Temperature = Value + Offset.", 0) }), 
       new SmartAttribute(0xC3, SmartNames.UnrecoverableEcc), 
       new SmartAttribute(0xC4, SmartNames.ReallocationEventCount, RawToInt),
       new SmartAttribute(0xE7, SmartNames.RemainingLife, null, 
@@ -59,10 +66,10 @@
       float? hostWritesToController = null;
       foreach (DriveAttributeValue value in values) {
         if (value.Identifier == 0xE9)
-          controllerWritesToNAND = RawToInt(value.RawValue, value.AttrValue);
+          controllerWritesToNAND = RawToInt(value.RawValue, value.AttrValue, null);
 
         if (value.Identifier == 0xEA)
-          hostWritesToController = RawToInt(value.RawValue, value.AttrValue);
+          hostWritesToController = RawToInt(value.RawValue, value.AttrValue, null);
       }
       if (controllerWritesToNAND.HasValue && hostWritesToController.HasValue) {
         if (hostWritesToController.Value > 0)
diff -r 3b8443edb0e6 -r ea86cea126bc Hardware/HDD/SmartAttribute.cs
--- a/Hardware/HDD/SmartAttribute.cs	Wed Jul 25 15:33:16 2012 +0000
+++ b/Hardware/HDD/SmartAttribute.cs	Wed Jul 25 16:03:36 2012 +0000
@@ -11,6 +11,7 @@
 
 using System;
 using System.Collections.Generic;
+using OpenHardwareMonitor.Collections;
 
 namespace OpenHardwareMonitor.Hardware.HDD {
   internal class SmartAttribute {
@@ -49,9 +50,12 @@
     /// the same sensor channel and type, then a sensor is created only for the  
     /// first attribute.</param>
     /// <param name="defaultHiddenSensor">True to hide the sensor initially.</param>
+    /// <param name="parameterDescriptions">Description for the parameters of the sensor 
+    /// (or null).</param>
     public SmartAttribute(byte identifier, string name,
       RawValueConversion rawValueConversion, SensorType? sensorType, 
-      int sensorChannel, bool defaultHiddenSensor = false) 
+      int sensorChannel, bool defaultHiddenSensor = false,
+      ParameterDescription[] parameterDescriptions = null) 
     {
       this.Identifier = identifier;
       this.Name = name;
@@ -59,6 +63,7 @@
       this.SensorType = sensorType;
       this.SensorChannel = sensorChannel;
       this.DefaultHiddenSensor = defaultHiddenSensor;
+      this.ParameterDescriptions = parameterDescriptions;
     }
 
     /// <summary>
@@ -74,20 +79,25 @@
 
     public bool DefaultHiddenSensor { get; private set; }
 
+    public ParameterDescription[] ParameterDescriptions { get; private set; }
+
     public bool HasRawValueConversion {
       get {
         return rawValueConversion != null;
       }
     }
 
-    public float ConvertValue(DriveAttributeValue value) {
+    public float ConvertValue(DriveAttributeValue value, 
+      IReadOnlyArray<IParameter> parameters) 
+    {
       if (rawValueConversion == null) {
         return value.AttrValue;
       } else {
-        return rawValueConversion(value.RawValue, value.AttrValue);
+        return rawValueConversion(value.RawValue, value.AttrValue, parameters);
       }
     }
 
-    public delegate float RawValueConversion(byte[] rawValue, byte value);
+    public delegate float RawValueConversion(byte[] rawValue, byte value,
+      IReadOnlyArray<IParameter> parameters);
   }
 }