diff --git a/Collections/Pair.cs b/Collections/Pair.cs new file mode 100644 index 0000000..e070587 --- /dev/null +++ b/Collections/Pair.cs @@ -0,0 +1,67 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; + +namespace OpenHardwareMonitor.Collections { + + public struct Pair { + private F first; + private S second; + + public Pair(F first, S second) { + this.first = first; + this.second = second; + } + + public F First { + get { return first; } + set { first = value; } + } + + public S Second { + get { return second; } + set { second = value; } + } + + public override int GetHashCode() { + return (first != null ? first.GetHashCode() : 0) ^ + (second != null ? second.GetHashCode() : 0); + } + } +} diff --git a/GUI/HardwareNode.cs b/GUI/HardwareNode.cs index aa7959f..eedf0cd 100644 --- a/GUI/HardwareNode.cs +++ b/GUI/HardwareNode.cs @@ -66,6 +66,7 @@ namespace OpenHardwareMonitor.GUI { typeNodes.Add(new TypeNode(SensorType.Control)); typeNodes.Add(new TypeNode(SensorType.Level)); typeNodes.Add(new TypeNode(SensorType.Power)); + typeNodes.Add(new TypeNode(SensorType.Data)); foreach (ISensor sensor in hardware.Sensors) SensorAdded(sensor); diff --git a/GUI/SensorGadget.cs b/GUI/SensorGadget.cs index 64a1812..889f204 100644 --- a/GUI/SensorGadget.cs +++ b/GUI/SensorGadget.cs @@ -518,6 +518,9 @@ namespace OpenHardwareMonitor.GUI { case SensorType.Power: format = "{0:F1} W"; break; + case SensorType.Data: + format = "{0:F1} GB"; + break; } if (sensor.SensorType == SensorType.Temperature && diff --git a/GUI/SensorNode.cs b/GUI/SensorNode.cs index b0a6ce1..7f75a4e 100644 --- a/GUI/SensorNode.cs +++ b/GUI/SensorNode.cs @@ -76,6 +76,7 @@ namespace OpenHardwareMonitor.GUI { case SensorType.Control: format = "{0:F1} %"; break; case SensorType.Level: format = "{0:F1} %"; break; case SensorType.Power: format = "{0:F1} W"; break; + case SensorType.Data: format = "{0:F1} GB"; break; } bool hidden = settings.GetValue(new Identifier(sensor.Identifier, diff --git a/GUI/SensorNotifyIcon.cs b/GUI/SensorNotifyIcon.cs index 7c75804..7d8b8be 100644 --- a/GUI/SensorNotifyIcon.cs +++ b/GUI/SensorNotifyIcon.cs @@ -198,6 +198,8 @@ namespace OpenHardwareMonitor.GUI { return string.Format("{0:F0}", sensor.Value); case SensorType.Power: return string.Format("{0:F0}", sensor.Value); + case SensorType.Data: + return string.Format("{0:F0}", sensor.Value); } return "-"; } @@ -286,6 +288,7 @@ namespace OpenHardwareMonitor.GUI { case SensorType.Control: format = "\n{0}: {1:F1} %"; break; case SensorType.Level: format = "\n{0}: {1:F1} %"; break; case SensorType.Power: format = "\n{0}: {1:F0} W"; break; + case SensorType.Data: format = "\n{0}: {1:F0} GB"; break; } string formattedValue = string.Format(format, sensor.Name, sensor.Value); string hardwareName = sensor.Hardware.Name; diff --git a/GUI/TypeNode.cs b/GUI/TypeNode.cs index 027ac6e..2fe57ff 100644 --- a/GUI/TypeNode.cs +++ b/GUI/TypeNode.cs @@ -84,6 +84,10 @@ namespace OpenHardwareMonitor.GUI { this.Image = Utilities.EmbeddedResources.GetImage("power.png"); this.Text = "Powers"; break; + case SensorType.Data: + this.Image = Utilities.EmbeddedResources.GetImage("data.png"); + this.Text = "Data"; + break; } NodeAdded += new NodeEventHandler(TypeNode_NodeAdded); diff --git a/Hardware/Computer.cs b/Hardware/Computer.cs index e14b803..407e6d5 100644 --- a/Hardware/Computer.cs +++ b/Hardware/Computer.cs @@ -16,7 +16,7 @@ The Initial Developer of the Original Code is Michael Möller . - Portions created by the Initial Developer are Copyright (C) 2009-2010 + Portions created by the Initial Developer are Copyright (C) 2009-2011 the Initial Developer. All Rights Reserved. Contributor(s): @@ -98,7 +98,7 @@ namespace OpenHardwareMonitor.Hardware { Add(new Heatmaster.HeatmasterGroup(settings)); if (hddEnabled) - Add(new HDD.HDDGroup(settings)); + Add(new HDD.HarddriveGroup(settings)); open = true; } @@ -109,11 +109,11 @@ namespace OpenHardwareMonitor.Hardware { [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] set { if (open && value && !hddEnabled) { - Add(new HDD.HDDGroup(settings)); + Add(new HDD.HarddriveGroup(settings)); } else if (open && !value && hddEnabled) { List list = new List(); foreach (IGroup group in groups) - if (group is HDD.HDDGroup) + if (group is HDD.HarddriveGroup) list.Add(group); foreach (IGroup group in list) Remove(group); diff --git a/Hardware/HDD/AbstractHarddrive.cs b/Hardware/HDD/AbstractHarddrive.cs new file mode 100644 index 0000000..4236b4f --- /dev/null +++ b/Hardware/HDD/AbstractHarddrive.cs @@ -0,0 +1,294 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2009-2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Paul Werelds + Roland Reinl + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using OpenHardwareMonitor.Collections; + +namespace OpenHardwareMonitor.Hardware.HDD { + internal abstract class AbstractHarddrive : Hardware { + + private const int UPDATE_DIVIDER = 30; // update only every 30s + + // array of all harddrive types, matching type is searched in this order + private static Type[] hddTypes = { + typeof(SSDPlextor), + typeof(SSDIntel), + typeof(SSDSandforce), + typeof(SSDIndilinx), + typeof(GenericHarddisk) + }; + + private readonly ISmart smart; + + private readonly IntPtr handle; + private readonly int index; + private int count; + + private IList smartAttributes; + private IDictionary sensors; + + protected AbstractHarddrive(ISmart smart, string name, int index, + IEnumerable smartAttributes, ISettings settings) + : base(name, new Identifier("hdd", + index.ToString(CultureInfo.InvariantCulture)), settings) + { + this.smart = smart; + handle = smart.OpenDrive(index); + + smart.EnableSmart(handle, index); + + this.index = index; + this.count = 0; + + this.smartAttributes = new List(smartAttributes); + + CreateSensors(); + } + + public static AbstractHarddrive CreateInstance(ISmart smart, + int driveIndex, ISettings settings) + { + IntPtr deviceHandle = smart.OpenDrive(driveIndex); + + if (deviceHandle == smart.InvalidHandle) + return null; + + string name = smart.ReadName(deviceHandle, driveIndex); + bool smartEnabled = smart.EnableSmart(deviceHandle, driveIndex); + + DriveAttributeValue[] values = {}; + if (smartEnabled) + values = smart.ReadSmartData(deviceHandle, driveIndex); + + smart.CloseHandle(deviceHandle); + + if (string.IsNullOrEmpty(name)) + return null; + + foreach (Type type in hddTypes) { + // get the array of name prefixes for the current type + NamePrefixAttribute[] namePrefixes = type.GetCustomAttributes( + typeof(NamePrefixAttribute), true) as NamePrefixAttribute[]; + + // get the array of the required SMART attributes for the current type + RequireSmartAttribute[] requiredAttributes = type.GetCustomAttributes( + typeof(RequireSmartAttribute), true) as RequireSmartAttribute[]; + + // check if all required attributes are present + bool allRequiredAttributesFound = true; + foreach (var requireAttribute in requiredAttributes) { + bool adttributeFound = false; + foreach (DriveAttributeValue value in values) { + if (value.Identifier == requireAttribute.AttributeId) { + adttributeFound = true; + break; + } + } + if (!adttributeFound) { + allRequiredAttributesFound = false; + break; + } + } + + // if an attribute is missing, then try the next type + if (!allRequiredAttributesFound) + continue; + + // check if there is a matching name prefix for this type + foreach (NamePrefixAttribute prefix in namePrefixes) { + if (name.StartsWith(prefix.Prefix, StringComparison.InvariantCulture)) + return Activator.CreateInstance(type, smart, name, driveIndex, + settings) as AbstractHarddrive; + } + } + + // no matching type has been found + return null; + } + + private void CreateSensors() { + sensors = new Dictionary(); + + IList> sensorTypeAndChannels = + new List>(); + + DriveAttributeValue[] values = smart.ReadSmartData(handle, index); + + foreach (SmartAttribute attribute in smartAttributes) { + if (!attribute.SensorType.HasValue) + continue; + + bool found = false; + foreach (DriveAttributeValue value in values) { + if (value.Identifier == attribute.Identifier) { + found = true; + break; + } + } + if (!found) + continue; + + Pair pair = new Pair( + attribute.SensorType.Value, attribute.SensorChannel); + + if (!sensorTypeAndChannels.Contains(pair)) { + Sensor sensor = new Sensor(attribute.Name, + attribute.SensorChannel, attribute.SensorType.Value, this, + settings); + + sensors.Add(attribute, sensor); + sensorTypeAndChannels.Add(pair); + } + } + } + + public override HardwareType HardwareType { + get { return HardwareType.HDD; } + } + + public override ISensor[] Sensors { + get { + Sensor[] array = new Sensor[sensors.Count]; + sensors.Values.CopyTo(array, 0); + return array; + } + } + + public override void Update() { + if (count == 0) { + DriveAttributeValue[] values = smart.ReadSmartData(handle, index); + + foreach (KeyValuePair keyValuePair in sensors) { + SmartAttribute attribute = keyValuePair.Key; + foreach (DriveAttributeValue value in values) { + if (value.Identifier == attribute.Identifier) { + Sensor sensor = keyValuePair.Value; + sensor.Value = attribute.ConvertValue(value); + } + } + } + } + + count++; + count %= UPDATE_DIVIDER; + } + + public override string GetReport() { + StringBuilder r = new StringBuilder(); + DriveAttributeValue[] values = smart.ReadSmartData(handle, index); + DriveThresholdValue[] thresholds = + smart.ReadSmartThresholds(handle, index); + + if (values.Length > 0) { + r.AppendLine(this.GetType().Name); + r.AppendLine(); + r.AppendLine("Drive name: " + name); + r.AppendLine(); + r.AppendFormat(CultureInfo.InvariantCulture, + " {0}{1}{2}{3}{4}{5}{6}{7}", + ("ID").PadRight(3), + ("Description").PadRight(32), + ("Raw Value").PadRight(13), + ("Worst").PadRight(6), + ("Value").PadRight(6), + ("Thres").PadRight(6), + ("Physical").PadRight(8), + Environment.NewLine); + + foreach (DriveAttributeValue value in values) { + if (value.Identifier == 0x00) + break; + + byte? threshold = null; + foreach (DriveThresholdValue t in thresholds) { + if (t.Identifier == value.Identifier) { + threshold = t.Threshold; + } + } + + string description = "Unknown"; + float? physical = null; + foreach (SmartAttribute a in smartAttributes) { + if (a.Identifier == value.Identifier) { + description = a.Name; + if (a.HasRawValueConversion | a.SensorType.HasValue) + physical = a.ConvertValue(value); + else + physical = null; + } + } + + string raw = BitConverter.ToString(value.RawValue); + r.AppendFormat(CultureInfo.InvariantCulture, + " {0}{1}{2}{3}{4}{5}{6}{7}", + value.Identifier.ToString("X2").PadRight(3), + description.PadRight(32), + raw.Replace("-", "").PadRight(13), + value.WorstValue.ToString(CultureInfo.InvariantCulture).PadRight(6), + value.AttrValue.ToString(CultureInfo.InvariantCulture).PadRight(6), + (threshold.HasValue ? threshold.Value.ToString( + CultureInfo.InvariantCulture) : "-").PadRight(6), + (physical.HasValue ? physical.Value.ToString( + CultureInfo.InvariantCulture) : "-").PadRight(8), + Environment.NewLine); + } + r.AppendLine(); + } + + return r.ToString(); + } + + protected static float RawToInt(byte[] raw, byte value) { + return (raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]; + } + + public override void Close() { + smart.CloseHandle(handle); + base.Close(); + } + + public override void Traverse(IVisitor visitor) { + foreach (ISensor sensor in Sensors) + sensor.Accept(visitor); + } + } +} diff --git a/Hardware/HDD/DebugSmart.cs b/Hardware/HDD/DebugSmart.cs new file mode 100644 index 0000000..f114d00 --- /dev/null +++ b/Hardware/HDD/DebugSmart.cs @@ -0,0 +1,287 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenHardwareMonitor.Hardware.HDD { + +#if DEBUG + + internal class DebugSmart : ISmart { + + private Drive[] drives = { + new Drive("KINGSTON SNV425S264GB", 16, + @" 01 000000000000 100 100 + 02 000000000000 100 100 + 03 000000000000 100 100 + 05 000000000000 100 100 + 07 000000000000 100 100 + 08 000000000000 100 100 + 09 821E00000000 100 100 + 0A 000000000000 100 100 + 0C 950200000000 100 100 + A8 000000000000 100 100 + AF 000000000000 100 100 + C0 000000000000 100 100 + C2 290014002B00 100 41 + C5 000000000000 100 100 + F0 000000000000 100 100 + AA 07007B000000 100 100 + AD 0E1E71304919 100 100"), + + new Drive("PLEXTOR PX-128M2S", 16, + @" 01 000000000000 100 100 0 + 03 000000000000 100 100 0 + 04 000000000000 100 100 0 + 05 000000000000 100 100 0 + 09 250100000000 100 100 0 + 0A 000000000000 100 100 0 + 0C D10000000000 100 100 0 + B2 000000000000 100 100 0 + BB 000000000000 100 100 0 + BE 000000000000 100 100 0 + C0 000000000000 100 100 0 + C1 000000000000 100 100 0 + C2 000000000000 100 100 0 + C3 000000000000 100 100 0 + C5 000000000000 100 100 0 + C6 000000000000 100 100 0 + C7 000000000000 100 100 0"), + + new Drive("OCZ-VERTEX2", 16, + @" 01 DADAD5000000 100 106 50 + 05 000000000000 100 100 3 + 09 DF0900004A2F 100 100 0 + 0C FC0100000000 100 100 0 + AB 000000000000 0 0 0 + AC 000000000000 0 0 0 + AE 1F0000000000 0 0 0 + B1 000000000000 0 0 0 + B5 000000000000 0 0 0 + B6 000000000000 0 0 0 + BB 000000000000 100 100 0 + C2 010081007F00 129 1 0 + C3 DADAD5000000 100 106 0 + C4 000000000000 100 100 0 + E7 000000000000 100 100 10 + E9 800400000000 0 0 0 + EA 000600000000 0 0 0 + F1 000600000000 0 0 0 + F2 801200000000 0 0 0"), + + new Drive("WDC WD5000AADS-00S9B0", 10, + @" 1 000000000000 200 200 + 3 820D00000000 149 150 + 4 610800000000 98 98 + 5 000000000000 200 200 + 7 000000000000 253 100 + 9 0F1F00000000 90 90 + 10 000000000000 100 100 + 11 000000000000 100 100 + 12 880200000000 100 100 + 192 6B0000000000 200 200 + 193 E9CB03000000 118 118 + 194 280000000000 94 103 + 196 000000000000 200 200 + 197 000000000000 200 200 + 198 000000000000 200 200 + 199 000000000000 200 200 + 200 000000000000 200 200 + 130 7B0300010002 1 41 + 5 000000000000 0 0 + 1 000000000000 0 0"), + + new Drive("INTEL SSDSA2M080G2GC", 10, + @" 3 000000000000 100 100 + 4 000000000000 100 100 + 5 010000000000 100 100 + 9 B10B00000000 100 100 + 12 DD0300000000 100 100 + 192 480000000000 100 100 + 225 89DB00000000 200 200 + 226 3D1B00000000 100 100 + 227 030000000000 100 100 + 228 7F85703C0000 100 100 + 232 000000000000 99 99 + 233 000000000000 98 98 + 184 000000000000 100 100 + 1 000000000000 0 0"), + + new Drive("OCZ-VERTEX", 10, + @" 1 000000000000 0 8 + 9 000000000000 30 99 + 12 000000000000 0 15 + 184 000000000000 0 7 + 195 000000000000 0 0 + 196 000000000000 0 2 + 197 000000000000 0 0 + 198 B9ED00000000 214 176 + 199 352701000000 143 185 + 200 B10500000000 105 55 + 201 F40A00000000 238 194 + 202 020000000000 137 35 + 203 020000000000 125 63 + 204 000000000000 0 0 + 205 000000000000 19 136 + 206 000000000000 22 54 + 207 010000000000 113 226 + 208 000000000000 49 232 + 209 000000000000 0 98 + 211 000000000000 0 0 + 212 000000000000 0 0 + 213 000000000000 0 0"), + + new Drive("INTEL SSDSA2CW120G3", 16, + @"03 000000000000 100 100 0 + 04 000000000000 100 100 0 + 05 000000000000 100 100 0 + 09 830200000000 100 100 0 + 0C 900100000000 100 100 0 + AA 000000000000 100 100 0 + AB 000000000000 100 100 0 + AC 000000000000 100 100 0 + B8 000000000000 100 100 0 + BB 000000000000 100 100 0 + C0 040000000000 100 100 0 + E1 FF4300000000 100 100 0 + E2 E57D14000000 100 100 0 + E3 000000000000 100 100 0 + E4 E39600000000 100 100 0 + E8 000000000000 100 100 0 + E9 000000000000 100 100 0 + F1 FF4300000000 100 100 0 + F2 264F00000000 100 100 0") + }; + + public IntPtr OpenDrive(int driveNumber) { + if (driveNumber < drives.Length) + return (IntPtr)driveNumber; + else + return InvalidHandle; + } + + public bool EnableSmart(IntPtr handle, int driveNumber) { + if (handle != (IntPtr)driveNumber) + throw new ArgumentOutOfRangeException(); + + return true; + } + + public DriveAttributeValue[] ReadSmartData(IntPtr handle, int driveNumber) { + if (handle != (IntPtr)driveNumber) + throw new ArgumentOutOfRangeException(); + + return drives[driveNumber].DriveAttributeValues; + } + + public DriveThresholdValue[] ReadSmartThresholds(IntPtr handle, + int driveNumber) + { + if (handle != (IntPtr)driveNumber) + throw new ArgumentOutOfRangeException(); + + return drives[driveNumber].DriveThresholdValues; + } + + public string ReadName(IntPtr handle, int driveNumber) { + if (handle != (IntPtr)driveNumber) + throw new ArgumentOutOfRangeException(); + + return drives[driveNumber].Name; + } + + public void CloseHandle(IntPtr handle) { } + + + private class Drive { + + public Drive(string name, int idBase, string value) { + this.Name = name; + + string[] lines = value.Split(new[] { '\r', '\n' }, + StringSplitOptions.RemoveEmptyEntries); + + DriveAttributeValues = new DriveAttributeValue[lines.Length]; + List thresholds = new List(); + + for (int i = 0; i < lines.Length; i++) { + + string[] array = lines[i].Split(new[] { ' ' }, + StringSplitOptions.RemoveEmptyEntries); + + if (array.Length != 4 && array.Length != 5) + throw new Exception(); + + DriveAttributeValue v = new DriveAttributeValue(); + v.Identifier = Convert.ToByte(array[0], idBase); + + v.RawValue = new byte[6]; + for (int j = 0; j < 6; j++) { + v.RawValue[j] = Convert.ToByte(array[1].Substring(2 * j, 2), 16); + } + + v.WorstValue = Convert.ToByte(array[2], 10); + v.AttrValue = Convert.ToByte(array[3], 10); + + DriveAttributeValues[i] = v; + + if (array.Length == 5) { + DriveThresholdValue t = new DriveThresholdValue(); + t.Identifier = v.Identifier; + t.Threshold = Convert.ToByte(array[4], 10); + thresholds.Add(t); + } + } + + DriveThresholdValues = thresholds.ToArray(); + } + + public DriveAttributeValue[] DriveAttributeValues { get; private set; } + + public DriveThresholdValue[] DriveThresholdValues { get; private set; } + + public string Name { get; private set; } + } + + public IntPtr InvalidHandle { get { return (IntPtr)(-1); } } + } + +#endif + +} diff --git a/Hardware/HDD/DriveAttributeValue.cs b/Hardware/HDD/DriveAttributeValue.cs new file mode 100644 index 0000000..3c200e1 --- /dev/null +++ b/Hardware/HDD/DriveAttributeValue.cs @@ -0,0 +1,55 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace OpenHardwareMonitor.Hardware.HDD { + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct DriveAttributeValue { + public byte Identifier; + public short StatusFlags; + public byte AttrValue; + public byte WorstValue; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] RawValue; + public byte Reserved; + } + +} diff --git a/Hardware/HDD/DriveThresholdValue.cs b/Hardware/HDD/DriveThresholdValue.cs new file mode 100644 index 0000000..c2992d7 --- /dev/null +++ b/Hardware/HDD/DriveThresholdValue.cs @@ -0,0 +1,51 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +namespace OpenHardwareMonitor.Hardware.HDD { + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct DriveThresholdValue { + public byte Identifier; + public byte Threshold; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public byte[] Unknown; + } + +} diff --git a/Hardware/HDD/HDD.cs b/Hardware/HDD/HDD.cs deleted file mode 100644 index 7e53e4f..0000000 --- a/Hardware/HDD/HDD.cs +++ /dev/null @@ -1,136 +0,0 @@ -/* - - Version: MPL 1.1/GPL 2.0/LGPL 2.1 - - The contents of this file are subject to the Mozilla Public License Version - 1.1 (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - for the specific language governing rights and limitations under the License. - - The Original Code is the Open Hardware Monitor code. - - The Initial Developer of the Original Code is - Michael Möller . - Portions created by the Initial Developer are Copyright (C) 2009-2011 - the Initial Developer. All Rights Reserved. - - Contributor(s): Paul Werelds - - Alternatively, the contents of this file may be used under the terms of - either the GNU General Public License Version 2 or later (the "GPL"), or - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - in which case the provisions of the GPL or the LGPL are applicable instead - of those above. If you wish to allow use of your version of this file only - under the terms of either the GPL or the LGPL, and not to allow others to - use your version of this file under the terms of the MPL, indicate your - decision by deleting the provisions above and replace them with the notice - and other provisions required by the GPL or the LGPL. If you do not delete - the provisions above, a recipient may use your version of this file under - the terms of any one of the MPL, the GPL or the LGPL. - -*/ - -using System; -using System.Collections.Generic; -using System.Globalization; - -namespace OpenHardwareMonitor.Hardware.HDD { - internal class HDD : Hardware { - - private const int UPDATE_DIVIDER = 30; // update only every 30s - - private readonly IntPtr handle; - private readonly int drive; - private int count; - - 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, SMART.AttributeID lifeID, - ISettings settings) : base(name, new Identifier("hdd", - drive.ToString(CultureInfo.InvariantCulture)), settings) - { - this.handle = handle; - this.drive = drive; - this.count = 0; - 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(); - } - - public override HardwareType HardwareType { - get { return HardwareType.HDD; } - } - - public override ISensor[] Sensors { - get { - if (lifeID != SMART.AttributeID.None) - return new ISensor[] { lifeSensor }; - - if (temperatureID != SMART.AttributeID.None) - return new ISensor[] { temperatureSensor }; - - return new ISensor[] {}; - } - } - - public override void Update() { - if (count == 0) { - SMART.DriveAttribute[] attributes = SMART.ReadSmart(handle, drive); - - if (temperatureID != SMART.AttributeID.None && - Array.Exists(attributes, attr => attr.ID == temperatureID)) - { - temperatureSensor.Value = Array - .Find(attributes, attr => attr.ID == temperatureID) - .RawValue[0]; - } - - if (lifeID != SMART.AttributeID.None && - Array.Exists(attributes, attr => attr.ID == lifeID)) - { - lifeSensor.Value = Array - .Find(attributes, attr => attr.ID == lifeID) - .AttrValue; - } - } else { - if (temperatureID != SMART.AttributeID.None) - temperatureSensor.Value = temperatureSensor.Value; - - if (lifeID != SMART.AttributeID.None) - lifeSensor.Value = lifeSensor.Value; - } - - count++; count %= UPDATE_DIVIDER; - } - - public override void Close() { - SMART.CloseHandle(handle); - base.Close(); - } - - public override void Traverse(IVisitor visitor) { - foreach (ISensor sensor in Sensors) - sensor.Accept(visitor); - } - } -} diff --git a/Hardware/HDD/HDDGeneric.cs b/Hardware/HDD/HDDGeneric.cs new file mode 100644 index 0000000..52f78a2 --- /dev/null +++ b/Hardware/HDD/HDDGeneric.cs @@ -0,0 +1,123 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Roland Reinl . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Paul Werelds + Michael Möller + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenHardwareMonitor.Hardware.HDD { + + [NamePrefix("")] + internal class GenericHarddisk : AbstractHarddrive { + + private static readonly List smartAttributes = + new List { + new SmartAttribute(0x01, SmartAttributeNames.ReadErrorRate), + new SmartAttribute(0x02, SmartAttributeNames.ThroughputPerformance), + new SmartAttribute(0x03, SmartAttributeNames.SpinUpTime), + new SmartAttribute(0x04, SmartAttributeNames.StartStopCount, RawToInt), + new SmartAttribute(0x05, SmartAttributeNames.ReallocatedSectorsCount), + new SmartAttribute(0x06, SmartAttributeNames.ReadChannelMargin), + new SmartAttribute(0x07, SmartAttributeNames.SeekErrorRate), + new SmartAttribute(0x08, SmartAttributeNames.SeekTimePerformance), + new SmartAttribute(0x09, SmartAttributeNames.PowerOnHours, RawToInt), + new SmartAttribute(0x0A, SmartAttributeNames.SpinRetryCount), + new SmartAttribute(0x0B, SmartAttributeNames.RecalibrationRetries), + new SmartAttribute(0x0C, SmartAttributeNames.PowerCycleCount, RawToInt), + new SmartAttribute(0x0D, SmartAttributeNames.SoftReadErrorRate), + new SmartAttribute(0xAA, SmartAttributeNames.Unknown), + new SmartAttribute(0xAB, SmartAttributeNames.Unknown), + new SmartAttribute(0xAC, SmartAttributeNames.Unknown), + new SmartAttribute(0xB7, SmartAttributeNames.SataDownshiftErrorCount), + new SmartAttribute(0xB8, SmartAttributeNames.EndToEndError), + new SmartAttribute(0xB9, SmartAttributeNames.HeadStability), + new SmartAttribute(0xBA, SmartAttributeNames.InducedOpVibrationDetection), + new SmartAttribute(0xBB, SmartAttributeNames.ReportedUncorrectableErrors), + new SmartAttribute(0xBC, SmartAttributeNames.CommandTimeout), + new SmartAttribute(0xBD, SmartAttributeNames.HighFlyWrites), + new SmartAttribute(0xBF, SmartAttributeNames.GSenseErrorRate), + new SmartAttribute(0xC0, SmartAttributeNames.EmergencyRetractCycleCount), + new SmartAttribute(0xC1, SmartAttributeNames.LoadCycleCount), + new SmartAttribute(0xC3, SmartAttributeNames.HardwareEccRecovered), + new SmartAttribute(0xC4, SmartAttributeNames.ReallocationEventCount), + new SmartAttribute(0xC5, SmartAttributeNames.CurrentPendingSectorCount), + new SmartAttribute(0xC6, SmartAttributeNames.UncorrectableSectorCount), + new SmartAttribute(0xC7, SmartAttributeNames.UltraDmaCrcErrorCount), + new SmartAttribute(0xC8, SmartAttributeNames.WriteErrorRate), + new SmartAttribute(0xCA, SmartAttributeNames.DataAddressMarkErrors), + new SmartAttribute(0xCB, SmartAttributeNames.RunOutCancel), + new SmartAttribute(0xCC, SmartAttributeNames.SoftEccCorrection), + new SmartAttribute(0xCD, SmartAttributeNames.ThermalAsperityRate), + new SmartAttribute(0xCE, SmartAttributeNames.FlyingHeight), + new SmartAttribute(0xCF, SmartAttributeNames.SpinHighCurrent), + new SmartAttribute(0xD0, SmartAttributeNames.SpinBuzz), + new SmartAttribute(0xD1, SmartAttributeNames.OfflineSeekPerformance), + new SmartAttribute(0xD3, SmartAttributeNames.VibrationDuringWrite), + new SmartAttribute(0xD4, SmartAttributeNames.ShockDuringWrite), + new SmartAttribute(0xDC, SmartAttributeNames.DiskShift), + new SmartAttribute(0xDD, SmartAttributeNames.AlternativeGSenseErrorRate), + new SmartAttribute(0xDE, SmartAttributeNames.LoadedHours), + new SmartAttribute(0xDF, SmartAttributeNames.LoadUnloadRetryCount), + new SmartAttribute(0xE0, SmartAttributeNames.LoadFriction), + new SmartAttribute(0xE1, SmartAttributeNames.LoadUnloadCycleCount), + new SmartAttribute(0xE2, SmartAttributeNames.LoadInTime), + new SmartAttribute(0xE3, SmartAttributeNames.TorqueAmplificationCount), + new SmartAttribute(0xE4, SmartAttributeNames.PowerOffRetractCycle), + new SmartAttribute(0xE6, SmartAttributeNames.GmrHeadAmplitude), + new SmartAttribute(0xE8, SmartAttributeNames.EnduranceRemaining), + new SmartAttribute(0xE9, SmartAttributeNames.PowerOnHours), + new SmartAttribute(0xF0, SmartAttributeNames.HeadFlyingHours), + new SmartAttribute(0xF1, SmartAttributeNames.TotalLbasWritten), + new SmartAttribute(0xF2, SmartAttributeNames.TotalLbasRead), + new SmartAttribute(0xFA, SmartAttributeNames.ReadErrorRetryRate), + new SmartAttribute(0xFE, SmartAttributeNames.FreeFallProtection), + + new SmartAttribute(0xC2, SmartAttributeNames.Temperature, + (byte[] r, byte v) => { return r[0]; }, SensorType.Temperature, 0), + new SmartAttribute(0xE7, SmartAttributeNames.Temperature, + (byte[] r, byte v) => { return r[0]; }, SensorType.Temperature, 0), + new SmartAttribute(0xBE, SmartAttributeNames.TemperatureDifferenceFrom100, + null, SensorType.Temperature, 0) + }; + + public GenericHarddisk(ISmart smart, string name, int index, + ISettings settings) + : base(smart, name, index, smartAttributes, settings) { } + } +} diff --git a/Hardware/HDD/HDDGroup.cs b/Hardware/HDD/HDDGroup.cs deleted file mode 100644 index 46b9eac..0000000 --- a/Hardware/HDD/HDDGroup.cs +++ /dev/null @@ -1,227 +0,0 @@ -/* - - Version: MPL 1.1/GPL 2.0/LGPL 2.1 - - The contents of this file are subject to the Mozilla Public License Version - 1.1 (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - for the specific language governing rights and limitations under the License. - - The Original Code is the Open Hardware Monitor code. - - The Initial Developer of the Original Code is - Michael Möller . - Portions created by the Initial Developer are Copyright (C) 2009-2010 - the Initial Developer. All Rights Reserved. - - Contributor(s): Paul Werelds - - Alternatively, the contents of this file may be used under the terms of - either the GNU General Public License Version 2 or later (the "GPL"), or - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - in which case the provisions of the GPL or the LGPL are applicable instead - of those above. If you wish to allow use of your version of this file only - under the terms of either the GPL or the LGPL, and not to allow others to - use your version of this file under the terms of the MPL, indicate your - decision by deleting the provisions above and replace them with the notice - and other provisions required by the GPL or the LGPL. If you do not delete - the provisions above, a recipient may use your version of this file under - the terms of any one of the MPL, the GPL or the LGPL. - -*/ - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text; - -namespace OpenHardwareMonitor.Hardware.HDD { - internal class HDDGroup : IGroup { - - private const int MAX_DRIVES = 32; - - private readonly List hardware = new List(); - - public HDDGroup(ISettings settings) { - int p = (int)Environment.OSVersion.Platform; - if (p == 4 || p == 128) return; - - for (int drive = 0; drive < MAX_DRIVES; drive++) { - IntPtr handle = SMART.OpenPhysicalDrive(drive); - - if (handle == SMART.INVALID_HANDLE_VALUE) - continue; - - if (!SMART.EnableSmart(handle, drive)) { - SMART.CloseHandle(handle); - continue; - } - - string name = SMART.ReadName(handle, drive); - if (name == null) { - SMART.CloseHandle(handle); - continue; - } - - SMART.DriveAttribute[] attributes = SMART.ReadSmart(handle, drive); - - if (attributes.Length < 1) { - SMART.CloseHandle(handle); - continue; - } - - SMART.AttributeID ssdLifeID = GetSSDLifeID(attributes); - if (ssdLifeID == SMART.AttributeID.None) { - SMART.AttributeID temperatureID = GetTemperatureIndex(attributes); - - 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, SMART.AttributeID.None, - ssdLifeID, settings)); - continue; - } - - SMART.CloseHandle(handle); - } - } - - private SMART.AttributeID GetSSDLifeID(SMART.DriveAttribute[] attributes) { - // ID E9 is present on Intel, JM, SF and Samsung (different meanings) - // 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 = ( - Array.Exists(attributes, attr => attr.ID == new SMART.AttributeID(0xE9)) || - Array.Exists(attributes, attr => attr.ID == new SMART.AttributeID(0xD2)) - ); - - 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.Length; i++) { - if (attributes[i].ID == SMART.SamsungAttributes.RemainingLife) - return SMART.SamsungAttributes.RemainingLife; - - if (attributes[i].ID == SMART.SandForceAttributes.ProgramFailCount) - return SMART.SandForceAttributes.RemainingLife; - - if (attributes[i].ID == SMART.IndilinxAttributes.UnknownUnique) - return SMART.IndilinxAttributes.RemainingLife; - } - - // TODO: Find out JMicron's Life attribute ID; their unique ID = 0xE4 - - // For Intel, we make sure we have their 3 most important ID's - // We do a traditional loop again, because we all we need to know - // is whether we can find all 3; pointless to use Exists() - int intelRegisterCount = 0; - foreach (SMART.DriveAttribute attribute in attributes) { - if (attribute.ID == SMART.IntelAttributes.HostWrites || - attribute.ID == SMART.IntelAttributes.RemainingLife || - attribute.ID == SMART.IntelAttributes.MediaWearOutIndicator - ) - intelRegisterCount++; - } - - return (intelRegisterCount == 3) - ? SMART.IntelAttributes.RemainingLife - : SMART.AttributeID.None; - } - - private SMART.AttributeID GetTemperatureIndex( - SMART.DriveAttribute[] attributes) - { - SMART.AttributeID[] validIds = new[] { - SMART.CommonAttributes.Temperature, - SMART.CommonAttributes.DriveTemperature, - SMART.CommonAttributes.AirflowTemperature - }; - - foreach (SMART.AttributeID validId in validIds) { - SMART.AttributeID id = validId; - if (Array.Exists(attributes, attr => attr.ID == id)) - return validId; - } - - return SMART.AttributeID.None; - } - - public IHardware[] Hardware { - get { - return hardware.ToArray(); - } - } - - public string GetReport() { - int p = (int)Environment.OSVersion.Platform; - if (p == 4 || p == 128) return null; - - StringBuilder r = new StringBuilder(); - - r.AppendLine("S.M.A.R.T Data"); - r.AppendLine(); - - for (int drive = 0; drive < MAX_DRIVES; drive++) { - IntPtr handle = SMART.OpenPhysicalDrive(drive); - - if (handle == SMART.INVALID_HANDLE_VALUE) - continue; - - if (!SMART.EnableSmart(handle, drive)) { - SMART.CloseHandle(handle); - continue; - } - - string name = SMART.ReadName(handle, drive); - if (name == null) { - SMART.CloseHandle(handle); - continue; - } - - SMART.DriveAttribute[] attributes = SMART.ReadSmart(handle, drive); - - if (attributes.Length > 0) { - r.AppendLine("Drive name: " + name); - r.AppendLine(); - r.AppendFormat(CultureInfo.InvariantCulture, " {0}{1}{2}{3}{4}", - ("ID").PadRight(6), - ("RawValue").PadRight(20), - ("WorstValue").PadRight(12), - ("AttrValue").PadRight(12), - Environment.NewLine); - - foreach (SMART.DriveAttribute a in attributes) { - if (a.ID == SMART.AttributeID.None) continue; - string raw = BitConverter.ToString(a.RawValue); - r.AppendFormat(CultureInfo.InvariantCulture, " {0}{1}{2}{3}{4}", - a.ID.ToString("d").PadRight(6), - raw.Replace("-", " ").PadRight(20), - a.WorstValue.ToString(CultureInfo.InvariantCulture).PadRight(12), - a.AttrValue.ToString(CultureInfo.InvariantCulture).PadRight(12), - Environment.NewLine); - } - r.AppendLine(); - } - - SMART.CloseHandle(handle); - } - - return r.ToString(); - } - - public void Close() { - foreach (HDD hdd in hardware) - hdd.Close(); - } - } -} diff --git a/Hardware/HDD/HarddriveGroup.cs b/Hardware/HDD/HarddriveGroup.cs new file mode 100644 index 0000000..370c236 --- /dev/null +++ b/Hardware/HDD/HarddriveGroup.cs @@ -0,0 +1,83 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2009-2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Paul Werelds + Roland Reinl + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +namespace OpenHardwareMonitor.Hardware.HDD { + internal class HarddriveGroup : IGroup { + + private const int MAX_DRIVES = 32; + + private readonly List hardware = + new List(); + + public HarddriveGroup(ISettings settings) { + int p = (int)Environment.OSVersion.Platform; + if (p == 4 || p == 128) return; + + ISmart smart = new WindowsSmart(); + + for (int drive = 0; drive < MAX_DRIVES; drive++) { + AbstractHarddrive instance = + AbstractHarddrive.CreateInstance(smart, drive, settings); + if (instance != null) { + this.hardware.Add(instance); + } + } + } + + public IHardware[] Hardware { + get { + return hardware.ToArray(); + } + } + + public string GetReport() { + return null; + } + + public void Close() { + foreach (AbstractHarddrive hdd in hardware) + hdd.Close(); + } + } +} diff --git a/Hardware/HDD/ISmart.cs b/Hardware/HDD/ISmart.cs new file mode 100644 index 0000000..887e6c7 --- /dev/null +++ b/Hardware/HDD/ISmart.cs @@ -0,0 +1,60 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; + + +namespace OpenHardwareMonitor.Hardware.HDD { + + public interface ISmart { + + IntPtr OpenDrive(int driveNumber); + + bool EnableSmart(IntPtr handle, int driveNumber); + + DriveAttributeValue[] ReadSmartData(IntPtr handle, int driveNumber); + + DriveThresholdValue[] ReadSmartThresholds(IntPtr handle, int driveNumber); + + string ReadName(IntPtr handle, int driveNumber); + + void CloseHandle(IntPtr handle); + + IntPtr InvalidHandle { get; } + } +} diff --git a/Hardware/HDD/NamePrefixAttribute.cs b/Hardware/HDD/NamePrefixAttribute.cs new file mode 100644 index 0000000..9242252 --- /dev/null +++ b/Hardware/HDD/NamePrefixAttribute.cs @@ -0,0 +1,53 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; + +namespace OpenHardwareMonitor.Hardware.HDD { + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + internal class NamePrefixAttribute : Attribute { + + public NamePrefixAttribute(string namePrefix) { + Prefix = namePrefix; + } + + public string Prefix { get; private set; } + + } +} diff --git a/Hardware/HDD/RequireSmartAttribute.cs b/Hardware/HDD/RequireSmartAttribute.cs new file mode 100644 index 0000000..eaed813 --- /dev/null +++ b/Hardware/HDD/RequireSmartAttribute.cs @@ -0,0 +1,53 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; + +namespace OpenHardwareMonitor.Hardware.HDD { + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + internal class RequireSmartAttribute : Attribute { + + public RequireSmartAttribute(byte attributeId) { + AttributeId = attributeId; + } + + public byte AttributeId { get; private set; } + + } +} diff --git a/Hardware/HDD/SMART.cs b/Hardware/HDD/SMART.cs deleted file mode 100644 index f568f3d..0000000 --- a/Hardware/HDD/SMART.cs +++ /dev/null @@ -1,508 +0,0 @@ -/* - - Version: MPL 1.1/GPL 2.0/LGPL 2.1 - - The contents of this file are subject to the Mozilla Public License Version - 1.1 (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - for the specific language governing rights and limitations under the License. - - The Original Code is the Open Hardware Monitor code. - - The Initial Developer of the Original Code is - Michael Möller . - Portions created by the Initial Developer are Copyright (C) 2009-2011 - the Initial Developer. All Rights Reserved. - - Contributor(s): Paul Werelds - - Alternatively, the contents of this file may be used under the terms of - either the GNU General Public License Version 2 or later (the "GPL"), or - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - in which case the provisions of the GPL or the LGPL are applicable instead - of those above. If you wish to allow use of your version of this file only - under the terms of either the GPL or the LGPL, and not to allow others to - use your version of this file under the terms of the MPL, indicate your - decision by deleting the provisions above and replace them with the notice - and other provisions required by the GPL or the LGPL. If you do not delete - the provisions above, a recipient may use your version of this file under - the terms of any one of the MPL, the GPL or the LGPL. - -*/ - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace OpenHardwareMonitor.Hardware.HDD { - - internal class SMART { - - [Flags] - public enum Status : ushort { - PreFailureWarranty = 0x01, - OnLineCollection = 0x02, - Performance = 0x04, - ErrorRate = 0x08, - EventCount = 0x10, - SelfPreserving = 0x20 - } - - [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); - } - - // These are the more-or-less standard S.M.A.R.T attributes - // TODO: Filter out unused/obscure ones; some are interpreted differently - // between manufacturers - public static class CommonAttributes { - public static readonly AttributeID - ReadErrorRate = new AttributeID(0x01), - ThroughputPerformance = new AttributeID(0x02), - SpinUpTime = new AttributeID(0x03), - StartStopCount = new AttributeID(0x04), - ReallocatedSectorsCount = new AttributeID(0x05), - ReadChannelMargin = new AttributeID(0x06), - SeekErrorRate = new AttributeID(0x07), - SeekTimePerformance = new AttributeID(0x08), - PowerOnHours = new AttributeID(0x09), - SpinRetryCount = new AttributeID(0x0A), - RecalibrationRetries = new AttributeID(0x0B), - PowerCycleCount = new AttributeID(0x0C), - SoftReadErrorRate = new AttributeID(0x0D), - SataDownshiftErrorCount = new AttributeID(0xB7), - EndToEndError = new AttributeID(0xB8), - HeadStability = new AttributeID(0xB9), - InducedOpVibrationDetection = new AttributeID(0xBA), - ReportedUncorrectableErrors = new AttributeID(0xBB), - CommandTimeout = new AttributeID(0xBC), - HighFlyWrites = new AttributeID(0xBD), - AirflowTemperature = new AttributeID(0xBE), - GSenseErrorRate = new AttributeID(0xBF), - PowerOffRetractCount = new AttributeID(0xC0), - LoadCycleCount = new AttributeID(0xC1), - Temperature = new AttributeID(0xC2), - HardwareEccRecovered = new AttributeID(0xC3), - ReallocationEventCount = new AttributeID(0xC4), - CurrentPendingSectorCount = new AttributeID(0xC5), - UncorrectableSectorCount = new AttributeID(0xC6), - UltraDmaCrcErrorCount = new AttributeID(0xC7), - WriteErrorRate = new AttributeID(0xC8), - DataAddressMarkerrors = new AttributeID(0xCA), - RunOutCancel = new AttributeID(0xCB), - SoftEccCorrection = new AttributeID(0xCC), - ThermalAsperityRate = new AttributeID(0xCD), - FlyingHeight = new AttributeID(0xCE), - SpinHighCurrent = new AttributeID(0xCF), - SpinBuzz = new AttributeID(0xD0), - OfflineSeekPerformance = new AttributeID(0xD1), - VibrationDuringWrite = new AttributeID(0xD3), - ShockDuringWrite = new AttributeID(0xD4), - DiskShift = new AttributeID(0xDC), - GSenseErrorRateAlt = new AttributeID(0xDD), // Alternative to 0xBF - LoadedHours = new AttributeID(0xDE), - LoadUnloadRetryCount = new AttributeID(0xDF), - LoadFriction = new AttributeID(0xE0), - LoadUnloadCycleCount = new AttributeID(0xE1), - LoadInTime = new AttributeID(0xE2), - TorqueAmplificationCount = new AttributeID(0xE3), - PowerOffRetractCycle = new AttributeID(0xE4), - GMRHeadAmplitude = new AttributeID(0xE6), - DriveTemperature = new AttributeID(0xE7), - HeadFlyingHours = new AttributeID(0xF0), - LBAsWrittenTotal = new AttributeID(0xF1), - LBAsReadTotal = new AttributeID(0xF2), - ReadErrorRetryRate = new AttributeID(0xFA), - FreeFallProtection = new AttributeID(0xFE) - ; - } - - // Indilinx SSD SMART attributes - // TODO: Find out the purpose of attribute 0xD2 - // Seems to be unique to Indilinx drives, hence its name of UnknownUnique. - public static class IndilinxAttributes { - public static readonly AttributeID - ReadErrorRate = CommonAttributes.ReadErrorRate, - PowerOnHours = CommonAttributes.PowerOnHours, - PowerCycleCount = CommonAttributes.PowerCycleCount, - InitialBadBlockCount = new AttributeID(0xB8), - RemainingLife = new AttributeID(0xD1), - ProgramFailure = new AttributeID(0xC3), - EraseFailure = new AttributeID(0xC4), - ReadFailure = new AttributeID(0xC5), - SectorsRead = new AttributeID(0xC6), - SectorsWritten = new AttributeID(0xC7), - ReadCommands = new AttributeID(0xC8), - WriteCommands = new AttributeID(0xC9), - BitErrors = new AttributeID(0xCA), - CorrectedErrors = new AttributeID(0xCB), - BadBlockFullFlag = new AttributeID(0xCC), - MaxCellcycles = new AttributeID(0xCD), - MinErase = new AttributeID(0xCE), - MaxErase = new AttributeID(0xCF), - AverageEraseCount = new AttributeID(0xD0), - UnknownUnique = new AttributeID(0xD2), - SataErrorCountCRC = new AttributeID(0xD3), - SataErrorCountHandshake = new AttributeID(0xD4) - ; - } - - // Intel SSD SMART attributes - // TODO: Find out the meaning behind 0xE2, 0xE3 and 0xE4 - public static class IntelAttributes { - public static readonly AttributeID - ReadErrorRate = CommonAttributes.ReadErrorRate, - SpinUpTime = CommonAttributes.SpinUpTime, - StartStopCount = CommonAttributes.StartStopCount, - ReallocatedSectorsCount = CommonAttributes.ReallocatedSectorsCount, - PowerOnHours = CommonAttributes.PowerOnHours, - PowerCycleCount = CommonAttributes.PowerCycleCount, - EndToEndError = CommonAttributes.EndToEndError, // Only on G2 drives! - - // Different from the common attribute PowerOffRetractCount, same ID - UnsafeShutdownCount = new AttributeID(0xC0), - HostWrites = new AttributeID(0xE1), - RemainingLife = new AttributeID(0xE8), - MediaWearOutIndicator = new AttributeID(0xE9) - ; - } - - // Samsung SSD SMART attributes - // TODO: AF, B0, B1, B5, B6, BB, C3, C6, C7, E8, E9 - public static class SamsungAttributes { - public static readonly AttributeID - PowerOnHours = CommonAttributes.PowerOnHours, - PowerCycleCount = CommonAttributes.PowerCycleCount, - UsedReservedBlockCountChip = new AttributeID(0xB2), // Unique - UsedReservedBlockCountTotal = new AttributeID(0xB3), // Unique - RemainingLife = new AttributeID(0xB4), // Unique - RuntimeBadBlockTotal = new AttributeID(0xB7) - ; - } - - // SandForce SSD SMART attributes - // Note: 0xE9 and 0xEA are reserved attributes and unique - public static class SandForceAttributes { - public static readonly AttributeID - ReadErrorRate = CommonAttributes.ReadErrorRate, - RetiredBlockCount = new AttributeID(0x05), - PowerOnHours = CommonAttributes.PowerOnHours, - PowerCycleCount = CommonAttributes.PowerCycleCount, - ProgramFailCount = new AttributeID(0xAB), // Unique - EraseFailCount = new AttributeID(0xAC), // Unique - UnexpectedPowerLossCount = new AttributeID(0xAE), // Unique - WearRangeDelta = new AttributeID(0xB1), // Unique - ProgramFailCountAlt = new AttributeID(0xB5), // Same as 0xAB - EraseFailCountAlt = new AttributeID(0xB6), // Same as 0xAC - ReportedUncorrectableErrors = - CommonAttributes.ReportedUncorrectableErrors, - - Temperature = CommonAttributes.Temperature, // SF-1500 only! - - // Opposite of the common attribute HardwareECCRecovered - UnrecoverableECC = new AttributeID(0xC3), - ReallocationEventCount = new AttributeID(0xC4), - RemainingLife = new AttributeID(0xE7), - LifetimeWrites = new AttributeID(0xF1), - LifetimeReads = new AttributeID(0xF2) - ; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct DriveAttribute { - public AttributeID ID; - public Status StatusFlags; - public byte AttrValue; - public byte WorstValue; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] - public byte[] RawValue; - public byte Reserved; - }; - - [Flags] - protected enum AccessMode : uint { - Read = 0x80000000, - Write = 0x40000000, - Execute = 0x20000000, - All = 0x10000000 - } - - [Flags] - protected enum ShareMode : uint { - None = 0, - Read = 1, - Write = 2, - Delete = 4 - } - - protected enum CreationMode : uint { - New = 1, - CreateAlways = 2, - OpenExisting = 3, - OpenAlways = 4, - TruncateExisting = 5 - } - - [Flags] - protected enum FileAttribute : uint { - Readonly = 0x00000001, - Hidden = 0x00000002, - System = 0x00000004, - Directory = 0x00000010, - Archive = 0x00000020, - Device = 0x00000040, - Normal = 0x00000080, - Temporary = 0x00000100, - SparseFile = 0x00000200, - ReparsePoint = 0x00000400, - Compressed = 0x00000800, - Offline = 0x00001000, - NotContentIndexed = 0x00002000, - Encrypted = 0x00004000, - } - - protected enum DriveCommand : uint { - GetVersion = 0x00074080, - SendDriveCommand = 0x0007c084, - ReceiveDriveData = 0x0007c088 - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - protected struct CommandBlockRegisters { - public byte Features; - public byte SectorCount; - public byte LBALow; - public byte LBAMid; - public byte LBAHigh; - public byte Device; - public byte Command; - public byte Reserved; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - protected struct DriveCommandParameter { - public uint BufferSize; - public CommandBlockRegisters Registers; - public byte DriveNumber; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] - public byte[] Reserved; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - protected struct DriverStatus { - public byte DriverError; - public byte IDEError; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] - public byte[] Reserved; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - protected struct DriveCommandResult { - public uint BufferSize; - public DriverStatus DriverStatus; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - protected struct DriveSmartReadResult { - public uint BufferSize; - public DriverStatus DriverStatus; - public byte Version; - public byte Reserved; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DRIVE_ATTRIBUTES)] - public DriveAttribute[] Attributes; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - protected struct Identify { - public ushort GeneralConfiguration; - public ushort NumberOfCylinders; - public ushort Reserved; - public ushort NumberOfHeads; - public ushort UnformattedBytesPerTrack; - public ushort UnformattedBytesPerSector; - public ushort SectorsPerTrack; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public ushort[] VendorUnique; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] - public byte[] SerialNumber; - public ushort BufferType; - public ushort BufferSectorSize; - public ushort NumberOfEccBytes; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public byte[] FirmwareRevision; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] - public byte[] ModelNumber; - public ushort MoreVendorUnique; - public ushort DoubleWordIo; - public ushort Capabilities; - public ushort MoreReserved; - public ushort PioCycleTimingMode; - public ushort DmaCycleTimingMode; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 406)] - public byte[] More; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - protected struct DriveIdentifyResult { - public uint BufferSize; - public DriverStatus DriverStatus; - public Identify Identify; - } - - public static readonly IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1); - - private const byte SMART_CMD = 0xB0; - private const byte ID_CMD = 0xEC; - - private const byte SMART_READ_DATA = 0xD0; - private const byte SMART_ENABLE_OPERATIONS = 0xD8; - - private const byte SMART_LBA_MID = 0x4F; - private const byte SMART_LBA_HI = 0xC2; - - private const int MAX_DRIVE_ATTRIBUTES = 512; - - private SMART() { } - - public static IntPtr OpenPhysicalDrive(int driveNumber) { - return NativeMethods.CreateFile(@"\\.\PhysicalDrive" + driveNumber, - AccessMode.Read | AccessMode.Write, ShareMode.Read | ShareMode.Write, - IntPtr.Zero, CreationMode.OpenExisting, FileAttribute.Device, - IntPtr.Zero); - } - - public static bool EnableSmart(IntPtr handle, int driveNumber) { - DriveCommandParameter parameter = new DriveCommandParameter(); - DriveCommandResult result; - uint bytesReturned; - - parameter.DriveNumber = (byte)driveNumber; - parameter.Registers.Features = SMART_ENABLE_OPERATIONS; - parameter.Registers.LBAMid = SMART_LBA_MID; - parameter.Registers.LBAHigh = SMART_LBA_HI; - parameter.Registers.Command = SMART_CMD; - - return NativeMethods.DeviceIoControl(handle, DriveCommand.SendDriveCommand, - ref parameter, Marshal.SizeOf(typeof(DriveCommandParameter)), out result, - Marshal.SizeOf(typeof(DriveCommandResult)), out bytesReturned, - IntPtr.Zero); - } - - public static DriveAttribute[] ReadSmart(IntPtr handle, - int driveNumber) - { - DriveCommandParameter parameter = new DriveCommandParameter(); - DriveSmartReadResult result; - uint bytesReturned; - - parameter.DriveNumber = (byte)driveNumber; - parameter.Registers.Features = SMART_READ_DATA; - parameter.Registers.LBAMid = SMART_LBA_MID; - parameter.Registers.LBAHigh = SMART_LBA_HI; - parameter.Registers.Command = SMART_CMD; - - bool isValid = NativeMethods.DeviceIoControl(handle, - DriveCommand.ReceiveDriveData, ref parameter, Marshal.SizeOf(parameter), - out result, Marshal.SizeOf(typeof(DriveSmartReadResult)), - out bytesReturned, IntPtr.Zero); - - return (isValid) ? result.Attributes : new DriveAttribute[0]; - } - - public static string ReadName(IntPtr handle, int driveNumber) { - DriveCommandParameter parameter = new DriveCommandParameter(); - DriveIdentifyResult result; - uint bytesReturned; - - parameter.DriveNumber = (byte)driveNumber; - parameter.Registers.Command = ID_CMD; - - bool valid = NativeMethods.DeviceIoControl(handle, - DriveCommand.ReceiveDriveData, ref parameter, Marshal.SizeOf(parameter), - out result, Marshal.SizeOf(typeof(DriveIdentifyResult)), - out bytesReturned, IntPtr.Zero); - - if (!valid) - return null; - else { - - byte[] bytes = result.Identify.ModelNumber; - char[] chars = new char[bytes.Length]; - for (int i = 0; i < bytes.Length; i += 2) { - chars[i] = (char)bytes[i + 1]; - chars[i + 1] = (char)bytes[i]; - } - - return new string(chars).Trim(new char[] {' ', '\0'}); - } - } - - public static int CloseHandle(IntPtr handle) { - return NativeMethods.CloseHandle(handle); - } - - protected static class NativeMethods { - private const string KERNEL = "kernel32.dll"; - - [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi, - CharSet = CharSet.Unicode)] - public static extern IntPtr CreateFile(string fileName, - AccessMode desiredAccess, ShareMode shareMode, IntPtr securityAttributes, - CreationMode creationDisposition, FileAttribute flagsAndAttributes, - IntPtr templateFilehandle); - - [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] - public static extern int CloseHandle(IntPtr handle); - - [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] - [return: MarshalAsAttribute(UnmanagedType.Bool)] - public static extern bool DeviceIoControl(IntPtr handle, - DriveCommand command, ref DriveCommandParameter parameter, - int parameterSize, out DriveSmartReadResult result, int resultSize, - out uint bytesReturned, IntPtr overlapped); - - [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] - [return: MarshalAsAttribute(UnmanagedType.Bool)] - public static extern bool DeviceIoControl(IntPtr handle, - DriveCommand command, ref DriveCommandParameter parameter, - int parameterSize, out DriveCommandResult result, int resultSize, - out uint bytesReturned, IntPtr overlapped); - - [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] - [return: MarshalAsAttribute(UnmanagedType.Bool)] - public static extern bool DeviceIoControl(IntPtr handle, - DriveCommand command, ref DriveCommandParameter parameter, - int parameterSize, out DriveIdentifyResult result, int resultSize, - out uint bytesReturned, IntPtr overlapped); - } - } -} diff --git a/Hardware/HDD/SSDIndilinx.cs b/Hardware/HDD/SSDIndilinx.cs new file mode 100644 index 0000000..fbcef7c --- /dev/null +++ b/Hardware/HDD/SSDIndilinx.cs @@ -0,0 +1,77 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Roland Reinl . + Portions created by the Initial Developer are Copyright (C) 2009-2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Paul Werelds + Michael Möller + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +namespace OpenHardwareMonitor.Hardware.HDD { + using System.Collections.Generic; + + [NamePrefix(""), RequireSmart(0xD1)] + internal class SSDIndilinx : AbstractHarddrive { + + private static readonly IEnumerable smartAttributes = + new List { + + new SmartAttribute(0xB8, SmartAttributeNames.InitialBadBlockCount), + new SmartAttribute(0xC3, SmartAttributeNames.ProgramFailure), + new SmartAttribute(0xC4, SmartAttributeNames.EraseFailure), + new SmartAttribute(0xC5, SmartAttributeNames.ReadFailure), + new SmartAttribute(0xC6, SmartAttributeNames.SectorsRead), + new SmartAttribute(0xC7, SmartAttributeNames.SectorsWritten), + new SmartAttribute(0xC8, SmartAttributeNames.ReadCommands), + new SmartAttribute(0xC9, SmartAttributeNames.WriteCommands), + new SmartAttribute(0xCA, SmartAttributeNames.BitErrors), + new SmartAttribute(0xCB, SmartAttributeNames.CorrectedErrors), + new SmartAttribute(0xCC, SmartAttributeNames.BadBlockFullFlag), + new SmartAttribute(0xCD, SmartAttributeNames.MaxCellCycles), + new SmartAttribute(0xCE, SmartAttributeNames.MinErase), + new SmartAttribute(0xCF, SmartAttributeNames.MaxErase), + new SmartAttribute(0xD0, SmartAttributeNames.AverageEraseCount), + new SmartAttribute(0xD1, SmartAttributeNames.RemainingLife, + null, SensorType.Level, 0), + new SmartAttribute(0xD2, SmartAttributeNames.UnknownUnique), + new SmartAttribute(0xD3, SmartAttributeNames.SataErrorCountCrc), + new SmartAttribute(0xD4, SmartAttributeNames.SataErrorCountHandshake), + }; + + public SSDIndilinx(ISmart smart, string name, int index, ISettings settings) + : base(smart, name, index, smartAttributes, settings) { } + } +} + + + diff --git a/Hardware/HDD/SSDIntel.cs b/Hardware/HDD/SSDIntel.cs new file mode 100644 index 0000000..372b216 --- /dev/null +++ b/Hardware/HDD/SSDIntel.cs @@ -0,0 +1,78 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2009-2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Paul Werelds + Roland Reinl + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +namespace OpenHardwareMonitor.Hardware.HDD { + using System.Collections.Generic; + + [NamePrefix("INTEL SSD"), + RequireSmart(0xE1), RequireSmart(0xE8), RequireSmart(0xE9)] + internal class SSDIntel : AbstractHarddrive { + + private static readonly IEnumerable smartAttributes = + new List { + + new SmartAttribute(0x01, SmartAttributeNames.ReadErrorRate), + new SmartAttribute(0x03, SmartAttributeNames.SpinUpTime), + new SmartAttribute(0x04, SmartAttributeNames.StartStopCount, RawToInt), + new SmartAttribute(0x05, SmartAttributeNames.ReallocatedSectorsCount), + new SmartAttribute(0x09, SmartAttributeNames.PowerOnHours, RawToInt), + new SmartAttribute(0x0C, SmartAttributeNames.PowerCycleCount, RawToInt), + new SmartAttribute(0xAA, SmartAttributeNames.AvailableReservedSpace), + new SmartAttribute(0xAB, SmartAttributeNames.ProgramFailCount), + new SmartAttribute(0xAC, SmartAttributeNames.EraseFailCount), + new SmartAttribute(0xB8, SmartAttributeNames.EndToEndError), + new SmartAttribute(0xC0, SmartAttributeNames.UnsafeShutdownCount), + new SmartAttribute(0xE1, SmartAttributeNames.HostWrites, + (byte[] r, byte v) => { return RawToInt(r, v) / 0x20; }, + SensorType.Data, 0), + new SmartAttribute(0xE8, SmartAttributeNames.RemainingLife, + null, SensorType.Level, 0), + new SmartAttribute(0xE9, SmartAttributeNames.MediaWearOutIndicator), + new SmartAttribute(0xF1, SmartAttributeNames.HostWrites, + (byte[] r, byte v) => { return RawToInt(r, v) / 0x20; }, + SensorType.Data, 0), + new SmartAttribute(0xF2, SmartAttributeNames.HostReads, + (byte[] r, byte v) => { return RawToInt(r, v) / 0x20; }, + SensorType.Data, 1), + }; + + public SSDIntel(ISmart smart, string name, int index, ISettings settings) + : base(smart, name, index, smartAttributes, settings) { } + } +} diff --git a/Hardware/HDD/SSDPlextor.cs b/Hardware/HDD/SSDPlextor.cs new file mode 100644 index 0000000..9271502 --- /dev/null +++ b/Hardware/HDD/SSDPlextor.cs @@ -0,0 +1,53 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +namespace OpenHardwareMonitor.Hardware.HDD { + using System.Collections.Generic; + + [NamePrefix("PLEXTOR")] + internal class SSDPlextor : AbstractHarddrive { + + private static readonly IEnumerable smartAttributes = + new List { + new SmartAttribute(0x09, SmartAttributeNames.PowerOnHours, RawToInt), + new SmartAttribute(0x0C, SmartAttributeNames.PowerCycleCount, RawToInt), + }; + + public SSDPlextor(ISmart smart, string name, int index, ISettings settings) + : base(smart, name, index, smartAttributes, settings) { } + } +} diff --git a/Hardware/HDD/SSDSandforce.cs b/Hardware/HDD/SSDSandforce.cs new file mode 100644 index 0000000..5c304ae --- /dev/null +++ b/Hardware/HDD/SSDSandforce.cs @@ -0,0 +1,72 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2009-2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Paul Werelds + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +namespace OpenHardwareMonitor.Hardware.HDD { + using System.Collections.Generic; + + [NamePrefix(""), RequireSmart(0xAB)] + internal class SSDSandforce : AbstractHarddrive { + + private static readonly IEnumerable smartAttributes = + new List { + new SmartAttribute(0x05, SmartAttributeNames.RetiredBlockCount), + new SmartAttribute(0x09, SmartAttributeNames.PowerOnHours, RawToInt), + new SmartAttribute(0x0C, SmartAttributeNames.PowerCycleCount, RawToInt), + new SmartAttribute(0xAB, SmartAttributeNames.ProgramFailCount), + new SmartAttribute(0xAC, SmartAttributeNames.EraseFailCount), + new SmartAttribute(0xAE, SmartAttributeNames.UnexpectedPowerLossCount), + new SmartAttribute(0xB1, SmartAttributeNames.WearRangeDelta), + new SmartAttribute(0xB5, SmartAttributeNames.AlternativeProgramFailCount), + new SmartAttribute(0xB6, SmartAttributeNames.AlternativeEraseFailCount), + new SmartAttribute(0xC3, SmartAttributeNames.UnrecoverableEcc), + new SmartAttribute(0xC4, SmartAttributeNames.ReallocationEventCount), + new SmartAttribute(0xE7, SmartAttributeNames.RemainingLife, + null, SensorType.Level, 0), + new SmartAttribute(0xF1, SmartAttributeNames.HostWrites, + (byte[] r, byte v) => { return RawToInt(r, v); }, + SensorType.Data, 0), + new SmartAttribute(0xF2, SmartAttributeNames.HostReads, + (byte[] r, byte v) => { return RawToInt(r, v); }, + SensorType.Data, 1) + }; + + public SSDSandforce(ISmart smart, string name, int index, + ISettings settings) + : base(smart, name, index, smartAttributes, settings) { } + } +} diff --git a/Hardware/HDD/SmartAttribute.cs b/Hardware/HDD/SmartAttribute.cs new file mode 100644 index 0000000..55686cd --- /dev/null +++ b/Hardware/HDD/SmartAttribute.cs @@ -0,0 +1,116 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Roland Reinl + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; + +namespace OpenHardwareMonitor.Hardware.HDD { + internal class SmartAttribute { + + private RawValueConversion rawValueConversion; + + /// + /// Initializes a new instance of the class. + /// + /// The SMART identifier of the attribute. + /// The name of the attribute. + public SmartAttribute(byte identifier, string name) : + this(identifier, name, null, null, 0) { } + + /// + /// Initializes a new instance of the class. + /// + /// The SMART identifier of the attribute. + /// The name of the attribute. + /// A delegate for converting the raw byte + /// array into a value (or null to use the attribute value). + public SmartAttribute(byte identifier, string name, + RawValueConversion rawValueConversion) : + this(identifier, name, rawValueConversion, null, 0) { } + + /// + /// Initializes a new instance of the class. + /// + /// The SMART identifier of the attribute. + /// The name of the attribute. + /// A delegate for converting the raw byte + /// array into a value (or null to use the attribute value). + /// Type of the sensor or null if no sensor is to + /// be created. + /// If there exists more than one attribute with + /// the same sensor channel and type, then a sensor is created only for the + /// first attribute. + public SmartAttribute(byte identifier, string name, + RawValueConversion rawValueConversion, SensorType? sensorType, + int sensorChannel) + { + this.Identifier = identifier; + this.Name = name; + this.rawValueConversion = rawValueConversion; + this.SensorType = sensorType; + this.SensorChannel = sensorChannel; + } + + /// + /// Gets the SMART identifier. + /// + public byte Identifier { get; private set; } + + public string Name { get; private set; } + + public SensorType? SensorType { get; private set; } + + public int SensorChannel { get; private set; } + + public bool HasRawValueConversion { + get { + return rawValueConversion != null; + } + } + + public float ConvertValue(DriveAttributeValue value) { + if (rawValueConversion == null) { + return value.AttrValue; + } else { + return rawValueConversion(value.RawValue, value.AttrValue); + } + } + + public delegate float RawValueConversion(byte[] rawValue, byte value); + } +} diff --git a/Hardware/HDD/SmartAttributeNames.cs b/Hardware/HDD/SmartAttributeNames.cs new file mode 100644 index 0000000..941fa4b --- /dev/null +++ b/Hardware/HDD/SmartAttributeNames.cs @@ -0,0 +1,449 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Roland Reinl . + Portions created by the Initial Developer are Copyright (C) 2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Michael Möller + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +namespace OpenHardwareMonitor.Hardware.HDD { + /// + /// Localization class for SMART attribute names. + /// + internal static class SmartAttributeNames { + + public static string AirflowTemperature { + get { return "Airflow Temperature"; } + } + + public static string Temperature { + get { return "Temperature"; } + } + + public static string RetiredBlockCount { + get { return "Retired Block Count"; } + } + + public static string ProgramFailCount { + get { return "Program Fail Count"; } + } + + public static string EraseFailCount { + get { return "Erase Fail Count"; } + } + + public static string UnexpectedPowerLossCount { + get { return "Unexpected Power Loss Count"; } + } + + public static string WearRangeDelta { + get { return "Wear Range Delta"; } + } + + public static string AlternativeProgramFailCount { + get { return "Alternative Program Fail Count"; } + } + + public static string AlternativeEraseFailCount { + get { return "Alternative Erase Fail Count"; } + } + + public static string UnrecoverableEcc { + get { return "Unrecoverable ECC"; } + } + + public static string ReallocationEventCount { + get { return "Reallocation Event Count"; } + } + + public static string RemainingLife { + get { return "Remaining Life"; } + } + + public static string AvailableReservedSpace { + get { return "Available Reserved Space"; } + } + + public static string CalibrationRetryCount { + get { return "Calibration Retry Count"; } + } + + public static string CommandTimeout { + get { return "Command Timeout"; } + } + + public static string CurrentPendingSectorCount { + get { return "Current Pending Sector Count"; } + } + + public static string DataAddressMarkErrors { + get { return "Data Address Mark errors"; } + } + + public static string DiskShift { + get { return "Disk Shift"; } + } + + public static string DriveTemperature { + get { return "Drive Temperature"; } + } + + public static string EmergencyRetractCycleCount { + get { return "Emergency Retract Cycle Count"; } + } + + public static string EndToEndError { + get { return "End-to-End error"; } + } + + public static string EnduranceRemaining { + get { return "Endurance Remaining"; } + } + + public static string FlyingHeight { + get { return "Flying Height"; } + } + + public static string FreeFallProtection { + get { return "Free Fall Protection"; } + } + + public static string GmrHeadAmplitude { + get { return "GMR Head Amplitude"; } + } + + public static string GSenseErrorRate { + get { return "G-sense Error Rate"; } + } + + public static string HardwareEccRecovered { + get { return "Hardware ECC Recovered"; } + } + + public static string HeadFlyingHours { + get { return "Head Flying Hours"; } + } + + public static string HeadStability { + get { return "Head Stability"; } + } + + public static string HighFlyWrites { + get { return "High Fly Writes"; } + } + + public static string InducedOpVibrationDetection { + get { return "Induced Op-Vibration Detection"; } + } + + public static string LoadedHours { + get { return "Loaded Hours"; } + } + + public static string LoadFriction { + get { return "Load Friction"; } + } + + public static string LoadInTime { + get { return "Load 'In'-time"; } + } + + public static string LoadUnloadCycleCount { + get { return "Load/Unload Cycle Count"; } + } + + public static string LoadUnloadCycleCountFujitsu { + get { return "Load/Unload Cycle Count (Fujitus)"; } + } + + public static string LoadUnloadRetryCount { + get { return "Load/Unload Retry Count"; } + } + + public static string MediaWearoutIndicator { + get { return "Media Wearout Indicator"; } + } + + public static string MultiZoneErrorRate { + get { return "Multi-Zone Error Rate"; } + } + + public static string OfflineSeekPerformance { + get { return "Offline Seek Performance"; } + } + + public static string PowerCycleCount { + get { return "Power Cycle Count"; } + } + + public static string PowerOffRetractCycle { + get { return "Power-Off Retract Cycle"; } + } + + public static string PowerOnHours { + get { return "Power-On Hours (POH)"; } + } + + public static string ReadChannelMargin { + get { return "Read Channel Margin"; } + } + + public static string ReadErrorRate { + get { return "Read Error Rate"; } + } + + public static string ReadErrorRetryRate { + get { return "Read Error Retry Rate"; } + } + + public static string ReallocatedSectorsCount { + get { return "Reallocated Sectors Count"; } + } + + public static string ReportedUncorrectableErrors { + get { return "Reported Uncorrectable Errors"; } + } + + public static string RunOutCancel { + get { return "Run Out Cancel"; } + } + + public static string SataDownshiftErrorCount { + get { return "SATA Downshift Error Count"; } + } + + public static string SeekErrorRate { + get { return "Seek Error Rate"; } + } + + public static string SeekTimePerformance { + get { return "Seek Time Performance"; } + } + + public static string ShockDuringWrite { + get { return "Shock During Write"; } + } + + public static string SoftEccCorrection { + get { return "Soft ECC Correction"; } + } + + public static string SoftReadErrorRate { + get { return "Soft Read Error Rate"; } + } + + public static string SpinBuzz { + get { return "Spin Buzz"; } + } + + public static string SpinHighCurrent { + get { return "Spin High Current"; } + } + + public static string SpinRetryCount { + get { return "Spin Retry Count"; } + } + + public static string SpinUpTime { + get { return "Spin-Up Time"; } + } + + public static string StartStopCount { + get { return "Start/Stop Count"; } + } + + public static string TaCounterDetected { + get { return "TA Counter Detected"; } + } + + public static string TemperatureDifferenceFrom100 { + get { return "Temperature Difference from 100"; } + } + + public static string ThermalAsperityRate { + get { return "Thermal Asperity Rate (TAR)"; } + } + + public static string ThroughputPerformance { + get { return "Throughput Performance"; } + } + + public static string TorqueAmplificationCount { + get { return "Torque Amplification Count"; } + } + + public static string TotalLbasRead { + get { return "Total LBAs Read"; } + } + + public static string TotalLbasWritten { + get { return "Total LBAs Written"; } + } + + public static string TransferErrorRate { + get { return "Transfer Error Rate"; } + } + + public static string UltraDmaCrcErrorCount { + get { return "UltraDMA CRC Error Count"; } + } + + public static string UncorrectableSectorCount { + get { return "Uncorrectable Sector Count"; } + } + + public static string Unknown { + get { return "Unknown"; } + } + + public static string VibrationDuringWrite { + get { return "Vibration During Write"; } + } + + public static string WriteErrorRate { + get { return "Write Error Rate"; } + } + + public static string RecalibrationRetries { + get { return "Recalibration Retries"; } + } + + public static string LoadCycleCount { + get { return "Load Cycle Count"; } + } + + public static string AlternativeGSenseErrorRate { + get { return "Alternative G-Sense Error Rate"; } + } + + public static string InitialBadBlockCount { + get { return "Initial Bad Block Count"; } + } + + public static string ProgramFailure { + get { return "Program Failure"; } + } + + public static string EraseFailure { + get { return "Erase Failure"; } + } + + public static string ReadFailure { + get { return "Read Failure"; } + } + + public static string SectorsRead { + get { return "Sectors Read"; } + } + + public static string SectorsWritten { + get { return "Sectors Written"; } + } + + public static string ReadCommands { + get { return "Read Commands"; } + } + + public static string WriteCommands { + get { return "Write Commands"; } + } + + public static string BitErrors { + get { return "Bit Errors"; } + } + + public static string CorrectedErrors { + get { return "Corrected Errors"; } + } + + public static string BadBlockFullFlag { + get { return "Bad Block Full Flag"; } + } + + public static string MaxCellCycles { + get { return "Max Cell Cycles"; } + } + + public static string MinErase { + get { return "Min Erase"; } + } + + public static string MaxErase { + get { return "Max Erase"; } + } + + public static string AverageEraseCount { + get { return "Average Erase Count"; } + } + + public static string UnknownUnique { + get { return "Unknown Unique"; } + } + + public static string SataErrorCountCrc { + get { return "SATA Error Count CRC"; } + } + + public static string SataErrorCountHandshake { + get { return "SATA Error Count Handshake"; } + } + + public static string UnsafeShutdownCount { + get { return "Unsafe Shutdown Count"; } + } + + public static string HostWrites { + get { return "Host Writes"; } + } + + public static string UsedReservedBlockCountChip { + get { return "Used Reserved Block Count Chip"; } + } + + public static string UsedReservedBlockCountTotal { + get { return "Used Reserved Block Count Total"; } + } + + public static string RuntimeBadBlockTotal { + get { return "Runtime Bad Block Total"; } + } + + public static string HostReads { + get { return "Host Reads"; } + } + + public static string MediaWearOutIndicator { + get { return "Media Wear Out Indicator"; } + } + } +} \ No newline at end of file diff --git a/Hardware/HDD/WindowsSmart.cs b/Hardware/HDD/WindowsSmart.cs new file mode 100644 index 0000000..f3001fb --- /dev/null +++ b/Hardware/HDD/WindowsSmart.cs @@ -0,0 +1,406 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2009-2011 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Paul Werelds + Roland Reinl + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace OpenHardwareMonitor.Hardware.HDD { + + internal class WindowsSmart : ISmart { + [Flags] + protected enum AccessMode : uint { + Read = 0x80000000, + Write = 0x40000000, + Execute = 0x20000000, + All = 0x10000000 + } + + [Flags] + protected enum ShareMode : uint { + None = 0, + Read = 1, + Write = 2, + Delete = 4 + } + + protected enum CreationMode : uint { + New = 1, + CreateAlways = 2, + OpenExisting = 3, + OpenAlways = 4, + TruncateExisting = 5 + } + + [Flags] + protected enum FileAttribute : uint { + Readonly = 0x00000001, + Hidden = 0x00000002, + System = 0x00000004, + Directory = 0x00000010, + Archive = 0x00000020, + Device = 0x00000040, + Normal = 0x00000080, + Temporary = 0x00000100, + SparseFile = 0x00000200, + ReparsePoint = 0x00000400, + Compressed = 0x00000800, + Offline = 0x00001000, + NotContentIndexed = 0x00002000, + Encrypted = 0x00004000, + } + + protected enum DriveCommand : uint { + GetVersion = 0x00074080, + SendDriveCommand = 0x0007c084, + ReceiveDriveData = 0x0007c088 + } + + protected enum RegisterCommand : byte { + /// + /// SMART data requested. + /// + SmartCmd = 0xB0, + + /// + /// Identify data is requested. + /// + IdCmd = 0xEC, + } + + protected enum RegisterFeature : byte { + /// + /// Read SMART data. + /// + SmartReadData = 0xD0, + + /// + /// Read SMART thresholds. + /// + SmartReadThresholds = 0xD1, /* obsolete */ + + /// + /// Autosave SMART data. + /// + SmartAutosave = 0xD2, + + /// + /// Save SMART attributes. + /// + SmartSaveAttr = 0xD3, + + /// + /// Set SMART to offline immediately. + /// + SmartImmediateOffline = 0xD4, + + /// + /// Read SMART log. + /// + SmartReadLog = 0xD5, + + /// + /// Write SMART log. + /// + SmartWriteLog = 0xD6, + + /// + /// Write SMART thresholds. + /// + SmartWriteThresholds = 0xD7, /* obsolete */ + + /// + /// Enable SMART. + /// + SmartEnableOperations = 0xD8, + + /// + /// Disable SMART. + /// + SmartDisableOperations = 0xD9, + + /// + /// Get SMART status. + /// + SmartStatus = 0xDA, + + /// + /// Set SMART to offline automatically. + /// + SmartAutoOffline = 0xDB, /* obsolete */ + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + protected struct CommandBlockRegisters { + public RegisterFeature Features; + public byte SectorCount; + public byte LBALow; + public byte LBAMid; + public byte LBAHigh; + public byte Device; + public RegisterCommand Command; + public byte Reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + protected struct DriveCommandParameter { + public uint BufferSize; + public CommandBlockRegisters Registers; + public byte DriveNumber; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] + public byte[] Reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + protected struct DriverStatus { + public byte DriverError; + public byte IDEError; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public byte[] Reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + protected struct DriveCommandResult { + public uint BufferSize; + public DriverStatus DriverStatus; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + protected struct DriveSmartReadDataResult { + public uint BufferSize; + public DriverStatus DriverStatus; + public byte Version; + public byte Reserved; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DRIVE_ATTRIBUTES)] + public DriveAttributeValue[] Attributes; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + protected struct DriveSmartReadThresholdsResult { + public uint BufferSize; + public DriverStatus DriverStatus; + public byte Version; + public byte Reserved; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DRIVE_ATTRIBUTES)] + public DriveThresholdValue[] Thresholds; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + protected struct Identify { + public ushort GeneralConfiguration; + public ushort NumberOfCylinders; + public ushort Reserved; + public ushort NumberOfHeads; + public ushort UnformattedBytesPerTrack; + public ushort UnformattedBytesPerSector; + public ushort SectorsPerTrack; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public ushort[] VendorUnique; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] + public byte[] SerialNumber; + public ushort BufferType; + public ushort BufferSectorSize; + public ushort NumberOfEccBytes; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] FirmwareRevision; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] + public byte[] ModelNumber; + public ushort MoreVendorUnique; + public ushort DoubleWordIo; + public ushort Capabilities; + public ushort MoreReserved; + public ushort PioCycleTimingMode; + public ushort DmaCycleTimingMode; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 406)] + public byte[] More; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + protected struct DriveIdentifyResult { + public uint BufferSize; + public DriverStatus DriverStatus; + public Identify Identify; + } + + public IntPtr InvalidHandle { get { return (IntPtr)(-1); } } + + private const byte SMART_LBA_MID = 0x4F; + private const byte SMART_LBA_HI = 0xC2; + + private const int MAX_DRIVE_ATTRIBUTES = 512; + + public IntPtr OpenDrive(int driveNumber) { + return NativeMethods.CreateFile(@"\\.\PhysicalDrive" + driveNumber, + AccessMode.Read | AccessMode.Write, ShareMode.Read | ShareMode.Write, + IntPtr.Zero, CreationMode.OpenExisting, FileAttribute.Device, + IntPtr.Zero); + } + + public bool EnableSmart(IntPtr handle, int driveNumber) { + DriveCommandParameter parameter = new DriveCommandParameter(); + DriveCommandResult result; + uint bytesReturned; + + parameter.DriveNumber = (byte)driveNumber; + parameter.Registers.Features = RegisterFeature.SmartEnableOperations; + parameter.Registers.LBAMid = SMART_LBA_MID; + parameter.Registers.LBAHigh = SMART_LBA_HI; + parameter.Registers.Command = RegisterCommand.SmartCmd; + + return NativeMethods.DeviceIoControl(handle, DriveCommand.SendDriveCommand, + ref parameter, Marshal.SizeOf(typeof(DriveCommandParameter)), out result, + Marshal.SizeOf(typeof(DriveCommandResult)), out bytesReturned, + IntPtr.Zero); + } + + public DriveAttributeValue[] ReadSmartData(IntPtr handle, int driveNumber) { + DriveCommandParameter parameter = new DriveCommandParameter(); + DriveSmartReadDataResult result; + uint bytesReturned; + + parameter.DriveNumber = (byte)driveNumber; + parameter.Registers.Features = RegisterFeature.SmartReadData; + parameter.Registers.LBAMid = SMART_LBA_MID; + parameter.Registers.LBAHigh = SMART_LBA_HI; + parameter.Registers.Command = RegisterCommand.SmartCmd; + + bool isValid = NativeMethods.DeviceIoControl(handle, + DriveCommand.ReceiveDriveData, ref parameter, Marshal.SizeOf(parameter), + out result, Marshal.SizeOf(typeof(DriveSmartReadDataResult)), + out bytesReturned, IntPtr.Zero); + + return (isValid) ? result.Attributes : new DriveAttributeValue[0]; + } + + public DriveThresholdValue[] ReadSmartThresholds(IntPtr handle, + int driveNumber) + { + DriveCommandParameter parameter = new DriveCommandParameter(); + DriveSmartReadThresholdsResult result; + uint bytesReturned = 0; + + parameter.DriveNumber = (byte)driveNumber; + parameter.Registers.Features = RegisterFeature.SmartReadThresholds; + parameter.Registers.LBAMid = SMART_LBA_MID; + parameter.Registers.LBAHigh = SMART_LBA_HI; + parameter.Registers.Command = RegisterCommand.SmartCmd; + + bool isValid = NativeMethods.DeviceIoControl(handle, + DriveCommand.ReceiveDriveData, ref parameter, Marshal.SizeOf(parameter), + out result, Marshal.SizeOf(typeof(DriveSmartReadThresholdsResult)), + out bytesReturned, IntPtr.Zero); + + return (isValid) ? result.Thresholds : new DriveThresholdValue[0]; + } + + public string ReadName(IntPtr handle, int driveNumber) { + DriveCommandParameter parameter = new DriveCommandParameter(); + DriveIdentifyResult result; + uint bytesReturned; + + parameter.DriveNumber = (byte)driveNumber; + parameter.Registers.Command = RegisterCommand.IdCmd; + + bool valid = NativeMethods.DeviceIoControl(handle, + DriveCommand.ReceiveDriveData, ref parameter, Marshal.SizeOf(parameter), + out result, Marshal.SizeOf(typeof(DriveIdentifyResult)), + out bytesReturned, IntPtr.Zero); + + if (!valid) + return null; + else { + + byte[] bytes = result.Identify.ModelNumber; + char[] chars = new char[bytes.Length]; + for (int i = 0; i < bytes.Length; i += 2) { + chars[i] = (char)bytes[i + 1]; + chars[i + 1] = (char)bytes[i]; + } + + return new string(chars).Trim(new char[] {' ', '\0'}); + } + } + + public void CloseHandle(IntPtr handle) { + NativeMethods.CloseHandle(handle); + } + + protected static class NativeMethods { + private const string KERNEL = "kernel32.dll"; + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi, + CharSet = CharSet.Unicode)] + public static extern IntPtr CreateFile(string fileName, + AccessMode desiredAccess, ShareMode shareMode, IntPtr securityAttributes, + CreationMode creationDisposition, FileAttribute flagsAndAttributes, + IntPtr templateFilehandle); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern int CloseHandle(IntPtr handle); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + [return: MarshalAsAttribute(UnmanagedType.Bool)] + public static extern bool DeviceIoControl(IntPtr handle, + DriveCommand command, ref DriveCommandParameter parameter, + int parameterSize, out DriveSmartReadDataResult result, int resultSize, + out uint bytesReturned, IntPtr overlapped); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + [return: MarshalAsAttribute(UnmanagedType.Bool)] + public static extern bool DeviceIoControl(IntPtr handle, + DriveCommand command, ref DriveCommandParameter parameter, + int parameterSize, out DriveSmartReadThresholdsResult result, + int resultSize, out uint bytesReturned, IntPtr overlapped); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + [return: MarshalAsAttribute(UnmanagedType.Bool)] + public static extern bool DeviceIoControl(IntPtr handle, + DriveCommand command, ref DriveCommandParameter parameter, + int parameterSize, out DriveCommandResult result, int resultSize, + out uint bytesReturned, IntPtr overlapped); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + [return: MarshalAsAttribute(UnmanagedType.Bool)] + public static extern bool DeviceIoControl(IntPtr handle, + DriveCommand command, ref DriveCommandParameter parameter, + int parameterSize, out DriveIdentifyResult result, int resultSize, + out uint bytesReturned, IntPtr overlapped); + } + } +} diff --git a/Hardware/ISensor.cs b/Hardware/ISensor.cs index 73023bf..dfae42e 100644 --- a/Hardware/ISensor.cs +++ b/Hardware/ISensor.cs @@ -42,15 +42,16 @@ using OpenHardwareMonitor.Collections; namespace OpenHardwareMonitor.Hardware { public enum SensorType { - Voltage, - Clock, - Temperature, - Load, - Fan, - Flow, - Control, - Level, - Power + Voltage, // V + Clock, // MHz + Temperature, // °C + Load, // % + Fan, // RPM + Flow, // L/h + Control, // % + Level, // % + Power, // W + Data, // GB = 2^30 Bytes } public struct SensorValue { diff --git a/OpenHardwareMonitor.csproj b/OpenHardwareMonitor.csproj index 4347540..6d52c81 100644 --- a/OpenHardwareMonitor.csproj +++ b/OpenHardwareMonitor.csproj @@ -43,8 +43,9 @@ TRACE;DEBUG prompt 4 - false + true AllRules.ruleset + AnyCPU none @@ -180,6 +181,7 @@ MainForm.cs + Designer ReportForm.cs @@ -220,6 +222,9 @@ + + + diff --git a/OpenHardwareMonitorLib.csproj b/OpenHardwareMonitorLib.csproj index e32505e..71fd40a 100644 --- a/OpenHardwareMonitorLib.csproj +++ b/OpenHardwareMonitorLib.csproj @@ -56,12 +56,26 @@ + + + + + + + + + + + + + + @@ -79,9 +93,9 @@ - - - + + + diff --git a/Resources/data.png b/Resources/data.png new file mode 100644 index 0000000..7f90aa8 Binary files /dev/null and b/Resources/data.png differ