Hardware/Heatmaster/HeatmasterGroup.cs
author moel.mich
Thu, 30 Sep 2010 16:51:09 +0000
changeset 201 958e9fe8afdf
parent 195 0ee888c485d5
child 256 6dc6410489f4
permissions -rw-r--r--
Improved the implementation for the AMD 10h family CPU clock speeds.
moel@171
     1
/*
moel@171
     2
  
moel@171
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@171
     4
moel@171
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@171
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@171
     7
  the License. You may obtain a copy of the License at
moel@171
     8
 
moel@171
     9
  http://www.mozilla.org/MPL/
moel@171
    10
moel@171
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@171
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@171
    13
  for the specific language governing rights and limitations under the License.
moel@171
    14
moel@171
    15
  The Original Code is the Open Hardware Monitor code.
moel@171
    16
moel@171
    17
  The Initial Developer of the Original Code is 
moel@171
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@171
    19
  Portions created by the Initial Developer are Copyright (C) 2010
moel@171
    20
  the Initial Developer. All Rights Reserved.
moel@171
    21
moel@171
    22
  Contributor(s):
moel@171
    23
moel@171
    24
  Alternatively, the contents of this file may be used under the terms of
moel@171
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@171
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@171
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@171
    28
  of those above. If you wish to allow use of your version of this file only
moel@171
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@171
    30
  use your version of this file under the terms of the MPL, indicate your
moel@171
    31
  decision by deleting the provisions above and replace them with the notice
moel@171
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@171
    33
  the provisions above, a recipient may use your version of this file under
moel@171
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@171
    35
 
moel@171
    36
*/
moel@171
    37
moel@171
    38
using System;
moel@171
    39
using System.Collections.Generic;
moel@182
    40
using System.Globalization;
moel@171
    41
using System.IO.Ports;
moel@172
    42
using System.Security;
moel@171
    43
using System.Text;
moel@171
    44
using System.Threading;
moel@172
    45
using Microsoft.Win32;
moel@171
    46
moel@171
    47
namespace OpenHardwareMonitor.Hardware.Heatmaster {
moel@171
    48
  internal class HeatmasterGroup : IGroup {
moel@171
    49
moel@195
    50
    private readonly List<Heatmaster> hardware = new List<Heatmaster>();
moel@195
    51
    private readonly StringBuilder report = new StringBuilder();
moel@171
    52
moel@171
    53
    private static string ReadLine(SerialPort port, int timeout) {
moel@171
    54
      int i = 0;
moel@171
    55
      StringBuilder builder = new StringBuilder();
moel@171
    56
      while (i < timeout) {
moel@171
    57
        while (port.BytesToRead > 0) {
moel@171
    58
          byte b = (byte)port.ReadByte();
moel@171
    59
          switch (b) {
moel@171
    60
            case 0xAA: return ((char)b).ToString();
moel@171
    61
            case 0x0D: return builder.ToString();
moel@171
    62
            default: builder.Append((char)b); break;
moel@171
    63
          }
moel@171
    64
        }
moel@171
    65
        i++;
moel@171
    66
        Thread.Sleep(1);
moel@171
    67
      }
moel@171
    68
      throw new TimeoutException();
moel@172
    69
    }
moel@172
    70
moel@172
    71
    private static string[] GetRegistryPortNames() {
moel@172
    72
      List<string> result = new List<string>();
moel@175
    73
      string[] paths = { "", "&MI_00" };
moel@172
    74
      try {
moel@175
    75
        foreach (string path in paths) {
moel@175
    76
          RegistryKey key = Registry.LocalMachine.OpenSubKey(
moel@175
    77
            @"SYSTEM\CurrentControlSet\Enum\USB\VID_10C4&PID_EA60" + path);
moel@175
    78
          if (key != null) {
moel@175
    79
            foreach (string subKeyName in key.GetSubKeyNames()) {
moel@175
    80
              RegistryKey subKey =
moel@175
    81
                key.OpenSubKey(subKeyName + "\\" + "Device Parameters");
moel@175
    82
              if (subKey != null) {
moel@175
    83
                string name = subKey.GetValue("PortName") as string;
moel@175
    84
                if (name != null && !result.Contains(name))
moel@195
    85
                  result.Add(name);
moel@175
    86
              }
moel@172
    87
            }
moel@172
    88
          }
moel@172
    89
        }
moel@172
    90
      } catch (SecurityException) { }
moel@172
    91
      return result.ToArray();
moel@172
    92
    }
moel@171
    93
moel@171
    94
    public HeatmasterGroup(ISettings settings) {
moel@172
    95
      
moel@172
    96
      // No implementation for Heatmaster on Unix systems
moel@195
    97
      int p = (int)Environment.OSVersion.Platform;
moel@172
    98
      if ((p == 4) || (p == 128))
moel@172
    99
        return;
moel@171
   100
moel@172
   101
      string[] portNames = GetRegistryPortNames();      
moel@199
   102
      for (int i = 0; i < portNames.Length; i++) {
moel@182
   103
        bool isValid = false;
moel@182
   104
        try {        
moel@182
   105
          using (SerialPort serialPort =
moel@182
   106
            new SerialPort(portNames[i], 38400, Parity.None, 8, StopBits.One)) {
moel@182
   107
            serialPort.NewLine = ((char)0x0D).ToString();            
moel@182
   108
            report.Append("Port Name: "); report.AppendLine(portNames[i]);
moel@171
   109
moel@182
   110
            try {
moel@182
   111
              serialPort.Open();
moel@182
   112
            } catch (UnauthorizedAccessException) {
moel@182
   113
              report.AppendLine("Exception: Access Denied");
moel@182
   114
            }
moel@171
   115
moel@182
   116
            if (serialPort.IsOpen) {
moel@182
   117
              serialPort.DiscardInBuffer();
moel@182
   118
              serialPort.DiscardOutBuffer();
moel@182
   119
              serialPort.Write(new byte[] { 0xAA }, 0, 1);
moel@171
   120
moel@182
   121
              int j = 0;
moel@182
   122
              while (serialPort.BytesToRead == 0 && j < 10) {
moel@182
   123
                Thread.Sleep(20);
moel@182
   124
                j++;
moel@171
   125
              }
moel@182
   126
              if (serialPort.BytesToRead > 0) {
moel@182
   127
                bool flag = false;
moel@182
   128
                while (serialPort.BytesToRead > 0 && !flag) {
moel@182
   129
                  flag |= (serialPort.ReadByte() == 0xAA);
moel@182
   130
                }
moel@182
   131
                if (flag) {
moel@182
   132
                  serialPort.WriteLine("[0:0]RH");
moel@182
   133
                  try {
moel@182
   134
                    int k = 0;
moel@182
   135
                    int revision = 0;
moel@182
   136
                    while (k < 5) {
moel@182
   137
                      string line = ReadLine(serialPort, 100);
moel@182
   138
                      if (line.StartsWith("-[0:0]RH:",
moel@182
   139
                        StringComparison.Ordinal)) {
moel@182
   140
                        revision = int.Parse(line.Substring(9), 
moel@182
   141
                          CultureInfo.InvariantCulture);
moel@182
   142
                        break;
moel@182
   143
                      }
moel@182
   144
                      k++;
moel@171
   145
                    }
moel@182
   146
                    isValid = (revision == 770);
moel@182
   147
                    if (!isValid) {
moel@182
   148
                      report.Append("Status: Wrong Hardware Revision " +
moel@182
   149
                        revision.ToString(CultureInfo.InvariantCulture));
moel@182
   150
                    }
moel@182
   151
                  } catch (TimeoutException) {
moel@182
   152
                    report.AppendLine("Status: Timeout Reading Revision");
moel@171
   153
                  }
moel@182
   154
                } else {
moel@182
   155
                  report.AppendLine("Status: Wrong Startflag");
moel@171
   156
                }
moel@171
   157
              } else {
moel@182
   158
                report.AppendLine("Status: No Response");
moel@171
   159
              }
moel@182
   160
              serialPort.DiscardInBuffer();
moel@171
   161
            } else {
moel@182
   162
              report.AppendLine("Status: Port not Open");
moel@182
   163
            }            
moel@171
   164
          }
moel@171
   165
        } catch (Exception e) {
moel@171
   166
          report.AppendLine(e.ToString());
moel@182
   167
        }
moel@182
   168
moel@182
   169
        if (isValid) {
moel@182
   170
          report.AppendLine("Status: OK");
moel@182
   171
          hardware.Add(new Heatmaster(portNames[i], settings));
moel@182
   172
        }
moel@171
   173
        report.AppendLine();
moel@171
   174
      }
moel@171
   175
    }
moel@171
   176
moel@171
   177
    public IHardware[] Hardware {
moel@171
   178
      get {
moel@171
   179
        return hardware.ToArray();
moel@171
   180
      }
moel@171
   181
    }
moel@171
   182
moel@171
   183
    public string GetReport() {
moel@171
   184
      if (report.Length > 0) {
moel@171
   185
        report.Insert(0, "Serial Port Heatmaster" + Environment.NewLine +
moel@171
   186
          Environment.NewLine);
moel@171
   187
        report.AppendLine();
moel@171
   188
        return report.ToString();
moel@171
   189
      } else
moel@171
   190
        return null;
moel@171
   191
    }
moel@171
   192
moel@171
   193
    public void Close() {
moel@171
   194
      foreach (Heatmaster heatmaster in hardware)
moel@171
   195
        heatmaster.Close();
moel@171
   196
    }
moel@171
   197
  }
moel@171
   198
}