Added experimental support for ITE IT8771E super I/O chips.
3 Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 The contents of this file are subject to the Mozilla Public License Version
6 1.1 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
9 http://www.mozilla.org/MPL/
11 Software distributed under the License is distributed on an "AS IS" basis,
12 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 for the specific language governing rights and limitations under the License.
15 The Original Code is the Open Hardware Monitor code.
17 The Initial Developer of the Original Code is
18 Michael Möller <m.moeller@gmx.ch>.
19 Portions created by the Initial Developer are Copyright (C) 2009-2012
20 the Initial Developer. All Rights Reserved.
24 Roland Reinl <roland-reinl@gmx.de>
26 Alternatively, the contents of this file may be used under the terms of
27 either the GNU General Public License Version 2 or later (the "GPL"), or
28 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 in which case the provisions of the GPL or the LGPL are applicable instead
30 of those above. If you wish to allow use of your version of this file only
31 under the terms of either the GPL or the LGPL, and not to allow others to
32 use your version of this file under the terms of the MPL, indicate your
33 decision by deleting the provisions above and replace them with the notice
34 and other provisions required by the GPL or the LGPL. If you do not delete
35 the provisions above, a recipient may use your version of this file under
36 the terms of any one of the MPL, the GPL or the LGPL.
41 using System.Collections.Generic;
42 using System.Globalization;
44 using OpenHardwareMonitor.Collections;
46 namespace OpenHardwareMonitor.Hardware.HDD {
47 internal abstract class AbstractHarddrive : Hardware {
49 private const int UPDATE_DIVIDER = 30; // update only every 30s
51 // array of all harddrive types, matching type is searched in this order
52 private static Type[] hddTypes = {
58 typeof(GenericHarddisk)
61 private string firmwareRevision;
62 private readonly ISmart smart;
64 private readonly IntPtr handle;
65 private readonly int index;
68 private IList<SmartAttribute> smartAttributes;
69 private IDictionary<SmartAttribute, Sensor> sensors;
71 protected AbstractHarddrive(ISmart smart, string name,
72 string firmwareRevision, int index,
73 IEnumerable<SmartAttribute> smartAttributes, ISettings settings)
74 : base(name, new Identifier("hdd",
75 index.ToString(CultureInfo.InvariantCulture)), settings)
77 this.firmwareRevision = firmwareRevision;
79 handle = smart.OpenDrive(index);
81 smart.EnableSmart(handle, index);
86 this.smartAttributes = new List<SmartAttribute>(smartAttributes);
91 public static AbstractHarddrive CreateInstance(ISmart smart,
92 int driveIndex, ISettings settings)
94 IntPtr deviceHandle = smart.OpenDrive(driveIndex);
96 if (deviceHandle == smart.InvalidHandle)
100 string firmwareRevision;
101 bool nameValid = smart.ReadNameAndFirmwareRevision(deviceHandle,
102 driveIndex, out name, out firmwareRevision);
103 bool smartEnabled = smart.EnableSmart(deviceHandle, driveIndex);
105 DriveAttributeValue[] values = {};
107 values = smart.ReadSmartData(deviceHandle, driveIndex);
109 smart.CloseHandle(deviceHandle);
111 if (!nameValid || string.IsNullOrEmpty(name))
114 foreach (Type type in hddTypes) {
115 // get the array of name prefixes for the current type
116 NamePrefixAttribute[] namePrefixes = type.GetCustomAttributes(
117 typeof(NamePrefixAttribute), true) as NamePrefixAttribute[];
119 // get the array of the required SMART attributes for the current type
120 RequireSmartAttribute[] requiredAttributes = type.GetCustomAttributes(
121 typeof(RequireSmartAttribute), true) as RequireSmartAttribute[];
123 // check if all required attributes are present
124 bool allRequiredAttributesFound = true;
125 foreach (var requireAttribute in requiredAttributes) {
126 bool adttributeFound = false;
127 foreach (DriveAttributeValue value in values) {
128 if (value.Identifier == requireAttribute.AttributeId) {
129 adttributeFound = true;
133 if (!adttributeFound) {
134 allRequiredAttributesFound = false;
139 // if an attribute is missing, then try the next type
140 if (!allRequiredAttributesFound)
143 // check if there is a matching name prefix for this type
144 foreach (NamePrefixAttribute prefix in namePrefixes) {
145 if (name.StartsWith(prefix.Prefix, StringComparison.InvariantCulture))
146 return Activator.CreateInstance(type, smart, name, firmwareRevision,
147 driveIndex, settings) as AbstractHarddrive;
151 // no matching type has been found
155 private void CreateSensors() {
156 sensors = new Dictionary<SmartAttribute, Sensor>();
158 IList<Pair<SensorType, int>> sensorTypeAndChannels =
159 new List<Pair<SensorType, int>>();
161 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
163 foreach (SmartAttribute attribute in smartAttributes) {
164 if (!attribute.SensorType.HasValue)
168 foreach (DriveAttributeValue value in values) {
169 if (value.Identifier == attribute.Identifier) {
177 Pair<SensorType, int> pair = new Pair<SensorType, int>(
178 attribute.SensorType.Value, attribute.SensorChannel);
180 if (!sensorTypeAndChannels.Contains(pair)) {
181 Sensor sensor = new Sensor(attribute.Name,
182 attribute.SensorChannel, attribute.DefaultHiddenSensor,
183 attribute.SensorType.Value, this, null, settings);
185 sensors.Add(attribute, sensor);
186 ActivateSensor(sensor);
187 sensorTypeAndChannels.Add(pair);
192 public override HardwareType HardwareType {
193 get { return HardwareType.HDD; }
196 public virtual void UpdateAdditionalSensors(DriveAttributeValue[] values) {}
198 public override void Update() {
200 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
202 foreach (KeyValuePair<SmartAttribute, Sensor> keyValuePair in sensors) {
203 SmartAttribute attribute = keyValuePair.Key;
204 foreach (DriveAttributeValue value in values) {
205 if (value.Identifier == attribute.Identifier) {
206 Sensor sensor = keyValuePair.Value;
207 sensor.Value = attribute.ConvertValue(value);
212 UpdateAdditionalSensors(values);
216 count %= UPDATE_DIVIDER;
219 public override string GetReport() {
220 StringBuilder r = new StringBuilder();
221 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
222 DriveThresholdValue[] thresholds =
223 smart.ReadSmartThresholds(handle, index);
225 if (values.Length > 0) {
226 r.AppendLine(this.GetType().Name);
228 r.AppendLine("Drive name: " + name);
229 r.AppendLine("Firmware version: " + firmwareRevision);
231 r.AppendFormat(CultureInfo.InvariantCulture,
232 " {0}{1}{2}{3}{4}{5}{6}{7}",
234 ("Description").PadRight(35),
235 ("Raw Value").PadRight(13),
236 ("Worst").PadRight(6),
237 ("Value").PadRight(6),
238 ("Thres").PadRight(6),
239 ("Physical").PadRight(8),
240 Environment.NewLine);
242 foreach (DriveAttributeValue value in values) {
243 if (value.Identifier == 0x00)
246 byte? threshold = null;
247 foreach (DriveThresholdValue t in thresholds) {
248 if (t.Identifier == value.Identifier) {
249 threshold = t.Threshold;
253 string description = "Unknown";
254 float? physical = null;
255 foreach (SmartAttribute a in smartAttributes) {
256 if (a.Identifier == value.Identifier) {
257 description = a.Name;
258 if (a.HasRawValueConversion | a.SensorType.HasValue)
259 physical = a.ConvertValue(value);
265 string raw = BitConverter.ToString(value.RawValue);
266 r.AppendFormat(CultureInfo.InvariantCulture,
267 " {0}{1}{2}{3}{4}{5}{6}{7}",
268 value.Identifier.ToString("X2").PadRight(3),
269 description.PadRight(35),
270 raw.Replace("-", "").PadRight(13),
271 value.WorstValue.ToString(CultureInfo.InvariantCulture).PadRight(6),
272 value.AttrValue.ToString(CultureInfo.InvariantCulture).PadRight(6),
273 (threshold.HasValue ? threshold.Value.ToString(
274 CultureInfo.InvariantCulture) : "-").PadRight(6),
275 (physical.HasValue ? physical.Value.ToString(
276 CultureInfo.InvariantCulture) : "-").PadRight(8),
277 Environment.NewLine);
285 protected static float RawToInt(byte[] raw, byte value) {
286 return (raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0];
289 public override void Close() {
290 smart.CloseHandle(handle);
294 public override void Traverse(IVisitor visitor) {
295 foreach (ISensor sensor in Sensors)
296 sensor.Accept(visitor);