# HG changeset patch # User moel.mich # Date 1287335558 0 # Node ID 30f5a06f5d8a22a17e59c563ea613836d6818279 # Parent 9abe65430da11d5817c04e5fc492a7bb91b702d6 Changed the SMART AttributeID type from an enum to a struct. diff -r 9abe65430da1 -r 30f5a06f5d8a Hardware/HDD/HDD.cs --- a/Hardware/HDD/HDD.cs Sun Oct 17 16:13:20 2010 +0000 +++ b/Hardware/HDD/HDD.cs Sun Oct 17 17:12:38 2010 +0000 @@ -49,36 +49,31 @@ private readonly int drive; private int count; - private readonly SMART.AttributeID temperatureID = 0x00; - private readonly SMART.SSDLifeID lifeID = 0x00; + private readonly SMART.AttributeID temperatureID = SMART.AttributeID.None; + private readonly SMART.AttributeID lifeID = SMART.AttributeID.None; private readonly Sensor temperatureSensor; private readonly Sensor lifeSensor; - public HDD(string name, IntPtr handle, int drive, - SMART.AttributeID temperatureID, ISettings settings) - { - this.name = name; - this.handle = handle; - this.drive = drive; - this.count = 0; - this.temperatureID = temperatureID; - this.temperatureSensor = new Sensor("HDD", 0, SensorType.Temperature, - this, settings); - - Update(); - } - - public HDD(string name, IntPtr handle, int drive, SMART.SSDLifeID lifeID, + public HDD(string name, IntPtr handle, int drive, + SMART.AttributeID temperatureID, SMART.AttributeID lifeID, ISettings settings) { this.name = name; this.handle = handle; this.drive = drive; this.count = 0; - this.lifeID = lifeID; - this.lifeSensor = new Sensor("Remaining life", 0, SensorType.Level, - this, settings); + if (temperatureID != SMART.AttributeID.None) { + this.temperatureID = temperatureID; + this.temperatureSensor = new Sensor("HDD", 0, SensorType.Temperature, + this, settings); + } + + if (lifeID != SMART.AttributeID.None) { + this.lifeID = lifeID; + this.lifeSensor = new Sensor("Remaining life", 0, SensorType.Level, + this, settings); + } Update(); } @@ -108,10 +103,10 @@ public ISensor[] Sensors { get { - if (lifeID != SMART.SSDLifeID.None) + if (lifeID != SMART.AttributeID.None) return new ISensor[] { lifeSensor }; - if (temperatureID != 0x00) + if (temperatureID != SMART.AttributeID.None) return new ISensor[] { temperatureSensor }; return new ISensor[] {}; @@ -125,27 +120,27 @@ public void Update() { if (count == 0) { List attributes = SMART.ReadSmart(handle, drive); - if (temperatureID != 0x00 && - attributes.Exists(attr => (int)attr.ID == (int)temperatureID)) + if (temperatureID != SMART.AttributeID.None && + attributes.Exists(attr => attr.ID == temperatureID)) { temperatureSensor.Value = attributes - .Find(attr => (int)attr.ID == (int)temperatureID) + .Find(attr => attr.ID == temperatureID) .RawValue[0]; } - if (lifeID != 0x00 && - attributes.Exists(attr => (int)attr.ID == (int)lifeID)) + if (lifeID != SMART.AttributeID.None && + attributes.Exists(attr => attr.ID == lifeID)) { lifeSensor.Value = attributes - .Find(attr => (int)attr.ID == (int)lifeID) + .Find(attr => attr.ID == lifeID) .AttrValue; } } else { - if (temperatureID != 0x00) { + if (temperatureID != SMART.AttributeID.None) { temperatureSensor.Value = temperatureSensor.Value; } - if (lifeID != 0x00) { + if (lifeID != SMART.AttributeID.None) { lifeSensor.Value = lifeSensor.Value; } } diff -r 9abe65430da1 -r 30f5a06f5d8a Hardware/HDD/HDDGroup.cs --- a/Hardware/HDD/HDDGroup.cs Sun Oct 17 16:13:20 2010 +0000 +++ b/Hardware/HDD/HDDGroup.cs Sun Oct 17 17:12:38 2010 +0000 @@ -76,16 +76,18 @@ continue; } - SMART.SSDLifeID ssdLifeID = GetSSDLifeID(attributes); - if (ssdLifeID == SMART.SSDLifeID.None) { + SMART.AttributeID ssdLifeID = GetSSDLifeID(attributes); + if (ssdLifeID == SMART.AttributeID.None) { SMART.AttributeID temperatureID = GetTemperatureIndex(attributes); - if (temperatureID != 0x00) { - hardware.Add(new HDD(name, handle, drive, temperatureID, settings)); + if (temperatureID != SMART.AttributeID.None) { + hardware.Add(new HDD(name, handle, drive, temperatureID, + SMART.AttributeID.None, settings)); continue; } } else { - hardware.Add(new HDD(name, handle, drive, ssdLifeID, settings)); + hardware.Add(new HDD(name, handle, drive, SMART.AttributeID.None, + ssdLifeID, settings)); continue; } @@ -93,29 +95,28 @@ } } - private SMART.SSDLifeID GetSSDLifeID(List attributes) { + private SMART.AttributeID GetSSDLifeID(List attributes) { // ID E9 is present on Intel, JM, SF and Samsung // ID D2 is present on Indilinx // Neither ID has been found on a mechanical hard drive (yet), // So this seems like a good way to check if it's an SSD. - bool isKnownSSD = (attributes.Exists(attr => (int)attr.ID == 0xE9) || - attributes.Exists(attr => (int)attr.ID == 0xD2) + bool isKnownSSD = ( + attributes.Exists(attr => attr.ID == new SMART.AttributeID(0xE9)) || + attributes.Exists(attr => attr.ID == new SMART.AttributeID(0xD2)) ); - if (!isKnownSSD) return SMART.SSDLifeID.None; + if (!isKnownSSD) return SMART.AttributeID.None; // We start with a traditional loop, because there are 4 unique ID's // that potentially identify one of the vendors for (int i = 0; i < attributes.Count; i++) { - switch ((int)attributes[i].ID) { - case 0xB4: - return SMART.SSDLifeID.Samsung; - case 0xAB: - return SMART.SSDLifeID.SandForce; - case 0xD2: - return SMART.SSDLifeID.Indilinx; - } + if (attributes[i].ID == SMART.SamsungAttributes.RemainingLife) + return SMART.SamsungAttributes.RemainingLife; + else if (attributes[i].ID == new SMART.AttributeID(0xAB)) + return SMART.SandForceAttributes.RemainingLife; + else if (attributes[i].ID == new SMART.AttributeID(0xD2)) + return SMART.IndilinxAttributes.RemainingLife; } // TODO: Find out JMicron's Life attribute ID; their unique ID = 0xE4 @@ -125,25 +126,25 @@ // is whether we can find all 3; pointless to use Exists() int intelRegisterCount = 0; foreach (SMART.DriveAttribute attribute in attributes) { - if ((int)attribute.ID == 0xE1 || - (int)attribute.ID == 0xE8 || - (int)attribute.ID == 0xE9 + if (attribute.ID == new SMART.AttributeID(0xE1) || + attribute.ID == new SMART.AttributeID(0xE8) || + attribute.ID == new SMART.AttributeID(0xE9) ) intelRegisterCount++; } return (intelRegisterCount == 3) - ? SMART.SSDLifeID.Intel - : SMART.SSDLifeID.None; + ? SMART.IntelAttributes.RemainingLife + : SMART.AttributeID.None; } private SMART.AttributeID GetTemperatureIndex( List attributes) { SMART.AttributeID[] validIds = new[] { - SMART.AttributeID.Temperature, - SMART.AttributeID.DriveTemperature, - SMART.AttributeID.AirflowTemperature + SMART.CommonAttributes.Temperature, + SMART.CommonAttributes.DriveTemperature, + SMART.CommonAttributes.AirflowTemperature }; foreach (SMART.AttributeID validId in validIds) { @@ -152,7 +153,7 @@ return validId; } - return 0x00; + return SMART.AttributeID.None; } public IHardware[] Hardware { @@ -201,7 +202,7 @@ Environment.NewLine); foreach (SMART.DriveAttribute a in attributes) { - if (a.ID == 0) continue; + if (a.ID == SMART.AttributeID.None) continue; string raw = BitConverter.ToString(a.RawValue); r.AppendFormat(CultureInfo.InvariantCulture, " {0}{1}{2}{3}{4}{5}", a.ID.ToString("d").PadRight(6), diff -r 9abe65430da1 -r 30f5a06f5d8a Hardware/HDD/SMART.cs --- a/Hardware/HDD/SMART.cs Sun Oct 17 16:13:20 2010 +0000 +++ b/Hardware/HDD/SMART.cs Sun Oct 17 17:12:38 2010 +0000 @@ -53,37 +53,100 @@ SelfPreserving = 0x20 } - public enum AttributeID : byte { - ReadErrorRate = 0x01, - ThroughputPerformance = 0x02, - SpinUpTime = 0x03, - StartStopCount = 0x04, - ReallocatedSectorsCount = 0x05, - ReadChannelMargin = 0x06, - SeekErrorRate = 0x07, - SeekTimePerformance = 0x08, - PowerOnHours = 0x09, - SpinRetryCount = 0x0A, - RecalibrationRetries = 0x0B, - PowerCycleCount = 0x0C, - SoftReadErrorRate = 0x0D, - AirflowTemperature = 0xBE, - Temperature = 0xC2, - HardwareECCRecovered = 0xC3, - ReallocationEventCount = 0xC4, - CurrentPendingSectorCount = 0xC5, - UncorrectableSectorCount = 0xC6, - UltraDMACRCErrorCount = 0xC7, - WriteErrorRate = 0xC8, - DriveTemperature = 0xE7 + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct AttributeID { + private byte value; + + public AttributeID(byte value) { + this.value = value; + } + + public override bool Equals(Object obj) { + return obj is AttributeID && this == (AttributeID)obj; + } + public override int GetHashCode() { + return value.GetHashCode() ^ value.GetHashCode(); + } + public static bool operator ==(AttributeID a, AttributeID b) { + return a.value == b.value; + } + public static bool operator !=(AttributeID a, AttributeID b) { + return !(a == b); + } + + public string ToString(string format) { + return value.ToString(format); + } + + public static readonly AttributeID None = new AttributeID(0x00); } - public enum SSDLifeID { - None = 0x00, - Indilinx = 0xD1, - Intel = 0xE8, - Samsung = 0xB4, - SandForce = 0xE7 + // Common SMART attributes + public static class CommonAttributes { + public static readonly AttributeID + ReadErrorRate = new AttributeID(0x01); + public static readonly AttributeID + ThroughputPerformance = new AttributeID(0x02); + public static readonly AttributeID + SpinUpTime = new AttributeID(0x03); + public static readonly AttributeID + StartStopCount = new AttributeID(0x04); + public static readonly AttributeID + ReallocatedSectorsCount = new AttributeID(0x05); + public static readonly AttributeID + ReadChannelMargin = new AttributeID(0x06); + public static readonly AttributeID + SeekErrorRate = new AttributeID(0x07); + public static readonly AttributeID + SeekTimePerformance = new AttributeID(0x08); + public static readonly AttributeID + PowerOnHours = new AttributeID(0x09); + public static readonly AttributeID + SpinRetryCount = new AttributeID(0x0A); + public static readonly AttributeID + RecalibrationRetries = new AttributeID(0x0B); + public static readonly AttributeID + PowerCycleCount = new AttributeID(0x0C); + public static readonly AttributeID + SoftReadErrorRate = new AttributeID(0x0D); + public static readonly AttributeID + AirflowTemperature = new AttributeID(0xBE); + public static readonly AttributeID + Temperature = new AttributeID(0xC2); + public static readonly AttributeID + HardwareECCRecovered = new AttributeID(0xC3); + public static readonly AttributeID + ReallocationEventCount = new AttributeID(0xC4); + public static readonly AttributeID + CurrentPendingSectorCount = new AttributeID(0xC5); + public static readonly AttributeID + UncorrectableSectorCount = new AttributeID(0xC6); + public static readonly AttributeID + UltraDMACRCErrorCount = new AttributeID(0xC7); + public static readonly AttributeID + WriteErrorRate = new AttributeID(0xC8); + public static readonly AttributeID + DriveTemperature = new AttributeID(0xE7); + } + + // Indilinx SSD SMART attributes + public static class IndilinxAttributes { + public static readonly AttributeID RemainingLife = new AttributeID(0xD1); + } + + // Intel SSD SMART attributes + public static class IntelAttributes { + public static readonly AttributeID RemainingLife = new AttributeID(0xE8); + } + + // Samsung SSD SMART attributes + public static class SamsungAttributes { + public static readonly AttributeID RemainingLife = new AttributeID(0xB4); + } + + // SandForce SSD SMART attributes + public static class SandForceAttributes { + public static readonly AttributeID RemainingLife = new AttributeID(0xE7); } [StructLayout(LayoutKind.Sequential, Pack = 1)]