Changed the SMART AttributeID type from an enum to a struct.
authormoel.mich
Sun, 17 Oct 2010 17:12:38 +0000
changeset 23130f5a06f5d8a
parent 230 9abe65430da1
child 232 475b7160e3bc
Changed the SMART AttributeID type from an enum to a struct.
Hardware/HDD/HDD.cs
Hardware/HDD/HDDGroup.cs
Hardware/HDD/SMART.cs
     1.1 --- a/Hardware/HDD/HDD.cs	Sun Oct 17 16:13:20 2010 +0000
     1.2 +++ b/Hardware/HDD/HDD.cs	Sun Oct 17 17:12:38 2010 +0000
     1.3 @@ -49,36 +49,31 @@
     1.4      private readonly int drive;
     1.5      private int count;
     1.6  
     1.7 -    private readonly SMART.AttributeID temperatureID = 0x00;    
     1.8 -    private readonly SMART.SSDLifeID lifeID = 0x00;
     1.9 +    private readonly SMART.AttributeID temperatureID = SMART.AttributeID.None;
    1.10 +    private readonly SMART.AttributeID lifeID = SMART.AttributeID.None;
    1.11  
    1.12      private readonly Sensor temperatureSensor;
    1.13      private readonly Sensor lifeSensor;
    1.14  
    1.15 -    public HDD(string name, IntPtr handle, int drive,
    1.16 -      SMART.AttributeID temperatureID, ISettings settings)
    1.17 -    {
    1.18 -      this.name = name;
    1.19 -      this.handle = handle;
    1.20 -      this.drive = drive;
    1.21 -      this.count = 0;
    1.22 -      this.temperatureID = temperatureID;
    1.23 -      this.temperatureSensor = new Sensor("HDD", 0, SensorType.Temperature,
    1.24 -        this, settings);
    1.25 -
    1.26 -      Update();
    1.27 -    }
    1.28 -
    1.29 -    public HDD(string name, IntPtr handle, int drive, SMART.SSDLifeID lifeID,
    1.30 +    public HDD(string name, IntPtr handle, int drive, 
    1.31 +      SMART.AttributeID temperatureID, SMART.AttributeID lifeID, 
    1.32        ISettings settings)
    1.33      {
    1.34        this.name = name;
    1.35        this.handle = handle;
    1.36        this.drive = drive;
    1.37        this.count = 0;
    1.38 -      this.lifeID = lifeID;
    1.39 -      this.lifeSensor = new Sensor("Remaining life", 0, SensorType.Level,
    1.40 -        this, settings);
    1.41 +      if (temperatureID != SMART.AttributeID.None) {
    1.42 +        this.temperatureID = temperatureID;
    1.43 +        this.temperatureSensor = new Sensor("HDD", 0, SensorType.Temperature,
    1.44 +          this, settings);
    1.45 +      }
    1.46 +
    1.47 +      if (lifeID != SMART.AttributeID.None) {
    1.48 +        this.lifeID = lifeID;
    1.49 +        this.lifeSensor = new Sensor("Remaining life", 0, SensorType.Level,
    1.50 +          this, settings);
    1.51 +      }
    1.52  
    1.53        Update();
    1.54      }
    1.55 @@ -108,10 +103,10 @@
    1.56  
    1.57      public ISensor[] Sensors {
    1.58        get {
    1.59 -        if (lifeID != SMART.SSDLifeID.None)
    1.60 +        if (lifeID != SMART.AttributeID.None)
    1.61            return new ISensor[] { lifeSensor };
    1.62  
    1.63 -        if (temperatureID != 0x00)
    1.64 +        if (temperatureID != SMART.AttributeID.None)
    1.65            return new ISensor[] { temperatureSensor };
    1.66  
    1.67          return new ISensor[] {};
    1.68 @@ -125,27 +120,27 @@
    1.69      public void Update() {
    1.70        if (count == 0) {
    1.71          List<SMART.DriveAttribute> attributes = SMART.ReadSmart(handle, drive);
    1.72 -        if (temperatureID != 0x00 &&
    1.73 -          attributes.Exists(attr => (int)attr.ID == (int)temperatureID))
    1.74 +        if (temperatureID != SMART.AttributeID.None &&
    1.75 +          attributes.Exists(attr => attr.ID == temperatureID))
    1.76          {
    1.77            temperatureSensor.Value = attributes
    1.78 -            .Find(attr => (int)attr.ID == (int)temperatureID)
    1.79 +            .Find(attr => attr.ID == temperatureID)
    1.80              .RawValue[0];
    1.81          }
    1.82  
    1.83 -        if (lifeID != 0x00 &&
    1.84 -          attributes.Exists(attr => (int)attr.ID == (int)lifeID))
    1.85 +        if (lifeID != SMART.AttributeID.None &&
    1.86 +          attributes.Exists(attr => attr.ID == lifeID))
    1.87          {
    1.88            lifeSensor.Value = attributes
    1.89 -            .Find(attr => (int)attr.ID == (int)lifeID)
    1.90 +            .Find(attr => attr.ID == lifeID)
    1.91              .AttrValue;
    1.92          }
    1.93        } else {
    1.94 -        if (temperatureID != 0x00) {
    1.95 +        if (temperatureID != SMART.AttributeID.None) {
    1.96            temperatureSensor.Value = temperatureSensor.Value;
    1.97          }
    1.98  
    1.99 -        if (lifeID != 0x00) {
   1.100 +        if (lifeID != SMART.AttributeID.None) {
   1.101            lifeSensor.Value = lifeSensor.Value;
   1.102          }
   1.103        }
     2.1 --- a/Hardware/HDD/HDDGroup.cs	Sun Oct 17 16:13:20 2010 +0000
     2.2 +++ b/Hardware/HDD/HDDGroup.cs	Sun Oct 17 17:12:38 2010 +0000
     2.3 @@ -76,16 +76,18 @@
     2.4            continue;
     2.5          }
     2.6  
     2.7 -        SMART.SSDLifeID ssdLifeID = GetSSDLifeID(attributes);
     2.8 -        if (ssdLifeID == SMART.SSDLifeID.None) {
     2.9 +        SMART.AttributeID ssdLifeID = GetSSDLifeID(attributes);
    2.10 +        if (ssdLifeID == SMART.AttributeID.None) {
    2.11            SMART.AttributeID temperatureID = GetTemperatureIndex(attributes);
    2.12  
    2.13 -          if (temperatureID != 0x00) {
    2.14 -            hardware.Add(new HDD(name, handle, drive, temperatureID, settings));
    2.15 +          if (temperatureID != SMART.AttributeID.None) {
    2.16 +            hardware.Add(new HDD(name, handle, drive, temperatureID, 
    2.17 +              SMART.AttributeID.None, settings));
    2.18              continue;
    2.19            }
    2.20          } else {
    2.21 -          hardware.Add(new HDD(name, handle, drive, ssdLifeID, settings));
    2.22 +          hardware.Add(new HDD(name, handle, drive, SMART.AttributeID.None, 
    2.23 +            ssdLifeID, settings));
    2.24            continue;
    2.25          }
    2.26          
    2.27 @@ -93,29 +95,28 @@
    2.28        }
    2.29      }
    2.30  
    2.31 -    private SMART.SSDLifeID GetSSDLifeID(List<SMART.DriveAttribute> attributes) {
    2.32 +    private SMART.AttributeID GetSSDLifeID(List<SMART.DriveAttribute> attributes) {
    2.33        // ID E9 is present on Intel, JM, SF and Samsung
    2.34        // ID D2 is present on Indilinx
    2.35        // Neither ID has been found on a mechanical hard drive (yet),
    2.36        // So this seems like a good way to check if it's an SSD.
    2.37 -      bool isKnownSSD = (attributes.Exists(attr => (int)attr.ID == 0xE9) ||
    2.38 -              attributes.Exists(attr => (int)attr.ID == 0xD2)
    2.39 +      bool isKnownSSD = (
    2.40 +        attributes.Exists(attr => attr.ID == new SMART.AttributeID(0xE9)) ||
    2.41 +        attributes.Exists(attr => attr.ID == new SMART.AttributeID(0xD2))
    2.42        );
    2.43  
    2.44 -      if (!isKnownSSD) return SMART.SSDLifeID.None;
    2.45 +      if (!isKnownSSD) return SMART.AttributeID.None;
    2.46  
    2.47        // We start with a traditional loop, because there are 4 unique ID's
    2.48        // that potentially identify one of the vendors
    2.49        for (int i = 0; i < attributes.Count; i++) {
    2.50  
    2.51 -        switch ((int)attributes[i].ID) {
    2.52 -          case 0xB4:
    2.53 -            return SMART.SSDLifeID.Samsung;
    2.54 -          case 0xAB:
    2.55 -            return SMART.SSDLifeID.SandForce;
    2.56 -          case 0xD2:
    2.57 -            return SMART.SSDLifeID.Indilinx;
    2.58 -        }
    2.59 +        if (attributes[i].ID == SMART.SamsungAttributes.RemainingLife)
    2.60 +          return SMART.SamsungAttributes.RemainingLife;
    2.61 +        else if (attributes[i].ID == new SMART.AttributeID(0xAB))          
    2.62 +          return  SMART.SandForceAttributes.RemainingLife;
    2.63 +        else if (attributes[i].ID == new SMART.AttributeID(0xD2))   
    2.64 +          return SMART.IndilinxAttributes.RemainingLife;        
    2.65        }
    2.66  
    2.67        // TODO: Find out JMicron's Life attribute ID; their unique ID = 0xE4
    2.68 @@ -125,25 +126,25 @@
    2.69        // is whether we can find all 3; pointless to use Exists()
    2.70        int intelRegisterCount = 0;
    2.71        foreach (SMART.DriveAttribute attribute in attributes) {
    2.72 -        if ((int)attribute.ID == 0xE1 ||
    2.73 -          (int)attribute.ID == 0xE8 ||
    2.74 -          (int)attribute.ID == 0xE9
    2.75 +        if (attribute.ID == new SMART.AttributeID(0xE1) ||
    2.76 +          attribute.ID == new SMART.AttributeID(0xE8) ||
    2.77 +          attribute.ID == new SMART.AttributeID(0xE9)
    2.78          )
    2.79            intelRegisterCount++;
    2.80        }
    2.81  
    2.82        return (intelRegisterCount == 3)
    2.83 -        ? SMART.SSDLifeID.Intel
    2.84 -        : SMART.SSDLifeID.None;
    2.85 +        ? SMART.IntelAttributes.RemainingLife
    2.86 +        : SMART.AttributeID.None;
    2.87      }
    2.88  
    2.89      private SMART.AttributeID GetTemperatureIndex(
    2.90        List<SMART.DriveAttribute> attributes)
    2.91      {
    2.92        SMART.AttributeID[] validIds = new[] {
    2.93 -        SMART.AttributeID.Temperature,
    2.94 -        SMART.AttributeID.DriveTemperature,
    2.95 -        SMART.AttributeID.AirflowTemperature
    2.96 +        SMART.CommonAttributes.Temperature,
    2.97 +        SMART.CommonAttributes.DriveTemperature,
    2.98 +        SMART.CommonAttributes.AirflowTemperature
    2.99        };
   2.100  
   2.101        foreach (SMART.AttributeID validId in validIds) {
   2.102 @@ -152,7 +153,7 @@
   2.103            return validId;
   2.104        }
   2.105  
   2.106 -      return 0x00;
   2.107 +      return SMART.AttributeID.None;
   2.108      }
   2.109  
   2.110      public IHardware[] Hardware {
   2.111 @@ -201,7 +202,7 @@
   2.112              Environment.NewLine);
   2.113  
   2.114            foreach (SMART.DriveAttribute a in attributes) {
   2.115 -            if (a.ID == 0) continue;
   2.116 +            if (a.ID == SMART.AttributeID.None) continue;
   2.117              string raw = BitConverter.ToString(a.RawValue);
   2.118              r.AppendFormat(CultureInfo.InvariantCulture, " {0}{1}{2}{3}{4}{5}",
   2.119                a.ID.ToString("d").PadRight(6), 
     3.1 --- a/Hardware/HDD/SMART.cs	Sun Oct 17 16:13:20 2010 +0000
     3.2 +++ b/Hardware/HDD/SMART.cs	Sun Oct 17 17:12:38 2010 +0000
     3.3 @@ -53,37 +53,100 @@
     3.4        SelfPreserving = 0x20
     3.5      }
     3.6  
     3.7 -    public enum AttributeID : byte {
     3.8 -      ReadErrorRate = 0x01,
     3.9 -      ThroughputPerformance = 0x02,
    3.10 -      SpinUpTime = 0x03,
    3.11 -      StartStopCount = 0x04,
    3.12 -      ReallocatedSectorsCount = 0x05,
    3.13 -      ReadChannelMargin = 0x06,
    3.14 -      SeekErrorRate = 0x07,
    3.15 -      SeekTimePerformance = 0x08,
    3.16 -      PowerOnHours = 0x09,
    3.17 -      SpinRetryCount = 0x0A,
    3.18 -      RecalibrationRetries = 0x0B,
    3.19 -      PowerCycleCount = 0x0C,
    3.20 -      SoftReadErrorRate = 0x0D,
    3.21 -      AirflowTemperature = 0xBE,
    3.22 -      Temperature = 0xC2,
    3.23 -      HardwareECCRecovered = 0xC3,
    3.24 -      ReallocationEventCount = 0xC4,
    3.25 -      CurrentPendingSectorCount = 0xC5,
    3.26 -      UncorrectableSectorCount = 0xC6,
    3.27 -      UltraDMACRCErrorCount = 0xC7,
    3.28 -      WriteErrorRate = 0xC8,
    3.29 -      DriveTemperature = 0xE7
    3.30 +    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    3.31 +    public struct AttributeID {
    3.32 +      private byte value;
    3.33 +
    3.34 +      public AttributeID(byte value) {
    3.35 +        this.value = value;
    3.36 +      }
    3.37 +
    3.38 +      public override bool Equals(Object obj) {
    3.39 +        return obj is AttributeID && this == (AttributeID)obj;
    3.40 +      }
    3.41 +      public override int GetHashCode() {
    3.42 +        return value.GetHashCode() ^ value.GetHashCode();
    3.43 +      }
    3.44 +      public static bool operator ==(AttributeID a, AttributeID b) {
    3.45 +        return a.value == b.value;
    3.46 +      }
    3.47 +      public static bool operator !=(AttributeID a, AttributeID b) {
    3.48 +        return !(a == b);
    3.49 +      }
    3.50 +
    3.51 +      public string ToString(string format) {
    3.52 +        return value.ToString(format);
    3.53 +      }
    3.54 +
    3.55 +      public static readonly AttributeID None = new AttributeID(0x00);
    3.56      }
    3.57  
    3.58 -    public enum SSDLifeID {
    3.59 -      None = 0x00,
    3.60 -      Indilinx = 0xD1,
    3.61 -      Intel = 0xE8,
    3.62 -      Samsung = 0xB4,
    3.63 -      SandForce = 0xE7
    3.64 +    // Common SMART attributes
    3.65 +    public static class CommonAttributes {      
    3.66 +      public static readonly AttributeID 
    3.67 +        ReadErrorRate = new AttributeID(0x01);
    3.68 +      public static readonly AttributeID 
    3.69 +        ThroughputPerformance = new AttributeID(0x02);
    3.70 +      public static readonly AttributeID 
    3.71 +        SpinUpTime = new AttributeID(0x03);
    3.72 +      public static readonly AttributeID 
    3.73 +        StartStopCount = new AttributeID(0x04);
    3.74 +      public static readonly AttributeID 
    3.75 +        ReallocatedSectorsCount = new AttributeID(0x05);
    3.76 +      public static readonly AttributeID 
    3.77 +        ReadChannelMargin = new AttributeID(0x06);
    3.78 +      public static readonly AttributeID 
    3.79 +        SeekErrorRate = new AttributeID(0x07);
    3.80 +      public static readonly AttributeID 
    3.81 +        SeekTimePerformance = new AttributeID(0x08);
    3.82 +      public static readonly AttributeID 
    3.83 +        PowerOnHours = new AttributeID(0x09);
    3.84 +      public static readonly AttributeID 
    3.85 +        SpinRetryCount = new AttributeID(0x0A);
    3.86 +      public static readonly AttributeID 
    3.87 +        RecalibrationRetries = new AttributeID(0x0B);
    3.88 +      public static readonly AttributeID 
    3.89 +        PowerCycleCount = new AttributeID(0x0C);
    3.90 +      public static readonly AttributeID 
    3.91 +        SoftReadErrorRate = new AttributeID(0x0D);
    3.92 +      public static readonly AttributeID 
    3.93 +        AirflowTemperature = new AttributeID(0xBE);
    3.94 +      public static readonly AttributeID 
    3.95 +        Temperature = new AttributeID(0xC2);
    3.96 +      public static readonly AttributeID 
    3.97 +        HardwareECCRecovered = new AttributeID(0xC3);
    3.98 +      public static readonly AttributeID 
    3.99 +        ReallocationEventCount = new AttributeID(0xC4);
   3.100 +      public static readonly AttributeID 
   3.101 +        CurrentPendingSectorCount = new AttributeID(0xC5);
   3.102 +      public static readonly AttributeID 
   3.103 +        UncorrectableSectorCount = new AttributeID(0xC6);
   3.104 +      public static readonly AttributeID 
   3.105 +        UltraDMACRCErrorCount = new AttributeID(0xC7);
   3.106 +      public static readonly AttributeID 
   3.107 +        WriteErrorRate = new AttributeID(0xC8);
   3.108 +      public static readonly AttributeID 
   3.109 +        DriveTemperature = new AttributeID(0xE7);
   3.110 +    }
   3.111 +
   3.112 +    // Indilinx SSD SMART attributes
   3.113 +    public static class IndilinxAttributes {      
   3.114 +      public static readonly AttributeID RemainingLife = new AttributeID(0xD1);
   3.115 +    }
   3.116 +
   3.117 +    // Intel SSD SMART attributes
   3.118 +    public static class IntelAttributes {      
   3.119 +      public static readonly AttributeID RemainingLife = new AttributeID(0xE8);
   3.120 +    }
   3.121 +
   3.122 +    // Samsung SSD SMART attributes
   3.123 +    public static class SamsungAttributes {      
   3.124 +      public static readonly AttributeID RemainingLife = new AttributeID(0xB4);
   3.125 +    }
   3.126 +
   3.127 +    // SandForce SSD SMART attributes
   3.128 +    public static class SandForceAttributes {      
   3.129 +      public static readonly AttributeID RemainingLife = new AttributeID(0xE7);
   3.130      }
   3.131  
   3.132      [StructLayout(LayoutKind.Sequential, Pack = 1)]