Hardware/LPC/LMSensors.cs
author moel.mich
Sat, 31 Dec 2011 17:31:04 +0000
changeset 324 c6ee430d6995
parent 268 844ba72c11de
child 344 3145aadca3d2
permissions -rwxr-xr-x
Modified and extended version of the patch v4 by Roland Reinl (see Issue 256). Main differences to the original patch: DeviceIoControl refactorings removed, SmartAttribute is now descriptive only and does not hold any state, report is written as one 80 columns table, sensors are created only for meaningful values and without duplicates (remaining life, temperatures, host writes and reads). Also the current implementation should really preserve all the functionality of the old system. Additionally there is now a simple SMART devices emulation class (DebugSmart) that can be used in place of WindowsSmart for testing with reported data.
moel@136
     1
/*
moel@136
     2
  
moel@136
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@136
     4
moel@136
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@136
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@136
     7
  the License. You may obtain a copy of the License at
moel@136
     8
 
moel@136
     9
  http://www.mozilla.org/MPL/
moel@136
    10
moel@136
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@136
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@136
    13
  for the specific language governing rights and limitations under the License.
moel@136
    14
moel@136
    15
  The Original Code is the Open Hardware Monitor code.
moel@136
    16
moel@136
    17
  The Initial Developer of the Original Code is 
moel@136
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@266
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2011
moel@136
    20
  the Initial Developer. All Rights Reserved.
moel@136
    21
moel@136
    22
  Contributor(s):
moel@136
    23
moel@136
    24
  Alternatively, the contents of this file may be used under the terms of
moel@136
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@136
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@136
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@136
    28
  of those above. If you wish to allow use of your version of this file only
moel@136
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@136
    30
  use your version of this file under the terms of the MPL, indicate your
moel@136
    31
  decision by deleting the provisions above and replace them with the notice
moel@136
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@136
    33
  the provisions above, a recipient may use your version of this file under
moel@136
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@136
    35
 
moel@136
    36
*/
moel@136
    37
moel@136
    38
using System.Collections.Generic;
moel@166
    39
using System.Globalization;
moel@136
    40
using System.IO;
moel@268
    41
using System.Text;
moel@136
    42
moel@136
    43
namespace OpenHardwareMonitor.Hardware.LPC {
moel@136
    44
moel@165
    45
  internal class LMSensors {
moel@136
    46
moel@195
    47
    private readonly List<LMChip> lmChips = new List<LMChip>();
moel@136
    48
moel@136
    49
    public LMSensors() {
moel@266
    50
      string[] basePaths = Directory.GetDirectories("/sys/class/hwmon/");
moel@266
    51
      foreach (string basePath in basePaths) {
moel@266
    52
        foreach (string devicePath in new[] { "/device", "" }) {
moel@266
    53
          string path = basePath + devicePath;
moel@136
    54
moel@266
    55
          string name = null;
moel@266
    56
          try {
moel@266
    57
            using (StreamReader reader = new StreamReader(path + "/name"))
moel@266
    58
              name = reader.ReadLine();
moel@266
    59
          } catch (IOException) { }
moel@136
    60
moel@266
    61
          switch (name) {
moel@266
    62
            case "atk0110":
moel@266
    63
              lmChips.Add(new LMChip(Chip.ATK0110, path)); break;
moel@266
    64
moel@266
    65
            case "f71858fg":
moel@266
    66
              lmChips.Add(new LMChip(Chip.F71858, path)); break;
moel@266
    67
            case "f71862fg":
moel@266
    68
              lmChips.Add(new LMChip(Chip.F71862, path)); break;
moel@266
    69
            case "f71882fg":
moel@266
    70
              lmChips.Add(new LMChip(Chip.F71882, path)); break;
moel@266
    71
            case "f71889fg":
moel@266
    72
              lmChips.Add(new LMChip(Chip.F71889F, path)); break;
moel@266
    73
moel@266
    74
            case "it8712":
moel@266
    75
              lmChips.Add(new LMChip(Chip.IT8712F, path)); break;
moel@266
    76
            case "it8716":
moel@266
    77
              lmChips.Add(new LMChip(Chip.IT8716F, path)); break;
moel@266
    78
            case "it8718":
moel@266
    79
              lmChips.Add(new LMChip(Chip.IT8718F, path)); break;
moel@266
    80
            case "it8720":
moel@266
    81
              lmChips.Add(new LMChip(Chip.IT8720F, path)); break;
moel@266
    82
moel@266
    83
            case "w83627ehf":
moel@266
    84
              lmChips.Add(new LMChip(Chip.W83627EHF, path)); break;
moel@266
    85
            case "w83627dhg":
moel@266
    86
              lmChips.Add(new LMChip(Chip.W83627DHG, path)); break;
moel@266
    87
            case "w83667hg":
moel@266
    88
              lmChips.Add(new LMChip(Chip.W83667HG, path)); break;
moel@266
    89
            case "w83627hf":
moel@266
    90
              lmChips.Add(new LMChip(Chip.W83627HF, path)); break;
moel@266
    91
            case "w83627thf":
moel@266
    92
              lmChips.Add(new LMChip(Chip.W83627THF, path)); break;
moel@266
    93
            case "w83687thf":
moel@266
    94
              lmChips.Add(new LMChip(Chip.W83687THF, path)); break;
moel@266
    95
          }
moel@136
    96
        }
moel@136
    97
      }
moel@136
    98
    }
moel@136
    99
moel@136
   100
    public void Close() {
moel@136
   101
      foreach (LMChip lmChip in lmChips)
moel@136
   102
        lmChip.Close();
moel@136
   103
    }
moel@136
   104
moel@136
   105
    public ISuperIO[] SuperIO {
moel@136
   106
      get {
moel@136
   107
        return lmChips.ToArray();
moel@136
   108
      }
moel@136
   109
    }
moel@136
   110
moel@136
   111
    private class LMChip : ISuperIO {
moel@136
   112
moel@136
   113
      private string path;
moel@195
   114
      private readonly Chip chip;
moel@136
   115
moel@195
   116
      private readonly float?[] voltages;
moel@195
   117
      private readonly float?[] temperatures;
moel@195
   118
      private readonly float?[] fans;
moel@323
   119
      private readonly float?[] controls;
moel@136
   120
moel@268
   121
      private readonly FileStream[] voltageStreams;
moel@268
   122
      private readonly FileStream[] temperatureStreams;
moel@268
   123
      private readonly FileStream[] fanStreams;
moel@136
   124
moel@136
   125
      public Chip Chip { get { return chip; } }
moel@136
   126
      public float?[] Voltages { get { return voltages; } }
moel@136
   127
      public float?[] Temperatures { get { return temperatures; } }
moel@136
   128
      public float?[] Fans { get { return fans; } }
moel@323
   129
      public float?[] Controls { get { return controls; } }
moel@136
   130
moel@136
   131
      public LMChip(Chip chip, string path) {
moel@136
   132
        this.path = path;
moel@136
   133
        this.chip = chip;
moel@136
   134
moel@136
   135
        string[] voltagePaths = Directory.GetFiles(path, "in*_input");
moel@136
   136
        this.voltages = new float?[voltagePaths.Length];
moel@268
   137
        this.voltageStreams = new FileStream[voltagePaths.Length];
moel@136
   138
        for (int i = 0; i < voltagePaths.Length; i++)
moel@268
   139
          voltageStreams[i] = new FileStream(voltagePaths[i],
moel@268
   140
            FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
moel@136
   141
moel@136
   142
        string[] temperaturePaths = Directory.GetFiles(path, "temp*_input");
moel@136
   143
        this.temperatures = new float?[temperaturePaths.Length];
moel@268
   144
        this.temperatureStreams = new FileStream[temperaturePaths.Length];
moel@136
   145
        for (int i = 0; i < temperaturePaths.Length; i++)
moel@268
   146
          temperatureStreams[i] = new FileStream(temperaturePaths[i],
moel@268
   147
            FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
moel@136
   148
moel@136
   149
        string[] fanPaths = Directory.GetFiles(path, "fan*_input");
moel@136
   150
        this.fans = new float?[fanPaths.Length];
moel@268
   151
        this.fanStreams = new FileStream[fanPaths.Length];
moel@136
   152
        for (int i = 0; i < fanPaths.Length; i++)
moel@268
   153
          fanStreams[i] = new FileStream(fanPaths[i],
moel@268
   154
            FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
moel@323
   155
moel@323
   156
        this.controls = new float?[0];
moel@136
   157
      }
moel@136
   158
moel@228
   159
      public byte? ReadGPIO(int index) {
moel@228
   160
        return null;
moel@228
   161
      }
moel@228
   162
moel@228
   163
      public void WriteGPIO(int index, byte value) { }
moel@228
   164
moel@136
   165
      public string GetReport() {
moel@136
   166
        return null;
moel@136
   167
      }
moel@136
   168
moel@323
   169
      public void SetControl(int index, byte? value) { }   
moel@323
   170
moel@268
   171
      private string ReadFirstLine(Stream stream) {
moel@268
   172
        StringBuilder sb = new StringBuilder();
moel@268
   173
        try {
moel@268
   174
          stream.Seek(0, SeekOrigin.Begin);
moel@268
   175
          int b = stream.ReadByte();
moel@268
   176
          while (b != -1 && b != 10) {
moel@268
   177
            sb.Append((char)b);
moel@268
   178
            b = stream.ReadByte();
moel@268
   179
          }
moel@268
   180
        } catch { }
moel@268
   181
        return sb.ToString();
moel@268
   182
      }
moel@268
   183
moel@136
   184
      public void Update() {
moel@136
   185
        for (int i = 0; i < voltages.Length; i++) {
moel@268
   186
          string s = ReadFirstLine(voltageStreams[i]);
moel@136
   187
          try {
moel@268
   188
            voltages[i] = 0.001f *
moel@166
   189
              long.Parse(s, CultureInfo.InvariantCulture);
moel@136
   190
          } catch {
moel@136
   191
            voltages[i] = null;
moel@136
   192
          }
moel@136
   193
        }
moel@136
   194
moel@136
   195
        for (int i = 0; i < temperatures.Length; i++) {
moel@268
   196
          string s = ReadFirstLine(temperatureStreams[i]);
moel@136
   197
          try {
moel@268
   198
            temperatures[i] = 0.001f *
moel@166
   199
              long.Parse(s, CultureInfo.InvariantCulture);
moel@136
   200
          } catch {
moel@136
   201
            temperatures[i] = null;
moel@136
   202
          }
moel@136
   203
        }
moel@136
   204
moel@136
   205
        for (int i = 0; i < fans.Length; i++) {
moel@268
   206
          string s = ReadFirstLine(fanStreams[i]);
moel@136
   207
          try {
moel@166
   208
            fans[i] = long.Parse(s, CultureInfo.InvariantCulture);
moel@136
   209
          } catch {
moel@136
   210
            fans[i] = null;
moel@136
   211
          }
moel@136
   212
        }
moel@136
   213
      }
moel@136
   214
moel@136
   215
      public void Close() {
moel@268
   216
        foreach (FileStream stream in voltageStreams)
moel@268
   217
          stream.Close();
moel@268
   218
        foreach (FileStream stream in temperatureStreams)
moel@268
   219
          stream.Close();
moel@268
   220
        foreach (FileStream stream in fanStreams)
moel@268
   221
          stream.Close();
moel@136
   222
      }
moel@136
   223
    }
moel@136
   224
  }
moel@136
   225
}