From c542e856d47347c2a7217804b3edf7a045e3145e Mon Sep 17 00:00:00 2001 From: Blacktempel <6657796+Blacktempel@users.noreply.github.com> Date: Sat, 8 Nov 2025 10:53:43 +0100 Subject: [PATCH] Replace Storage implementation with CrystalDiskInfo based implementation (#2015) * Replace Storage implementation with CrystalDiskInfo based implementation. * Formatting. * Code review. * Code review. * Increase space for attribute name in report. * Implement dynamic disk handling for usage sensor. Disable unused warnings. * Further cleanup in NativeMethods.txt and referenced. --- LibreHardwareMonitor/UI/MainForm.cs | 4 +- .../Hardware/Memory/MemoryGroup.cs | 2 + .../Hardware/Motherboard/Motherboard.cs | 2 + .../Hardware/Storage/ATAStorage.cs | 315 --- .../Hardware/Storage/AbstractStorage.cs | 292 --- .../Hardware/Storage/DebugSmart.cs | 425 ---- .../Hardware/Storage/GenericHardDisk.cs | 88 - .../Hardware/Storage/INVMeDrive.cs | 19 - .../Hardware/Storage/ISmart.cs | 20 +- .../Hardware/Storage/NVMeGeneric.cs | 167 -- .../Hardware/Storage/NVMeHealthInfo.cs | 46 - .../Hardware/Storage/NVMeInfo.cs | 31 - .../Hardware/Storage/NVMeIntel.cs | 174 -- .../Hardware/Storage/NVMeIntelRst.cs | 174 -- .../Hardware/Storage/NVMeSamsung.cs | 283 --- .../Hardware/Storage/NVMeSmart.cs | 196 -- .../Hardware/Storage/NVMeWindows.cs | 127 -- .../Hardware/Storage/NamePrefixAttribute.cs | 20 - .../Hardware/Storage/RequireSmartAttribute.cs | 20 - .../Hardware/Storage/SmartAttribute.cs | 86 +- .../Storage/SmartAttributeTranslator.cs | 1760 +++++++++++++++++ .../Hardware/Storage/SmartNames.cs | 263 --- .../Hardware/Storage/SsdIndilinx.cs | 43 - .../Hardware/Storage/SsdIntel.cs | 49 - .../Hardware/Storage/SsdMicron.cs | 117 -- .../Hardware/Storage/SsdPlextor.cs | 30 - .../Hardware/Storage/SsdSamsung.cs | 57 - .../Hardware/Storage/SsdSandforce.cs | 79 - .../Hardware/Storage/StorageDevice.cs | 381 ++++ .../Hardware/Storage/StorageDeviceSensor.cs | 27 + .../Hardware/Storage/StorageGeneric.cs | 29 - .../Hardware/Storage/StorageGroup.cs | 181 +- .../Hardware/Storage/StorageInfo.cs | 39 - .../Hardware/Storage/WindowsSmart.cs | 235 --- .../Hardware/Storage/WindowsStorage.cs | 102 - LibreHardwareMonitorLib/Interop/AtaSmart.cs | 101 - .../Interop/ByteExtensions.cs | 30 - .../LibreHardwareMonitorLib.csproj | 3 +- LibreHardwareMonitorLib/NativeMethods.txt | 29 - 39 files changed, 2247 insertions(+), 3799 deletions(-) delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/ATAStorage.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/AbstractStorage.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/DebugSmart.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/GenericHardDisk.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/INVMeDrive.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/NVMeGeneric.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/NVMeHealthInfo.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/NVMeInfo.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/NVMeIntel.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/NVMeIntelRst.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/NVMeSamsung.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/NVMeSmart.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/NVMeWindows.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/NamePrefixAttribute.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/RequireSmartAttribute.cs create mode 100644 LibreHardwareMonitorLib/Hardware/Storage/SmartAttributeTranslator.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/SmartNames.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/SsdIndilinx.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/SsdIntel.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/SsdMicron.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/SsdPlextor.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/SsdSamsung.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/SsdSandforce.cs create mode 100644 LibreHardwareMonitorLib/Hardware/Storage/StorageDevice.cs create mode 100644 LibreHardwareMonitorLib/Hardware/Storage/StorageDeviceSensor.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/StorageGeneric.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/StorageInfo.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/WindowsSmart.cs delete mode 100644 LibreHardwareMonitorLib/Hardware/Storage/WindowsStorage.cs delete mode 100644 LibreHardwareMonitorLib/Interop/AtaSmart.cs diff --git a/LibreHardwareMonitor/UI/MainForm.cs b/LibreHardwareMonitor/UI/MainForm.cs index bd9e545..3990d41 100644 --- a/LibreHardwareMonitor/UI/MainForm.cs +++ b/LibreHardwareMonitor/UI/MainForm.cs @@ -436,11 +436,11 @@ public sealed partial class MainForm : Form switch (_throttleAtaUpdate.Value) { case true: - AtaStorage.ThrottleInterval = TimeSpan.FromSeconds(30); + StorageDevice.ThrottleInterval = TimeSpan.FromSeconds(30); break; case false: - AtaStorage.ThrottleInterval = TimeSpan.Zero; + StorageDevice.ThrottleInterval = TimeSpan.Zero; break; } }; diff --git a/LibreHardwareMonitorLib/Hardware/Memory/MemoryGroup.cs b/LibreHardwareMonitorLib/Hardware/Memory/MemoryGroup.cs index 901d37a..8f31c07 100644 --- a/LibreHardwareMonitorLib/Hardware/Memory/MemoryGroup.cs +++ b/LibreHardwareMonitorLib/Hardware/Memory/MemoryGroup.cs @@ -50,8 +50,10 @@ internal class MemoryGroup : IGroup, IHardwareChanged } } +#pragma warning disable 67 public event HardwareEventHandler HardwareAdded; public event HardwareEventHandler HardwareRemoved; +#pragma warning restore 67 public IReadOnlyList Hardware => _hardware; diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Motherboard.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Motherboard.cs index 0205f50..c4910e7 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Motherboard.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Motherboard.cs @@ -94,11 +94,13 @@ public class Motherboard : IHardware SubHardware = subHardwareList.ToArray(); } +#pragma warning disable 67 /// public event SensorEventHandler SensorAdded; /// public event SensorEventHandler SensorRemoved; +#pragma warning restore 67 /// public HardwareType HardwareType => HardwareType.Motherboard; diff --git a/LibreHardwareMonitorLib/Hardware/Storage/ATAStorage.cs b/LibreHardwareMonitorLib/Hardware/Storage/ATAStorage.cs deleted file mode 100644 index 42cf0d6..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/ATAStorage.cs +++ /dev/null @@ -1,315 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using LibreHardwareMonitor.Interop; - -namespace LibreHardwareMonitor.Hardware.Storage; - -public abstract class AtaStorage : AbstractStorage -{ - // array of all hard drive types, matching type is searched in this order - private static readonly Type[] _hddTypes = { typeof(SsdPlextor), typeof(SsdIntel), typeof(SsdSandforce), typeof(SsdIndilinx), typeof(SsdSamsung), typeof(SsdMicron), typeof(GenericHardDisk) }; - - private IDictionary _sensors; - - private static TimeSpan _throttleInterval = TimeSpan.Zero; - private DateTime _lastUpdate = DateTime.MinValue; - - /// - /// Gets the SMART data. - /// - public ISmart Smart { get; } - - /// - /// Gets the SMART attributes. - /// - public IReadOnlyList SmartAttributes { get; } - - internal AtaStorage(StorageInfo storageInfo, ISmart smart, string name, string firmwareRevision, string id, int index, IReadOnlyList smartAttributes, ISettings settings) - : base(storageInfo, name, firmwareRevision, id, index, settings) - { - Smart = smart; - if (smart.IsValid) - smart.EnableSmart(); - - SmartAttributes = smartAttributes; - CreateSensors(); - } - - internal static AbstractStorage CreateInstance(StorageInfo storageInfo, ISettings settings) - { - ISmart smart = new WindowsSmart(storageInfo.Index); - string name = null; - string firmwareRevision = null; - AtaSmart.SMART_ATTRIBUTE[] smartAttributes = []; - - if (smart.IsValid) - { - bool nameValid = smart.ReadNameAndFirmwareRevision(out name, out firmwareRevision); - bool smartEnabled = smart.EnableSmart(); - - if (smartEnabled) - smartAttributes = smart.ReadSmartData(); - - if (!nameValid) - { - name = null; - firmwareRevision = null; - } - } - else - { - string[] logicalDrives = WindowsStorage.GetLogicalDrives(storageInfo.Index); - if (logicalDrives == null || logicalDrives.Length == 0) - { - smart.Close(); - return null; - } - - bool hasNonZeroSizeDrive = false; - foreach (string logicalDrive in logicalDrives) - { - try - { - var driveInfo = new DriveInfo(logicalDrive); - if (driveInfo.TotalSize > 0) - { - hasNonZeroSizeDrive = true; - break; - } - } - catch (ArgumentException) { } - catch (IOException) { } - catch (UnauthorizedAccessException) { } - } - - if (!hasNonZeroSizeDrive) - { - smart.Close(); - return null; - } - } - - if (string.IsNullOrEmpty(name)) - name = string.IsNullOrEmpty(storageInfo.Name) ? "Generic Hard Disk" : storageInfo.Name; - - if (string.IsNullOrEmpty(firmwareRevision)) - firmwareRevision = string.IsNullOrEmpty(storageInfo.Revision) ? "Unknown" : storageInfo.Revision; - - foreach (Type type in _hddTypes) - { - // get the array of the required SMART attributes for the current type - - // check if all required attributes are present - bool allAttributesFound = true; - - if (type.GetCustomAttributes(typeof(RequireSmartAttribute), true) is RequireSmartAttribute[] requiredAttributes) - { - foreach (RequireSmartAttribute requireAttribute in requiredAttributes) - { - bool attributeFound = false; - - foreach (AtaSmart.SMART_ATTRIBUTE value in smartAttributes) - { - if (value.Id == requireAttribute.AttributeId) - { - attributeFound = true; - break; - } - } - - if (!attributeFound) - { - allAttributesFound = false; - break; - } - } - } - - // if an attribute is missing, then try the next type - if (!allAttributesFound) - continue; - - // check if there is a matching name prefix for this type - if (type.GetCustomAttributes(typeof(NamePrefixAttribute), true) is NamePrefixAttribute[] namePrefixes) - { - foreach (NamePrefixAttribute prefix in namePrefixes) - { - if (name.StartsWith(prefix.Prefix, StringComparison.InvariantCulture)) - { - const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; - - return Activator.CreateInstance(type, flags, null, [storageInfo, smart, name, firmwareRevision, storageInfo.Index, settings], null) as AtaStorage; - } - } - } - } - - // no matching type has been found - smart.Close(); - return null; - } - - protected sealed override void CreateSensors() - { - _sensors = new Dictionary(); - - if (Smart.IsValid) - { - byte[] smartIds = Smart.ReadSmartData().Select(x => x.Id).ToArray(); - - // unique attributes by SensorType and SensorChannel. - IEnumerable smartAttributes = SmartAttributes - .Where(x => x.SensorType.HasValue && smartIds.Contains(x.Id)) - .GroupBy(x => new { x.SensorType.Value, x.SensorChannel }) - .Select(x => x.First()); - - _sensors = smartAttributes.ToDictionary(attribute => attribute, - attribute => new Sensor(attribute.SensorName, - attribute.SensorChannel, - attribute.DefaultHiddenSensor, - attribute.SensorType.GetValueOrDefault(), - this, - attribute.ParameterDescriptions, - _settings)); - - foreach (KeyValuePair sensor in _sensors) - ActivateSensor(sensor.Value); - } - - base.CreateSensors(); - } - - public static TimeSpan ThrottleInterval - { - get - { - return _throttleInterval; - } - set - { - _throttleInterval = value; - } - } - - protected virtual void UpdateAdditionalSensors(AtaSmart.SMART_ATTRIBUTE[] values) { } - - protected override void UpdateSensors() - { - if (DateTime.UtcNow - _lastUpdate < ThrottleInterval) - { - return; - } - _lastUpdate = DateTime.UtcNow; - - if (Smart.IsValid) - { - AtaSmart.SMART_ATTRIBUTE[] smartAttributes = Smart.ReadSmartData(); - - foreach (KeyValuePair keyValuePair in _sensors) - { - SmartAttribute attribute = keyValuePair.Key; - foreach (AtaSmart.SMART_ATTRIBUTE value in smartAttributes) - { - if (value.Id == attribute.Id) - { - Sensor sensor = keyValuePair.Value; - sensor.Value = attribute.ConvertValue(value, sensor.Parameters); - } - } - } - - UpdateAdditionalSensors(smartAttributes); - } - } - - protected override unsafe void GetReport(StringBuilder r) - { - if (Smart.IsValid) - { - AtaSmart.SMART_ATTRIBUTE[] values = Smart.ReadSmartData(); - AtaSmart.SMART_THRESHOLD[] thresholds = Smart.ReadSmartThresholds(); - if (values.Length > 0) - { - r.AppendFormat(CultureInfo.InvariantCulture, - " {0}{1}{2}{3}{4}{5}{6}{7}", - "Id".PadRight(3), - "Description".PadRight(35), - "Raw Value".PadRight(13), - "Worst".PadRight(6), - "Value".PadRight(6), - "Threshold".PadRight(6), - "Physical".PadRight(8), - Environment.NewLine); - - foreach (AtaSmart.SMART_ATTRIBUTE value in values) - { - if (value.Id == 0x00) - break; - - byte? threshold = null; - foreach (AtaSmart.SMART_THRESHOLD t in thresholds) - { - if (t.Id == value.Id) - { - threshold = t.Threshold; - } - } - - string description = "Unknown"; - float? physical = null; - foreach (SmartAttribute a in SmartAttributes) - { - if (a.Id == value.Id) - { - description = a.Name; - if (a.HasRawValueConversion | a.SensorType.HasValue) - physical = a.ConvertValue(value, null); - else - physical = null; - } - } - - Span rawValue = new(value.RawValue, 6); - string raw = BitConverter.ToString(rawValue.ToArray()); - - r.AppendFormat(CultureInfo.InvariantCulture, - " {0}{1}{2}{3}{4}{5}{6}{7}", - value.Id.ToString("X2").PadRight(3), - description.PadRight(35), - raw.Replace("-", string.Empty).PadRight(13), - value.WorstValue.ToString(CultureInfo.InvariantCulture).PadRight(6), - value.CurrentValue.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(); - } - } - } - - protected static float RawToInt(byte[] raw, byte value, IReadOnlyList parameters) - { - return (raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]; - } - - public override void Close() - { - Smart.Close(); - base.Close(); - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/AbstractStorage.cs b/LibreHardwareMonitorLib/Hardware/Storage/AbstractStorage.cs deleted file mode 100644 index 2092e25..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/AbstractStorage.cs +++ /dev/null @@ -1,292 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Text; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.Storage.FileSystem; -using Windows.Win32.System.Ioctl; -using LibreHardwareMonitor.Interop; - -namespace LibreHardwareMonitor.Hardware.Storage; - -public abstract class AbstractStorage : Hardware -{ - private readonly PerformanceValue _perfRead = new(); - private readonly PerformanceValue _perfTotal = new(); - private readonly PerformanceValue _perfWrite = new(); - private readonly StorageInfo _storageInfo; - - private long _lastReadCount; - private long _lastTime; - private long _lastWriteCount; - private Sensor _sensorDiskReadActivity; - private Sensor _sensorDiskReadRate; - private Sensor _sensorDiskTotalActivity; - private Sensor _sensorDiskWriteActivity; - private Sensor _sensorDiskWriteRate; - private Sensor _usageSensor; - - internal AbstractStorage(StorageInfo storageInfo, string name, string firmwareRevision, string id, int index, ISettings settings) - : base(name, new Identifier(id, index.ToString(CultureInfo.InvariantCulture)), settings) - { - _storageInfo = storageInfo; - FirmwareRevision = firmwareRevision; - Index = index; - - string[] logicalDrives = WindowsStorage.GetLogicalDrives(index); - var driveInfoList = new List(logicalDrives.Length); - - foreach (string logicalDrive in logicalDrives) - { - try - { - var di = new DriveInfo(logicalDrive); - if (di.TotalSize > 0) - driveInfoList.Add(new DriveInfo(logicalDrive)); - } - catch (ArgumentException) - { } - catch (IOException) - { } - catch (UnauthorizedAccessException) - { } - } - - DriveInfos = driveInfoList.ToArray(); - } - - public DriveInfo[] DriveInfos { get; } - - public string FirmwareRevision { get; } - - public override HardwareType HardwareType => HardwareType.Storage; - - public int Index { get; } - - /// - public override void Close() - { - _storageInfo.Handle?.Close(); - base.Close(); - } - - public static AbstractStorage CreateInstance(string deviceId, uint driveNumber, ulong diskSize, int scsiPort, ISettings settings) - { - StorageInfo info = WindowsStorage.GetStorageInfo(deviceId, driveNumber); - if (info == null || info.Removable || info.BusType is STORAGE_BUS_TYPE.BusTypeVirtual or STORAGE_BUS_TYPE.BusTypeFileBackedVirtual) - return null; - - info.DiskSize = diskSize; - info.DeviceId = deviceId; - info.Handle = PInvoke.CreateFile(deviceId, - (uint)FileAccess.ReadWrite, - FILE_SHARE_MODE.FILE_SHARE_READ | FILE_SHARE_MODE.FILE_SHARE_WRITE, - null, - FILE_CREATION_DISPOSITION.OPEN_EXISTING, - FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, - null); - info.Scsi = $@"\\.\SCSI{scsiPort}:"; - - //fallback, when it is not possible to read out with the nvme implementation, - //try it with the sata smart implementation - if (info.BusType == STORAGE_BUS_TYPE.BusTypeNvme) - { - AbstractStorage x = NVMeGeneric.CreateInstance(info, settings); - if (x != null) - return x; - } - - return info.BusType is STORAGE_BUS_TYPE.BusTypeAta or STORAGE_BUS_TYPE.BusTypeSata or STORAGE_BUS_TYPE.BusTypeNvme - ? AtaStorage.CreateInstance(info, settings) - : StorageGeneric.CreateInstance(info, settings); - } - - protected virtual void CreateSensors() - { - if (DriveInfos.Length > 0) - { - _usageSensor = new Sensor("Used Space", 0, SensorType.Load, this, _settings); - ActivateSensor(_usageSensor); - } - - _sensorDiskReadActivity = new Sensor("Read Activity", 31, SensorType.Load, this, _settings); - ActivateSensor(_sensorDiskReadActivity); - - _sensorDiskWriteActivity = new Sensor("Write Activity", 32, SensorType.Load, this, _settings); - ActivateSensor(_sensorDiskWriteActivity); - - _sensorDiskTotalActivity = new Sensor("Total Activity", 33, SensorType.Load, this, _settings); - ActivateSensor(_sensorDiskTotalActivity); - - _sensorDiskReadRate = new Sensor("Read Rate", 34, SensorType.Throughput, this, _settings); - ActivateSensor(_sensorDiskReadRate); - - _sensorDiskWriteRate = new Sensor("Write Rate", 35, SensorType.Throughput, this, _settings); - ActivateSensor(_sensorDiskWriteRate); - } - - protected abstract void UpdateSensors(); - - public override void Update() - { - // Update statistics. - if (_storageInfo != null) - { - try - { - UpdatePerformanceSensors(); - } - catch - { - // Ignored. - } - } - - UpdateSensors(); - - if (_usageSensor != null) - { - long totalSize = 0; - long totalFreeSpace = 0; - - for (int i = 0; i < DriveInfos.Length; i++) - { - if (!DriveInfos[i].IsReady) - continue; - - try - { - totalSize += DriveInfos[i].TotalSize; - totalFreeSpace += DriveInfos[i].TotalFreeSpace; - } - catch (IOException) - { } - catch (UnauthorizedAccessException) - { } - } - - if (totalSize > 0) - _usageSensor.Value = 100.0f - (100.0f * totalFreeSpace / totalSize); - else - _usageSensor.Value = null; - } - } - - private unsafe void UpdatePerformanceSensors() - { - DISK_PERFORMANCE diskPerformance = new(); - - uint bytesReturned; - if (!PInvoke.DeviceIoControl((HANDLE)_storageInfo.Handle.DangerousGetHandle(), PInvoke.IOCTL_DISK_PERFORMANCE, null, 0, &diskPerformance, (uint)sizeof(DISK_PERFORMANCE), &bytesReturned, null)) - { - return; - } - - _perfRead.Update(diskPerformance.ReadTime, diskPerformance.QueryTime); - _sensorDiskReadActivity.Value = (float)_perfRead.Result; - - _perfWrite.Update(diskPerformance.WriteTime, diskPerformance.QueryTime); - _sensorDiskWriteActivity.Value = (float)_perfWrite.Result; - - _perfTotal.Update(diskPerformance.IdleTime, diskPerformance.QueryTime); - _sensorDiskTotalActivity.Value = (float)(100 - _perfTotal.Result); - - long readCount = diskPerformance.BytesRead; - long readDiff = readCount - _lastReadCount; - _lastReadCount = readCount; - - long writeCount = diskPerformance.BytesWritten; - long writeDiff = writeCount - _lastWriteCount; - _lastWriteCount = writeCount; - - long currentTime = Stopwatch.GetTimestamp(); - if (_lastTime != 0) - { - double timeDeltaSeconds = TimeSpan.FromTicks(currentTime - _lastTime).TotalSeconds; - - double writeSpeed = writeDiff * (1 / timeDeltaSeconds); - _sensorDiskWriteRate.Value = (float)writeSpeed; - - double readSpeed = readDiff * (1 / timeDeltaSeconds); - _sensorDiskReadRate.Value = (float)readSpeed; - } - - _lastTime = currentTime; - } - - protected abstract void GetReport(StringBuilder r); - - public override string GetReport() - { - var r = new StringBuilder(); - r.AppendLine("Storage"); - r.AppendLine(); - r.AppendLine("Drive Name: " + _name); - r.AppendLine("Firmware Version: " + FirmwareRevision); - r.AppendLine(); - GetReport(r); - - foreach (DriveInfo di in DriveInfos) - { - if (!di.IsReady) - continue; - - try - { - r.AppendLine("Logical Drive Name: " + di.Name); - r.AppendLine("Format: " + di.DriveFormat); - r.AppendLine("Total Size: " + di.TotalSize); - r.AppendLine("Total Free Space: " + di.TotalFreeSpace); - r.AppendLine(); - } - catch (IOException) - { } - catch (UnauthorizedAccessException) - { } - } - - return r.ToString(); - } - - public override void Traverse(IVisitor visitor) - { - foreach (ISensor sensor in Sensors) - sensor.Accept(visitor); - } - - /// - /// Helper to calculate the disk performance with base timestamps - /// https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-perfrawdata - /// - private class PerformanceValue - { - public double Result { get; private set; } - - private long Time { get; set; } - - private long Value { get; set; } - - public void Update(long val, long valBase) - { - long diffValue = val - Value; - long diffTime = valBase - Time; - - Value = val; - Time = valBase; - Result = 100.0 / diffTime * diffValue; - - //sometimes it is possible that diff_value > diff_timebase - //limit result to 100%, this is because timing issues during read from pcie controller an latency between IO operation - if (Result > 100) - Result = 100; - } - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/DebugSmart.cs b/LibreHardwareMonitorLib/Hardware/Storage/DebugSmart.cs deleted file mode 100644 index d547672..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/DebugSmart.cs +++ /dev/null @@ -1,425 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -#if DEBUG - -using System; -using LibreHardwareMonitor.Interop; - -namespace LibreHardwareMonitor.Hardware.Storage -{ - internal class DebugSmart : ISmart - { - private readonly Drive[] _drives = - [ - new("KINGSTON SNV425S264GB", null, 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("PLEXTOR PX-128M2S", "1.03", 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("OCZ-VERTEX2", "1.25", 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("WDC WD5000AADS-00S9B0", null, 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("INTEL SSDSA2M080G2GC", null, 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("OCZ-VERTEX", null, 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("INTEL SSDSA2CW120G3", null, 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"), - new("CORSAIR CMFSSD-128GBG2D", "VBM19C1Q", 16, - @"09 100900000000 99 99 0 - 0C 560200000000 99 99 0 - AF 000000000000 100 100 10 - B0 000000000000 100 100 10 - B1 2A0000000000 99 99 17 - B2 180000000000 60 60 10 - B3 4B0000000000 98 98 10 - B4 B50E00000000 98 98 10 - B5 000000000000 100 100 10 - B6 000000000000 100 100 10 - B7 000000000000 100 100 10 - BB 000000000000 100 100 0 - C3 000000000000 200 200 0 - C6 000000000000 100 100 0 - C7 810100000000 253 253 0 - E8 240000000000 60 60 10 - E9 630594120000 92 92 0"), - new("Maxtor 6L300R0", null, 10, - @"3 9E5500000000 183 193 - 4 0A0D00000000 252 252 - 5 010000000000 253 253 - 6 000000000000 253 253 - 7 000000000000 252 253 - 8 DFA700000000 224 245 - 9 CE5700000000 155 155 - 10 000000000000 252 253 - 11 000000000000 252 253 - 12 BA0400000000 250 250 - 192 000000000000 253 253 - 193 000000000000 253 253 - 194 3D0000000000 253 42 - 195 5D1F00000000 252 253 - 196 000000000000 253 253 - 197 010000000000 253 253 - 198 000000000000 253 253 - 199 030000000000 196 199 - 200 000000000000 252 253 - 201 000000000000 252 253 - 202 000000000000 252 253 - 203 000000000000 252 253 - 204 000000000000 252 253 - 205 000000000000 252 253 - 207 000000000000 252 253 - 208 000000000000 252 253 - 209 EA0000000000 234 234 - 210 000000000000 252 253 - 211 000000000000 252 253 - 212 000000000000 252 253 - 130 5B0300010002 1 9 - 59 FC3203030100 205 0 - 1 000000000000 0 0 - 144 000000000000 0 34 "), - new("M4-CT256M4SSD2", "0309", 16, - @"01 000000000000 100 100 50 - 05 000000000000 100 100 10 - 09 AB0100000000 100 100 1 - 0C 6E0000000000 100 100 1 - AA 000000000000 100 100 10 - AB 000000000000 100 100 1 - AC 000000000000 100 100 1 - AD 060000000000 100 100 10 - AE 000000000000 100 100 1 - B5 79003D00B700 100 100 1 - B7 000000000000 100 100 1 - B8 000000000000 100 100 50 - BB 000000000000 100 100 1 - BC 000000000000 100 100 1 - BD 5B0000000000 100 100 1 - C2 000000000000 100 100 0 - C3 000000000000 100 100 1 - C4 000000000000 100 100 1 - C5 000000000000 100 100 1 - C6 000000000000 100 100 1 - C7 000000000000 100 100 1 - CA 000000000000 100 100 1 - CE 000000000000 100 100 1 "), - new("C300-CTFDDAC256MAG", "0007", 16, - @"01 000000000000 100 100 0 - 05 000000000000 100 100 0 - 09 4C0A00000000 100 100 0 - 0C 0F0100000000 100 100 0 - AA 000000000000 100 100 0 - AB 000000000000 100 100 0 - AC 000000000000 100 100 0 - AD 1B0000000000 100 100 0 - AE 000000000000 100 100 0 - B5 D30357012B05 100 100 0 - B7 000000000000 100 100 0 - B8 000000000000 100 100 0 - BB 000000000000 100 100 0 - BC 000000000000 100 100 0 - BD C60100000000 100 100 0 - C3 000000000000 100 100 0 - C4 000000000000 100 100 0 - C5 000000000000 100 100 0 - C6 000000000000 100 100 0 - C7 000000000000 100 100 0 - CA 000000000000 100 100 0 - CE 000000000000 100 100 0"), - new("M4-CT064M4SSD2", "0009", 16, - @"01 000000000000 100 100 50 - 05 000000000000 100 100 10 - 09 260000000000 100 100 1 - 0C 5A0000000000 100 100 1 - AA 000000000000 100 100 10 - AB 000000000000 100 100 1 - AC 000000000000 100 100 1 - AD 010000000000 100 100 10 - AE 000000000000 100 100 1 - B5 2B000E003A00 100 100 1 - B7 000000000000 100 100 1 - B8 000000000000 100 100 50 - BB 000000000000 100 100 1 - BC 000000000000 100 100 1 - BD 310000000000 100 100 1 - C2 000000000000 100 100 0 - C3 000000000000 100 100 1 - C4 000000000000 100 100 1 - C5 000000000000 100 100 1 - C6 000000000000 100 100 1 - C7 000000000000 100 100 1 - CA 000000000000 100 100 1 - CE 000000000000 100 100 1"), - new("M4-CT128M4SSD2", "000F", 16, - @"01 000000000000 100 100 50 - 05 000000000000 100 100 10 - 09 CA1400000000 100 100 1 - 0C A30200000000 100 100 1 - AA 000000000000 100 100 10 - AB 000000000000 100 100 1 - AC 000000000000 100 100 1 - AD 1F0000000000 99 99 10 - AE 140000000000 100 100 1 - B5 12037C028E05 100 100 1 - B7 000000000000 100 100 1 - B8 000000000000 100 100 50 - BB 000000000000 100 100 1 - BC 000000000000 100 100 1 - BD 510000000000 100 100 1 - C2 000000000000 100 100 0 - C3 000000000000 100 100 1 - C4 000000000000 100 100 1 - C5 000000000000 100 100 1 - C6 000000000000 100 100 1 - C7 000000000000 100 100 1 - CA 010000000000 99 99 1 - CE 000000000000 100 100 1 "), - new("Samsung SSD 840 PRO Series", "DXM05B0Q", 16, - @"05 000000000000 100 100 10 - 09 541200000000 99 99 0 - 0C 820500000000 98 98 0 - B1 B90200000000 80 80 0 - B3 000000000000 100 100 10 - B5 000000000000 100 100 10 - B6 000000000000 100 100 10 - B7 000000000000 100 100 10 - BB 000000000000 100 100 0 - BE 1C0000000000 48 72 0 - C3 000000000000 200 200 0 - C7 020000000000 99 99 0 - EB 690000000000 99 99 0 - F1 A56AA1F60200 99 99 0") - ]; - - private int _driveNumber; - - public DebugSmart(int driveNumber) - { - _driveNumber = driveNumber; - } - - public bool IsValid => true; - - public void Close() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public bool EnableSmart() - { - if (_driveNumber < 0) - throw new ObjectDisposedException(nameof(DebugSmart)); - return true; - } - - public AtaSmart.SMART_ATTRIBUTE[] ReadSmartData() - { - if (_driveNumber < 0) - throw new ObjectDisposedException(nameof(DebugSmart)); - return _drives[_driveNumber].DriveAttributeValues; - } - - public AtaSmart.SMART_THRESHOLD[] ReadSmartThresholds() - { - if (_driveNumber < 0) - throw new ObjectDisposedException(nameof(DebugSmart)); - return _drives[_driveNumber].DriveThresholdValues; - } - - public bool ReadNameAndFirmwareRevision(out string name, out string firmwareRevision) - { - if (_driveNumber < 0) - throw new ObjectDisposedException(nameof(DebugSmart)); - name = _drives[_driveNumber].Name; - firmwareRevision = _drives[_driveNumber].FirmwareVersion; - return true; - } - - public void Dispose() - { - Close(); - } - - protected void Dispose(bool disposing) - { - if (disposing) - _driveNumber = -1; - } - - private class Drive - { - public unsafe Drive(string name, string firmware, int idBase, string value) - { - Name = name; - FirmwareVersion = firmware; - - string[] lines = value.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - DriveAttributeValues = new AtaSmart.SMART_ATTRIBUTE[lines.Length]; - var thresholds = new System.Collections.Generic.List(); - - for (int i = 0; i < lines.Length; i++) - { - string[] array = lines[i].Split([' '], StringSplitOptions.RemoveEmptyEntries); - - if (array.Length is not 4 and not 5) - throw new Exception(); - - var v = new AtaSmart.SMART_ATTRIBUTE { Id = Convert.ToByte(array[0], idBase) }; - - 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.CurrentValue = Convert.ToByte(array[3], 10); - - DriveAttributeValues[i] = v; - - if (array.Length == 5) - { - var t = new AtaSmart.SMART_THRESHOLD { Id = v.Id, Threshold = Convert.ToByte(array[4], 10) }; - thresholds.Add(t); - } - } - - DriveThresholdValues = thresholds.ToArray(); - } - - public AtaSmart.SMART_ATTRIBUTE[] DriveAttributeValues { get; } - - public AtaSmart.SMART_THRESHOLD[] DriveThresholdValues { get; } - - public string FirmwareVersion { get; } - - public string Name { get; } - } - } -} - -#endif diff --git a/LibreHardwareMonitorLib/Hardware/Storage/GenericHardDisk.cs b/LibreHardwareMonitorLib/Hardware/Storage/GenericHardDisk.cs deleted file mode 100644 index 96a1b72..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/GenericHardDisk.cs +++ /dev/null @@ -1,88 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System.Collections.Generic; - -namespace LibreHardwareMonitor.Hardware.Storage; - -[NamePrefix("")] -public class GenericHardDisk : AtaStorage -{ - private static readonly List _smartAttributes = new() - { - new SmartAttribute(0x01, SmartNames.ReadErrorRate), - new SmartAttribute(0x02, SmartNames.ThroughputPerformance), - new SmartAttribute(0x03, SmartNames.SpinUpTime), - new SmartAttribute(0x04, SmartNames.StartStopCount, RawToInt), - new SmartAttribute(0x05, SmartNames.ReallocatedSectorsCount), - new SmartAttribute(0x06, SmartNames.ReadChannelMargin), - new SmartAttribute(0x07, SmartNames.SeekErrorRate), - new SmartAttribute(0x08, SmartNames.SeekTimePerformance), - new SmartAttribute(0x09, SmartNames.PowerOnHours, RawToInt), - new SmartAttribute(0x0A, SmartNames.SpinRetryCount), - new SmartAttribute(0x0B, SmartNames.RecalibrationRetries), - new SmartAttribute(0x0C, SmartNames.PowerCycleCount, RawToInt), - new SmartAttribute(0x0D, SmartNames.SoftReadErrorRate), - new SmartAttribute(0xAA, SmartNames.Unknown), - new SmartAttribute(0xAB, SmartNames.Unknown), - new SmartAttribute(0xAC, SmartNames.Unknown), - new SmartAttribute(0xB7, SmartNames.SataDownshiftErrorCount, RawToInt), - new SmartAttribute(0xB8, SmartNames.EndToEndError), - new SmartAttribute(0xB9, SmartNames.HeadStability), - new SmartAttribute(0xBA, SmartNames.InducedOpVibrationDetection), - new SmartAttribute(0xBB, SmartNames.ReportedUncorrectableErrors, RawToInt), - new SmartAttribute(0xBC, SmartNames.CommandTimeout, RawToInt), - new SmartAttribute(0xBD, SmartNames.HighFlyWrites), - new SmartAttribute(0xBF, SmartNames.GSenseErrorRate), - new SmartAttribute(0xC0, SmartNames.EmergencyRetractCycleCount), - new SmartAttribute(0xC1, SmartNames.LoadCycleCount), - new SmartAttribute(0xC3, SmartNames.HardwareEccRecovered), - new SmartAttribute(0xC4, SmartNames.ReallocationEventCount), - new SmartAttribute(0xC5, SmartNames.CurrentPendingSectorCount), - new SmartAttribute(0xC6, SmartNames.UncorrectableSectorCount), - new SmartAttribute(0xC7, SmartNames.UltraDmaCrcErrorCount), - new SmartAttribute(0xC8, SmartNames.WriteErrorRate), - new SmartAttribute(0xCA, SmartNames.DataAddressMarkErrors), - new SmartAttribute(0xCB, SmartNames.RunOutCancel), - new SmartAttribute(0xCC, SmartNames.SoftEccCorrection), - new SmartAttribute(0xCD, SmartNames.ThermalAsperityRate), - new SmartAttribute(0xCE, SmartNames.FlyingHeight), - new SmartAttribute(0xCF, SmartNames.SpinHighCurrent), - new SmartAttribute(0xD0, SmartNames.SpinBuzz), - new SmartAttribute(0xD1, SmartNames.OfflineSeekPerformance), - new SmartAttribute(0xD3, SmartNames.VibrationDuringWrite), - new SmartAttribute(0xD4, SmartNames.ShockDuringWrite), - new SmartAttribute(0xDC, SmartNames.DiskShift), - new SmartAttribute(0xDD, SmartNames.AlternativeGSenseErrorRate), - new SmartAttribute(0xDE, SmartNames.LoadedHours), - new SmartAttribute(0xDF, SmartNames.LoadUnloadRetryCount), - new SmartAttribute(0xE0, SmartNames.LoadFriction), - new SmartAttribute(0xE1, SmartNames.LoadUnloadCycleCount), - new SmartAttribute(0xE2, SmartNames.LoadInTime), - new SmartAttribute(0xE3, SmartNames.TorqueAmplificationCount), - new SmartAttribute(0xE4, SmartNames.PowerOffRetractCycle), - new SmartAttribute(0xE6, SmartNames.GmrHeadAmplitude), - new SmartAttribute(0xE8, SmartNames.EnduranceRemaining), - new SmartAttribute(0xE9, SmartNames.PowerOnHours), - new SmartAttribute(0xF0, SmartNames.HeadFlyingHours), - new SmartAttribute(0xF1, SmartNames.TotalLbasWritten), - new SmartAttribute(0xF2, SmartNames.TotalLbasRead), - new SmartAttribute(0xFA, SmartNames.ReadErrorRetryRate), - new SmartAttribute(0xFE, SmartNames.FreeFallProtection), - new SmartAttribute(0xC2, SmartNames.Temperature, (r, _, p) => r[0] + (p?[0].Value ?? 0), - SensorType.Temperature, 0, SmartNames.Temperature, false, - new[] { new ParameterDescription("Offset [°C]", "Temperature offset of the thermal sensor.\n" + "Temperature = Value + Offset.", 0) }), - new SmartAttribute(0xE7, SmartNames.Temperature, (r, _, p) => r[0] + (p?[0].Value ?? 0), - SensorType.Temperature, 0, SmartNames.Temperature, false, - new[] { new ParameterDescription("Offset [°C]", "Temperature offset of the thermal sensor.\n" + "Temperature = Value + Offset.", 0) }), - new SmartAttribute(0xBE, SmartNames.TemperatureDifferenceFrom100, (r, _, p) => r[0] + (p?[0].Value ?? 0), - SensorType.Temperature, 0, "Temperature", false, - new[] { new ParameterDescription("Offset [°C]", "Temperature offset of the thermal sensor.\n" + "Temperature = Value + Offset.", 0) }) - }; - - internal GenericHardDisk(StorageInfo storageInfo, ISmart smart, string name, string firmwareRevision, int index, ISettings settings) - : base(storageInfo, smart, name, firmwareRevision, "hdd", index, _smartAttributes, settings) { } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/INVMeDrive.cs b/LibreHardwareMonitorLib/Hardware/Storage/INVMeDrive.cs deleted file mode 100644 index 3ceedb3..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/INVMeDrive.cs +++ /dev/null @@ -1,19 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using System.Runtime.InteropServices; -using Windows.Win32.Storage.Nvme; -using LibreHardwareMonitor.Interop; - -namespace LibreHardwareMonitor.Hardware.Storage; - -internal interface INVMeDrive -{ - SafeHandle Identify(StorageInfo storageInfo); - - bool IdentifyController(SafeHandle hDevice, out NVME_IDENTIFY_CONTROLLER_DATA data); - - bool HealthInfoLog(SafeHandle hDevice, out NVME_HEALTH_INFO_LOG data); -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/ISmart.cs b/LibreHardwareMonitorLib/Hardware/Storage/ISmart.cs index 559b5f1..838febf 100644 --- a/LibreHardwareMonitorLib/Hardware/Storage/ISmart.cs +++ b/LibreHardwareMonitorLib/Hardware/Storage/ISmart.cs @@ -4,22 +4,14 @@ // Partial Copyright (C) Michael Möller and Contributors. // All Rights Reserved. -using System; -using LibreHardwareMonitor.Interop; +using System.Collections.Generic; namespace LibreHardwareMonitor.Hardware.Storage; -public interface ISmart : IDisposable +public interface ISmart { - bool IsValid { get; } - - void Close(); - - bool EnableSmart(); - - AtaSmart.SMART_ATTRIBUTE[] ReadSmartData(); - - AtaSmart.SMART_THRESHOLD[] ReadSmartThresholds(); - - bool ReadNameAndFirmwareRevision(out string name, out string firmwareRevision); + /// + /// Gets all available smart attributes. + /// + IReadOnlyList Attributes { get; } } diff --git a/LibreHardwareMonitorLib/Hardware/Storage/NVMeGeneric.cs b/LibreHardwareMonitorLib/Hardware/Storage/NVMeGeneric.cs deleted file mode 100644 index 4ea9c6f..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/NVMeGeneric.cs +++ /dev/null @@ -1,167 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using System.Collections.Generic; -using System.Text; -using LibreHardwareMonitor.Interop; - -namespace LibreHardwareMonitor.Hardware.Storage; - -public sealed class NVMeGeneric : AbstractStorage -{ - private const ulong Scale = 1000000; - private const ulong Units = 512; - private readonly NVMeInfo _info; - private readonly List _sensors = new(); - - /// - /// Gets the SMART data. - /// - public NVMeSmart Smart { get; } - - private NVMeGeneric(StorageInfo storageInfo, NVMeInfo info, int index, ISettings settings) - : base(storageInfo, info.Model, info.Revision, "nvme", index, settings) - { - Smart = new NVMeSmart(storageInfo); - _info = info; - CreateSensors(); - } - - private static NVMeInfo GetDeviceInfo(StorageInfo storageInfo) - { - var smart = new NVMeSmart(storageInfo); - return smart.GetInfo(); - } - - internal static AbstractStorage CreateInstance(StorageInfo storageInfo, ISettings settings) - { - NVMeInfo nvmeInfo = GetDeviceInfo(storageInfo); - return nvmeInfo == null ? null : new NVMeGeneric(storageInfo, nvmeInfo, storageInfo.Index, settings); - } - - protected override void CreateSensors() - { - NVMeHealthInfo log = Smart.GetHealthInfo(); - if (log != null) - { - AddSensor("Temperature", 0, false, SensorType.Temperature, health => health.Temperature); - AddSensor("Available Spare", 1, false, SensorType.Level, health => health.AvailableSpare); - AddSensor("Available Spare Threshold", 2, false, SensorType.Level, health => health.AvailableSpareThreshold); - AddSensor("Percentage Used", 3, false, SensorType.Level, health => health.PercentageUsed); - AddSensor("Data Read", 4, false, SensorType.Data, health => UnitsToData(health.DataUnitRead)); - AddSensor("Data Written", 5, false, SensorType.Data, health => UnitsToData(health.DataUnitWritten)); - - int sensorIdx = 6; - for (int i = 0; i < log.TemperatureSensors.Length; i++) - { - int idx = i; - if (log.TemperatureSensors[idx] > short.MinValue) - { - AddSensor("Temperature " + (idx + 1), sensorIdx, false, SensorType.Temperature, health => health.TemperatureSensors[idx]); - sensorIdx++; - } - } - } - - base.CreateSensors(); - } - - private void AddSensor(string name, int index, bool defaultHidden, SensorType sensorType, GetSensorValue getValue) - { - var sensor = new NVMeSensor(name, index, defaultHidden, sensorType, this, _settings, getValue) - { - Value = 0 - }; - ActivateSensor(sensor); - _sensors.Add(sensor); - } - - private static float UnitsToData(ulong u) - { - // one unit is 512 * 1000 bytes, return in GB (not GiB) - return Units * u / Scale; - } - - protected override void UpdateSensors() - { - NVMeHealthInfo health = Smart.GetHealthInfo(); - if (health == null) - return; - - foreach (NVMeSensor sensor in _sensors) - sensor.Update(health); - } - - protected override void GetReport(StringBuilder r) - { - if (_info == null) - return; - - r.AppendLine("PCI Vendor ID: 0x" + _info.VID.ToString("x04")); - if (_info.VID != _info.SSVID) - r.AppendLine("PCI Subsystem Vendor ID: 0x" + _info.VID.ToString("x04")); - - r.AppendLine("IEEE OUI Identifier: 0x" + _info.IEEE[2].ToString("x02") + _info.IEEE[1].ToString("x02") + _info.IEEE[0].ToString("x02")); - r.AppendLine("Total NVM Capacity: " + _info.TotalCapacity); - r.AppendLine("Unallocated NVM Capacity: " + _info.UnallocatedCapacity); - r.AppendLine("Controller ID: " + _info.ControllerId); - r.AppendLine("Number of Namespaces: " + _info.NumberNamespaces); - - NVMeHealthInfo health = Smart.GetHealthInfo(); - if (health == null) - return; - - r.AppendLine("Temperature: " + health.Temperature + " Celsius"); - r.AppendLine("Available Spare: " + health.AvailableSpare + "%"); - r.AppendLine("Available Spare Threshold: " + health.AvailableSpareThreshold + "%"); - r.AppendLine("Percentage Used: " + health.PercentageUsed + "%"); - r.AppendLine("Data Units Read: " + health.DataUnitRead); - r.AppendLine("Data Units Written: " + health.DataUnitWritten); - r.AppendLine("Host Read Commands: " + health.HostReadCommands); - r.AppendLine("Host Write Commands: " + health.HostWriteCommands); - r.AppendLine("Controller Busy Time: " + health.ControllerBusyTime); - r.AppendLine("Power Cycles: " + health.PowerCycle); - r.AppendLine("Power On Hours: " + health.PowerOnHours); - r.AppendLine("Unsafe Shutdowns: " + health.UnsafeShutdowns); - r.AppendLine("Media Errors: " + health.MediaErrors); - r.AppendLine("Number of Error Information Log Entries: " + health.ErrorInfoLogEntryCount); - r.AppendLine("Warning Composite Temperature Time: " + health.WarningCompositeTemperatureTime); - r.AppendLine("Critical Composite Temperature Time: " + health.CriticalCompositeTemperatureTime); - for (int i = 0; i < health.TemperatureSensors.Length; i++) - { - if (health.TemperatureSensors[i] > short.MinValue) - r.AppendLine("Temperature Sensor " + (i + 1) + ": " + health.TemperatureSensors[i] + " Celsius"); - } - } - - public override void Close() - { - Smart?.Close(); - - base.Close(); - } - - private delegate float GetSensorValue(NVMeHealthInfo health); - - private class NVMeSensor : Sensor - { - private readonly GetSensorValue _getValue; - - public NVMeSensor(string name, int index, bool defaultHidden, SensorType sensorType, Hardware hardware, ISettings settings, GetSensorValue getValue) - : base(name, index, defaultHidden, sensorType, hardware, null, settings) - { - _getValue = getValue; - } - - public void Update(NVMeHealthInfo health) - { - float v = _getValue(health); - if (SensorType == SensorType.Temperature && v is < -1000 or > 1000) - return; - - Value = v; - } - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/NVMeHealthInfo.cs b/LibreHardwareMonitorLib/Hardware/Storage/NVMeHealthInfo.cs deleted file mode 100644 index 58955c1..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/NVMeHealthInfo.cs +++ /dev/null @@ -1,46 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using Windows.Win32.Storage.Nvme; -using LibreHardwareMonitor.Interop; - -namespace LibreHardwareMonitor.Hardware.Storage; - -public abstract class NVMeHealthInfo -{ - public byte AvailableSpare { get; protected set; } - - public byte AvailableSpareThreshold { get; protected set; } - - public ulong ControllerBusyTime { get; protected set; } - - public uint CriticalCompositeTemperatureTime { get; protected set; } - - public ulong DataUnitRead { get; protected set; } - - public ulong DataUnitWritten { get; protected set; } - - public ulong ErrorInfoLogEntryCount { get; protected set; } - - public ulong HostReadCommands { get; protected set; } - - public ulong HostWriteCommands { get; protected set; } - - public ulong MediaErrors { get; protected set; } - - public byte PercentageUsed { get; protected set; } - - public ulong PowerCycle { get; protected set; } - - public ulong PowerOnHours { get; protected set; } - - public short Temperature { get; protected set; } - - public short[] TemperatureSensors { get; protected set; } - - public ulong UnsafeShutdowns { get; protected set; } - - public uint WarningCompositeTemperatureTime { get; protected set; } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/NVMeInfo.cs b/LibreHardwareMonitorLib/Hardware/Storage/NVMeInfo.cs deleted file mode 100644 index a11e9a5..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/NVMeInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -namespace LibreHardwareMonitor.Hardware.Storage; - -public abstract class NVMeInfo -{ - public ushort ControllerId { get; protected set; } - - public byte[] IEEE { get; protected set; } - - public int Index { get; protected set; } - - public string Model { get; protected set; } - - public uint NumberNamespaces { get; protected set; } - - public string Revision { get; protected set; } - - public string Serial { get; protected set; } - - public ushort SSVID { get; protected set; } - - public ulong TotalCapacity { get; protected set; } - - public ulong UnallocatedCapacity { get; protected set; } - - public ushort VID { get; protected set; } -} \ No newline at end of file diff --git a/LibreHardwareMonitorLib/Hardware/Storage/NVMeIntel.cs b/LibreHardwareMonitorLib/Hardware/Storage/NVMeIntel.cs deleted file mode 100644 index cd8ea5b..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/NVMeIntel.cs +++ /dev/null @@ -1,174 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using System; -using System.IO; -using System.Runtime.InteropServices; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.Storage.FileSystem; -using Windows.Win32.Storage.IscsiDisc; -using Windows.Win32.Storage.Nvme; -using Windows.Win32.System.Ioctl; -using LibreHardwareMonitor.Interop; -using Microsoft.Win32.SafeHandles; - -namespace LibreHardwareMonitor.Hardware.Storage; - -internal class NVMeIntel : INVMeDrive -{ - //intel nvme access - - public SafeHandle Identify(StorageInfo storageInfo) - { - return NVMeWindows.IdentifyDevice(storageInfo); - } - - public unsafe bool IdentifyController(SafeHandle hDevice, out NVME_IDENTIFY_CONTROLLER_DATA data) - { - data = new NVME_IDENTIFY_CONTROLLER_DATA(); - if (hDevice?.IsInvalid != false) - return false; - - bool result = false; - - AtaSmart.NVME_PASS_THROUGH_IOCTL passThrough = new(); - passThrough.SrbIoCtrl.HeaderLength = (uint)sizeof(SRB_IO_CONTROL); - - ReadOnlySpan signature = "NvmeMini"u8; - for (int i = 0; i < signature.Length; i++) - passThrough.SrbIoCtrl.Signature[i] = signature[i]; - - passThrough.SrbIoCtrl.Timeout = 10; - passThrough.SrbIoCtrl.ControlCode = AtaSmart.NVME_PASS_THROUGH_SRB_IO_CODE; - passThrough.SrbIoCtrl.ReturnCode = 0; - passThrough.SrbIoCtrl.Length = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL) - (uint)sizeof(SRB_IO_CONTROL); - passThrough.NVMeCmd[0] = 6; //identify - passThrough.NVMeCmd[10] = 1; //return to host - passThrough.Direction = AtaSmart.NVME_DATA_IN; - passThrough.QueueId = 0; - passThrough.DataBufferLen = AtaSmart.IOCTL_BUFFER_SIZE; - passThrough.MetaDataLen = 0; - passThrough.ReturnBufferLen = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - - int length = sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - IntPtr buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(passThrough, buffer, false); - - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)hDevice.DangerousGetHandle(), PInvoke.IOCTL_SCSI_MINIPORT, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - if (validTransfer) - { - IntPtr offset = Marshal.OffsetOf(nameof(AtaSmart.NVME_PASS_THROUGH_IOCTL.DataBuffer)); - var newPtr = IntPtr.Add(buffer, offset.ToInt32()); - data = *(NVME_IDENTIFY_CONTROLLER_DATA*)newPtr; - Marshal.FreeHGlobal(buffer); - result = true; - } - else - { - Marshal.FreeHGlobal(buffer); - } - - return result; - } - - public unsafe bool HealthInfoLog(SafeHandle hDevice, out NVME_HEALTH_INFO_LOG data) - { - data = new NVME_HEALTH_INFO_LOG(); - if (hDevice?.IsInvalid != false) - return false; - - bool result = false; - - AtaSmart.NVME_PASS_THROUGH_IOCTL passThrough = new(); - passThrough.SrbIoCtrl.HeaderLength = (uint)sizeof(SRB_IO_CONTROL); - - ReadOnlySpan signature = "NvmeMini"u8; - for (int i = 0; i < signature.Length; i++) - passThrough.SrbIoCtrl.Signature[i] = signature[i]; - - passThrough.SrbIoCtrl.Timeout = 10; - passThrough.SrbIoCtrl.ControlCode = AtaSmart.NVME_PASS_THROUGH_SRB_IO_CODE; - passThrough.SrbIoCtrl.ReturnCode = 0; - passThrough.SrbIoCtrl.Length = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL) - (uint)sizeof(SRB_IO_CONTROL); - passThrough.NVMeCmd[0] = (uint)STORAGE_PROTOCOL_NVME_DATA_TYPE.NVMeDataTypeLogPage; // GetLogPage - passThrough.NVMeCmd[1] = 0xFFFFFFFF; // address - passThrough.NVMeCmd[10] = 0x007f0002; // uint cdw10 = 0x000000002 | (((size / 4) - 1) << 16); - passThrough.Direction = AtaSmart.NVME_DATA_IN; - passThrough.QueueId = 0; - passThrough.DataBufferLen = AtaSmart.IOCTL_BUFFER_SIZE; - passThrough.MetaDataLen = 0; - passThrough.ReturnBufferLen = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - - int length = sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - IntPtr buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(passThrough, buffer, false); - - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)hDevice.DangerousGetHandle(), PInvoke.IOCTL_SCSI_MINIPORT, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - if (validTransfer) - { - IntPtr offset = Marshal.OffsetOf(nameof(AtaSmart.NVME_PASS_THROUGH_IOCTL.DataBuffer)); - var newPtr = IntPtr.Add(buffer, offset.ToInt32()); - data = *(NVME_HEALTH_INFO_LOG*)newPtr; - Marshal.FreeHGlobal(buffer); - result = true; - } - else - { - Marshal.FreeHGlobal(buffer); - } - - return result; - } - - public static unsafe SafeHandle IdentifyDevice(StorageInfo storageInfo) - { - SafeFileHandle handle = PInvoke.CreateFile(storageInfo.Scsi, - (uint)FileAccess.ReadWrite, - FILE_SHARE_MODE.FILE_SHARE_READ | FILE_SHARE_MODE.FILE_SHARE_WRITE, - null, - FILE_CREATION_DISPOSITION.OPEN_EXISTING, - FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, - null); - if (handle?.IsInvalid != false) - return null; - - AtaSmart.NVME_PASS_THROUGH_IOCTL passThrough = new(); - passThrough.SrbIoCtrl.HeaderLength = (uint)sizeof(SRB_IO_CONTROL); - - ReadOnlySpan signature = "NvmeMini"u8; - for (int i = 0; i < signature.Length; i++) - passThrough.SrbIoCtrl.Signature[i] = signature[i]; - - passThrough.SrbIoCtrl.Timeout = 10; - passThrough.SrbIoCtrl.ControlCode = AtaSmart.NVME_PASS_THROUGH_SRB_IO_CODE; - passThrough.SrbIoCtrl.ReturnCode = 0; - passThrough.SrbIoCtrl.Length = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL) - (uint)sizeof(SRB_IO_CONTROL); - passThrough.NVMeCmd[0] = 6; //identify - passThrough.NVMeCmd[10] = 1; //return to host - passThrough.Direction = AtaSmart.NVME_DATA_IN; - passThrough.QueueId = 0; - passThrough.DataBufferLen = AtaSmart.IOCTL_BUFFER_SIZE; - passThrough.MetaDataLen = 0; - passThrough.ReturnBufferLen = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - - int length = sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - IntPtr buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(passThrough, buffer, false); - - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)handle.DangerousGetHandle(), PInvoke.IOCTL_SCSI_MINIPORT, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - Marshal.FreeHGlobal(buffer); - - if (validTransfer) - { } - else - { - handle.Close(); - handle = null; - } - - return handle; - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/NVMeIntelRst.cs b/LibreHardwareMonitorLib/Hardware/Storage/NVMeIntelRst.cs deleted file mode 100644 index 81344f4..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/NVMeIntelRst.cs +++ /dev/null @@ -1,174 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using System; -using System.IO; -using System.Runtime.InteropServices; -using LibreHardwareMonitor.Interop; -using Microsoft.Win32.SafeHandles; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.Storage.FileSystem; -using Windows.Win32.Storage.IscsiDisc; -using Windows.Win32.Storage.Nvme; -using Windows.Win32.System.Ioctl; - -namespace LibreHardwareMonitor.Hardware.Storage; - -internal class NVMeIntelRst : INVMeDrive -{ - //intel RST (raid) nvme access - - public SafeHandle Identify(StorageInfo storageInfo) - { - return NVMeWindows.IdentifyDevice(storageInfo); - } - - public unsafe bool IdentifyController(SafeHandle hDevice, out NVME_IDENTIFY_CONTROLLER_DATA data) - { - data = new NVME_IDENTIFY_CONTROLLER_DATA(); - if (hDevice?.IsInvalid != false) - return false; - - bool result = false; - - AtaSmart.NVME_PASS_THROUGH_IOCTL passThrough = new(); - passThrough.SrbIoCtrl.HeaderLength = (uint)sizeof(SRB_IO_CONTROL); - - ReadOnlySpan signature = "IntelNvm"u8; - for (int i = 0; i < signature.Length; i++) - passThrough.SrbIoCtrl.Signature[i] = signature[i]; - - passThrough.SrbIoCtrl.Timeout = 10; - passThrough.SrbIoCtrl.ControlCode = AtaSmart.NVME_PASS_THROUGH_SRB_IO_CODE; - passThrough.SrbIoCtrl.ReturnCode = 0; - passThrough.SrbIoCtrl.Length = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL) - (uint)sizeof(SRB_IO_CONTROL); - passThrough.NVMeCmd[0] = 6; //identify - passThrough.NVMeCmd[10] = 1; //return to host - passThrough.Direction = AtaSmart.NVME_DATA_IN; - passThrough.QueueId = 0; - passThrough.DataBufferLen = AtaSmart.IOCTL_BUFFER_SIZE; - passThrough.MetaDataLen = 0; - passThrough.ReturnBufferLen = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - - int length = sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - IntPtr buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(passThrough, buffer, false); - - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)hDevice.DangerousGetHandle(), PInvoke.IOCTL_SCSI_MINIPORT, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - if (validTransfer) - { - IntPtr offset = Marshal.OffsetOf(nameof(AtaSmart.NVME_PASS_THROUGH_IOCTL.DataBuffer)); - var newPtr = IntPtr.Add(buffer, offset.ToInt32()); - data = *(NVME_IDENTIFY_CONTROLLER_DATA*)newPtr; - Marshal.FreeHGlobal(buffer); - result = true; - } - else - { - Marshal.FreeHGlobal(buffer); - } - - return result; - } - - public unsafe bool HealthInfoLog(SafeHandle hDevice, out NVME_HEALTH_INFO_LOG data) - { - data = new NVME_HEALTH_INFO_LOG(); - if (hDevice?.IsInvalid != false) - return false; - - bool result = false; - - AtaSmart.NVME_PASS_THROUGH_IOCTL passThrough = new(); - passThrough.SrbIoCtrl.HeaderLength = (uint)sizeof(SRB_IO_CONTROL); - - ReadOnlySpan signature = "IntelNvm"u8; - for (int i = 0; i < signature.Length; i++) - passThrough.SrbIoCtrl.Signature[i] = signature[i]; - - passThrough.SrbIoCtrl.Timeout = 10; - passThrough.SrbIoCtrl.ControlCode = AtaSmart.NVME_PASS_THROUGH_SRB_IO_CODE; - passThrough.SrbIoCtrl.ReturnCode = 0; - passThrough.SrbIoCtrl.Length = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL) - (uint)sizeof(SRB_IO_CONTROL); - passThrough.NVMeCmd[0] = (uint)STORAGE_PROTOCOL_NVME_DATA_TYPE.NVMeDataTypeLogPage; // GetLogPage - passThrough.NVMeCmd[1] = 0xFFFFFFFF; // address - passThrough.NVMeCmd[10] = 0x007f0002; // uint cdw10 = 0x000000002 | (((size / 4) - 1) << 16); - passThrough.Direction = AtaSmart.NVME_DATA_IN; - passThrough.QueueId = 0; - passThrough.DataBufferLen = AtaSmart.IOCTL_BUFFER_SIZE; - passThrough.MetaDataLen = 0; - passThrough.ReturnBufferLen = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - - int length = sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - IntPtr buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(passThrough, buffer, false); - - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)hDevice.DangerousGetHandle(), PInvoke.IOCTL_SCSI_MINIPORT, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - if (validTransfer) - { - IntPtr offset = Marshal.OffsetOf(nameof(AtaSmart.NVME_PASS_THROUGH_IOCTL.DataBuffer)); - var newPtr = IntPtr.Add(buffer, offset.ToInt32()); - data = *(NVME_HEALTH_INFO_LOG*)newPtr; - Marshal.FreeHGlobal(buffer); - result = true; - } - else - { - Marshal.FreeHGlobal(buffer); - } - - return result; - } - - public static unsafe SafeHandle IdentifyDevice(StorageInfo storageInfo) - { - SafeFileHandle handle = PInvoke.CreateFile(storageInfo.Scsi, - (uint)FileAccess.ReadWrite, - FILE_SHARE_MODE.FILE_SHARE_READ | FILE_SHARE_MODE.FILE_SHARE_WRITE, - null, - FILE_CREATION_DISPOSITION.OPEN_EXISTING, - FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, - null); - if (handle?.IsInvalid != false) - return null; - - AtaSmart.NVME_PASS_THROUGH_IOCTL passThrough = new(); - passThrough.SrbIoCtrl.HeaderLength = (uint)sizeof(SRB_IO_CONTROL); - - ReadOnlySpan signature = "IntelNvm"u8; - for (int i = 0; i < signature.Length; i++) - passThrough.SrbIoCtrl.Signature[i] = signature[i]; - - passThrough.SrbIoCtrl.Timeout = 10; - passThrough.SrbIoCtrl.ControlCode = AtaSmart.NVME_PASS_THROUGH_SRB_IO_CODE; - passThrough.SrbIoCtrl.ReturnCode = 0; - passThrough.SrbIoCtrl.Length = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL) - (uint)sizeof(SRB_IO_CONTROL); - passThrough.NVMeCmd[0] = 6; //identify - passThrough.NVMeCmd[10] = 1; //return to host - passThrough.Direction = AtaSmart.NVME_DATA_IN; - passThrough.QueueId = 0; - passThrough.DataBufferLen = AtaSmart.IOCTL_BUFFER_SIZE; - passThrough.MetaDataLen = 0; - passThrough.ReturnBufferLen = (uint)sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - - int length = sizeof(AtaSmart.NVME_PASS_THROUGH_IOCTL); - IntPtr buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(passThrough, buffer, false); - - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)handle.DangerousGetHandle(), PInvoke.IOCTL_SCSI_MINIPORT, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - Marshal.FreeHGlobal(buffer); - - if (validTransfer) - { } - else - { - handle.Close(); - handle = null; - } - - return handle; - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/NVMeSamsung.cs b/LibreHardwareMonitorLib/Hardware/Storage/NVMeSamsung.cs deleted file mode 100644 index 5ca1883..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/NVMeSamsung.cs +++ /dev/null @@ -1,283 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using System; -using System.IO; -using System.Runtime.InteropServices; -using LibreHardwareMonitor.Interop; -using Microsoft.Win32.SafeHandles; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.Storage.FileSystem; -using Windows.Win32.Storage.IscsiDisc; -using Windows.Win32.Storage.Nvme; - -namespace LibreHardwareMonitor.Hardware.Storage; - -internal class NVMeSamsung : INVMeDrive -{ - //samsung nvme access - //https://github.com/hiyohiyo/CrystalDiskInfo - //https://github.com/hiyohiyo/CrystalDiskInfo/blob/master/AtaSmart.cpp - - public SafeHandle Identify(StorageInfo storageInfo) - { - return NVMeWindows.IdentifyDevice(storageInfo); - } - - public unsafe bool IdentifyController(SafeHandle hDevice, out NVME_IDENTIFY_CONTROLLER_DATA data) - { - data = new NVME_IDENTIFY_CONTROLLER_DATA(); - if (hDevice?.IsInvalid != false) - return false; - - AtaSmart.SCSI_PASS_THROUGH buffers = new(); - - buffers.Spt.Length = (ushort)sizeof(SCSI_PASS_THROUGH); - buffers.Spt.PathId = 0; - buffers.Spt.TargetId = 0; - buffers.Spt.Lun = 0; - buffers.Spt.SenseInfoLength = 24; - buffers.Spt.DataTransferLength = AtaSmart.IOCTL_BUFFER_SIZE; - buffers.Spt.TimeOutValue = 2; - buffers.Spt.DataBufferOffset = new UIntPtr((ulong)Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.DataBuf))); - buffers.Spt.SenseInfoOffset = (uint)Marshal.OffsetOf(typeof(AtaSmart.SCSI_PASS_THROUGH), nameof(AtaSmart.SCSI_PASS_THROUGH.SenseBuf)); - - buffers.Spt.CdbLength = 16; - buffers.Spt.Cdb[0] = 0xB5; // SECURITY PROTOCOL IN - buffers.Spt.Cdb[1] = 0xFE; // Samsung Protocol - buffers.Spt.Cdb[3] = 5; // Identify - buffers.Spt.Cdb[8] = 0; // Transfer Length - buffers.Spt.Cdb[9] = 0x40; // Transfer Length - buffers.Spt.DataIn = (byte)PInvoke.SCSI_IOCTL_DATA_OUT; - buffers.DataBuf[0] = 1; - - int length = (int)(Marshal.OffsetOf(typeof(AtaSmart.SCSI_PASS_THROUGH), nameof(AtaSmart.SCSI_PASS_THROUGH.DataBuf)).ToInt32() + buffers.Spt.DataTransferLength); - IntPtr buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(buffers, buffer, false); - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)hDevice.DangerousGetHandle(), PInvoke.IOCTL_SCSI_PASS_THROUGH, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - Marshal.FreeHGlobal(buffer); - - bool result = false; - - if (validTransfer) - { - //read data from samsung SSD - buffers = new AtaSmart.SCSI_PASS_THROUGH(); - buffers.Spt.Length = (ushort)sizeof(SCSI_PASS_THROUGH); - buffers.Spt.PathId = 0; - buffers.Spt.TargetId = 0; - buffers.Spt.Lun = 0; - buffers.Spt.SenseInfoLength = 24; - buffers.Spt.DataTransferLength = AtaSmart.IOCTL_BUFFER_SIZE; - buffers.Spt.TimeOutValue = 2; - buffers.Spt.DataBufferOffset = new UIntPtr((ulong)Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.DataBuf))); - buffers.Spt.SenseInfoOffset = (uint)Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.SenseBuf)); - - buffers.Spt.CdbLength = 16; - buffers.Spt.Cdb[0] = 0xA2; // SECURITY PROTOCOL IN - buffers.Spt.Cdb[1] = 0xFE; // Samsung Protocol - buffers.Spt.Cdb[3] = 5; // Identify - buffers.Spt.Cdb[8] = 1; // Transfer Length (high) - buffers.Spt.Cdb[9] = 0; // Transfer Length (low) - buffers.Spt.DataIn = (byte)PInvoke.SCSI_IOCTL_DATA_IN; - - buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(buffers, buffer, false); - - validTransfer = PInvoke.DeviceIoControl((HANDLE)hDevice.DangerousGetHandle(), PInvoke.IOCTL_SCSI_PASS_THROUGH, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - - buffers = Marshal.PtrToStructure(buffer); - - if (validTransfer && !IsAllZero(buffers.DataBuf, AtaSmart.IOCTL_BUFFER_SIZE)) - { - IntPtr offset = Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.DataBuf)); - IntPtr newPtr = IntPtr.Add(buffer, offset.ToInt32()); - data = Marshal.PtrToStructure(newPtr); - result = true; - - Marshal.FreeHGlobal(buffer); - } - } - - return result; - } - - public unsafe bool HealthInfoLog(SafeHandle hDevice, out NVME_HEALTH_INFO_LOG data) - { - data = new NVME_HEALTH_INFO_LOG(); - if (hDevice?.IsInvalid != false) - return false; - - bool result = false; - AtaSmart.SCSI_PASS_THROUGH buffers = new(); - - buffers.Spt.Length = (ushort)sizeof(SCSI_PASS_THROUGH); - buffers.Spt.PathId = 0; - buffers.Spt.TargetId = 0; - buffers.Spt.Lun = 0; - buffers.Spt.SenseInfoLength = 24; - buffers.Spt.DataTransferLength = AtaSmart.IOCTL_BUFFER_SIZE; - buffers.Spt.TimeOutValue = 2; - buffers.Spt.DataBufferOffset = new UIntPtr((ulong)Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.DataBuf))); - buffers.Spt.SenseInfoOffset = (uint)Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.SenseBuf)); - buffers.Spt.CdbLength = 16; - buffers.Spt.Cdb[0] = 0xB5; // SECURITY PROTOCOL IN - buffers.Spt.Cdb[1] = 0xFE; // Samsung Protocol - buffers.Spt.Cdb[3] = 6; // Log Data - buffers.Spt.Cdb[8] = 0; // Transfer Length - buffers.Spt.Cdb[9] = 0x40; // Transfer Length - buffers.Spt.DataIn = (byte)PInvoke.SCSI_IOCTL_DATA_OUT; - buffers.DataBuf[0] = 2; - buffers.DataBuf[4] = 0xff; - buffers.DataBuf[5] = 0xff; - buffers.DataBuf[6] = 0xff; - buffers.DataBuf[7] = 0xff; - - int length = Marshal.SizeOf(); - IntPtr buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(buffers, buffer, false); - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)hDevice.DangerousGetHandle(), PInvoke.IOCTL_SCSI_PASS_THROUGH, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - Marshal.FreeHGlobal(buffer); - - if (validTransfer) - { - //read data from samsung SSD - buffers = new AtaSmart.SCSI_PASS_THROUGH(); - buffers.Spt.Length = (ushort)sizeof(SCSI_PASS_THROUGH); - buffers.Spt.PathId = 0; - buffers.Spt.TargetId = 0; - buffers.Spt.Lun = 0; - buffers.Spt.SenseInfoLength = 24; - buffers.Spt.DataTransferLength = AtaSmart.IOCTL_BUFFER_SIZE; - buffers.Spt.TimeOutValue = 2; - buffers.Spt.DataBufferOffset = new UIntPtr((ulong)Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.DataBuf))); - buffers.Spt.SenseInfoOffset = (uint)Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.SenseBuf)); - buffers.Spt.CdbLength = 16; - buffers.Spt.Cdb[0] = 0xA2; // SECURITY PROTOCOL IN - buffers.Spt.Cdb[1] = 0xFE; // Samsung Protocol - buffers.Spt.Cdb[3] = 6; // Log Data - buffers.Spt.Cdb[8] = 2; // Transfer Length (high) - buffers.Spt.Cdb[9] = 0; // Transfer Length (low) - buffers.Spt.DataIn = (byte)PInvoke.SCSI_IOCTL_DATA_IN; - - length = Marshal.SizeOf(); - buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(buffers, buffer, false); - - validTransfer = PInvoke.DeviceIoControl((HANDLE)hDevice.DangerousGetHandle(), PInvoke.IOCTL_SCSI_PASS_THROUGH, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - if (validTransfer) - { - IntPtr offset = Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.DataBuf)); - IntPtr newPtr = IntPtr.Add(buffer, offset.ToInt32()); - data = Marshal.PtrToStructure(newPtr); - Marshal.FreeHGlobal(buffer); - result = true; - } - else - { - Marshal.FreeHGlobal(buffer); - } - } - - return result; - } - - public static unsafe SafeHandle IdentifyDevice(StorageInfo storageInfo) - { - SafeFileHandle handle = PInvoke.CreateFile(storageInfo.DeviceId, - (uint)FileAccess.ReadWrite, - FILE_SHARE_MODE.FILE_SHARE_READ | FILE_SHARE_MODE.FILE_SHARE_WRITE, - null, - FILE_CREATION_DISPOSITION.OPEN_EXISTING, - FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, - null); - if (handle?.IsInvalid != false) - return null; - - AtaSmart.SCSI_PASS_THROUGH buffers = new(); - - buffers.Spt.Length = (ushort)sizeof(SCSI_PASS_THROUGH); - buffers.Spt.PathId = 0; - buffers.Spt.TargetId = 0; - buffers.Spt.Lun = 0; - buffers.Spt.SenseInfoLength = 24; - buffers.Spt.DataTransferLength = AtaSmart.IOCTL_BUFFER_SIZE; - buffers.Spt.TimeOutValue = 2; - buffers.Spt.DataBufferOffset = new UIntPtr((ulong)Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.DataBuf))); - buffers.Spt.SenseInfoOffset = (uint)Marshal.OffsetOf(typeof(AtaSmart.SCSI_PASS_THROUGH), nameof(AtaSmart.SCSI_PASS_THROUGH.SenseBuf)); - buffers.Spt.CdbLength = 16; - buffers.Spt.Cdb[0] = 0xB5; // SECURITY PROTOCOL IN - buffers.Spt.Cdb[1] = 0xFE; // Samsung Protocol - buffers.Spt.Cdb[3] = 5; // Identify - buffers.Spt.Cdb[8] = 0; // Transfer Length - buffers.Spt.Cdb[9] = 0x40; - buffers.Spt.DataIn = (byte)PInvoke.SCSI_IOCTL_DATA_OUT; - buffers.DataBuf[0] = 1; - - int length = Marshal.SizeOf(); - IntPtr buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(buffers, buffer, false); - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)handle.DangerousGetHandle(), PInvoke.IOCTL_SCSI_PASS_THROUGH, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - Marshal.FreeHGlobal(buffer); - - if (validTransfer) - { - //read data from samsung SSD - buffers = new AtaSmart.SCSI_PASS_THROUGH(); - buffers.Spt.Length = (ushort)sizeof(SCSI_PASS_THROUGH); - buffers.Spt.PathId = 0; - buffers.Spt.TargetId = 0; - buffers.Spt.Lun = 0; - buffers.Spt.SenseInfoLength = 24; - buffers.Spt.DataTransferLength = AtaSmart.IOCTL_BUFFER_SIZE; - buffers.Spt.TimeOutValue = 2; - buffers.Spt.DataBufferOffset = new UIntPtr((ulong)Marshal.OffsetOf(nameof(AtaSmart.SCSI_PASS_THROUGH.DataBuf))); - buffers.Spt.SenseInfoOffset = (uint)Marshal.OffsetOf(typeof(AtaSmart.SCSI_PASS_THROUGH), nameof(AtaSmart.SCSI_PASS_THROUGH.SenseBuf)); - buffers.Spt.CdbLength = 16; - buffers.Spt.Cdb[0] = 0xA2; // SECURITY PROTOCOL IN - buffers.Spt.Cdb[1] = 0xFE; // Samsung Protocol - buffers.Spt.Cdb[3] = 5; // Identify - buffers.Spt.Cdb[8] = 2; // Transfer Length - buffers.Spt.Cdb[9] = 0; - buffers.Spt.DataIn = (byte)PInvoke.SCSI_IOCTL_DATA_IN; - - length = Marshal.SizeOf(); - buffer = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(buffers, buffer, false); - - validTransfer = PInvoke.DeviceIoControl((HANDLE)handle.DangerousGetHandle(), PInvoke.IOCTL_SCSI_PASS_THROUGH, (void*)buffer, (uint)length, (void*)buffer, (uint)length, null, null); - if (validTransfer) - { - AtaSmart.SCSI_PASS_THROUGH result = Marshal.PtrToStructure(buffer); - - if (IsAllZero(result.DataBuf, AtaSmart.IOCTL_BUFFER_SIZE)) - { - handle.Close(); - handle = null; - } - } - else - { - handle.Close(); - handle = null; - } - - Marshal.FreeHGlobal(buffer); - } - - return handle; - } - - private static unsafe bool IsAllZero(byte* bytes, int length) - { - for (int i = 0; i < length; i++) - { - if (bytes[i] != 0) - return false; - } - return true; - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/NVMeSmart.cs b/LibreHardwareMonitorLib/Hardware/Storage/NVMeSmart.cs deleted file mode 100644 index aa2c16a..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/NVMeSmart.cs +++ /dev/null @@ -1,196 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using System; -using System.Runtime.InteropServices; -using System.Text; -using Windows.Win32.Storage.Nvme; -using LibreHardwareMonitor.Interop; - -namespace LibreHardwareMonitor.Hardware.Storage; - -public class NVMeSmart : IDisposable -{ - private readonly int _driveNumber; - private readonly SafeHandle _handle; - - internal NVMeSmart(StorageInfo storageInfo) - { - _driveNumber = storageInfo.Index; - NVMeDrive = null; - string name = storageInfo.Name; - - // Test Windows generic driver protocol. - if (NVMeDrive == null) - { - _handle = NVMeWindows.IdentifyDevice(storageInfo); - if (_handle != null) - { - NVMeDrive = new NVMeWindows(); - } - } - - // Test Samsung protocol. - if (NVMeDrive == null && name.IndexOf("Samsung", StringComparison.OrdinalIgnoreCase) > -1) - { - _handle = NVMeSamsung.IdentifyDevice(storageInfo); - if (_handle != null) - { - NVMeDrive = new NVMeSamsung(); - if (!NVMeDrive.IdentifyController(_handle, out _)) - { - NVMeDrive = null; - } - } - } - - // Test Intel protocol. - if (NVMeDrive == null && name.IndexOf("Intel", StringComparison.OrdinalIgnoreCase) > -1) - { - _handle = NVMeIntel.IdentifyDevice(storageInfo); - if (_handle != null) - { - NVMeDrive = new NVMeIntel(); - } - } - - // Test Intel raid protocol. - if (NVMeDrive == null && name.IndexOf("Intel", StringComparison.OrdinalIgnoreCase) > -1) - { - _handle = NVMeIntelRst.IdentifyDevice(storageInfo); - if (_handle != null) - { - NVMeDrive = new NVMeIntelRst(); - } - } - } - - public bool IsValid - { - get - { - return _handle is { IsInvalid: false }; - } - } - - internal INVMeDrive NVMeDrive { get; } - - public void Dispose() - { - Close(); - } - - private static string GetString(byte[] s) - { - return Encoding.ASCII.GetString(s).Trim('\t', '\n', '\r', ' ', '\0'); - } - - private static short KelvinToCelsius(ushort k) - { - return (short)(k > 0 ? k - 273 : short.MinValue); - } - - private static short KelvinToCelsius(byte[] k) - { - return KelvinToCelsius(BitConverter.ToUInt16(k, 0)); - } - - public void Close() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected void Dispose(bool disposing) - { - if (disposing && _handle is { IsClosed: false }) - { - _handle.Close(); - } - } - - public Storage.NVMeInfo GetInfo() - { - if (_handle?.IsClosed != false) - return null; - - bool valid = false; - var data = new NVME_IDENTIFY_CONTROLLER_DATA(); - if (NVMeDrive != null) - valid = NVMeDrive.IdentifyController(_handle, out data); - - if (!valid) - return null; - - return new NVMeInfo(_driveNumber, data); - } - - public Storage.NVMeHealthInfo GetHealthInfo() - { - if (_handle?.IsClosed != false) - return null; - - bool valid = false; - var data = new NVME_HEALTH_INFO_LOG(); - if (NVMeDrive != null) - valid = NVMeDrive.HealthInfoLog(_handle, out data); - - if (!valid) - return null; - - return new NVMeHealthInfo(data); - } - - private class NVMeInfo : Storage.NVMeInfo - { - public NVMeInfo(int index, NVME_IDENTIFY_CONTROLLER_DATA data) - { - Index = index; - VID = data.VID; - SSVID = data.SSVID; - Serial = GetString(data.SN.ToArray()); - Model = GetString(data.MN.ToArray()); - Revision = GetString(data.FR.ToArray()); - IEEE = data.IEEE.ToArray(); - TotalCapacity = BitConverter.ToUInt64(data.TNVMCAP.ToArray(), 0); // 128bit little endian - UnallocatedCapacity = BitConverter.ToUInt64(data.UNVMCAP.ToArray(), 0); - ControllerId = data.CNTLID; - NumberNamespaces = data.NN; - } - } - - private class NVMeHealthInfo : Storage.NVMeHealthInfo - { - public NVMeHealthInfo(NVME_HEALTH_INFO_LOG log) - { - Temperature = KelvinToCelsius(log.Temperature.ToArray()); - AvailableSpare = log.AvailableSpare; - AvailableSpareThreshold = log.AvailableSpareThreshold; - PercentageUsed = log.PercentageUsed; - DataUnitRead = BitConverter.ToUInt64(log.DataUnitRead.ToArray(), 0); - DataUnitWritten = BitConverter.ToUInt64(log.DataUnitWritten.ToArray(), 0); - HostReadCommands = BitConverter.ToUInt64(log.HostReadCommands.ToArray(), 0); - HostWriteCommands = BitConverter.ToUInt64(log.HostWrittenCommands.ToArray(), 0); - ControllerBusyTime = BitConverter.ToUInt64(log.ControllerBusyTime.ToArray(), 0); - PowerCycle = BitConverter.ToUInt64(log.PowerCycle.ToArray(), 0); - PowerOnHours = BitConverter.ToUInt64(log.PowerOnHours.ToArray(), 0); - UnsafeShutdowns = BitConverter.ToUInt64(log.UnsafeShutdowns.ToArray(), 0); - MediaErrors = BitConverter.ToUInt64(log.MediaErrors.ToArray(), 0); - ErrorInfoLogEntryCount = BitConverter.ToUInt64(log.ErrorInfoLogEntryCount.ToArray(), 0); - WarningCompositeTemperatureTime = log.WarningCompositeTemperatureTime; - CriticalCompositeTemperatureTime = log.CriticalCompositeTemperatureTime; - - TemperatureSensors = new short[8]; - TemperatureSensors[0] = KelvinToCelsius(log.TemperatureSensor1); - TemperatureSensors[1] = KelvinToCelsius(log.TemperatureSensor2); - TemperatureSensors[2] = KelvinToCelsius(log.TemperatureSensor3); - TemperatureSensors[3] = KelvinToCelsius(log.TemperatureSensor4); - TemperatureSensors[4] = KelvinToCelsius(log.TemperatureSensor5); - TemperatureSensors[5] = KelvinToCelsius(log.TemperatureSensor6); - TemperatureSensors[6] = KelvinToCelsius(log.TemperatureSensor7); - TemperatureSensors[7] = KelvinToCelsius(log.TemperatureSensor8); - } - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/NVMeWindows.cs b/LibreHardwareMonitorLib/Hardware/Storage/NVMeWindows.cs deleted file mode 100644 index ea8ce4d..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/NVMeWindows.cs +++ /dev/null @@ -1,127 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using System; -using System.IO; -using System.Runtime.InteropServices; -using LibreHardwareMonitor.Interop; -using Microsoft.Win32.SafeHandles; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.Storage.FileSystem; -using Windows.Win32.Storage.Nvme; -using Windows.Win32.System.Ioctl; - -namespace LibreHardwareMonitor.Hardware.Storage; - -internal class NVMeWindows : INVMeDrive -{ - //windows generic driver nvme access - public SafeHandle Identify(StorageInfo storageInfo) - { - return IdentifyDevice(storageInfo); - } - - public unsafe bool IdentifyController(SafeHandle hDevice, out NVME_IDENTIFY_CONTROLLER_DATA data) - { - data = new NVME_IDENTIFY_CONTROLLER_DATA(); - if (hDevice?.IsInvalid != false) - return false; - - bool result = false; - - int cb = sizeof(STORAGE_PROPERTY_QUERY) + sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA) + sizeof(NVME_IDENTIFY_CONTROLLER_DATA); - IntPtr ptr = Marshal.AllocHGlobal(cb); - Marshal.Copy(new byte[cb], 0, ptr, cb); // Zero memory. - - STORAGE_PROPERTY_QUERY* query = (STORAGE_PROPERTY_QUERY*)ptr; - query->PropertyId = STORAGE_PROPERTY_ID.StorageAdapterProtocolSpecificProperty; - query->QueryType = STORAGE_QUERY_TYPE.PropertyStandardQuery; - - STORAGE_PROTOCOL_SPECIFIC_DATA* protocolData = (STORAGE_PROTOCOL_SPECIFIC_DATA*)(&query->AdditionalParameters); - protocolData->ProtocolType = STORAGE_PROTOCOL_TYPE.ProtocolTypeNvme; - protocolData->DataType = (uint)STORAGE_PROTOCOL_NVME_DATA_TYPE.NVMeDataTypeIdentify; - protocolData->ProtocolDataRequestValue = 1; - protocolData->ProtocolDataOffset = (uint)sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA); - protocolData->ProtocolDataLength = (uint)sizeof(NVME_IDENTIFY_CONTROLLER_DATA); - - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)hDevice.DangerousGetHandle(), PInvoke.IOCTL_STORAGE_QUERY_PROPERTY, (void*)ptr, (uint)cb, (void*)ptr, (uint)cb, null, null); - if (validTransfer) - { - var dataDescriptor = (STORAGE_PROTOCOL_DATA_DESCRIPTOR*)ptr; - protocolData = &dataDescriptor->ProtocolSpecificData; - data = *(NVME_IDENTIFY_CONTROLLER_DATA*)((byte*)protocolData + protocolData->ProtocolDataOffset); - Marshal.FreeHGlobal(ptr); - result = true; - } - else - { - Marshal.FreeHGlobal(ptr); - } - - return result; - } - - public unsafe bool HealthInfoLog(SafeHandle hDevice, out NVME_HEALTH_INFO_LOG data) - { - data = new NVME_HEALTH_INFO_LOG(); - if (hDevice?.IsInvalid != false) - return false; - - bool result = false; - - int cb = sizeof(STORAGE_PROPERTY_QUERY) + sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA) + sizeof(NVME_HEALTH_INFO_LOG); - IntPtr ptr = Marshal.AllocHGlobal(cb); - Marshal.Copy(new byte[cb], 0, ptr, cb); // Zero memory. - - STORAGE_PROPERTY_QUERY* query = (STORAGE_PROPERTY_QUERY*)ptr; - query->PropertyId = STORAGE_PROPERTY_ID.StorageAdapterProtocolSpecificProperty; - query->QueryType = STORAGE_QUERY_TYPE.PropertyStandardQuery; - - STORAGE_PROTOCOL_SPECIFIC_DATA* protocolData = (STORAGE_PROTOCOL_SPECIFIC_DATA*)(&query->AdditionalParameters); - protocolData->ProtocolType = STORAGE_PROTOCOL_TYPE.ProtocolTypeNvme; - protocolData->DataType = (uint)STORAGE_PROTOCOL_NVME_DATA_TYPE.NVMeDataTypeLogPage; - protocolData->ProtocolDataRequestValue = (uint)NVME_LOG_PAGES.NVME_LOG_PAGE_HEALTH_INFO; - protocolData->ProtocolDataOffset = (uint)sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA); - protocolData->ProtocolDataLength = (uint)sizeof(NVME_HEALTH_INFO_LOG); - - bool validTransfer = PInvoke.DeviceIoControl((HANDLE)hDevice.DangerousGetHandle(), PInvoke.IOCTL_STORAGE_QUERY_PROPERTY, (void*)ptr, (uint)cb, (void*)ptr, (uint)cb, null, null); - if (validTransfer) - { - var dataDescriptor = (STORAGE_PROTOCOL_DATA_DESCRIPTOR*)ptr; - protocolData = &dataDescriptor->ProtocolSpecificData; - - data = *(NVME_HEALTH_INFO_LOG*)((byte*)protocolData + protocolData->ProtocolDataOffset); - Marshal.FreeHGlobal(ptr); - result = true; - } - else - { - Marshal.FreeHGlobal(ptr); - } - - return result; - } - - public static SafeHandle IdentifyDevice(StorageInfo storageInfo) - { - SafeFileHandle handle = PInvoke.CreateFile(storageInfo.DeviceId, - (uint)FileAccess.ReadWrite, - FILE_SHARE_MODE.FILE_SHARE_READ | FILE_SHARE_MODE.FILE_SHARE_WRITE, - null, - FILE_CREATION_DISPOSITION.OPEN_EXISTING, - FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, - null); - if (handle?.IsInvalid != false) - return null; - - NVMeWindows nvme = new(); - if (nvme.IdentifyController(handle, out _)) - return handle; - - handle.Close(); - return null; - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/NamePrefixAttribute.cs b/LibreHardwareMonitorLib/Hardware/Storage/NamePrefixAttribute.cs deleted file mode 100644 index fa94076..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/NamePrefixAttribute.cs +++ /dev/null @@ -1,20 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System; - -namespace LibreHardwareMonitor.Hardware.Storage; - -[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -internal class NamePrefixAttribute : Attribute -{ - public NamePrefixAttribute(string namePrefix) - { - Prefix = namePrefix; - } - - public string Prefix { get; } -} \ No newline at end of file diff --git a/LibreHardwareMonitorLib/Hardware/Storage/RequireSmartAttribute.cs b/LibreHardwareMonitorLib/Hardware/Storage/RequireSmartAttribute.cs deleted file mode 100644 index c16aff5..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/RequireSmartAttribute.cs +++ /dev/null @@ -1,20 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System; - -namespace LibreHardwareMonitor.Hardware.Storage; - -[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -internal class RequireSmartAttribute : Attribute -{ - public RequireSmartAttribute(byte attributeId) - { - AttributeId = attributeId; - } - - public byte AttributeId { get; } -} \ No newline at end of file diff --git a/LibreHardwareMonitorLib/Hardware/Storage/SmartAttribute.cs b/LibreHardwareMonitorLib/Hardware/Storage/SmartAttribute.cs index fb5ef7c..06d0c7f 100644 --- a/LibreHardwareMonitorLib/Hardware/Storage/SmartAttribute.cs +++ b/LibreHardwareMonitorLib/Hardware/Storage/SmartAttribute.cs @@ -4,48 +4,14 @@ // Partial Copyright (C) Michael Möller and Contributors. // All Rights Reserved. -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using LibreHardwareMonitor.Interop; - namespace LibreHardwareMonitor.Hardware.Storage; -public class SmartAttribute +public sealed class SmartAttribute { - private readonly RawValueConversion _rawValueConversion; - - public delegate float RawValueConversion(byte[] rawValue, byte value, IReadOnlyList parameters); - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The SMART id of the attribute. - /// The name of the attribute. - public SmartAttribute(byte id, string name) : this(id, name, null, null, 0, null) - { } - - /// - /// Initializes a new instance of the class. - /// - /// The SMART id 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 id, string name, RawValueConversion rawValueConversion) : this(id, name, rawValueConversion, null, 0, null) - { } - - /// - /// Initializes a new instance of the class. - /// - /// The SMART id 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). - /// + /// The SMART attribute. /// /// Type of the sensor or null if no sensor is to /// be created. @@ -60,47 +26,25 @@ public class SmartAttribute /// no sensor is created. /// /// True to hide the sensor initially. - /// - /// Description for the parameters of the sensor - /// (or null). - /// - public SmartAttribute(byte id, string name, RawValueConversion rawValueConversion, SensorType? sensorType, int sensorChannel, string sensorName, bool defaultHiddenSensor = false, ParameterDescription[] parameterDescriptions = null) + public SmartAttribute(DiskInfoToolkit.SmartAttribute smartAttribute, SensorType? sensorType, int sensorChannel, string sensorName, bool defaultHiddenSensor = false) { - Id = id; - Name = name; - _rawValueConversion = rawValueConversion; + Attribute = smartAttribute; SensorType = sensorType; SensorChannel = sensorChannel; - SensorName = sensorName; - DefaultHiddenSensor = defaultHiddenSensor; - ParameterDescriptions = parameterDescriptions; + SensorName = sensorName ?? Name; + IsHiddenByDefault = defaultHiddenSensor; } - public bool DefaultHiddenSensor { get; } + public DiskInfoToolkit.SmartAttribute Attribute { get; internal set; } - public bool HasRawValueConversion => _rawValueConversion != null; - - /// - /// Gets the SMART identifier. - /// - public byte Id { get; } - - public string Name { get; } - - public ParameterDescription[] ParameterDescriptions { get; } - - public int SensorChannel { get; } - - public string SensorName { get; } + public byte Id => Attribute.Info.ID; + public string Name => Attribute.Info.Name; public SensorType? SensorType { get; } + public int SensorChannel { get; } + public string SensorName { get; } + public bool IsHiddenByDefault { get; } - internal unsafe float ConvertValue(AtaSmart.SMART_ATTRIBUTE value, IReadOnlyList parameters) - { - if (_rawValueConversion == null) - return value.CurrentValue; - - Span rawValue = new(value.RawValue, 6); - return _rawValueConversion(rawValue.ToArray(), value.CurrentValue, parameters); - } + public float Value => Attribute.Attribute.RawValueULong; + public byte Threshold => Attribute.Attribute.Threshold; } diff --git a/LibreHardwareMonitorLib/Hardware/Storage/SmartAttributeTranslator.cs b/LibreHardwareMonitorLib/Hardware/Storage/SmartAttributeTranslator.cs new file mode 100644 index 0000000..d319a40 --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Storage/SmartAttributeTranslator.cs @@ -0,0 +1,1760 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// Partial Copyright (C) Michael Möller and Contributors. +// All Rights Reserved. + +using System.Collections.Generic; +using DiskInfoToolkit.Interop.Enums; + +namespace LibreHardwareMonitor.Hardware.Storage; + +internal static class SmartAttributeTranslator +{ + const int SensorChannelStartIndex = 30; + + public static List GetAttributesFor(DiskInfoToolkit.Storage storage) + { + switch (storage.SmartKey) + { + case SmartKey.Smart: + return GetSmart(storage); + case SmartKey.SSD: + return GetSSD(storage); + case SmartKey.Mtron: + return GetMtron(storage); + case SmartKey.Indilinx: + return GetIndilinx(storage); + case SmartKey.JMicron60x: + return GetJMicron60X(storage); + case SmartKey.Intel: + return GetIntel(storage); + case SmartKey.Samsung: + return GetSamsung(storage); + case SmartKey.SandForce: + return GetSandforce(storage); + case SmartKey.JMicron61x: + return GetJMicron61X(storage); + case SmartKey.Micron: + return GetMicron(storage); + case SmartKey.MicronMU02: + return GetMicronMU03(storage); + case SmartKey.Ocz: + return GetOcz(storage); + case SmartKey.Plextor: + return GetPlextor(storage); + case SmartKey.SanDisk: + return GetSandisk(storage); + case SmartKey.OczVector: + return GetOczVector(storage); + case SmartKey.Corsair: + return GetCorsair(storage); + case SmartKey.Toshiba: + return GetToshiba(storage); + case SmartKey.SanDiskGb: + return GetSandiskGB(storage); + case SmartKey.Kingston: + return GetKingston(storage); + case SmartKey.NVMe: + return GetNVME(storage); + case SmartKey.Realtek: + return GetRealtek(storage); + case SmartKey.SKhynix: + return GetSkhynix(storage); + case SmartKey.Kioxia: + return GetKioxia(storage); + case SmartKey.WDC: + return GetWdc(storage); + case SmartKey.KingstonSuv: + return GetKingstonSUV(storage); + case SmartKey.KingstonKC600: + return GetKingstonKC600(storage); + case SmartKey.KingstonDC500: + return GetKingstonDC500(storage); + case SmartKey.KingstonSA400: + return GetKingstonSA400(storage); + case SmartKey.Ssstc: + return GetSSSTC(storage); + case SmartKey.IntelDc: + return GetIntelDC(storage); + case SmartKey.Apacer: + return GetAPACER(storage); + case SmartKey.SiliconMotion: + return GetSiliconMotion(storage); + case SmartKey.JMicron66x: + return GetJMicron66X(storage); + case SmartKey.Phison: + return GetPhison(storage); + case SmartKey.Seagate: + return GetSeagate(storage); + case SmartKey.SeagateIronWolf: + return GetSeagateIronWolf(storage); + case SmartKey.Marvell: + return GetMarvell(storage); + case SmartKey.Maxiotek: + return GetMaxiotek(storage); + case SmartKey.SeagateBarraCuda: + return GetSeagateBarraCuda(storage); + case SmartKey.Ymtc: + return GetYMTC(storage); + case SmartKey.Scy: + return GetSCY(storage); + case SmartKey.Recadata: + return GetRecadata(storage); + case SmartKey.SanDiskHP: + return GetSandiskHP(storage); + case SmartKey.SanDiskHPVenus: + return GetSandiskHPVenus(storage); + case SmartKey.SanDiskDell: + return GetSandiskDell(storage); + case SmartKey.SanDiskLenovo: + return GetSandiskLenovo(storage); + case SmartKey.SanDiskLenovoHelenVenus: + return GetSandiskLenovoHelenVenus(storage); + case SmartKey.MicronMU03: + return GetMicronMU03(storage); + case SmartKey.SanDiskCloud: + return GetSandiskCloud(storage); + case SmartKey.SiliconMotionCVC: + return GetSiliconMotionCVC(storage); + case SmartKey.AdataIndustrial: + return GetAdataIndustrial(storage); + default: + return new(); + } + } + + private static List GetSmart(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ThroughputPerformance), + Get(storage, SmartAttributeType.SpinUpTime), + Get(storage, SmartAttributeType.StartStopCount), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.ReadChannelMargin), + Get(storage, SmartAttributeType.SeekErrorRate), + Get(storage, SmartAttributeType.SeekTimePerformance), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.SpinRetryCount), + Get(storage, SmartAttributeType.RecalibrationRetries), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SoftReadErrorRateStab), + Get(storage, SmartAttributeType.CurrentHeliumLevel), + Get(storage, SmartAttributeType.EndToEndError), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.HighFlyWrites), + Get(storage, SmartAttributeType.AirflowTemperature), + Get(storage, SmartAttributeType.GSenseErrorRate), + Get(storage, SmartAttributeType.PowerOffRetractCount), + Get(storage, SmartAttributeType.LoadUnloadCycleCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.HardwareECCRecovered), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.UncorrectableSectorCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.WriteErrorRate), + Get(storage, SmartAttributeType.SoftReadErrorRate), + Get(storage, SmartAttributeType.DataAddressMarkError), + Get(storage, SmartAttributeType.RunOutCancel), + Get(storage, SmartAttributeType.SoftECCCorrection), + Get(storage, SmartAttributeType.ThermalAsperityRate), + Get(storage, SmartAttributeType.FlyingHeight), + Get(storage, SmartAttributeType.SpinHighCurrent), + Get(storage, SmartAttributeType.SpinBuzz), + Get(storage, SmartAttributeType.OfflineSeekPerformance), + Get(storage, SmartAttributeType.VibrationDuringWrite), + Get(storage, SmartAttributeType.ShockDuringWrite), + Get(storage, SmartAttributeType.DiskShift), + Get(storage, SmartAttributeType.GSenseErrorRate), + Get(storage, SmartAttributeType.LoadedHours), + Get(storage, SmartAttributeType.LoadUnloadCycleCount), + Get(storage, SmartAttributeType.LoadFriction), + Get(storage, SmartAttributeType.LoadUnloadCycleCount), + Get(storage, SmartAttributeType.LoadInTime), + Get(storage, SmartAttributeType.TorqueAmplificationCount), + Get(storage, SmartAttributeType.PowerOffRetractCount), + Get(storage, SmartAttributeType.GMRHeadAmplitude), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.HeadFlyingHours), + Get(storage, SmartAttributeType.ReadErrorRetryRate), + Get(storage, SmartAttributeType.FreeFallProtection), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.HeliumConditionLower), + Get(storage, SmartAttributeType.HeliumConditionUpper), + Get(storage, SmartAttributeType.MAMRHealthMonitor), + ]; + } + + private static List GetSSD(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ThroughputPerformance), + Get(storage, SmartAttributeType.SpinUpTime), + Get(storage, SmartAttributeType.StartStopCount), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.ReadChannelMargin), + Get(storage, SmartAttributeType.SeekErrorRate), + Get(storage, SmartAttributeType.SeekTimePerformance), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.SpinRetryCount), + Get(storage, SmartAttributeType.RecalibrationRetries), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SoftReadErrorRateStab), + Get(storage, SmartAttributeType.UnsafeShutdownCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.UncorrectableSectorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + ]; + } + + private static List GetMtron(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.TotalEraseCount), + ]; + } + + private static List GetIndilinx(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ProgramFailureBlockCount), + Get(storage, SmartAttributeType.EraseFailureBlockCount), + Get(storage, SmartAttributeType.ReadFailureBlockCount), + Get(storage, SmartAttributeType.TotalCountReadSectors), + Get(storage, SmartAttributeType.TotalCountWriteSectors), + Get(storage, SmartAttributeType.TotalCountReadCommands), + Get(storage, SmartAttributeType.TotalCountWriteCommands), + Get(storage, SmartAttributeType.TotalCountErrorBitsFromFlash), + Get(storage, SmartAttributeType.TotalCountReadSectorsWithCorrectableBitErrors), + Get(storage, SmartAttributeType.BadBlockFullFlag), + Get(storage, SmartAttributeType.MaximumPECountSpecification), + Get(storage, SmartAttributeType.MinimumEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.RemainingLife), + ]; + } + + private static List GetIntel(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.SpinUpTime), + Get(storage, SmartAttributeType.StartStopCount), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.PowerLossProtectionFailure), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.EndToEndError), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.UnsafeShutdownCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.TimedWorkloadMediaWear), + Get(storage, SmartAttributeType.TimedWorkloadHostReadWriteRatio), + Get(storage, SmartAttributeType.TimedWorkloadTimer), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.ThermalThrottleStatus), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetSamsung(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.UsedReservedBlockCount), + Get(storage, SmartAttributeType.UsedReservedBlockCount), + Get(storage, SmartAttributeType.UnusedReservedBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.RuntimeBadBlock), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.AirflowTemperature), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ECCErrorRate), + Get(storage, SmartAttributeType.OfflineUncorrectableErrors), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.SuperCapStatus), + Get(storage, SmartAttributeType.SSDModeStatus), + Get(storage, SmartAttributeType.PORRecoveryCount), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.UnusedReservedBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ErrorDetection), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + ]; + } + + private static List GetSandforce(DiskInfoToolkit.Storage storage) + { + int sensorStart = SensorChannelStartIndex; + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.RetiredBlockCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SoftReadErrorRate), + Get(storage, SmartAttributeType.GigabytesErased), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.WearRangeDelta), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.IOErrorDetectionCodeErrors), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.UncorrectableSectorCount), + Get(storage, SmartAttributeType.SATARErrors), + Get(storage, SmartAttributeType.SoftReadErrorRate), + Get(storage, SmartAttributeType.SoftECCCorrection), + Get(storage, SmartAttributeType.DriveLifeProtectionStatus), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.NandDataWritten, SensorType.Data, sensorStart++), + Get(storage, SmartAttributeType.PowerFailBackupHealth), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + ]; + } + + private static List GetMicron(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedNANDBlocks), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SoftReadErrorRate), + Get(storage, SmartAttributeType.DeviceCapacity), + Get(storage, SmartAttributeType.UserCapacity), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.RemainingSpareBlocks), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.UnusedReservedBlockCount), + Get(storage, SmartAttributeType.UnalignedAccessCount), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.ErrorCorrectionCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ECCBitCorrectionCount), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.OfflineUncorrectableErrors), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.LifetimeUsed), + Get(storage, SmartAttributeType.WriteErrorRate), + Get(storage, SmartAttributeType.SuccessfulRAINRecoveryCount), + Get(storage, SmartAttributeType.TotalBytesRead), + Get(storage, SmartAttributeType.WriteProtectProgress), + Get(storage, SmartAttributeType.ECCBitsCorrected), + Get(storage, SmartAttributeType.ECCCumulativeThresholdEvents), + Get(storage, SmartAttributeType.CumulativeProgramNANDPages), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostProgramPageCount), + Get(storage, SmartAttributeType.BackgroundProgramPageCount), + Get(storage, SmartAttributeType.TotalRefreshISPCount), + Get(storage, SmartAttributeType.TotalDoRefCalCount), + Get(storage, SmartAttributeType.TotalNANDReadPlaneCountLow), + Get(storage, SmartAttributeType.TotalNANDReadPlaneCountHigh), + Get(storage, SmartAttributeType.TotalBlockReMapPassCount), + Get(storage, SmartAttributeType.TotalBackgroundScanOverLimitCount), + Get(storage, SmartAttributeType.TotalBackgroundScan), + ]; + } + + private static List GetOcz(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.SpinUpTime), + Get(storage, SmartAttributeType.StartStopCount), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.TotalCountWriteSectors), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.TotalBlocksErased), + Get(storage, SmartAttributeType.SSDProtectMode), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.TotalNumberCorrectedBits), + Get(storage, SmartAttributeType.MaxRatedPECounts), + Get(storage, SmartAttributeType.MinimumEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.NandReadRetryCount), + Get(storage, SmartAttributeType.SimpleReadRetryAttempts), + Get(storage, SmartAttributeType.AdaptiveReadRetryAttempts), + Get(storage, SmartAttributeType.OfflineUncorrectableErrors), + Get(storage, SmartAttributeType.RAIDRecoveryCount), + Get(storage, SmartAttributeType.PowerLossProtectionFailure), + Get(storage, SmartAttributeType.NandDataRead), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetSeagate(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.RetiredBlockCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.RemainingSpareBlocks), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.WearRangeDelta), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.SoftReadErrorRate), + Get(storage, SmartAttributeType.SoftECCCorrection), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.ReadFailureBlockCount), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataRead), + ]; + } + + private static List GetWdc(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedNANDBlocks), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.TotalNANDEraseCount), + Get(storage, SmartAttributeType.MinimumPECycles), + Get(storage, SmartAttributeType.MaximumBadBlocksPerDie), + Get(storage, SmartAttributeType.MaximumPECycles), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.GrownBadBlocks), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AveragePECycles), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.EndToEndErrorsCorrected), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.ThermalThrottleStatus), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetPlextor(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ProgramFailCountWorstCase), + Get(storage, SmartAttributeType.EraseFailCountWorstCase), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.UsedReservedBlockCountWorstCase), + Get(storage, SmartAttributeType.UsedReservedBlockCount), + Get(storage, SmartAttributeType.UnusedReservedBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.EndToEndErrorsCorrected), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.UnsafeShutdownCount), + Get(storage, SmartAttributeType.ECCErrorRate), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.UncorrectableSectorCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + ]; + } + + private static List GetSandisk(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReallocatedNANDBlocks), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.PercentOfTotalEraseCount), + Get(storage, SmartAttributeType.RemainingSpareBlocks), + Get(storage, SmartAttributeType.PercentOfTotalEraseCountBCBlocks), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + ]; + } + + private static List GetOczVector(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.RuntimeBadBlock), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.TotalUncorrectableNANDReads), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.TotalReadFailures), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.TotalBlocksErased), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.TotalNumberCorrectedBits), + Get(storage, SmartAttributeType.MaxRatedPECounts), + Get(storage, SmartAttributeType.MinimumEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.NandReadRetryCount), + Get(storage, SmartAttributeType.SimpleReadRetryAttempts), + Get(storage, SmartAttributeType.AdaptiveReadRetryAttempts), + Get(storage, SmartAttributeType.OfflineUncorrectableErrors), + Get(storage, SmartAttributeType.RAIDRecoveryCount), + Get(storage, SmartAttributeType.InWarranty), + Get(storage, SmartAttributeType.DASPolarity), + Get(storage, SmartAttributeType.PartialPfail), + Get(storage, SmartAttributeType.WriteThrottlingActivationFlag), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataRead), + ]; + } + + private static List GetToshiba(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ThroughputPerformance), + Get(storage, SmartAttributeType.SpinUpTime), + Get(storage, SmartAttributeType.StartStopCount), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.SeekErrorRate), + Get(storage, SmartAttributeType.SeekTimePerformance), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.SpinRetryCount), + Get(storage, SmartAttributeType.RecalibrationRetries), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SSDProtectMode), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.UncorrectableSectorCount), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + ]; + } + + private static List GetCorsair(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.RetiredBlockCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + ]; + } + + private static List GetKingston(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ThroughputPerformance), + Get(storage, SmartAttributeType.SpinUpTime), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.SeekErrorRate), + Get(storage, SmartAttributeType.SeekTimePerformance), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.SpinRetryCount), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.BadClusterTableCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.UnsafeShutdownCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.WriteHead), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.TotalEraseCount), + ]; + } + + private static List GetMicronMU03(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedNANDBlocks), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.UnusedSpareNANDBlocks), + Get(storage, SmartAttributeType.Non4KAlignedAccess), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.ErrorCorrectionCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.ErrorCorrectionCount), + Get(storage, SmartAttributeType.OfflineUncorrectableErrors), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.WriteErrorRate), + Get(storage, SmartAttributeType.SuccessfulRAINRecoveryCount), + Get(storage, SmartAttributeType.HostProgramPageCount), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.HostProgramPageCount), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.CumulativeProgramNANDPages), + Get(storage, SmartAttributeType.CumulativeProgramNANDPages), + ]; + } + + private static List GetNVME(DiskInfoToolkit.Storage storage) + { + int sensorStart = SensorChannelStartIndex; + return + [ + Get(storage, SmartAttributeType.CriticalWarning), + Get(storage, SmartAttributeType.CompositeTemperature), + Get(storage, SmartAttributeType.AvailableSpare, SensorType.Level, sensorStart++), + Get(storage, SmartAttributeType.AvailableSpareThreshold, SensorType.Level, sensorStart++), + Get(storage, SmartAttributeType.PercentageUsed, SensorType.Level, sensorStart++), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostReadCommands), + Get(storage, SmartAttributeType.HostWriteCommands), + Get(storage, SmartAttributeType.ControllerBusyTime), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.UnsafeShutdownCount), + Get(storage, SmartAttributeType.MediaAndDataIntegrityErrors), + Get(storage, SmartAttributeType.NumberOfErrorInformationLogEntries), + Get(storage, SmartAttributeType.WarningCompositeTemperatureTime), + Get(storage, SmartAttributeType.CriticalCompositeTemperatureTime), + Get(storage, SmartAttributeType.TemperatureSensor1), + Get(storage, SmartAttributeType.TemperatureSensor2), + Get(storage, SmartAttributeType.TemperatureSensor3), + Get(storage, SmartAttributeType.TemperatureSensor4), + Get(storage, SmartAttributeType.TemperatureSensor5), + Get(storage, SmartAttributeType.TemperatureSensor6), + Get(storage, SmartAttributeType.TemperatureSensor7), + Get(storage, SmartAttributeType.TemperatureSensor8), + Get(storage, SmartAttributeType.ThermalManagementTemperature1TransitionCount), + Get(storage, SmartAttributeType.ThermalManagementTemperature2TransitionCount), + Get(storage, SmartAttributeType.TotalTimeThermalManagementTemperature1), + Get(storage, SmartAttributeType.TotalTimeThermalManagementTemperature2), + ]; + } + + private static List GetRealtek(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.RawDataErrorRate), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.GDN), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.MaximumPECycles), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.SSDProtectMode), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ECCFailRecord), + Get(storage, SmartAttributeType.UnalignedAccessCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ECCBitCorrectionCount), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.MinimumEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetSkhynix(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.MinimumEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ProgramFailCountWorstCase), + Get(storage, SmartAttributeType.EraseFailCountWorstCase), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.UsedReservedBlockCountWorstCase), + Get(storage, SmartAttributeType.UsedReservedBlockCount), + Get(storage, SmartAttributeType.UnusedReservedBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.EndToEndError), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.ShockEventCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ECCErrorRate), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.UncorrectableSectorCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.UncorrectableSoftReadErrorRate), + Get(storage, SmartAttributeType.SoftECCCorrection), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataRead), + ]; + } + + private static List GetKioxia(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SSDProtectMode), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.HostDataWritten), + ]; + } + + private static List GetSSSTC(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedNANDBlocks), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ProgramFailCountWorstCase), + Get(storage, SmartAttributeType.EraseFailCountWorstCase), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.UsedReservedBlockCountWorstCase), + Get(storage, SmartAttributeType.UsedReservedBlockCount), + Get(storage, SmartAttributeType.UnusedReservedBlockCount), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.EndToEndError), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ECCErrorRate), + Get(storage, SmartAttributeType.OfflineUncorrectableErrors), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.PowerLossProtectionFailure), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetIntelDC(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedNANDBlocks), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.DeviceCapacity), + Get(storage, SmartAttributeType.UserCapacity), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.RemainingSpareBlocks), + Get(storage, SmartAttributeType.TotalBlockEraseFailure), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.PowerLossProtectionFailure), + Get(storage, SmartAttributeType.ProgramFailureBlockCount), + Get(storage, SmartAttributeType.EndToEndError), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.OfflineUncorrectableErrors), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.LifetimeUsed), + Get(storage, SmartAttributeType.TimedWorkloadMediaWear), + Get(storage, SmartAttributeType.TimedWorkloadHostReadWriteRatio), + Get(storage, SmartAttributeType.TimedWorkloadTimer), + Get(storage, SmartAttributeType.ThermalThrottleStatus), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetAPACER(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.SSDProtectMode), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.BadClusterTableCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.HostDataWritten), + ]; + } + + private static List GetSiliconMotion(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SLCTotalEraseCount), + Get(storage, SmartAttributeType.SLCMaximumEraseCount), + Get(storage, SmartAttributeType.SLCMinimumEraseCount), + Get(storage, SmartAttributeType.SLCAverageEraseCount), + Get(storage, SmartAttributeType.DRAM1BitErrorCount), + Get(storage, SmartAttributeType.UncorrectableSectorCount), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.NumberOfCacheDataBlock), + Get(storage, SmartAttributeType.NumberOfInvalidBlocks), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.MinimumEraseCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.MaxEraseCountOfSpec), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.ProgramFailCountInWorstDie), + Get(storage, SmartAttributeType.EraseFailCountInWorstDie), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.RuntimeBadBlock), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.PowerOffRetractCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.HardwareECCRecovered), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.OfflineUncorrectableErrors), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.TotalCountWriteSectors), + ]; + } + + private static List GetPhison(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.HostDataWritten), + ]; + } + + private static List GetMarvell(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.MinimumEraseCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.PowerOffRetractCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + ]; + } + + private static List GetMaxiotek(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SSDProtectMode), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.BadClusterTableCount), + Get(storage, SmartAttributeType.ReadErrorRetryRate), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.MinimumEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.SLCMinimumEraseCount), + Get(storage, SmartAttributeType.SLCMaximumEraseCount), + Get(storage, SmartAttributeType.SLCAverageEraseCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataRead), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.BitErrorCount), + ]; + } + + private static List GetYMTC(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.MaximumBadBlocksPerDie), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.BadClusterTableCount), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.EndToEndErrorsCorrected), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.MinimumEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.SLCMinimumEraseCount), + Get(storage, SmartAttributeType.SLCMaximumEraseCount), + Get(storage, SmartAttributeType.SLCAverageEraseCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataRead), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NANDTemperature), + Get(storage, SmartAttributeType.BitErrorCount), + ]; + } + + private static List GetSCY(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.SeekErrorRate), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.ReadErrorRetryRate), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.RuntimeBadBlock), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ECCBitCorrectionCount), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetJMicron60X(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.HaltSystemIDFlashID), + Get(storage, SmartAttributeType.FirmwareVersion), + Get(storage, SmartAttributeType.ECCFailRecord), + Get(storage, SmartAttributeType.AverageEraseCountMaxEraseCount), + Get(storage, SmartAttributeType.GoodBlockCountSystemBlockCount), + ]; + } + + private static List GetJMicron61X(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ThroughputPerformance), + Get(storage, SmartAttributeType.SpinUpTime), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.SeekErrorRate), + Get(storage, SmartAttributeType.SeekTimePerformance), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.SpinRetryCount), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.ECCFailRecord), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.TotalEraseCount), + ]; + } + + private static List GetJMicron66X(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ThroughputPerformance), + Get(storage, SmartAttributeType.SpinUpTime), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.SeekErrorRate), + Get(storage, SmartAttributeType.SeekTimePerformance), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.SpinRetryCount), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SSDProtectMode), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.BadClusterTableCount), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.WriteHead), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + ]; + } + + private static List GetSeagateIronWolf(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.GigabytesErased), + Get(storage, SmartAttributeType.LifetimePS4EntryCount), + Get(storage, SmartAttributeType.LifetimePS3EntryCount), + Get(storage, SmartAttributeType.GrownBadBlocks), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.WearRangeDelta), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.RAISEECCCorrectableCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.DriveLifeProtectionStatus), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.FreeSpace), + ]; + } + + private static List GetSeagateBarraCuda(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.RetiredBlockCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.RemainingSpareBlocks), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.WearRangeDelta), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.SoftReadErrorRate), + Get(storage, SmartAttributeType.SoftECCCorrection), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.ReadFailureBlockCount), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataRead), + ]; + } + + private static List GetSandiskGB(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedNANDBlocks), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.TotalBlocksErased), + Get(storage, SmartAttributeType.MinimumPECycles), + Get(storage, SmartAttributeType.MaximumBadBlocksPerDie), + Get(storage, SmartAttributeType.MaximumPECycles), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.GrownBadBlocks), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.PECycles), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.EndToEndErrorsCorrected), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.ThermalThrottleStatus), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetKingstonSUV(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ProgramFailCountInWorstDie), + Get(storage, SmartAttributeType.EraseFailCountInWorstDie), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.UsedReservedBlockCountWorstDie), + Get(storage, SmartAttributeType.UnusedReservedBlockCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ECCErrorRate), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.SoftECCCorrection), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataRead), + ]; + } + + private static List GetKingstonKC600(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedNANDBlocks), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.Reserved), + Get(storage, SmartAttributeType.Reserved), + Get(storage, SmartAttributeType.Reserved), + Get(storage, SmartAttributeType.SLCAverageEraseCount), + Get(storage, SmartAttributeType.DRAM1BitErrorCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.Reserved), + Get(storage, SmartAttributeType.Reserved), + Get(storage, SmartAttributeType.Reserved), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.Reserved), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.Reserved), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.HardwareECCRecovered), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.UnusedReservedBlockCount), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.HostDataWritten), + ]; + } + + private static List GetKingstonDC500(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SSDProtectMode), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.BadBlockFullFlag), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.ThermalThrottleStatus), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.TotalReadFailures), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.TotalEraseCount), + ]; + } + + private static List GetKingstonSA400(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.VendorUnique), + Get(storage, SmartAttributeType.VendorUnique), + Get(storage, SmartAttributeType.VendorUnique), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.VendorUnique), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.VendorUnique), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.VendorUnique), + Get(storage, SmartAttributeType.VendorUnique), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.TotalEraseCount), + ]; + } + + private static List GetRecadata(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.SeekErrorRate), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.ReadErrorRetryRate), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.RuntimeBadBlock), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ECCBitCorrectionCount), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.PendingSectorCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetSandiskDell(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.UsedReservedBlockCountWorstCase), + Get(storage, SmartAttributeType.UsedReservedBlockCount), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ECCErrorRate), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + ]; + } + + private static List GetSandiskHP(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.EndToEndError), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.AirflowTemperature), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.ThrottleStatistics), + Get(storage, SmartAttributeType.ThermalThrottleStatus), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetSandiskHPVenus(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.WearLevelingCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.EndToEndError), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.AirflowTemperature), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ReallocationEventCount), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.ThermalThrottleStatus), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetSandiskLenovo(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.MinimumPECycles), + Get(storage, SmartAttributeType.MaximumBadBlocksPerDie), + Get(storage, SmartAttributeType.MaximumPECycles), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.GrownBadBlocks), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AveragePECycles), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.RemainingSpareBlocks), + Get(storage, SmartAttributeType.EndToEndErrorsCorrected), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.ThrottleStatistics), + Get(storage, SmartAttributeType.ThermalThrottleStatus), + ]; + } + + private static List GetSandiskLenovoHelenVenus(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.MinimumPECycles), + Get(storage, SmartAttributeType.MaximumBadBlocksPerDie), + Get(storage, SmartAttributeType.MaximumPECycles), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.GrownBadBlocks), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AveragePECycles), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.UsedReservedBlockCount), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.EndToEndError), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.CommandTimeout), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.AvailableReservedSpace), + Get(storage, SmartAttributeType.MediaWearoutIndicator), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.ThrottleStatistics), + Get(storage, SmartAttributeType.ThermalThrottleStatus), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetSandiskCloud(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.RetiredBlockCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.WriteAmplificationMultipliedBy100), + Get(storage, SmartAttributeType.WriteAmplificationFactor), + Get(storage, SmartAttributeType.ReserveBlockCount), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.CleanShutdownCount), + Get(storage, SmartAttributeType.UnsafeShutdownCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.ReallocatedNANDBlocks), + Get(storage, SmartAttributeType.PercentOfTotalEraseCount), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.CapacitorHealth), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.ThermalThrottleStatus), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.SPITestsRemaining), + ]; + } + + private static List GetSiliconMotionCVC(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.ReallocatedSectorsCount), + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SLCCache), + Get(storage, SmartAttributeType.GrownBadBlocks), + Get(storage, SmartAttributeType.ProgramFailCount), + Get(storage, SmartAttributeType.EraseFailCount), + Get(storage, SmartAttributeType.AverageEraseCount), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.ProgramFailCountWorstCase), + Get(storage, SmartAttributeType.SATADownshiftCount), + Get(storage, SmartAttributeType.EndToEndError), + Get(storage, SmartAttributeType.UncorrectableErrors), + Get(storage, SmartAttributeType.MaximumEraseCount), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.MinimumEraseCount), + Get(storage, SmartAttributeType.ReadErrorRate), + Get(storage, SmartAttributeType.OfflineUncorrectableErrors), + Get(storage, SmartAttributeType.CRCErrorCount), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.NandDataWritten), + Get(storage, SmartAttributeType.HostDataWritten), + Get(storage, SmartAttributeType.HostDataRead), + Get(storage, SmartAttributeType.RAIDEventCount), + Get(storage, SmartAttributeType.RAIDUncorrectableCount), + Get(storage, SmartAttributeType.SSDProtectMode), + Get(storage, SmartAttributeType.ReadErrorRetryRate), + Get(storage, SmartAttributeType.NandDataWritten), + ]; + } + + private static List GetAdataIndustrial(DiskInfoToolkit.Storage storage) + { + return + [ + Get(storage, SmartAttributeType.PowerOnHours), + Get(storage, SmartAttributeType.PowerCycleCount), + Get(storage, SmartAttributeType.SSDProtectMode), + Get(storage, SmartAttributeType.SATAPhysicalErrorCount), + Get(storage, SmartAttributeType.BadBlockCount), + Get(storage, SmartAttributeType.TotalEraseCount), + Get(storage, SmartAttributeType.BadClusterTableCount), + Get(storage, SmartAttributeType.SpareBlocksAvailable), + Get(storage, SmartAttributeType.UnexpectedPowerLoss), + Get(storage, SmartAttributeType.Temperature), + Get(storage, SmartAttributeType.RemainingLife), + Get(storage, SmartAttributeType.FlashWriteSectorCount), + Get(storage, SmartAttributeType.FlashReadSectorCount), + Get(storage, SmartAttributeType.TotalCountWriteSectors), + Get(storage, SmartAttributeType.TotalCountReadSectors), + ]; + } + + private static SmartAttribute Get(DiskInfoToolkit.Storage storage, SmartAttributeType smartAttributeType, SensorType? sensorType = null, int sensorChannel = 0, string sensorName = null) + { + var attr = storage.Smart.SmartAttributes.Find(sa => sa.Info.Type == smartAttributeType); + + if (attr == null) + { + return null; + } + else + { + return new(attr, sensorType, sensorChannel, sensorName); + } + } +} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/SmartNames.cs b/LibreHardwareMonitorLib/Hardware/Storage/SmartNames.cs deleted file mode 100644 index 6fbce31..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/SmartNames.cs +++ /dev/null @@ -1,263 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -namespace LibreHardwareMonitor.Hardware.Storage; - -/// -/// Localization class for SMART attribute names. -/// -public static class SmartNames -{ - public static string AirflowTemperature => "Airflow Temperature"; - - public static string AlternativeEraseFailCount => "Alternative Erase Fail Count"; - - public static string AlternativeGSenseErrorRate => "Alternative G-Sense Error Rate"; - - public static string AlternativeProgramFailCount => "Alternative Program Fail Count"; - - public static string AvailableReservedSpace => "Available Reserved Space"; - - public static string AverageEraseCount => "Average Erase Count"; - - public static string BadBlockFullFlag => "Bad Block Full Flag"; - - public static string BitErrors => "Bit Errors"; - - public static string CalibrationRetryCount => "Calibration Retry Count"; - - public static string CommandTimeout => "Command Timeout"; - - public static string ControllerWritesToNand => "Controller Writes to NAND"; - - public static string CorrectedErrors => "Corrected Errors"; - - public static string CrcErrorCount => "CRC Error Count"; - - public static string CurrentPendingSectorCount => "Current Pending Sector Count"; - - public static string DataAddressMarkErrors => "Data Address Mark errors"; - - public static string DiskShift => "Disk Shift"; - - public static string DriveTemperature => "Drive Temperature"; - - public static string EccRate => "ECC Rate"; - - public static string EmergencyRetractCycleCount => "Emergency Retract Cycle Count"; - - public static string EndToEndError => "End-to-End error"; - - public static string EnduranceRemaining => "Endurance Remaining"; - - public static string EraseFailCount => "Erase Fail Count"; - - public static string EraseFailCountChip => "Erase Fail Count (Chip)"; - - public static string EraseFailCountTotal => "Erase Fail Count (Total)"; - - public static string EraseFailure => "Erase Failure"; - - public static string ErrorCorrectionCount => "Error Correction Count"; - - public static string ExceptionModeStatus => "Exception Mode Status"; - - public static string FactoryBadBlockCount => "Factory Bad Block Count"; - - public static string FlyingHeight => "Flying Height"; - - public static string FreeFallProtection => "Free Fall Protection"; - - public static string FTLProgramNANDPagesCount => "FTL Program NAND Pages Count"; - - public static string GmrHeadAmplitude => "GMR Head Amplitude"; - - public static string GSenseErrorRate => "G-sense Error Rate"; - - public static string HardwareEccRecovered => "Hardware ECC Recovered"; - - public static string HeadFlyingHours => "Head Flying Hours"; - - public static string HeadStability => "Head Stability"; - - public static string HighFlyWrites => "High Fly Writes"; - - public static string HostProgramNANDPagesCount => "Host Program NAND Pages Count"; - - public static string HostReads => "Host Reads"; - - public static string HostWrites => "Host Writes"; - - public static string HostWritesToController => "Host Writes to Controller"; - - public static string InducedOpVibrationDetection => "Induced Op-Vibration Detection"; - - public static string InitialBadBlockCount => "Initial Bad Block Count"; - - public static string LoadCycleCount => "Load Cycle Count"; - - public static string LoadedHours => "Loaded Hours"; - - public static string LoadFriction => "Load Friction"; - - public static string LoadInTime => "Load 'In'-time"; - - public static string LoadUnloadCycleCount => "Load/Unload Cycle Count"; - - public static string LoadUnloadCycleCountFujitsu => "Load/Unload Cycle Count (Fujitus)"; - - public static string LoadUnloadRetryCount => "Load/Unload Retry Count"; - - public static string MaxCellCycles => "Max Cell Cycles"; - - public static string MaxErase => "Max Erase"; - - public static string MediaWearOutIndicator => "Media Wear Out Indicator"; - - public static string MinErase => "Min Erase"; - - public static string MultiZoneErrorRate => "Multi-Zone Error Rate"; - - public static string NewFailingBlockCount => "New Failing Block Count"; - - public static string Non4KAlignedAccess => "Non-4k Aligned Access"; - - public static string OfflineSeekPerformance => "Offline Seek Performance"; - - public static string OffLineUncorrectableErrorCount => "Off-Line Uncorrectable Error Count"; - - public static string PowerCycleCount => "Power Cycle Count"; - - public static string PowerOffRetractCycle => "Power-Off Retract Cycle"; - - public static string PowerOnHours => "Power-On Hours (POH)"; - - public static string PowerRecoveryCount => "Power Recovery Count"; - - public static string ProgramFailCount => "Program Fail Count"; - - public static string ProgramFailCountChip => "Program Fail Count (Chip)"; - - public static string ProgramFailCountTotal => "Program Fail Count (Total)"; - - public static string ProgramFailure => "Program Failure"; - - public static string RawReadErrorRate => "Raw Read Error Rate"; - - public static string ReadChannelMargin => "Read Channel Margin"; - - public static string ReadCommands => "Read Commands"; - - public static string ReadErrorRate => "Read Error Rate"; - - public static string ReadErrorRetryRate => "Read Error Retry Rate"; - - public static string ReadFailure => "Read Failure"; - - public static string ReallocatedNANDBlockCount => "Reallocated NAND Block Count"; - - public static string ReallocatedSectorsCount => "Reallocated Sectors Count"; - - public static string ReallocationEventCount => "Reallocation Event Count"; - - public static string RecalibrationRetries => "Recalibration Retries"; - - public static string RemainingLife => "Remaining Life"; - - public static string ReportedUncorrectableErrors => "Reported Uncorrectable Errors"; - - public static string RetiredBlockCount => "Retired Block Count"; - - public static string RunOutCancel => "Run Out Cancel"; - - public static string RuntimeBadBlockTotal => "Runtime Bad Block Total"; - - public static string SataDownshiftErrorCount => "SATA Downshift Error Count"; - - public static string SataErrorCountCrc => "SATA Error Count CRC"; - - public static string SataErrorCountHandshake => "SATA Error Count Handshake"; - - public static string SectorsRead => "Sectors Read"; - - public static string SectorsWritten => "Sectors Written"; - - public static string SeekErrorRate => "Seek Error Rate"; - - public static string SeekTimePerformance => "Seek Time Performance"; - - public static string ShockDuringWrite => "Shock During Write"; - - public static string SoftEccCorrection => "Soft ECC Correction"; - - public static string SoftReadErrorRate => "Soft Read Error Rate"; - - public static string SpinBuzz => "Spin Buzz"; - - public static string SpinHighCurrent => "Spin High Current"; - - public static string SpinRetryCount => "Spin Retry Count"; - - public static string SpinUpTime => "Spin-Up Time"; - - public static string StartStopCount => "Start/Stop Count"; - - public static string SuccessfulRAINRecoveryCount => "Successful RAIN Recovery Count"; - - public static string SupercapStatus => "Supercap Status"; - - public static string TaCounterDetected => "TA Counter Detected"; - - public static string Temperature => "Temperature"; - - public static string TemperatureDifferenceFrom100 => "Temperature Difference from 100"; - - public static string TemperatureExceedCount => "Temperature Exceed Count"; - - public static string ThermalAsperityRate => "Thermal Asperity Rate (TAR)"; - - public static string ThroughputPerformance => "Throughput Performance"; - - public static string TorqueAmplificationCount => "Torque Amplification Count"; - - public static string TotalLbasRead => "Total LBAs Read"; - - public static string TotalLbasWritten => "Total LBAs Written"; - - public static string TransferErrorRate => "Transfer Error Rate"; - - public static string UltraDmaCrcErrorCount => "UltraDMA CRC Error Count"; - - public static string UncorrectableErrorCount => "Uncorrectable Error Count"; - - public static string UncorrectableSectorCount => "Uncorrectable Sector Count"; - - public static string UnexpectedPowerLossCount => "Unexpected Power Loss Count"; - - public static string Unknown => "Unknown"; - - public static string UnknownUnique => "Unknown Unique"; - - public static string UnrecoverableEcc => "Unrecoverable ECC"; - - public static string UnsafeShutdownCount => "Unsafe Shutdown Count"; - - public static string UnusedReserveNANDBlocks => "Unused Reserve NAND Blocks"; - - public static string UsedReservedBlockCountChip => "Used Reserved Block Count (Chip)"; - - public static string UsedReservedBlockCountTotal => "Used Reserved Block Count (Total)"; - - public static string VibrationDuringWrite => "Vibration During Write"; - - public static string WearLevelingCount => "Wear Leveling Count"; - - public static string WearRangeDelta => "Wear Range Delta"; - - public static string WriteCommands => "Write Commands"; - - public static string WriteErrorRate => "Write Error Rate"; -} \ No newline at end of file diff --git a/LibreHardwareMonitorLib/Hardware/Storage/SsdIndilinx.cs b/LibreHardwareMonitorLib/Hardware/Storage/SsdIndilinx.cs deleted file mode 100644 index 3f69875..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/SsdIndilinx.cs +++ /dev/null @@ -1,43 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System.Collections.Generic; - -namespace LibreHardwareMonitor.Hardware.Storage; - -[NamePrefix(""), RequireSmart(0x01), RequireSmart(0x09), RequireSmart(0x0C), RequireSmart(0xD1), RequireSmart(0xCE), RequireSmart(0xCF)] -internal class SsdIndilinx : AtaStorage -{ - private static readonly IReadOnlyList _smartAttributes = new List - { - new(0x01, SmartNames.ReadErrorRate), - new(0x09, SmartNames.PowerOnHours), - new(0x0C, SmartNames.PowerCycleCount), - new(0xB8, SmartNames.InitialBadBlockCount), - new(0xC3, SmartNames.ProgramFailure), - new(0xC4, SmartNames.EraseFailure), - new(0xC5, SmartNames.ReadFailure), - new(0xC6, SmartNames.SectorsRead), - new(0xC7, SmartNames.SectorsWritten), - new(0xC8, SmartNames.ReadCommands), - new(0xC9, SmartNames.WriteCommands), - new(0xCA, SmartNames.BitErrors), - new(0xCB, SmartNames.CorrectedErrors), - new(0xCC, SmartNames.BadBlockFullFlag), - new(0xCD, SmartNames.MaxCellCycles), - new(0xCE, SmartNames.MinErase), - new(0xCF, SmartNames.MaxErase), - new(0xD0, SmartNames.AverageEraseCount), - new(0xD1, SmartNames.RemainingLife, null, SensorType.Level, 0, SmartNames.RemainingLife), - new(0xD2, SmartNames.UnknownUnique), - new(0xD3, SmartNames.SataErrorCountCrc), - new(0xD4, SmartNames.SataErrorCountHandshake) - }; - - public SsdIndilinx(StorageInfo storageInfo, ISmart smart, string name, string firmwareRevision, int index, ISettings settings) - : base(storageInfo, smart, name, firmwareRevision, "ssd", index, _smartAttributes, settings) - { } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/SsdIntel.cs b/LibreHardwareMonitorLib/Hardware/Storage/SsdIntel.cs deleted file mode 100644 index 8c09f09..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/SsdIntel.cs +++ /dev/null @@ -1,49 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System.Collections.Generic; - -namespace LibreHardwareMonitor.Hardware.Storage; - -[NamePrefix("INTEL SSD"), RequireSmart(0xE1), RequireSmart(0xE8), RequireSmart(0xE9)] -internal class SsdIntel : AtaStorage -{ - private static readonly IReadOnlyList _smartAttributes = new List - { - new(0x01, SmartNames.ReadErrorRate), - new(0x03, SmartNames.SpinUpTime), - new(0x04, SmartNames.StartStopCount, RawToInt), - new(0x05, SmartNames.ReallocatedSectorsCount), - new(0x09, SmartNames.PowerOnHours, RawToInt), - new(0x0C, SmartNames.PowerCycleCount, RawToInt), - new(0xAA, SmartNames.AvailableReservedSpace), - new(0xAB, SmartNames.ProgramFailCount), - new(0xAC, SmartNames.EraseFailCount), - new(0xAE, SmartNames.UnexpectedPowerLossCount, RawToInt), - new(0xB7, SmartNames.SataDownshiftErrorCount, RawToInt), - new(0xB8, SmartNames.EndToEndError), - new(0xBB, SmartNames.UncorrectableErrorCount, RawToInt), - new(0xBE, - SmartNames.Temperature, - (r, _, p) => r[0] + (p?[0].Value ?? 0), - SensorType.Temperature, - 0, - SmartNames.AirflowTemperature, - false, - new[] { new ParameterDescription("Offset [°C]", "Temperature offset of the thermal sensor.\nTemperature = Value + Offset.", 0) }), - new(0xC0, SmartNames.UnsafeShutdownCount), - new(0xC7, SmartNames.CrcErrorCount, RawToInt), - new(0xE1, SmartNames.HostWrites, (r, v, p) => RawToInt(r, v, p) / 0x20, SensorType.Data, 0, SmartNames.HostWrites), - new(0xE8, SmartNames.RemainingLife, null, SensorType.Level, 0, SmartNames.RemainingLife), - new(0xE9, SmartNames.MediaWearOutIndicator), - new(0xF1, SmartNames.HostWrites, (r, v, p) => RawToInt(r, v, p) / 0x20, SensorType.Data, 0, SmartNames.HostWrites), - new(0xF2, SmartNames.HostReads, (r, v, p) => RawToInt(r, v, p) / 0x20, SensorType.Data, 1, SmartNames.HostReads) - }; - - public SsdIntel(StorageInfo storageInfo, ISmart smart, string name, string firmwareRevision, int index, ISettings settings) - : base(storageInfo, smart, name, firmwareRevision, "ssd", index, _smartAttributes, settings) - { } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/SsdMicron.cs b/LibreHardwareMonitorLib/Hardware/Storage/SsdMicron.cs deleted file mode 100644 index 4ae6c2e..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/SsdMicron.cs +++ /dev/null @@ -1,117 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System; -using System.Collections.Generic; -using LibreHardwareMonitor.Interop; - -namespace LibreHardwareMonitor.Hardware.Storage; - -[NamePrefix(""), RequireSmart(0xAB), RequireSmart(0xAC), RequireSmart(0xAD), RequireSmart(0xAE), RequireSmart(0xC4), RequireSmart(0xCA), RequireSmart(0xCE)] -internal class SsdMicron : AtaStorage -{ - private static readonly IReadOnlyList _smartAttributes = new List - { - new(0x01, SmartNames.ReadErrorRate, RawToInt), - new(0x05, SmartNames.ReallocatedNANDBlockCount, RawToInt), - new(0x09, SmartNames.PowerOnHours, RawToInt), - new(0x0C, SmartNames.PowerCycleCount, RawToInt), - new(0xAA, SmartNames.NewFailingBlockCount, RawToInt), - new(0xAB, SmartNames.ProgramFailCount, RawToInt), - new(0xAC, SmartNames.EraseFailCount, RawToInt), - new(0xAD, SmartNames.WearLevelingCount, RawToInt), - new(0xAE, SmartNames.UnexpectedPowerLossCount, RawToInt), - new(0xB4, SmartNames.UnusedReserveNANDBlocks, RawToInt), - new(0xB5, SmartNames.Non4KAlignedAccess, (raw, _, _) => 6e4f * ((raw[5] << 8) | raw[4])), - new(0xB7, SmartNames.SataDownshiftErrorCount, RawToInt), - new(0xB8, SmartNames.ErrorCorrectionCount, RawToInt), - new(0xBB, SmartNames.ReportedUncorrectableErrors, RawToInt), - new(0xBC, SmartNames.CommandTimeout, RawToInt), - new(0xBD, SmartNames.FactoryBadBlockCount, RawToInt), - new(0xC2, SmartNames.Temperature, RawToInt), - new(0xC4, SmartNames.ReallocationEventCount, RawToInt), - new(0xC5, SmartNames.CurrentPendingSectorCount), - new(0xC6, SmartNames.OffLineUncorrectableErrorCount, RawToInt), - new(0xC7, SmartNames.UltraDmaCrcErrorCount, RawToInt), - new(0xCA, SmartNames.RemainingLife, (raw, value, p) => 100 - RawToInt(raw, value, p), SensorType.Level, 0, SmartNames.RemainingLife), - new(0xCE, SmartNames.WriteErrorRate, (raw, _, _) => 6e4f * ((raw[1] << 8) | raw[0])), - new(0xD2, SmartNames.SuccessfulRAINRecoveryCount, RawToInt), - new(0xF6, - SmartNames.TotalLbasWritten, - (r, _, _) => (((long)r[5] << 40) | - ((long)r[4] << 32) | - ((long)r[3] << 24) | - ((long)r[2] << 16) | - ((long)r[1] << 8) | - r[0]) * - (512.0f / 1024 / 1024 / 1024), - SensorType.Data, - 0, - "Total Bytes Written"), - new(0xF7, SmartNames.HostProgramNANDPagesCount, RawToInt), - new(0xF8, SmartNames.FTLProgramNANDPagesCount, RawToInt) - }; - - private readonly Sensor _temperature; - private readonly Sensor _writeAmplification; - - public SsdMicron(StorageInfo storageInfo, ISmart smart, string name, string firmwareRevision, int index, ISettings settings) - : base(storageInfo, smart, name, firmwareRevision, "ssd", index, _smartAttributes, settings) - { - _temperature = new Sensor("Temperature", - 0, - false, - SensorType.Temperature, - this, - new[] - { - new ParameterDescription("Offset [°C]", - "Temperature offset of the thermal sensor.\n" + - "Temperature = Value + Offset.", - 0) - }, - settings); - - _writeAmplification = new Sensor("Write Amplification", - 0, - SensorType.Factor, - this, - settings); - } - - /// - protected override unsafe void UpdateAdditionalSensors(AtaSmart.SMART_ATTRIBUTE[] values) - { - float? hostProgramPagesCount = null; - float? ftlProgramPagesCount = null; - - foreach (AtaSmart.SMART_ATTRIBUTE value in values) - { - byte[] rawValue = new Span(value.RawValue, 6).ToArray(); - - if (value.Id == 0xF7) - hostProgramPagesCount = RawToInt(rawValue, value.CurrentValue, null); - - if (value.Id == 0xF8) - ftlProgramPagesCount = RawToInt(rawValue, value.CurrentValue, null); - - if (value.Id == 0xC2) - { - _temperature.Value = rawValue[0] + _temperature.Parameters[0].Value; - - if (rawValue[0] != 0) - ActivateSensor(_temperature); - } - } - - if (hostProgramPagesCount.HasValue && ftlProgramPagesCount.HasValue) - { - _writeAmplification.Value = hostProgramPagesCount.Value > 0 ? (hostProgramPagesCount.Value + ftlProgramPagesCount) / hostProgramPagesCount.Value : 0; - - ActivateSensor(_writeAmplification); - } - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/SsdPlextor.cs b/LibreHardwareMonitorLib/Hardware/Storage/SsdPlextor.cs deleted file mode 100644 index 361e5af..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/SsdPlextor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System.Collections.Generic; - -namespace LibreHardwareMonitor.Hardware.Storage; - -[NamePrefix("PLEXTOR")] -internal class SsdPlextor : AtaStorage -{ - private static readonly IReadOnlyList _smartAttributes = new List - { - new(0x09, SmartNames.PowerOnHours, RawToInt), - new(0x0C, SmartNames.PowerCycleCount, RawToInt), - new(0xF1, SmartNames.HostWrites, RawToGb, SensorType.Data, 0, SmartNames.HostWrites), - new(0xF2, SmartNames.HostReads, RawToGb, SensorType.Data, 1, SmartNames.HostReads) - }; - - public SsdPlextor(StorageInfo storageInfo, ISmart smart, string name, string firmwareRevision, int index, ISettings settings) - : base(storageInfo, smart, name, firmwareRevision, "ssd", index, _smartAttributes, settings) - { } - - private static float RawToGb(byte[] rawValue, byte value, IReadOnlyList parameters) - { - return RawToInt(rawValue, value, parameters) / 32; - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/SsdSamsung.cs b/LibreHardwareMonitorLib/Hardware/Storage/SsdSamsung.cs deleted file mode 100644 index 73492d2..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/SsdSamsung.cs +++ /dev/null @@ -1,57 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System.Collections.Generic; - -namespace LibreHardwareMonitor.Hardware.Storage; - -[NamePrefix(""), RequireSmart(0xB1), RequireSmart(0xB3), RequireSmart(0xB5), RequireSmart(0xB6), RequireSmart(0xB7), RequireSmart(0xBB), RequireSmart(0xC3), RequireSmart(0xC7)] -internal class SsdSamsung : AtaStorage -{ - private static readonly IReadOnlyList _smartAttributes = new List - { - new(0x05, SmartNames.ReallocatedSectorsCount), - new(0x09, SmartNames.PowerOnHours, RawToInt), - new(0x0C, SmartNames.PowerCycleCount, RawToInt), - new(0xAF, SmartNames.ProgramFailCountChip, RawToInt), - new(0xB0, SmartNames.EraseFailCountChip, RawToInt), - new(0xB1, SmartNames.WearLevelingCount, RawToInt), - new(0xB2, SmartNames.UsedReservedBlockCountChip, RawToInt), - new(0xB3, SmartNames.UsedReservedBlockCountTotal, RawToInt), - - // Unused Reserved Block Count (Total) - new(0xB4, SmartNames.RemainingLife, null, SensorType.Level, 0, SmartNames.RemainingLife), - new(0xB5, SmartNames.ProgramFailCountTotal, RawToInt), - new(0xB6, SmartNames.EraseFailCountTotal, RawToInt), - new(0xB7, SmartNames.RuntimeBadBlockTotal, RawToInt), - new(0xBB, SmartNames.UncorrectableErrorCount, RawToInt), - new(0xBE, - SmartNames.Temperature, - (r, _, p) => r[0] + (p?[0].Value ?? 0), - SensorType.Temperature, - 0, - SmartNames.Temperature, - false, - new[] { new ParameterDescription("Offset [°C]", "Temperature offset of the thermal sensor.\nTemperature = Value + Offset.", 0) }), - new(0xC2, SmartNames.AirflowTemperature), - new(0xC3, SmartNames.EccRate), - new(0xC6, SmartNames.OffLineUncorrectableErrorCount, RawToInt), - new(0xC7, SmartNames.CrcErrorCount, RawToInt), - new(0xC9, SmartNames.SupercapStatus), - new(0xCA, SmartNames.ExceptionModeStatus), - new(0xEB, SmartNames.PowerRecoveryCount), - new(0xF1, - SmartNames.TotalLbasWritten, - (r, _, _) => (((long)r[5] << 40) | ((long)r[4] << 32) | ((long)r[3] << 24) | ((long)r[2] << 16) | ((long)r[1] << 8) | r[0]) * (512.0f / 1024 / 1024 / 1024), - SensorType.Data, - 0, - "Total Bytes Written") - }; - - public SsdSamsung(StorageInfo storageInfo, ISmart smart, string name, string firmwareRevision, int index, ISettings settings) - : base(storageInfo, smart, name, firmwareRevision, "ssd", index, _smartAttributes, settings) - { } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/SsdSandforce.cs b/LibreHardwareMonitorLib/Hardware/Storage/SsdSandforce.cs deleted file mode 100644 index cd15703..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/SsdSandforce.cs +++ /dev/null @@ -1,79 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System; -using System.Collections.Generic; -using LibreHardwareMonitor.Interop; - -namespace LibreHardwareMonitor.Hardware.Storage; - -[NamePrefix(""), RequireSmart(0xAB), RequireSmart(0xB1)] -internal class SsdSandforce : AtaStorage -{ - private static readonly IReadOnlyList _smartAttributes = new List - { - new(0x01, SmartNames.RawReadErrorRate), - new(0x05, SmartNames.RetiredBlockCount, RawToInt), - new(0x09, SmartNames.PowerOnHours, RawToInt), - new(0x0C, SmartNames.PowerCycleCount, RawToInt), - new(0xAB, SmartNames.ProgramFailCount, RawToInt), - new(0xAC, SmartNames.EraseFailCount, RawToInt), - new(0xAE, SmartNames.UnexpectedPowerLossCount, RawToInt), - new(0xB1, SmartNames.WearRangeDelta, RawToInt), - new(0xB5, SmartNames.AlternativeProgramFailCount, RawToInt), - new(0xB6, SmartNames.AlternativeEraseFailCount, RawToInt), - new(0xBB, SmartNames.UncorrectableErrorCount, RawToInt), - new(0xC2, - SmartNames.Temperature, - (_, value, p) => value + (p?[0].Value ?? 0), - SensorType.Temperature, - 0, - SmartNames.Temperature, - true, - new[] { new ParameterDescription("Offset [°C]", "Temperature offset of the thermal sensor.\nTemperature = Value + Offset.", 0) }), - new(0xC3, SmartNames.UnrecoverableEcc), - new(0xC4, SmartNames.ReallocationEventCount, RawToInt), - new(0xE7, SmartNames.RemainingLife, null, SensorType.Level, 0, SmartNames.RemainingLife), - new(0xE9, SmartNames.ControllerWritesToNand, RawToInt, SensorType.Data, 0, SmartNames.ControllerWritesToNand), - new(0xEA, SmartNames.HostWritesToController, RawToInt, SensorType.Data, 1, SmartNames.HostWritesToController), - new(0xF1, SmartNames.HostWrites, RawToInt, SensorType.Data, 1, SmartNames.HostWrites), - new(0xF2, SmartNames.HostReads, RawToInt, SensorType.Data, 2, SmartNames.HostReads) - }; - - private readonly Sensor _writeAmplification; - - public SsdSandforce(StorageInfo storageInfo, ISmart smart, string name, string firmwareRevision, int index, ISettings settings) - : base(storageInfo, smart, name, firmwareRevision, "ssd", index, _smartAttributes, settings) - { - _writeAmplification = new Sensor("Write Amplification", 1, SensorType.Factor, this, settings); - } - - protected override unsafe void UpdateAdditionalSensors(AtaSmart.SMART_ATTRIBUTE[] values) - { - float? controllerWritesToNand = null; - float? hostWritesToController = null; - foreach (AtaSmart.SMART_ATTRIBUTE value in values) - { - byte[] rawValue = new Span(value.RawValue, 6).ToArray(); - - if (value.Id == 0xE9) - controllerWritesToNand = RawToInt(rawValue, value.CurrentValue, null); - - if (value.Id == 0xEA) - hostWritesToController = RawToInt(rawValue, value.CurrentValue, null); - } - - if (controllerWritesToNand.HasValue && hostWritesToController.HasValue) - { - if (hostWritesToController.Value > 0) - _writeAmplification.Value = controllerWritesToNand.Value / hostWritesToController.Value; - else - _writeAmplification.Value = 0; - - ActivateSensor(_writeAmplification); - } - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/StorageDevice.cs b/LibreHardwareMonitorLib/Hardware/Storage/StorageDevice.cs new file mode 100644 index 0000000..c55e9a8 --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Storage/StorageDevice.cs @@ -0,0 +1,381 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// Partial Copyright (C) Michael Möller and Contributors. +// All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using BlackSharp.Core.Converters; +using DiskInfoToolkit.Interop.Enums; +using Windows.Win32; +using Windows.Win32.Foundation; +using Windows.Win32.Storage.FileSystem; +using Windows.Win32.System.Ioctl; + +namespace LibreHardwareMonitor.Hardware.Storage; + +public sealed class StorageDevice : Hardware, ISmart +{ + private readonly PerformanceValue _perfRead = new(); + private readonly PerformanceValue _perfTotal = new(); + private readonly PerformanceValue _perfWrite = new(); + + private readonly DiskInfoToolkit.Storage _storage; + + private long _lastReadCount; + private long _lastTime; + private long _lastWriteCount; + + private static DateTime _lastUpdate; + + private readonly List _sensors = new(); + + private readonly List _attributes = new(); + + private Sensor _sensorDiskReadActivity; + private Sensor _sensorDiskReadRate; + private Sensor _sensorDiskTotalActivity; + private Sensor _sensorDiskWriteActivity; + private Sensor _sensorDiskWriteRate; + private Sensor _usageSensor; + + public StorageDevice(DiskInfoToolkit.Storage storage, string id, ISettings settings) + : base(storage.Model, new Identifier(id, storage.DriveNumber.ToString(CultureInfo.InvariantCulture)), settings) + { + _storage = storage; + + CreateAttributes(); + + CreateSensors(); + } + + public override HardwareType HardwareType => HardwareType.Storage; + + internal DiskInfoToolkit.Storage Storage => _storage; + + public IReadOnlyList Attributes => _attributes; + + public static TimeSpan ThrottleInterval { get; set; } + + public override void Update() + { + if (DateTime.UtcNow - _lastUpdate < ThrottleInterval) + { + return; + } + + _lastUpdate = DateTime.UtcNow; + + //Toggle usage sensor + ToggleUsageSensor(); + + //Update performance sensors + UpdatePerformanceSensors(); + + //Update storage object + _storage.Update(); + + //Update usage sensors + UpdateUsageSensor(); + + //Update general sensors + _sensors.ForEach(s => s.Update(_storage)); + + //Update attributes + foreach (var attribute in _storage.Smart.SmartAttributes) + { + //Try to find attribute + var found = _attributes.Find(sa => sa.Id == attribute.Info.ID); + + //Found attribute, update it + if (found != null) + { + found.Attribute = attribute; + } + } + } + + public override string GetReport() + { + var r = new StringBuilder(); + r.AppendLine("Storage"); + r.AppendLine(); + r.AppendLine($"Drive Name: {_storage.Model}"); + r.AppendLine($"Firmware Version and Revision: {_storage.Firmware}; {_storage.FirmwareRev}"); + r.AppendLine(); + r.AppendLine("Smart Attributes:"); + r.AppendLine("ID, Description, Value, Threshold"); + + foreach (var attribute in _attributes) + { + r.AppendLine($"{attribute.Id,3}, {attribute.Name,60}, {attribute.Value,18}, {attribute.Threshold,3}"); + } + + r.AppendLine(); + + if (!_storage.IsDynamicDisk) + { + r.AppendLine("Partitions:"); + + foreach (var partition in _storage.Partitions) + { + r.AppendLine($"Partition #{partition.PartitionNumber}"); + + if (partition.DriveLetter != null) + { + r.AppendLine($"Drive Letter: {partition.DriveLetter}"); + } + + if (partition.AvailableFreeSpace != null) + { + r.AppendLine($"Available Free Space: {partition.AvailableFreeSpace}"); + } + } + + r.AppendLine(); + + r.AppendLine($"Total Free Size: {_storage.TotalFreeSize}"); + } + + r.AppendLine($"Total Size: {_storage.TotalSize}"); + + return r.ToString(); + } + + public override void Traverse(IVisitor visitor) + { + foreach (ISensor sensor in Sensors) + sensor.Accept(visitor); + } + + private void CreateAttributes() + { + _attributes.Clear(); + + var attributes = SmartAttributeTranslator.GetAttributesFor(_storage); + + _attributes.AddRange(attributes.Where(a => a != null)); + } + + private void CreateSensors() + { + _usageSensor = new Sensor("Used Space", 0, SensorType.Load, this, _settings); + ToggleUsageSensor(); + + int index = 0; + + AddSensor("Temperature", index++, false, SensorType.Temperature, s => s.Smart.Temperature.GetValueOrDefault()); + + if (_storage.Smart.Life.HasValue) + { + AddSensor("Life", index++, false, SensorType.Level, s => s.Smart.Life.GetValueOrDefault()); + } + + if (_storage.Smart.HostReads.HasValue) + { + AddSensor("Data read", index++, false, SensorType.Data, s => s.Smart.HostReads.GetValueOrDefault()); + } + + if (_storage.Smart.HostWrites.HasValue) + { + AddSensor("Data written", index++, false, SensorType.Data, s => s.Smart.HostWrites.GetValueOrDefault()); + } + + AddSensor("Power on count", index++, false, SensorType.Factor, s => s.Smart.PowerOnCount); + AddSensor("Power on hours", index++, false, SensorType.Factor, s => Math.Max(s.Smart.MeasuredPowerOnHours, s.Smart.DetectedPowerOnHours)); + + if (_storage.IsNVMe) + { + AddSensor("Temperature warning", index++, false, SensorType.Factor, s => s.Smart.TemperatureWarning.GetValueOrDefault()); + AddSensor("Temperature critical", index++, false, SensorType.Factor, s => s.Smart.TemperatureCritical.GetValueOrDefault()); + + TryAddTemperatureSensor(index++, false, 1, SmartAttributeType.TemperatureSensor1); + TryAddTemperatureSensor(index++, false, 2, SmartAttributeType.TemperatureSensor2); + TryAddTemperatureSensor(index++, false, 3, SmartAttributeType.TemperatureSensor3); + TryAddTemperatureSensor(index++, false, 4, SmartAttributeType.TemperatureSensor4); + TryAddTemperatureSensor(index++, false, 5, SmartAttributeType.TemperatureSensor5); + TryAddTemperatureSensor(index++, false, 6, SmartAttributeType.TemperatureSensor6); + TryAddTemperatureSensor(index++, false, 7, SmartAttributeType.TemperatureSensor7); + TryAddTemperatureSensor(index++, false, 8, SmartAttributeType.TemperatureSensor8); + } + + _sensorDiskReadActivity = new Sensor("Read Activity", 51, SensorType.Load, this, _settings); + ActivateSensor(_sensorDiskReadActivity); + + _sensorDiskWriteActivity = new Sensor("Write Activity", 52, SensorType.Load, this, _settings); + ActivateSensor(_sensorDiskWriteActivity); + + _sensorDiskTotalActivity = new Sensor("Total Activity", 53, SensorType.Load, this, _settings); + ActivateSensor(_sensorDiskTotalActivity); + + _sensorDiskReadRate = new Sensor("Read Rate", 54, SensorType.Throughput, this, _settings); + ActivateSensor(_sensorDiskReadRate); + + _sensorDiskWriteRate = new Sensor("Write Rate", 55, SensorType.Throughput, this, _settings); + ActivateSensor(_sensorDiskWriteRate); + + AddSmartAttributeSensors(); + } + + private void TryAddTemperatureSensor(int index, bool defaultHidden, int thermalSensorIndex, SmartAttributeType type) + { + var attr = GetSmartAttribute(type); + + //Does the sensor have a value ? + if (attr != null && attr.Attribute.RawValueULong > 0) + { + AddSensor($"Temperature {thermalSensorIndex}", index, defaultHidden, SensorType.Temperature, s => + { + var a = GetSmartAttribute(type); + if (a != null) + { + return TemperatureConverter.KelvinToCelsius(a.Attribute.RawValueULong); + } + + return 0; + }); + } + } + + private DiskInfoToolkit.SmartAttribute GetSmartAttribute(SmartAttributeType type) + { + return _storage.Smart.SmartAttributes.FirstOrDefault(sa => sa.Info.Type == type); + } + + private void AddSensor(string name, int index, bool defaultHidden, SensorType sensorType, GetStorageDeviceSensorValue getValue) + { + var sensor = new StorageDeviceSensor(name, index, defaultHidden, sensorType, this, _settings, getValue) + { + Value = 0 + }; + + ActivateSensor(sensor); + _sensors.Add(sensor); + } + + private unsafe void UpdatePerformanceSensors() + { + DISK_PERFORMANCE diskPerformance = new(); + + using var handle = PInvoke.CreateFile(_storage.PhysicalPath, + (uint)FileAccess.ReadWrite, + FILE_SHARE_MODE.FILE_SHARE_READ | FILE_SHARE_MODE.FILE_SHARE_WRITE, + null, + FILE_CREATION_DISPOSITION.OPEN_EXISTING, + FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, + null); + + uint bytesReturned; + if (!PInvoke.DeviceIoControl((HANDLE)handle.DangerousGetHandle(), PInvoke.IOCTL_DISK_PERFORMANCE, null, 0, &diskPerformance, (uint)sizeof(DISK_PERFORMANCE), &bytesReturned, null)) + { + return; + } + + _perfRead.Update(diskPerformance.ReadTime, diskPerformance.QueryTime); + _sensorDiskReadActivity.Value = (float)_perfRead.Result; + + _perfWrite.Update(diskPerformance.WriteTime, diskPerformance.QueryTime); + _sensorDiskWriteActivity.Value = (float)_perfWrite.Result; + + _perfTotal.Update(diskPerformance.IdleTime, diskPerformance.QueryTime); + _sensorDiskTotalActivity.Value = (float)(100 - _perfTotal.Result); + + long readCount = diskPerformance.BytesRead; + long readDiff = readCount - _lastReadCount; + _lastReadCount = readCount; + + long writeCount = diskPerformance.BytesWritten; + long writeDiff = writeCount - _lastWriteCount; + _lastWriteCount = writeCount; + + long currentTime = Stopwatch.GetTimestamp(); + if (_lastTime != 0) + { + double timeDeltaSeconds = TimeSpan.FromTicks(currentTime - _lastTime).TotalSeconds; + + double writeSpeed = writeDiff * (1 / timeDeltaSeconds); + _sensorDiskWriteRate.Value = (float)writeSpeed; + + double readSpeed = readDiff * (1 / timeDeltaSeconds); + _sensorDiskReadRate.Value = (float)readSpeed; + } + + _lastTime = currentTime; + } + + private void ToggleUsageSensor() + { + if (!_storage.IsDynamicDisk) + { + ActivateSensor(_usageSensor); + } + else + { + DeactivateSensor(_usageSensor); + } + } + + private void UpdateUsageSensor() + { + if (_storage.TotalSize > 0) + { + //Set sensor value + _usageSensor.Value = 100.0f - (100.0f * _storage.TotalFreeSize / _storage.TotalSize); + } + else + { + _usageSensor.Value = null; + } + } + + private void AddSmartAttributeSensors() + { + //Unique attributes by sensor- type and channel + var attributes = Attributes.Where(sa => sa.SensorType.HasValue) + .GroupBy(sa => new { sa.SensorType.Value, sa.SensorChannel }) + .Select(sa => sa.First()); + + foreach (var attr in attributes) + { + AddSensor(attr.SensorName, + attr.SensorChannel, + attr.IsHiddenByDefault, + attr.SensorType.Value, + s => attr.Value); + } + } + + /// + /// Helper to calculate the disk performance with base timestamps + /// https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-perfrawdata + /// + private class PerformanceValue + { + public double Result { get; private set; } + + private long Time { get; set; } + + private long Value { get; set; } + + public void Update(long val, long valBase) + { + long diffValue = val - Value; + long diffTime = valBase - Time; + + Value = val; + Time = valBase; + Result = 100.0 / diffTime * diffValue; + + //sometimes it is possible that diff_value > diff_timebase + //limit result to 100%, this is because timing issues during read from pcie controller an latency between IO operation + if (Result > 100) + Result = 100; + } + } +} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/StorageDeviceSensor.cs b/LibreHardwareMonitorLib/Hardware/Storage/StorageDeviceSensor.cs new file mode 100644 index 0000000..b1f8dfe --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Storage/StorageDeviceSensor.cs @@ -0,0 +1,27 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// Partial Copyright (C) Michael Möller and Contributors. +// All Rights Reserved. + +namespace LibreHardwareMonitor.Hardware.Storage; + +internal delegate float GetStorageDeviceSensorValue(DiskInfoToolkit.Storage storage); + +internal class StorageDeviceSensor : Sensor +{ + private readonly GetStorageDeviceSensorValue _getValue; + + public StorageDeviceSensor(string name, int index, bool defaultHidden, SensorType sensorType, Hardware hardware, ISettings settings, GetStorageDeviceSensorValue getValue) + : base(name, index, defaultHidden, sensorType, hardware, null, settings) + { + _getValue = getValue; + } + + public void Update(DiskInfoToolkit.Storage storage) + { + var value = _getValue(storage); + + Value = value; + } +} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/StorageGeneric.cs b/LibreHardwareMonitorLib/Hardware/Storage/StorageGeneric.cs deleted file mode 100644 index 980966c..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/StorageGeneric.cs +++ /dev/null @@ -1,29 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System.Text; - -namespace LibreHardwareMonitor.Hardware.Storage; - -internal sealed class StorageGeneric : AbstractStorage -{ - private StorageGeneric(StorageInfo storageInfo, string name, string firmwareRevision, int index, ISettings settings) - : base(storageInfo, name, firmwareRevision, "hdd", index, settings) - { - CreateSensors(); - } - - public static AbstractStorage CreateInstance(StorageInfo info, ISettings settings) - { - string name = string.IsNullOrEmpty(info.Name) ? "Generic Hard Disk" : info.Name; - string firmwareRevision = string.IsNullOrEmpty(info.Revision) ? "Unknown" : info.Revision; - return new StorageGeneric(info, name, firmwareRevision, info.Index, settings); - } - - protected override void UpdateSensors() { } - - protected override void GetReport(StringBuilder r) { } -} \ No newline at end of file diff --git a/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs b/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs index 9b753e9..64da879 100644 --- a/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs +++ b/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs @@ -4,163 +4,82 @@ // Partial Copyright (C) Michael Möller and Contributors. // All Rights Reserved. -using System; using System.Collections.Generic; -using System.Management; +using System.Linq; +using DiskInfoToolkit; +using DiskInfoToolkit.Events; namespace LibreHardwareMonitor.Hardware.Storage; -#pragma warning disable CA1416 // Validate platform compatibility - -internal class StorageGroup : IGroup +internal class StorageGroup : IGroup, IHardwareChanged { - private readonly List _hardware = new(); + private readonly List _hardware = new(); + + private readonly ISettings _settings; + + public event HardwareEventHandler HardwareAdded; + public event HardwareEventHandler HardwareRemoved; public StorageGroup(ISettings settings) { if (Software.OperatingSystem.IsUnix) return; - Dictionary> storageSpaceDiskToPhysicalDiskMap = GetStorageSpaceDiskToPhysicalDiskMap(); - AddHardware(settings, storageSpaceDiskToPhysicalDiskMap); + _settings = settings; + + AddHardware(settings); } public IReadOnlyList Hardware => _hardware; - /// - /// Adds the hardware. - /// - /// The settings. - /// The storage space disk to physical disk map. - private void AddHardware(ISettings settings, Dictionary> storageSpaceDiskToPhysicalDiskMap) + private void AddHardware(ISettings settings) { - try + StorageManager.StoragesChanged -= OnStoragesChanged; + + //Reload storage devices + StorageManager.ReloadStorages(); + + //Transform storage device to hardware + _hardware.AddRange(StorageManager.Storages.Select(s => new StorageDevice(s, GetID(s), settings))); + + StorageManager.StoragesChanged += OnStoragesChanged; + } + + private void OnStoragesChanged(StoragesChangedEventArgs e) + { + StorageDevice storageDevice = null; + + switch (e.StorageChangeIdentifier) { - // https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskdrive - using var diskDriveSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive") { Options = { Timeout = TimeSpan.FromSeconds(10) } }; + case StorageChangeIdentifier.Added: + storageDevice = new StorageDevice(e.Storage, GetID(e.Storage), _settings); - foreach (ManagementBaseObject diskDrive in diskDriveSearcher.Get()) - { - string deviceId = (string)diskDrive.Properties["DeviceId"].Value; // is \\.\PhysicalDrive0..n - uint index = Convert.ToUInt32(diskDrive.Properties["Index"].Value); - ulong diskSize = Convert.ToUInt64(diskDrive.Properties["Size"].Value); - int scsi = Convert.ToInt32(diskDrive.Properties["SCSIPort"].Value); + _hardware.Add(storageDevice); + HardwareAdded?.Invoke(storageDevice); + break; + case StorageChangeIdentifier.Removed: + storageDevice = _hardware.Find(sd => sd.Storage == e.Storage); - if (deviceId != null) + if (storageDevice != null) { - var instance = AbstractStorage.CreateInstance(deviceId, index, diskSize, scsi, settings); - if (instance != null) - _hardware.Add(instance); - - if (storageSpaceDiskToPhysicalDiskMap.ContainsKey(index)) - { - foreach ((uint, ulong) physicalDisk in storageSpaceDiskToPhysicalDiskMap[index]) - { - var physicalDiskInstance = AbstractStorage.CreateInstance(@$"\\.\PHYSICALDRIVE{physicalDisk.Item1}", physicalDisk.Item1, physicalDisk.Item2, scsi, settings); - if (physicalDiskInstance != null) - _hardware.Add(physicalDiskInstance); - } - } + _hardware.Remove(storageDevice); + HardwareRemoved?.Invoke(storageDevice); } - } - } - catch - { - // Ignored. + break; } } - /// - /// Maps each StorageSpace to the PhysicalDisks it is composed of. - /// - private static Dictionary> GetStorageSpaceDiskToPhysicalDiskMap() + private string GetID(DiskInfoToolkit.Storage storage) { - var diskToPhysicalDisk = new Dictionary>(); - - if (!Software.OperatingSystem.IsWindows8OrGreater) - return diskToPhysicalDisk; - - try - { - ManagementScope scope = new(@"\root\Microsoft\Windows\Storage"); - - // https://learn.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-disk - // Lists all the disks visible to your system, the output is the same as Win32_DiskDrive. - // If you're using a storage Space, the "hidden" disks which compose your storage space will not be listed. - using var diskSearcher = new ManagementObjectSearcher(scope, new ObjectQuery("SELECT * FROM MSFT_Disk")); - - foreach (ManagementBaseObject disk in diskSearcher.Get()) - { - try - { - List<(uint, ulong)> map = MapDiskToPhysicalDisk(disk, scope); - if (map.Count > 0) - diskToPhysicalDisk[(uint)disk["Number"]] = map; - } - catch - { - // Ignored. - } - } - } - catch - { - // Ignored. - } - - return diskToPhysicalDisk; + if (storage.IsNVMe) + return "nvme"; + else if (storage.IsSSD) + return "ssd"; + else + return "hdd"; } - /// - /// Maps a disk to a physical disk. - /// - /// The disk. - /// The scope. - private static List<(uint, ulong)> MapDiskToPhysicalDisk(ManagementBaseObject disk, ManagementScope scope) - { - var map = new List<(uint, ulong)>(); + public void Close() { } - // https://learn.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-virtualdisk - // Maps the current Disk to its corresponding VirtualDisk. If the current Disk is not a storage space, it does not have a corresponding VirtualDisk. - // Each Disk maps to one or zero VirtualDisk. - using var toVirtualDisk = new ManagementObjectSearcher(scope, new ObjectQuery(FollowAssociationQuery("MSFT_Disk", (string)disk["ObjectId"], "MSFT_VirtualDiskToDisk"))); - - foreach (ManagementBaseObject virtualDisk in toVirtualDisk.Get()) - { - // https://learn.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-physicaldisk - // Maps the current VirtualDisk to the PhysicalDisk it is composed of. - // Each VirtualDisk maps to one or more PhysicalDisk. - - using var toPhysicalDisk = new ManagementObjectSearcher(scope, - new ObjectQuery(FollowAssociationQuery("MSFT_VirtualDisk", - (string)virtualDisk["ObjectId"], - "MSFT_VirtualDiskToPhysicalDisk"))); - - foreach (ManagementBaseObject physicalDisk in toPhysicalDisk.Get()) - { - ulong physicalDiskSize = (ulong)physicalDisk["Size"]; - - if (uint.TryParse((string)physicalDisk["DeviceId"], out uint physicalDiskId)) - map.Add((physicalDiskId, physicalDiskSize)); - } - } - - return map; - } - - private static string FollowAssociationQuery(string source, string objectId, string associationClass) - { - return @$"ASSOCIATORS OF {{{source}.ObjectId=""{objectId.Replace(@"\", @"\\").Replace(@"""", @"\""")}""}} WHERE AssocClass = {associationClass}"; - } - - public string GetReport() - { - return null; - } - - public void Close() - { - foreach (AbstractStorage storage in _hardware) - storage.Close(); - } + public string GetReport() => null; } diff --git a/LibreHardwareMonitorLib/Hardware/Storage/StorageInfo.cs b/LibreHardwareMonitorLib/Hardware/Storage/StorageInfo.cs deleted file mode 100644 index d08dcb1..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/StorageInfo.cs +++ /dev/null @@ -1,39 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using Windows.Win32.Storage.FileSystem; -using Microsoft.Win32.SafeHandles; - -namespace LibreHardwareMonitor.Hardware.Storage; - -internal abstract class StorageInfo -{ - public STORAGE_BUS_TYPE BusType { get; protected set; } - - public string DeviceId { get; set; } - - public ulong DiskSize { get; set; } - - public SafeFileHandle Handle { get; set; } - - public int Index { get; protected set; } - - public string Name => (Vendor + " " + Product).Trim(); - - public string Product { get; protected set; } - - public byte[] RawData { get; protected set; } - - public bool Removable { get; protected set; } - - public string Revision { get; protected set; } - - public string Scsi { get; set; } - - public string Serial { get; protected set; } - - public string Vendor { get; protected set; } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/WindowsSmart.cs b/LibreHardwareMonitorLib/Hardware/Storage/WindowsSmart.cs deleted file mode 100644 index 5ce7565..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/WindowsSmart.cs +++ /dev/null @@ -1,235 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// Partial Copyright (C) Michael Möller and Contributors. -// All Rights Reserved. - -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using LibreHardwareMonitor.Interop; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.Storage.FileSystem; -using Windows.Win32.System.Ioctl; -using static LibreHardwareMonitor.Interop.AtaSmart; - -namespace LibreHardwareMonitor.Hardware.Storage; - -internal class WindowsSmart : ISmart -{ - private readonly int _driveNumber; - private readonly SafeHandle _handle; - - public WindowsSmart(int driveNumber) - { - _driveNumber = driveNumber; - _handle = PInvoke.CreateFile(@"\\.\PhysicalDrive" + driveNumber, (uint)FileAccess.ReadWrite, FILE_SHARE_MODE.FILE_SHARE_READ | FILE_SHARE_MODE.FILE_SHARE_WRITE, null, FILE_CREATION_DISPOSITION.OPEN_EXISTING, FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, null); - } - - public bool IsValid => !_handle.IsInvalid && !_handle.IsClosed; - - public void Dispose() - { - Close(); - } - - public void Close() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public unsafe bool EnableSmart() - { - if (_handle.IsClosed) - throw new ObjectDisposedException(nameof(WindowsSmart)); - - var parameter = new SENDCMDINPARAMS - { - bDriveNumber = (byte)_driveNumber, - irDriveRegs = - { - bFeaturesReg = 0xD8, - bCylLowReg = (byte)PInvoke.SMART_CYL_LOW, - bCylHighReg = (byte)PInvoke.SMART_CYL_HI, - bCommandReg = (byte) PInvoke.SMART_CMD - } - }; - - var result = new SENDCMDOUTPARAMS(); - - return PInvoke.DeviceIoControl((HANDLE)_handle.DangerousGetHandle(), - PInvoke.SMART_SEND_DRIVE_COMMAND, - ¶meter, - (uint)sizeof(SENDCMDINPARAMS), - &result, - (uint)sizeof(SENDCMDOUTPARAMS), - null, - null); - } - - public unsafe SMART_ATTRIBUTE[] ReadSmartData() - { - if (_handle.IsClosed) - throw new ObjectDisposedException(nameof(WindowsSmart)); - - var parameter = new SENDCMDINPARAMS - { - bDriveNumber = (byte)_driveNumber, - irDriveRegs = - { - bFeaturesReg = (byte)PInvoke.READ_ATTRIBUTES, - bCylLowReg = (byte)PInvoke.SMART_CYL_LOW, - bCylHighReg = (byte)PInvoke.SMART_CYL_HI, - bCommandReg = (byte) PInvoke.SMART_CMD - } - }; - - int cb = sizeof(SENDCMDOUTPARAMS) + 512; // 512 bytes buffer. - IntPtr buffer = Marshal.AllocHGlobal(cb); - - bool isValid = PInvoke.DeviceIoControl((HANDLE)_handle.DangerousGetHandle(), - PInvoke.SMART_RCV_DRIVE_DATA, - ¶meter, - (uint)sizeof(SENDCMDINPARAMS), - (void*)buffer, - (uint)cb, - null, - null); - - if (isValid) - { - var attributes = new SMART_ATTRIBUTE[30]; // A maximum of 30 are returned. - - var sendCmdOutParams = (SENDCMDOUTPARAMS*)buffer; - fixed (byte* pBuffer = &sendCmdOutParams->bBuffer[0]) - { - var pAttribute = (SMART_ATTRIBUTE*)(pBuffer + 2); // + 2 padding. - - for (int i = 0; i < attributes.Length; i++) - attributes[i] = pAttribute[i]; - } - - Marshal.FreeHGlobal(buffer); - return attributes; - } - - Marshal.FreeHGlobal(buffer); - - return []; - } - - public unsafe SMART_THRESHOLD[] ReadSmartThresholds() - { - if (_handle.IsClosed) - throw new ObjectDisposedException(nameof(WindowsSmart)); - - var parameter = new SENDCMDINPARAMS - { - bDriveNumber = (byte)_driveNumber, - irDriveRegs = - { - bFeaturesReg = (byte)PInvoke.READ_THRESHOLDS, - bCylLowReg = (byte)PInvoke.SMART_CYL_LOW, - bCylHighReg = (byte)PInvoke.SMART_CYL_HI, - bCommandReg = (byte) PInvoke.SMART_CMD - } - }; - - int cb = sizeof(SENDCMDOUTPARAMS) + 512; // 2 bytes padding + 512 bytes buffer. - IntPtr buffer = Marshal.AllocHGlobal(cb); - bool isValid = PInvoke.DeviceIoControl((HANDLE)_handle.DangerousGetHandle(), - PInvoke.SMART_RCV_DRIVE_DATA, - ¶meter, - (uint)sizeof(SENDCMDINPARAMS), - (void*)buffer, - (uint)cb, - null, - null); - - if (isValid) - { - var thresholds = new SMART_THRESHOLD[30]; // A maximum of 30 are returned. - - var sendCmdOutParams = (SENDCMDOUTPARAMS*)buffer; - fixed (byte* pBuffer = &sendCmdOutParams->bBuffer[0]) - { - var pThreshold = (SMART_THRESHOLD*)(pBuffer + 2); // + 2 padding. - - for (int i = 0; i < thresholds.Length; i++) - thresholds[i] = pThreshold[i]; - } - - Marshal.FreeHGlobal(buffer); - return thresholds; - } - - Marshal.FreeHGlobal(buffer); - return null; - } - - public unsafe bool ReadNameAndFirmwareRevision(out string name, out string firmwareRevision) - { - if (_handle.IsClosed) - throw new ObjectDisposedException(nameof(WindowsSmart)); - - var parameter = new SENDCMDINPARAMS - { - bDriveNumber = (byte)_driveNumber, - irDriveRegs = - { - bCommandReg = 0xEC - } - }; - - int cb = sizeof(SENDCMDOUTPARAMS) + sizeof(IDENTIFY_DEVICE_DATA); - IntPtr buffer = Marshal.AllocHGlobal(cb); - - bool valid = PInvoke.DeviceIoControl((HANDLE)_handle.DangerousGetHandle(), - PInvoke.SMART_RCV_DRIVE_DATA, - ¶meter, - (uint)sizeof(SENDCMDINPARAMS), - (void*)buffer, - (uint)cb, - null, - null); - - if (!valid) - { - Marshal.FreeHGlobal(buffer); - name = null; - firmwareRevision = null; - return false; - } - - IDENTIFY_DEVICE_DATA identity = *(IDENTIFY_DEVICE_DATA*)((byte*)buffer + (int)Marshal.OffsetOf(nameof(SENDCMDOUTPARAMS.bBuffer))); - - byte* p = identity.ModelNumber; - for (int i = 0; i < 40; i += 2) - { - (p[i], p[i + 1]) = (p[i + 1], p[i]); - } - - p = identity.FirmwareRevision; - for (int i = 0; i < 8; i += 2) - { - (p[i], p[i + 1]) = (p[i + 1], p[i]); - } - - name = Encoding.ASCII.GetString(identity.ModelNumber, 40).Trim(); - firmwareRevision = Encoding.ASCII.GetString(identity.FirmwareRevision, 8); - - Marshal.FreeHGlobal(buffer); - return true; - } - - protected void Dispose(bool disposing) - { - if (disposing && !_handle.IsClosed) - { - _handle.Close(); - } - } -} diff --git a/LibreHardwareMonitorLib/Hardware/Storage/WindowsStorage.cs b/LibreHardwareMonitorLib/Hardware/Storage/WindowsStorage.cs deleted file mode 100644 index 69c8fe8..0000000 --- a/LibreHardwareMonitorLib/Hardware/Storage/WindowsStorage.cs +++ /dev/null @@ -1,102 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Management; -using System.Runtime.InteropServices; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.Storage.FileSystem; -using Windows.Win32.System.Ioctl; -using Microsoft.Win32.SafeHandles; - -namespace LibreHardwareMonitor.Hardware.Storage; - -internal static class WindowsStorage -{ - public static unsafe Storage.StorageInfo GetStorageInfo(string deviceId, uint driveIndex) - { - using SafeFileHandle handle = PInvoke.CreateFile(deviceId, - (uint)FileAccess.ReadWrite, - FILE_SHARE_MODE.FILE_SHARE_READ | FILE_SHARE_MODE.FILE_SHARE_WRITE, - null, - FILE_CREATION_DISPOSITION.OPEN_EXISTING, - FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, - null); - - if (handle?.IsInvalid != false) - return null; - - var query = new STORAGE_PROPERTY_QUERY { PropertyId = STORAGE_PROPERTY_ID.StorageDeviceProperty, QueryType = STORAGE_QUERY_TYPE.PropertyStandardQuery }; - STORAGE_DESCRIPTOR_HEADER result = new(); - - if (!PInvoke.DeviceIoControl((HANDLE)handle.DangerousGetHandle(), PInvoke.IOCTL_STORAGE_QUERY_PROPERTY, &query, (uint)sizeof(STORAGE_PROPERTY_QUERY), &result, (uint)sizeof(STORAGE_DESCRIPTOR_HEADER), null, null)) - { - return null; - } - - IntPtr descriptorPtr = Marshal.AllocHGlobal((int)result.Size); - - try - { - return PInvoke.DeviceIoControl((HANDLE)handle.DangerousGetHandle(), PInvoke.IOCTL_STORAGE_QUERY_PROPERTY, &query, (uint)sizeof(STORAGE_PROPERTY_QUERY), (void*)descriptorPtr, result.Size, null, null) - ? new StorageInfo((int)driveIndex, descriptorPtr) - : null; - } - finally - { - Marshal.FreeHGlobal(descriptorPtr); - } - } - - public static string[] GetLogicalDrives(int driveIndex) - { - var list = new List(); - - try - { - using var s = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DiskPartition " + "WHERE DiskIndex = " + driveIndex); - - foreach (ManagementBaseObject o in s.Get()) - { - if (o is ManagementObject dp) - { - foreach (ManagementBaseObject ld in dp.GetRelated("Win32_LogicalDisk")) - list.Add(((string)ld["Name"]).TrimEnd(':')); - } - } - } - catch - { - // Ignored. - } - - return list.ToArray(); - } - - private class StorageInfo : Storage.StorageInfo - { - public unsafe StorageInfo(int index, IntPtr descriptorPtr) - { - STORAGE_DEVICE_DESCRIPTOR descriptor = *(STORAGE_DEVICE_DESCRIPTOR*)descriptorPtr; - Index = index; - Vendor = GetString(descriptorPtr, descriptor.VendorIdOffset, descriptor.Size); - Product = GetString(descriptorPtr, descriptor.ProductIdOffset, descriptor.Size); - Revision = GetString(descriptorPtr, descriptor.ProductRevisionOffset, descriptor.Size); - Serial = GetString(descriptorPtr, descriptor.SerialNumberOffset, descriptor.Size); - BusType = descriptor.BusType; - Removable = descriptor.RemovableMedia; - RawData = new byte[descriptor.Size]; - Marshal.Copy(descriptorPtr, RawData, 0, RawData.Length); - } - - private static string GetString(IntPtr descriptorPtr, uint offset, uint size) - { - return offset > 0 && offset < size ? Marshal.PtrToStringAnsi(IntPtr.Add(descriptorPtr, (int)offset))?.Trim() : string.Empty; - } - } -} diff --git a/LibreHardwareMonitorLib/Interop/AtaSmart.cs b/LibreHardwareMonitorLib/Interop/AtaSmart.cs deleted file mode 100644 index 2a9b18f..0000000 --- a/LibreHardwareMonitorLib/Interop/AtaSmart.cs +++ /dev/null @@ -1,101 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Copyright (C) LibreHardwareMonitor and Contributors. -// All Rights Reserved. - -using System.Runtime.InteropServices; -using Windows.Win32.Storage.IscsiDisc; - -// ReSharper disable InconsistentNaming - -namespace LibreHardwareMonitor.Interop; - -public unsafe class AtaSmart -{ - internal const int IOCTL_BUFFER_SIZE = 4096; - internal const int SCSI_IOCTL_SENSE_SIZE = 24; - internal const int NVME_IOCTL_CMD_DW_SIZE = 16; - internal const int NVME_IOCTL_COMPLETE_DW_SIZE = 4; - internal const int NVME_IOCTL_VENDOR_SPECIFIC_DW_SIZE = 6; - - internal const int NVME_DATA_OUT = 1; - internal const int NVME_DATA_IN = 2; - - internal const uint NVME_PASS_THROUGH_SRB_IO_CODE = 0xe0002000; - - internal const byte SMART_LBA_HI = 0xC2; - internal const byte SMART_LBA_MID = 0x4F; - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct SMART_ATTRIBUTE - { - internal byte Id; - internal ushort Flags; - internal byte CurrentValue; - internal byte WorstValue; - internal fixed byte RawValue[6]; - internal byte Reserved; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct SMART_THRESHOLD - { - public byte Id; - public byte Threshold; - public fixed byte Reserved[10]; - } - - internal struct IDENTIFY_DEVICE_DATA - { - public ushort GeneralConfiguration; - public ushort NumberOfCylinders; - public ushort Reserved1; - public ushort NumberOfHeads; - public ushort UnformattedBytesPerTrack; - public ushort UnformattedBytesPerSector; - public ushort SectorsPerTrack; - public fixed ushort VendorUnique[3]; - public fixed byte SerialNumber[20]; - public ushort BufferType; - public ushort BufferSectorSize; - public ushort NumberOfEccBytes; - public fixed byte FirmwareRevision[8]; - public fixed byte ModelNumber[40]; - public byte MaximumBlockTransfer; - public byte VendorUnique2; - public ushort DoubleWordIo; - public ushort Capabilities; - public ushort Reserved2; - public byte VendorUnique3; - public byte PioCycleTimingMode; - public byte VendorUnique4; - public byte DmaCycleTimingMode; - public ushort TranslationFieldsValid; - public ushort NumberOfCurrentCylinders; - public ushort NumberOfCurrentHeads; - public ushort CurrentSectorsPerTrack; - public uint CurrentSectorCapacity; - public fixed ushort Reserved3[197]; - } - - internal struct NVME_PASS_THROUGH_IOCTL - { - public SRB_IO_CONTROL SrbIoCtrl; - public fixed uint VendorSpecific[NVME_IOCTL_VENDOR_SPECIFIC_DW_SIZE]; - public fixed uint NVMeCmd[NVME_IOCTL_CMD_DW_SIZE]; - public fixed uint CplEntry[NVME_IOCTL_COMPLETE_DW_SIZE]; - public uint Direction; - public uint QueueId; - public uint DataBufferLen; - public uint MetaDataLen; - public uint ReturnBufferLen; - public fixed byte DataBuffer[IOCTL_BUFFER_SIZE]; - } - - internal struct SCSI_PASS_THROUGH - { - public Windows.Win32.Storage.IscsiDisc.SCSI_PASS_THROUGH Spt; - public fixed byte SenseBuf[SCSI_IOCTL_SENSE_SIZE]; - public fixed byte DataBuf[IOCTL_BUFFER_SIZE]; - } -} diff --git a/LibreHardwareMonitorLib/Interop/ByteExtensions.cs b/LibreHardwareMonitorLib/Interop/ByteExtensions.cs index 554de96..8f5292e 100644 --- a/LibreHardwareMonitorLib/Interop/ByteExtensions.cs +++ b/LibreHardwareMonitorLib/Interop/ByteExtensions.cs @@ -6,40 +6,10 @@ namespace LibreHardwareMonitor.Interop; internal static class ByteExtensions { - public static byte[] ToArray(this __byte_2 bytes) - { - return bytes.AsReadOnlySpan().ToArray(); - } - - public static byte[] ToArray(this __byte_3 bytes) - { - return bytes.AsReadOnlySpan().ToArray(); - } - public static byte[] ToArray(this __byte_4 bytes) { return bytes.AsReadOnlySpan().ToArray(); } - - public static byte[] ToArray(this __byte_8 bytes) - { - return bytes.AsReadOnlySpan().ToArray(); - } - - public static byte[] ToArray(this __byte_16 bytes) - { - return bytes.AsReadOnlySpan().ToArray(); - } - - public static byte[] ToArray(this __byte_20 bytes) - { - return bytes.AsReadOnlySpan().ToArray(); - } - - public static byte[] ToArray(this __byte_40 bytes) - { - return bytes.AsReadOnlySpan().ToArray(); - } } #endif diff --git a/LibreHardwareMonitorLib/LibreHardwareMonitorLib.csproj b/LibreHardwareMonitorLib/LibreHardwareMonitorLib.csproj index c2a55d3..a14f281 100644 --- a/LibreHardwareMonitorLib/LibreHardwareMonitorLib.csproj +++ b/LibreHardwareMonitorLib/LibreHardwareMonitorLib.csproj @@ -55,12 +55,13 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/LibreHardwareMonitorLib/NativeMethods.txt b/LibreHardwareMonitorLib/NativeMethods.txt index 338bbda..87b3b26 100644 --- a/LibreHardwareMonitorLib/NativeMethods.txt +++ b/LibreHardwareMonitorLib/NativeMethods.txt @@ -27,35 +27,12 @@ GROUP_AFFINITY SetThreadGroupAffinity EnumSystemFirmwareTables GetSystemFirmwareTable -STORAGE_PROTOCOL_TYPE -STORAGE_BUS_TYPE -STORAGE_PROTOCOL_NVME_DATA_TYPE -STORAGE_PROPERTY_ID -STORAGE_PROTOCOL_SPECIFIC_DATA -STORAGE_QUERY_TYPE -STORAGE_DESCRIPTOR_HEADER -STORAGE_DEVICE_DESCRIPTOR -STORAGE_PROPERTY_QUERY -STORAGE_PROTOCOL_SPECIFIC_DATA -STORAGE_PROTOCOL_DATA_DESCRIPTOR -SRB_IO_CONTROL -SCSI_PASS_THROUGH -NVME_LOG_PAGES -NVME_POWER_STATE_DESC -NVME_HEALTH_INFO_LOG -NVME_IDENTIFY_CONTROLLER_DATA DISK_PERFORMANCE -DRIVERSTATUS -SENDCMDINPARAMS -SENDCMDOUTPARAMS -IDEREGS BATTERY_QUERY_INFORMATION BATTERY_INFORMATION BATTERY_SYSTEM_BATTERY BATTERY_STATUS BATTERY_WAIT_STATUS -SMART_SEND_DRIVE_COMMAND -SMART_RCV_DRIVE_DATA CreateFile VirtualFree VirtualAlloc @@ -64,10 +41,4 @@ IOCTL_* LoadLibrary FreeLibrary GetProcAddress -SCSI_IOCTL_* -SMART_CMD BATTERY_UNKNOWN_* -SMART_CYL_LOW -SMART_CYL_HI -READ_ATTRIBUTES -READ_THRESHOLDS