Changed the SMART AttributeID type from an enum to a struct.
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)]