Hardware/Heatmaster/HeatmasterGroup.cs
author moel.mich
Sun, 23 Sep 2012 18:37:43 +0000
changeset 380 573f1fff48b2
parent 256 6dc6410489f4
permissions -rw-r--r--
Fixed Issue 387. The new implementation does not try to start a ring 0 driver that already exists, but could not be opened. It tries to delete the driver and install it new. The driver is now stored temporarily in the application folder. The driver is not correctly removed on system shutdown.
moel@171
     1
/*
moel@171
     2
 
moel@344
     3
  This Source Code Form is subject to the terms of the Mozilla Public
moel@344
     4
  License, v. 2.0. If a copy of the MPL was not distributed with this
moel@344
     5
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
moel@171
     6
 
moel@344
     7
  Copyright (C) 2010 Michael Möller <mmoeller@openhardwaremonitor.org>
moel@344
     8
	
moel@171
     9
*/
moel@171
    10
moel@171
    11
using System;
moel@171
    12
using System.Collections.Generic;
moel@182
    13
using System.Globalization;
moel@171
    14
using System.IO.Ports;
moel@172
    15
using System.Security;
moel@171
    16
using System.Text;
moel@171
    17
using System.Threading;
moel@172
    18
using Microsoft.Win32;
moel@171
    19
moel@171
    20
namespace OpenHardwareMonitor.Hardware.Heatmaster {
moel@171
    21
  internal class HeatmasterGroup : IGroup {
moel@171
    22
moel@195
    23
    private readonly List<Heatmaster> hardware = new List<Heatmaster>();
moel@195
    24
    private readonly StringBuilder report = new StringBuilder();
moel@171
    25
moel@171
    26
    private static string ReadLine(SerialPort port, int timeout) {
moel@171
    27
      int i = 0;
moel@171
    28
      StringBuilder builder = new StringBuilder();
moel@171
    29
      while (i < timeout) {
moel@171
    30
        while (port.BytesToRead > 0) {
moel@171
    31
          byte b = (byte)port.ReadByte();
moel@171
    32
          switch (b) {
moel@171
    33
            case 0xAA: return ((char)b).ToString();
moel@171
    34
            case 0x0D: return builder.ToString();
moel@171
    35
            default: builder.Append((char)b); break;
moel@171
    36
          }
moel@171
    37
        }
moel@171
    38
        i++;
moel@171
    39
        Thread.Sleep(1);
moel@171
    40
      }
moel@171
    41
      throw new TimeoutException();
moel@172
    42
    }
moel@172
    43
moel@172
    44
    private static string[] GetRegistryPortNames() {
moel@172
    45
      List<string> result = new List<string>();
moel@175
    46
      string[] paths = { "", "&MI_00" };
moel@172
    47
      try {
moel@175
    48
        foreach (string path in paths) {
moel@175
    49
          RegistryKey key = Registry.LocalMachine.OpenSubKey(
moel@175
    50
            @"SYSTEM\CurrentControlSet\Enum\USB\VID_10C4&PID_EA60" + path);
moel@175
    51
          if (key != null) {
moel@175
    52
            foreach (string subKeyName in key.GetSubKeyNames()) {
moel@175
    53
              RegistryKey subKey =
moel@175
    54
                key.OpenSubKey(subKeyName + "\\" + "Device Parameters");
moel@175
    55
              if (subKey != null) {
moel@175
    56
                string name = subKey.GetValue("PortName") as string;
moel@175
    57
                if (name != null && !result.Contains(name))
moel@195
    58
                  result.Add(name);
moel@175
    59
              }
moel@172
    60
            }
moel@172
    61
          }
moel@172
    62
        }
moel@172
    63
      } catch (SecurityException) { }
moel@172
    64
      return result.ToArray();
moel@172
    65
    }
moel@171
    66
moel@171
    67
    public HeatmasterGroup(ISettings settings) {
moel@172
    68
      
moel@172
    69
      // No implementation for Heatmaster on Unix systems
moel@195
    70
      int p = (int)Environment.OSVersion.Platform;
moel@172
    71
      if ((p == 4) || (p == 128))
moel@172
    72
        return;
moel@171
    73
moel@172
    74
      string[] portNames = GetRegistryPortNames();      
moel@199
    75
      for (int i = 0; i < portNames.Length; i++) {
moel@182
    76
        bool isValid = false;
moel@182
    77
        try {        
moel@182
    78
          using (SerialPort serialPort =
moel@182
    79
            new SerialPort(portNames[i], 38400, Parity.None, 8, StopBits.One)) {
moel@182
    80
            serialPort.NewLine = ((char)0x0D).ToString();            
moel@182
    81
            report.Append("Port Name: "); report.AppendLine(portNames[i]);
moel@171
    82
moel@182
    83
            try {
moel@182
    84
              serialPort.Open();
moel@182
    85
            } catch (UnauthorizedAccessException) {
moel@182
    86
              report.AppendLine("Exception: Access Denied");
moel@182
    87
            }
moel@171
    88
moel@182
    89
            if (serialPort.IsOpen) {
moel@182
    90
              serialPort.DiscardInBuffer();
moel@182
    91
              serialPort.DiscardOutBuffer();
moel@182
    92
              serialPort.Write(new byte[] { 0xAA }, 0, 1);
moel@171
    93
moel@182
    94
              int j = 0;
moel@182
    95
              while (serialPort.BytesToRead == 0 && j < 10) {
moel@182
    96
                Thread.Sleep(20);
moel@182
    97
                j++;
moel@171
    98
              }
moel@182
    99
              if (serialPort.BytesToRead > 0) {
moel@182
   100
                bool flag = false;
moel@182
   101
                while (serialPort.BytesToRead > 0 && !flag) {
moel@182
   102
                  flag |= (serialPort.ReadByte() == 0xAA);
moel@182
   103
                }
moel@182
   104
                if (flag) {
moel@182
   105
                  serialPort.WriteLine("[0:0]RH");
moel@182
   106
                  try {
moel@182
   107
                    int k = 0;
moel@182
   108
                    int revision = 0;
moel@182
   109
                    while (k < 5) {
moel@182
   110
                      string line = ReadLine(serialPort, 100);
moel@182
   111
                      if (line.StartsWith("-[0:0]RH:",
moel@182
   112
                        StringComparison.Ordinal)) {
moel@182
   113
                        revision = int.Parse(line.Substring(9), 
moel@182
   114
                          CultureInfo.InvariantCulture);
moel@182
   115
                        break;
moel@182
   116
                      }
moel@182
   117
                      k++;
moel@171
   118
                    }
moel@182
   119
                    isValid = (revision == 770);
moel@182
   120
                    if (!isValid) {
moel@182
   121
                      report.Append("Status: Wrong Hardware Revision " +
moel@182
   122
                        revision.ToString(CultureInfo.InvariantCulture));
moel@182
   123
                    }
moel@182
   124
                  } catch (TimeoutException) {
moel@182
   125
                    report.AppendLine("Status: Timeout Reading Revision");
moel@171
   126
                  }
moel@182
   127
                } else {
moel@182
   128
                  report.AppendLine("Status: Wrong Startflag");
moel@171
   129
                }
moel@171
   130
              } else {
moel@182
   131
                report.AppendLine("Status: No Response");
moel@171
   132
              }
moel@182
   133
              serialPort.DiscardInBuffer();
moel@171
   134
            } else {
moel@182
   135
              report.AppendLine("Status: Port not Open");
moel@182
   136
            }            
moel@171
   137
          }
moel@171
   138
        } catch (Exception e) {
moel@171
   139
          report.AppendLine(e.ToString());
moel@182
   140
        }
moel@182
   141
moel@182
   142
        if (isValid) {
moel@182
   143
          report.AppendLine("Status: OK");
moel@182
   144
          hardware.Add(new Heatmaster(portNames[i], settings));
moel@182
   145
        }
moel@171
   146
        report.AppendLine();
moel@171
   147
      }
moel@171
   148
    }
moel@171
   149
moel@171
   150
    public IHardware[] Hardware {
moel@171
   151
      get {
moel@171
   152
        return hardware.ToArray();
moel@171
   153
      }
moel@171
   154
    }
moel@171
   155
moel@171
   156
    public string GetReport() {
moel@171
   157
      if (report.Length > 0) {
moel@256
   158
        StringBuilder r = new StringBuilder();
moel@256
   159
        r.AppendLine("Serial Port Heatmaster");
moel@256
   160
        r.AppendLine();
moel@256
   161
        r.Append(report);
moel@256
   162
        r.AppendLine();
moel@256
   163
        return r.ToString();
moel@171
   164
      } else
moel@171
   165
        return null;
moel@171
   166
    }
moel@171
   167
moel@171
   168
    public void Close() {
moel@171
   169
      foreach (Heatmaster heatmaster in hardware)
moel@171
   170
        heatmaster.Close();
moel@171
   171
    }
moel@171
   172
  }
moel@171
   173
}