Files
ReLibreHardwareMonitor/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/LMSensors.cs
T
Michael SpiegelandPhyxionNL 8ab4def93a Fix NullReferenceException on linux systems where the specified paths don't exist (#1300)
* feat(SMBios): Handle null reference exception when accessing Board information

Changed the ReadSysFs method in the class SMBios to return an empty string instead of null when unable to find the needed paths on Linux, preventing NullReference Exception when getting the manufacturer and model in the Motherboard class.

* fix(LMSensors): Prevent exception in LMSensors constructor

Introduced string array subDirectories  which is initialized empty. Added checking if the hwmon directory exists otherwise the array subDirectories will stay empty so it does not throw an exception if it can't find the path.

* Simplify.

---------

Co-authored-by: PhyxionNL <7643972+PhyxionNL@users.noreply.github.com>
2024-07-31 17:30:30 +02:00

302 lines
10 KiB
C#

// 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 <mmoeller@openhardwaremonitor.org> and Contributors.
// All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
// ReSharper disable once InconsistentNaming
namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc;
internal class LMSensors
{
private const string HwMonPath = "/sys/class/hwmon/";
private readonly List<ISuperIO> _superIOs = [];
public LMSensors()
{
if (!Directory.Exists(HwMonPath))
return;
foreach (string basePath in Directory.GetDirectories(HwMonPath))
{
foreach (string devicePath in new[] { "/device", string.Empty })
{
string path = basePath + devicePath;
string name = null;
try
{
using StreamReader reader = new(path + "/name");
name = reader.ReadLine();
}
catch (IOException)
{ }
switch (name)
{
case "atk0110":
_superIOs.Add(new LMChip(Chip.ATK0110, path));
break;
case "f71858fg":
_superIOs.Add(new LMChip(Chip.F71858, path));
break;
case "f71862fg":
_superIOs.Add(new LMChip(Chip.F71862, path));
break;
case "f71869":
_superIOs.Add(new LMChip(Chip.F71869, path));
break;
case "f71869a":
_superIOs.Add(new LMChip(Chip.F71869A, path));
break;
case "f71882fg":
_superIOs.Add(new LMChip(Chip.F71882, path));
break;
case "f71889a":
_superIOs.Add(new LMChip(Chip.F71889AD, path));
break;
case "f71878ad":
_superIOs.Add(new LMChip(Chip.F71878AD, path));
break;
case "f71889ed":
_superIOs.Add(new LMChip(Chip.F71889ED, path));
break;
case "f71889fg":
_superIOs.Add(new LMChip(Chip.F71889F, path));
break;
case "f71808e":
_superIOs.Add(new LMChip(Chip.F71808E, path));
break;
case "it8705":
_superIOs.Add(new LMChip(Chip.IT8705F, path));
break;
case "it8712":
_superIOs.Add(new LMChip(Chip.IT8712F, path));
break;
case "it8716":
_superIOs.Add(new LMChip(Chip.IT8716F, path));
break;
case "it8718":
_superIOs.Add(new LMChip(Chip.IT8718F, path));
break;
case "it8720":
_superIOs.Add(new LMChip(Chip.IT8720F, path));
break;
case "nct6775":
_superIOs.Add(new LMChip(Chip.NCT6771F, path));
break;
case "nct6776":
_superIOs.Add(new LMChip(Chip.NCT6776F, path));
break;
case "nct6779":
_superIOs.Add(new LMChip(Chip.NCT6779D, path));
break;
case "nct6791":
_superIOs.Add(new LMChip(Chip.NCT6791D, path));
break;
case "nct6792":
_superIOs.Add(new LMChip(Chip.NCT6792D, path));
break;
case "nct6793":
_superIOs.Add(new LMChip(Chip.NCT6793D, path));
break;
case "nct6795":
_superIOs.Add(new LMChip(Chip.NCT6795D, path));
break;
case "nct6796":
_superIOs.Add(new LMChip(Chip.NCT6796D, path));
break;
case "nct6797":
_superIOs.Add(new LMChip(Chip.NCT6797D, path));
break;
case "nct6798":
_superIOs.Add(new LMChip(Chip.NCT6798D, path));
break;
case "nct6799":
_superIOs.Add(new LMChip(Chip.NCT6799D, path));
break;
case "w83627ehf":
_superIOs.Add(new LMChip(Chip.W83627EHF, path));
break;
case "w83627dhg":
_superIOs.Add(new LMChip(Chip.W83627DHG, path));
break;
case "w83667hg":
_superIOs.Add(new LMChip(Chip.W83667HG, path));
break;
case "w83627hf":
_superIOs.Add(new LMChip(Chip.W83627HF, path));
break;
case "w83627thf":
_superIOs.Add(new LMChip(Chip.W83627THF, path));
break;
case "w83687thf":
_superIOs.Add(new LMChip(Chip.W83687THF, path));
break;
}
}
}
}
public IReadOnlyList<ISuperIO> SuperIO
{
get { return _superIOs; }
}
public void Close()
{
foreach (ISuperIO superIO in _superIOs)
{
if (superIO is LMChip lmChip)
lmChip.Close();
}
}
private class LMChip : ISuperIO
{
private readonly FileStream[] _fanStreams;
private readonly FileStream[] _temperatureStreams;
private readonly FileStream[] _voltageStreams;
private string _path;
public LMChip(Chip chip, string path)
{
_path = path;
Chip = chip;
string[] voltagePaths = Directory.GetFiles(path, "in*_input");
Voltages = new float?[voltagePaths.Length];
_voltageStreams = new FileStream[voltagePaths.Length];
for (int i = 0; i < voltagePaths.Length; i++)
_voltageStreams[i] = new FileStream(voltagePaths[i], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
string[] temperaturePaths = Directory.GetFiles(path, "temp*_input");
Temperatures = new float?[temperaturePaths.Length];
_temperatureStreams = new FileStream[temperaturePaths.Length];
for (int i = 0; i < temperaturePaths.Length; i++)
_temperatureStreams[i] = new FileStream(temperaturePaths[i], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
string[] fanPaths = Directory.GetFiles(path, "fan*_input");
Fans = new float?[fanPaths.Length];
_fanStreams = new FileStream[fanPaths.Length];
for (int i = 0; i < fanPaths.Length; i++)
_fanStreams[i] = new FileStream(fanPaths[i], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Controls = Array.Empty<float?>();
}
public Chip Chip { get; }
public float?[] Controls { get; }
public float?[] Fans { get; }
public float?[] Temperatures { get; }
public float?[] Voltages { get; }
public byte? ReadGpio(int index)
{
return null;
}
public void WriteGpio(int index, byte value)
{ }
public string GetReport()
{
return null;
}
public void SetControl(int index, byte? value)
{ }
public void Update()
{
for (int i = 0; i < Voltages.Length; i++)
{
string s = ReadFirstLine(_voltageStreams[i]);
try
{
Voltages[i] = 0.001f *
long.Parse(s, CultureInfo.InvariantCulture);
}
catch
{
Voltages[i] = null;
}
}
for (int i = 0; i < Temperatures.Length; i++)
{
string s = ReadFirstLine(_temperatureStreams[i]);
try
{
Temperatures[i] = 0.001f *
long.Parse(s, CultureInfo.InvariantCulture);
}
catch
{
Temperatures[i] = null;
}
}
for (int i = 0; i < Fans.Length; i++)
{
string s = ReadFirstLine(_fanStreams[i]);
try
{
Fans[i] = long.Parse(s, CultureInfo.InvariantCulture);
}
catch
{
Fans[i] = null;
}
}
}
private static string ReadFirstLine(Stream stream)
{
StringBuilder sb = new();
try
{
stream.Seek(0, SeekOrigin.Begin);
int b = stream.ReadByte();
while (b is not -1 and not 10)
{
sb.Append((char)b);
b = stream.ReadByte();
}
}
catch
{ }
return sb.ToString();
}
public void Close()
{
foreach (FileStream stream in _voltageStreams)
stream.Close();
foreach (FileStream stream in _temperatureStreams)
stream.Close();
foreach (FileStream stream in _fanStreams)
stream.Close();
}
}
}