moel@308: /* moel@308: moel@308: Version: MPL 1.1/GPL 2.0/LGPL 2.1 moel@308: moel@308: The contents of this file are subject to the Mozilla Public License Version moel@308: 1.1 (the "License"); you may not use this file except in compliance with moel@308: the License. You may obtain a copy of the License at moel@308: moel@308: http://www.mozilla.org/MPL/ moel@308: moel@308: Software distributed under the License is distributed on an "AS IS" basis, moel@308: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License moel@308: for the specific language governing rights and limitations under the License. moel@308: moel@308: The Original Code is the Open Hardware Monitor code. moel@308: moel@308: The Initial Developer of the Original Code is moel@308: Michael Möller . moel@308: Portions created by the Initial Developer are Copyright (C) 2011 moel@308: the Initial Developer. All Rights Reserved. moel@308: moel@308: Contributor(s): moel@308: moel@308: Alternatively, the contents of this file may be used under the terms of moel@308: either the GNU General Public License Version 2 or later (the "GPL"), or moel@308: the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), moel@308: in which case the provisions of the GPL or the LGPL are applicable instead moel@308: of those above. If you wish to allow use of your version of this file only moel@308: under the terms of either the GPL or the LGPL, and not to allow others to moel@308: use your version of this file under the terms of the MPL, indicate your moel@308: decision by deleting the provisions above and replace them with the notice moel@308: and other provisions required by the GPL or the LGPL. If you do not delete moel@308: the provisions above, a recipient may use your version of this file under moel@308: the terms of any one of the MPL, the GPL or the LGPL. moel@308: moel@308: */ moel@308: moel@308: using System; moel@308: using System.Collections.Generic; moel@308: using System.IO; moel@308: using System.IO.Compression; moel@308: using System.Runtime.InteropServices; moel@308: using System.Text; moel@308: moel@308: namespace OpenHardwareMonitor.Hardware.Mainboard { moel@308: moel@308: internal class GigabyteTAMG { moel@308: private byte[] table; moel@308: moel@308: private Sensor[] sensors; moel@308: moel@308: private struct Sensor { moel@308: public string Name; moel@308: public SensorType Type; moel@308: public int Channel; moel@308: public float Value; moel@308: } moel@308: moel@308: private enum SensorType { moel@308: Voltage = 1, moel@308: Temperature = 2, moel@308: Fan = 4, moel@308: Case = 8, moel@308: } moel@308: moel@308: public GigabyteTAMG(byte[] table) { moel@308: if (table == null) moel@308: throw new ArgumentNullException("table"); moel@308: moel@308: this.table = table; moel@308: moel@308: int index = IndexOf(table, Encoding.ASCII.GetBytes("$HEALTH$"), 0); moel@308: moel@308: if (index >= 0) { moel@308: index += 8; moel@308: using (MemoryStream m = moel@308: new MemoryStream(table, index, table.Length - index)) moel@308: using (BinaryReader r = new BinaryReader(m)) { moel@308: try { moel@308: r.ReadInt64(); moel@308: int count = r.ReadInt32(); moel@308: r.ReadInt64(); moel@308: r.ReadInt32(); moel@308: sensors = new Sensor[count]; moel@308: for (int i = 0; i < sensors.Length; i++) { moel@308: sensors[i].Name = new string(r.ReadChars(32)).TrimEnd('\0'); moel@308: sensors[i].Type = (SensorType)r.ReadByte(); moel@308: sensors[i].Channel = r.ReadInt16(); moel@308: sensors[i].Channel |= r.ReadByte() << 24; moel@308: r.ReadInt64(); moel@308: int value = r.ReadInt32(); moel@308: switch (sensors[i].Type) { moel@308: case SensorType.Voltage: moel@308: sensors[i].Value = 1e-3f * value; break; moel@308: default: moel@308: sensors[i].Value = value; break; moel@308: } moel@308: r.ReadInt64(); moel@308: } moel@308: } catch (IOException) { sensors = new Sensor[0]; } moel@308: } moel@308: } else { moel@308: sensors = new Sensor[0]; moel@308: } moel@308: } moel@308: moel@308: public static int IndexOf(byte[] array, byte[] pattern, int startIndex) { moel@308: if (array == null || pattern == null || pattern.Length > array.Length) moel@308: return -1; moel@308: moel@308: for (int i = startIndex; i < array.Length - pattern.Length; i++) { moel@308: bool found = true; moel@308: for (int j = 0; j < pattern.Length; j++) { moel@308: if (array[i + j] != pattern[j]) { moel@308: found = false; moel@308: break; moel@308: } moel@308: } moel@308: if (found) moel@308: return i; moel@308: } moel@308: return -1; moel@308: } moel@308: moel@308: private string GetCompressedAndEncodedTable() { moel@308: string base64; moel@308: using (MemoryStream m = new MemoryStream()) { moel@308: using (GZipStream c = new GZipStream(m, CompressionMode.Compress)) { moel@308: c.Write(table, 0, table.Length); moel@308: } moel@308: base64 = Convert.ToBase64String(m.ToArray()); moel@308: } moel@308: moel@308: StringBuilder r = new StringBuilder(); moel@308: for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) { moel@308: r.Append(" "); moel@308: for (int j = 0; j < 0x40; j++) { moel@308: int index = (i << 6) | j; moel@308: if (index < base64.Length) { moel@308: r.Append(base64[index]); moel@308: } moel@308: } moel@308: r.AppendLine(); moel@308: } moel@308: moel@308: return r.ToString(); moel@308: } moel@308: moel@308: public string GetReport() { moel@308: StringBuilder r = new StringBuilder(); moel@308: moel@308: if (sensors.Length > 0) { moel@308: r.AppendLine("Gigabyte TAMG Sensors"); moel@308: r.AppendLine(); moel@308: moel@308: foreach (Sensor sensor in sensors) { moel@308: r.AppendFormat(" {0,-10}: {1,8:G6} ({2})", sensor.Name, sensor.Value, moel@308: sensor.Type); moel@308: r.AppendLine(); moel@308: } moel@308: r.AppendLine(); moel@308: } moel@308: moel@308: if (table.Length > 0) { moel@308: r.AppendLine("Gigabyte TAMG Table"); moel@308: r.AppendLine(); moel@308: r.Append(GetCompressedAndEncodedTable()); moel@308: r.AppendLine(); moel@308: } moel@308: moel@308: return r.ToString(); moel@308: } moel@308: } moel@308: }