Hardware/Mainboard/GigabyteTAMG.cs
author moel.mich
Thu, 07 Jul 2011 20:41:09 +0000
changeset 308 d882720734bf
child 344 3145aadca3d2
permissions -rw-r--r--
Added support for reading the TAMG ACPI table on Gigabyte mainboards. Fixed a small problem with HDD/SSD names (0 chars are trimmed now as well).
moel@308
     1
/*
moel@308
     2
  
moel@308
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@308
     4
moel@308
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@308
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@308
     7
  the License. You may obtain a copy of the License at
moel@308
     8
 
moel@308
     9
  http://www.mozilla.org/MPL/
moel@308
    10
moel@308
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@308
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@308
    13
  for the specific language governing rights and limitations under the License.
moel@308
    14
moel@308
    15
  The Original Code is the Open Hardware Monitor code.
moel@308
    16
moel@308
    17
  The Initial Developer of the Original Code is 
moel@308
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@308
    19
  Portions created by the Initial Developer are Copyright (C) 2011
moel@308
    20
  the Initial Developer. All Rights Reserved.
moel@308
    21
moel@308
    22
  Contributor(s):
moel@308
    23
moel@308
    24
  Alternatively, the contents of this file may be used under the terms of
moel@308
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@308
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@308
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@308
    28
  of those above. If you wish to allow use of your version of this file only
moel@308
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@308
    30
  use your version of this file under the terms of the MPL, indicate your
moel@308
    31
  decision by deleting the provisions above and replace them with the notice
moel@308
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@308
    33
  the provisions above, a recipient may use your version of this file under
moel@308
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@308
    35
 
moel@308
    36
*/
moel@308
    37
moel@308
    38
using System;
moel@308
    39
using System.Collections.Generic;
moel@308
    40
using System.IO;
moel@308
    41
using System.IO.Compression;
moel@308
    42
using System.Runtime.InteropServices;
moel@308
    43
using System.Text;
moel@308
    44
moel@308
    45
namespace OpenHardwareMonitor.Hardware.Mainboard {
moel@308
    46
  
moel@308
    47
  internal class GigabyteTAMG {
moel@308
    48
    private byte[] table;
moel@308
    49
moel@308
    50
    private Sensor[] sensors;
moel@308
    51
moel@308
    52
    private struct Sensor {
moel@308
    53
      public string Name;
moel@308
    54
      public SensorType Type;
moel@308
    55
      public int Channel;
moel@308
    56
      public float Value;
moel@308
    57
    }
moel@308
    58
moel@308
    59
    private enum SensorType {
moel@308
    60
      Voltage = 1,
moel@308
    61
      Temperature = 2,      
moel@308
    62
      Fan = 4,
moel@308
    63
      Case = 8,
moel@308
    64
    }
moel@308
    65
moel@308
    66
    public GigabyteTAMG(byte[] table) {
moel@308
    67
      if (table == null)
moel@308
    68
        throw new ArgumentNullException("table");
moel@308
    69
moel@308
    70
      this.table = table;
moel@308
    71
      
moel@308
    72
      int index = IndexOf(table, Encoding.ASCII.GetBytes("$HEALTH$"), 0);
moel@308
    73
moel@308
    74
      if (index >= 0) {
moel@308
    75
        index += 8;
moel@308
    76
        using (MemoryStream m =
moel@308
    77
          new MemoryStream(table, index, table.Length - index))
moel@308
    78
        using (BinaryReader r = new BinaryReader(m)) {
moel@308
    79
          try {
moel@308
    80
            r.ReadInt64();
moel@308
    81
            int count = r.ReadInt32();
moel@308
    82
            r.ReadInt64();
moel@308
    83
            r.ReadInt32();
moel@308
    84
            sensors = new Sensor[count];
moel@308
    85
            for (int i = 0; i < sensors.Length; i++) {
moel@308
    86
              sensors[i].Name = new string(r.ReadChars(32)).TrimEnd('\0');
moel@308
    87
              sensors[i].Type = (SensorType)r.ReadByte();
moel@308
    88
              sensors[i].Channel = r.ReadInt16();
moel@308
    89
              sensors[i].Channel |= r.ReadByte() << 24;
moel@308
    90
              r.ReadInt64();
moel@308
    91
              int value = r.ReadInt32();
moel@308
    92
              switch (sensors[i].Type) {
moel@308
    93
                case SensorType.Voltage:
moel@308
    94
                  sensors[i].Value = 1e-3f * value; break;
moel@308
    95
                default:
moel@308
    96
                  sensors[i].Value = value; break;
moel@308
    97
              }
moel@308
    98
              r.ReadInt64();
moel@308
    99
            }
moel@308
   100
          } catch (IOException) { sensors = new Sensor[0]; }
moel@308
   101
        }
moel@308
   102
      } else {
moel@308
   103
        sensors = new Sensor[0]; 
moel@308
   104
      }
moel@308
   105
    }
moel@308
   106
moel@308
   107
    public static int IndexOf(byte[] array, byte[] pattern, int startIndex) {
moel@308
   108
      if (array == null || pattern == null || pattern.Length > array.Length)
moel@308
   109
        return -1;
moel@308
   110
moel@308
   111
      for (int i = startIndex; i < array.Length - pattern.Length; i++) {
moel@308
   112
        bool found = true;
moel@308
   113
        for (int j = 0; j < pattern.Length; j++) {
moel@308
   114
          if (array[i + j] != pattern[j]) {
moel@308
   115
            found = false;
moel@308
   116
            break;
moel@308
   117
          }
moel@308
   118
        }
moel@308
   119
        if (found) 
moel@308
   120
          return i;
moel@308
   121
      }
moel@308
   122
      return -1;
moel@308
   123
    }
moel@308
   124
moel@308
   125
    private string GetCompressedAndEncodedTable() {
moel@308
   126
      string base64;
moel@308
   127
      using (MemoryStream m = new MemoryStream()) {
moel@308
   128
        using (GZipStream c = new GZipStream(m, CompressionMode.Compress)) {
moel@308
   129
          c.Write(table, 0, table.Length);          
moel@308
   130
        }
moel@308
   131
        base64 = Convert.ToBase64String(m.ToArray());
moel@308
   132
      }
moel@308
   133
moel@308
   134
      StringBuilder r = new StringBuilder();
moel@308
   135
      for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) {
moel@308
   136
        r.Append(" ");
moel@308
   137
        for (int j = 0; j < 0x40; j++) {
moel@308
   138
          int index = (i << 6) | j;
moel@308
   139
          if (index < base64.Length) {
moel@308
   140
            r.Append(base64[index]);
moel@308
   141
          }
moel@308
   142
        }
moel@308
   143
        r.AppendLine();
moel@308
   144
      }
moel@308
   145
moel@308
   146
      return r.ToString();
moel@308
   147
    }
moel@308
   148
moel@308
   149
    public string GetReport() {
moel@308
   150
      StringBuilder r = new StringBuilder();
moel@308
   151
moel@308
   152
      if (sensors.Length > 0) {
moel@308
   153
        r.AppendLine("Gigabyte TAMG Sensors");
moel@308
   154
        r.AppendLine();
moel@308
   155
moel@308
   156
        foreach (Sensor sensor in sensors) {
moel@308
   157
          r.AppendFormat(" {0,-10}: {1,8:G6} ({2})", sensor.Name, sensor.Value,
moel@308
   158
            sensor.Type);
moel@308
   159
          r.AppendLine();
moel@308
   160
        }
moel@308
   161
        r.AppendLine();
moel@308
   162
      }
moel@308
   163
moel@308
   164
      if (table.Length > 0) {
moel@308
   165
        r.AppendLine("Gigabyte TAMG Table");
moel@308
   166
        r.AppendLine();
moel@308
   167
        r.Append(GetCompressedAndEncodedTable());
moel@308
   168
        r.AppendLine();
moel@308
   169
      }
moel@308
   170
moel@308
   171
      return r.ToString();
moel@308
   172
    }
moel@308
   173
  }
moel@308
   174
}