Hardware/Mainboard/GigabyteTAMG.cs
author moel.mich
Sat, 31 Dec 2011 17:31:04 +0000
changeset 324 c6ee430d6995
child 344 3145aadca3d2
permissions -rw-r--r--
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@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
}