# HG changeset patch # User moel.mich # Date 1325352664 0 # Node ID c6ee430d6995bcf4aa62ce460b4672269d457209 # Parent 3f2d9ebacf38a7ed9562696130c47d4df8c07639 Modified and extended version of the patch v4 by Roland Reinl (see Issue 256). Main differences to the original patch: DeviceIoControl refactorings removed, SmartAttribute is now descriptive only and does not hold any state, report is written as one 80 columns table, sensors are created only for meaningful values and without duplicates (remaining life, temperatures, host writes and reads). Also the current implementation should really preserve all the functionality of the old system. Additionally there is now a simple SMART devices emulation class (DebugSmart) that can be used in place of WindowsSmart for testing with reported data. diff -r 3f2d9ebacf38 -r c6ee430d6995 Collections/Pair.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Collections/Pair.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 GUI/HardwareNode.cs --- a/GUI/HardwareNode.cs Wed Aug 31 22:48:49 2011 +0000 +++ b/GUI/HardwareNode.cs Sat Dec 31 17:31:04 2011 +0000 @@ -66,6 +66,7 @@ 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 -r 3f2d9ebacf38 -r c6ee430d6995 GUI/SensorGadget.cs --- a/GUI/SensorGadget.cs Wed Aug 31 22:48:49 2011 +0000 +++ b/GUI/SensorGadget.cs Sat Dec 31 17:31:04 2011 +0000 @@ -518,6 +518,9 @@ case SensorType.Power: format = "{0:F1} W"; break; + case SensorType.Data: + format = "{0:F1} GB"; + break; } if (sensor.SensorType == SensorType.Temperature && diff -r 3f2d9ebacf38 -r c6ee430d6995 GUI/SensorNode.cs --- a/GUI/SensorNode.cs Wed Aug 31 22:48:49 2011 +0000 +++ b/GUI/SensorNode.cs Sat Dec 31 17:31:04 2011 +0000 @@ -76,6 +76,7 @@ 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 -r 3f2d9ebacf38 -r c6ee430d6995 GUI/SensorNotifyIcon.cs --- a/GUI/SensorNotifyIcon.cs Wed Aug 31 22:48:49 2011 +0000 +++ b/GUI/SensorNotifyIcon.cs Sat Dec 31 17:31:04 2011 +0000 @@ -198,6 +198,8 @@ 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 @@ 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 -r 3f2d9ebacf38 -r c6ee430d6995 GUI/TypeNode.cs --- a/GUI/TypeNode.cs Wed Aug 31 22:48:49 2011 +0000 +++ b/GUI/TypeNode.cs Sat Dec 31 17:31:04 2011 +0000 @@ -84,6 +84,10 @@ 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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/Computer.cs --- a/Hardware/Computer.cs Wed Aug 31 22:48:49 2011 +0000 +++ b/Hardware/Computer.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 @@ Add(new Heatmaster.HeatmasterGroup(settings)); if (hddEnabled) - Add(new HDD.HDDGroup(settings)); + Add(new HDD.HarddriveGroup(settings)); open = true; } @@ -109,11 +109,11 @@ [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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/AbstractHarddrive.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/AbstractHarddrive.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/DebugSmart.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/DebugSmart.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/DriveAttributeValue.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/DriveAttributeValue.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/DriveThresholdValue.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/DriveThresholdValue.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/HDD.cs --- a/Hardware/HDD/HDD.cs Wed Aug 31 22:48:49 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/HDDGeneric.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/HDDGeneric.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/HDDGroup.cs --- a/Hardware/HDD/HDDGroup.cs Wed Aug 31 22:48:49 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/HarddriveGroup.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/HarddriveGroup.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/ISmart.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/ISmart.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/NamePrefixAttribute.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/NamePrefixAttribute.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/RequireSmartAttribute.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/RequireSmartAttribute.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/SMART.cs --- a/Hardware/HDD/SMART.cs Wed Aug 31 22:48:49 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/SSDIndilinx.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/SSDIndilinx.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/SSDIntel.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/SSDIntel.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/SSDPlextor.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/SSDPlextor.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/SSDSandforce.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/SSDSandforce.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/SmartAttribute.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/SmartAttribute.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/SmartAttributeNames.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/SmartAttributeNames.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/HDD/WindowsSmart.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/HDD/WindowsSmart.cs Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 Hardware/ISensor.cs --- a/Hardware/ISensor.cs Wed Aug 31 22:48:49 2011 +0000 +++ b/Hardware/ISensor.cs Sat Dec 31 17:31:04 2011 +0000 @@ -42,15 +42,16 @@ 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 -r 3f2d9ebacf38 -r c6ee430d6995 OpenHardwareMonitor.csproj --- a/OpenHardwareMonitor.csproj Wed Aug 31 22:48:49 2011 +0000 +++ b/OpenHardwareMonitor.csproj Sat Dec 31 17:31:04 2011 +0000 @@ -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 -r 3f2d9ebacf38 -r c6ee430d6995 OpenHardwareMonitorLib.csproj --- a/OpenHardwareMonitorLib.csproj Wed Aug 31 22:48:49 2011 +0000 +++ b/OpenHardwareMonitorLib.csproj Sat Dec 31 17:31:04 2011 +0000 @@ -56,12 +56,26 @@ + + + + + + + + + + + + + + @@ -79,9 +93,9 @@ - - - + + + diff -r 3f2d9ebacf38 -r c6ee430d6995 Resources/data.png Binary file Resources/data.png has changed