repo time

Dependencies:   mbed MAX14720 MAX30205 USBDevice

Committer:
darienf
Date:
Tue Apr 06 06:41:40 2021 +0000
Revision:
20:6d2af70c92ab
another repo

Who changed what in which revision?

UserRevisionLine numberNew contents of line
darienf 20:6d2af70c92ab 1 // Copyright 2010-2014 Zach Saw
darienf 20:6d2af70c92ab 2 //
darienf 20:6d2af70c92ab 3 // Licensed under the Apache License, Version 2.0 (the "License");
darienf 20:6d2af70c92ab 4 // you may not use this file except in compliance with the License.
darienf 20:6d2af70c92ab 5 // You may obtain a copy of the License at
darienf 20:6d2af70c92ab 6 //
darienf 20:6d2af70c92ab 7 // http://www.apache.org/licenses/LICENSE-2.0
darienf 20:6d2af70c92ab 8 //
darienf 20:6d2af70c92ab 9 // Unless required by applicable law or agreed to in writing, software
darienf 20:6d2af70c92ab 10 // distributed under the License is distributed on an "AS IS" BASIS,
darienf 20:6d2af70c92ab 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
darienf 20:6d2af70c92ab 12 // See the License for the specific language governing permissions and
darienf 20:6d2af70c92ab 13 // limitations under the License.
darienf 20:6d2af70c92ab 14
darienf 20:6d2af70c92ab 15 using System;
darienf 20:6d2af70c92ab 16 using System.IO;
darienf 20:6d2af70c92ab 17 using System.IO.Ports;
darienf 20:6d2af70c92ab 18 using System.Runtime.InteropServices;
darienf 20:6d2af70c92ab 19 using System.Text;
darienf 20:6d2af70c92ab 20 using Microsoft.Win32.SafeHandles;
darienf 20:6d2af70c92ab 21
darienf 20:6d2af70c92ab 22 namespace SerialPortTester
darienf 20:6d2af70c92ab 23 {
darienf 20:6d2af70c92ab 24 public class SerialPortFixer : IDisposable
darienf 20:6d2af70c92ab 25 {
darienf 20:6d2af70c92ab 26 public static void Execute(string portName)
darienf 20:6d2af70c92ab 27 {
darienf 20:6d2af70c92ab 28 using (new SerialPortFixer(portName))
darienf 20:6d2af70c92ab 29 {
darienf 20:6d2af70c92ab 30 }
darienf 20:6d2af70c92ab 31 }
darienf 20:6d2af70c92ab 32 #region IDisposable Members
darienf 20:6d2af70c92ab 33
darienf 20:6d2af70c92ab 34 public void Dispose()
darienf 20:6d2af70c92ab 35 {
darienf 20:6d2af70c92ab 36 if (m_Handle != null)
darienf 20:6d2af70c92ab 37 {
darienf 20:6d2af70c92ab 38 m_Handle.Close();
darienf 20:6d2af70c92ab 39 m_Handle = null;
darienf 20:6d2af70c92ab 40 }
darienf 20:6d2af70c92ab 41 }
darienf 20:6d2af70c92ab 42
darienf 20:6d2af70c92ab 43 #endregion
darienf 20:6d2af70c92ab 44
darienf 20:6d2af70c92ab 45 #region Implementation
darienf 20:6d2af70c92ab 46
darienf 20:6d2af70c92ab 47 private const int DcbFlagAbortOnError = 14;
darienf 20:6d2af70c92ab 48 private const int CommStateRetries = 10;
darienf 20:6d2af70c92ab 49 private SafeFileHandle m_Handle;
darienf 20:6d2af70c92ab 50
darienf 20:6d2af70c92ab 51 private SerialPortFixer(string portName)
darienf 20:6d2af70c92ab 52 {
darienf 20:6d2af70c92ab 53 const int dwFlagsAndAttributes = 0x40000000;
darienf 20:6d2af70c92ab 54 const int dwAccess = unchecked((int) 0xC0000000);
darienf 20:6d2af70c92ab 55
darienf 20:6d2af70c92ab 56 if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
darienf 20:6d2af70c92ab 57 {
darienf 20:6d2af70c92ab 58 throw new ArgumentException("Invalid Serial Port", "portName");
darienf 20:6d2af70c92ab 59 }
darienf 20:6d2af70c92ab 60 SafeFileHandle hFile = CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,
darienf 20:6d2af70c92ab 61 IntPtr.Zero);
darienf 20:6d2af70c92ab 62 if (hFile.IsInvalid)
darienf 20:6d2af70c92ab 63 {
darienf 20:6d2af70c92ab 64 WinIoError();
darienf 20:6d2af70c92ab 65 }
darienf 20:6d2af70c92ab 66 try
darienf 20:6d2af70c92ab 67 {
darienf 20:6d2af70c92ab 68 int fileType = GetFileType(hFile);
darienf 20:6d2af70c92ab 69 if ((fileType != 2) && (fileType != 0))
darienf 20:6d2af70c92ab 70 {
darienf 20:6d2af70c92ab 71 throw new ArgumentException("Invalid Serial Port", "portName");
darienf 20:6d2af70c92ab 72 }
darienf 20:6d2af70c92ab 73 m_Handle = hFile;
darienf 20:6d2af70c92ab 74 InitializeDcb();
darienf 20:6d2af70c92ab 75 }
darienf 20:6d2af70c92ab 76 catch
darienf 20:6d2af70c92ab 77 {
darienf 20:6d2af70c92ab 78 hFile.Close();
darienf 20:6d2af70c92ab 79 m_Handle = null;
darienf 20:6d2af70c92ab 80 throw;
darienf 20:6d2af70c92ab 81 }
darienf 20:6d2af70c92ab 82 }
darienf 20:6d2af70c92ab 83
darienf 20:6d2af70c92ab 84 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
darienf 20:6d2af70c92ab 85 private static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId,
darienf 20:6d2af70c92ab 86 StringBuilder lpBuffer, int nSize, IntPtr arguments);
darienf 20:6d2af70c92ab 87
darienf 20:6d2af70c92ab 88 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
darienf 20:6d2af70c92ab 89 private static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
darienf 20:6d2af70c92ab 90
darienf 20:6d2af70c92ab 91 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
darienf 20:6d2af70c92ab 92 private static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
darienf 20:6d2af70c92ab 93
darienf 20:6d2af70c92ab 94 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
darienf 20:6d2af70c92ab 95 private static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat);
darienf 20:6d2af70c92ab 96
darienf 20:6d2af70c92ab 97 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
darienf 20:6d2af70c92ab 98 private static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
darienf 20:6d2af70c92ab 99 IntPtr securityAttrs, int dwCreationDisposition,
darienf 20:6d2af70c92ab 100 int dwFlagsAndAttributes, IntPtr hTemplateFile);
darienf 20:6d2af70c92ab 101
darienf 20:6d2af70c92ab 102 [DllImport("kernel32.dll", SetLastError = true)]
darienf 20:6d2af70c92ab 103 private static extern int GetFileType(SafeFileHandle hFile);
darienf 20:6d2af70c92ab 104
darienf 20:6d2af70c92ab 105 private void InitializeDcb()
darienf 20:6d2af70c92ab 106 {
darienf 20:6d2af70c92ab 107 Dcb dcb = new Dcb();
darienf 20:6d2af70c92ab 108 GetCommStateNative(ref dcb);
darienf 20:6d2af70c92ab 109 dcb.Flags &= ~(1u << DcbFlagAbortOnError);
darienf 20:6d2af70c92ab 110 SetCommStateNative(ref dcb);
darienf 20:6d2af70c92ab 111 }
darienf 20:6d2af70c92ab 112
darienf 20:6d2af70c92ab 113 private static string GetMessage(int errorCode)
darienf 20:6d2af70c92ab 114 {
darienf 20:6d2af70c92ab 115 StringBuilder lpBuffer = new StringBuilder(0x200);
darienf 20:6d2af70c92ab 116 if (
darienf 20:6d2af70c92ab 117 FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,
darienf 20:6d2af70c92ab 118 IntPtr.Zero) != 0)
darienf 20:6d2af70c92ab 119 {
darienf 20:6d2af70c92ab 120 return lpBuffer.ToString();
darienf 20:6d2af70c92ab 121 }
darienf 20:6d2af70c92ab 122 return "Unknown Error";
darienf 20:6d2af70c92ab 123 }
darienf 20:6d2af70c92ab 124
darienf 20:6d2af70c92ab 125 private static int MakeHrFromErrorCode(int errorCode)
darienf 20:6d2af70c92ab 126 {
darienf 20:6d2af70c92ab 127 return (int) (0x80070000 | (uint) errorCode);
darienf 20:6d2af70c92ab 128 }
darienf 20:6d2af70c92ab 129
darienf 20:6d2af70c92ab 130 private static void WinIoError()
darienf 20:6d2af70c92ab 131 {
darienf 20:6d2af70c92ab 132 int errorCode = Marshal.GetLastWin32Error();
darienf 20:6d2af70c92ab 133 throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));
darienf 20:6d2af70c92ab 134 }
darienf 20:6d2af70c92ab 135
darienf 20:6d2af70c92ab 136 private void GetCommStateNative(ref Dcb lpDcb)
darienf 20:6d2af70c92ab 137 {
darienf 20:6d2af70c92ab 138 int commErrors = 0;
darienf 20:6d2af70c92ab 139 Comstat comStat = new Comstat();
darienf 20:6d2af70c92ab 140
darienf 20:6d2af70c92ab 141 for (int i = 0; i < CommStateRetries; i++)
darienf 20:6d2af70c92ab 142 {
darienf 20:6d2af70c92ab 143 if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
darienf 20:6d2af70c92ab 144 {
darienf 20:6d2af70c92ab 145 WinIoError();
darienf 20:6d2af70c92ab 146 }
darienf 20:6d2af70c92ab 147 if (GetCommState(m_Handle, ref lpDcb))
darienf 20:6d2af70c92ab 148 {
darienf 20:6d2af70c92ab 149 break;
darienf 20:6d2af70c92ab 150 }
darienf 20:6d2af70c92ab 151 if (i == CommStateRetries - 1)
darienf 20:6d2af70c92ab 152 {
darienf 20:6d2af70c92ab 153 WinIoError();
darienf 20:6d2af70c92ab 154 }
darienf 20:6d2af70c92ab 155 }
darienf 20:6d2af70c92ab 156 }
darienf 20:6d2af70c92ab 157
darienf 20:6d2af70c92ab 158 private void SetCommStateNative(ref Dcb lpDcb)
darienf 20:6d2af70c92ab 159 {
darienf 20:6d2af70c92ab 160 int commErrors = 0;
darienf 20:6d2af70c92ab 161 Comstat comStat = new Comstat();
darienf 20:6d2af70c92ab 162
darienf 20:6d2af70c92ab 163 for (int i = 0; i < CommStateRetries; i++)
darienf 20:6d2af70c92ab 164 {
darienf 20:6d2af70c92ab 165 if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
darienf 20:6d2af70c92ab 166 {
darienf 20:6d2af70c92ab 167 WinIoError();
darienf 20:6d2af70c92ab 168 }
darienf 20:6d2af70c92ab 169 if (SetCommState(m_Handle, ref lpDcb))
darienf 20:6d2af70c92ab 170 {
darienf 20:6d2af70c92ab 171 break;
darienf 20:6d2af70c92ab 172 }
darienf 20:6d2af70c92ab 173 if (i == CommStateRetries - 1)
darienf 20:6d2af70c92ab 174 {
darienf 20:6d2af70c92ab 175 WinIoError();
darienf 20:6d2af70c92ab 176 }
darienf 20:6d2af70c92ab 177 }
darienf 20:6d2af70c92ab 178 }
darienf 20:6d2af70c92ab 179
darienf 20:6d2af70c92ab 180 #region Nested type: COMSTAT
darienf 20:6d2af70c92ab 181
darienf 20:6d2af70c92ab 182 [StructLayout(LayoutKind.Sequential)]
darienf 20:6d2af70c92ab 183 private struct Comstat
darienf 20:6d2af70c92ab 184 {
darienf 20:6d2af70c92ab 185 public readonly uint Flags;
darienf 20:6d2af70c92ab 186 public readonly uint cbInQue;
darienf 20:6d2af70c92ab 187 public readonly uint cbOutQue;
darienf 20:6d2af70c92ab 188 }
darienf 20:6d2af70c92ab 189
darienf 20:6d2af70c92ab 190 #endregion
darienf 20:6d2af70c92ab 191
darienf 20:6d2af70c92ab 192 #region Nested type: DCB
darienf 20:6d2af70c92ab 193
darienf 20:6d2af70c92ab 194 [StructLayout(LayoutKind.Sequential)]
darienf 20:6d2af70c92ab 195 private struct Dcb
darienf 20:6d2af70c92ab 196 {
darienf 20:6d2af70c92ab 197 public readonly uint DCBlength;
darienf 20:6d2af70c92ab 198 public readonly uint BaudRate;
darienf 20:6d2af70c92ab 199 public uint Flags;
darienf 20:6d2af70c92ab 200 public readonly ushort wReserved;
darienf 20:6d2af70c92ab 201 public readonly ushort XonLim;
darienf 20:6d2af70c92ab 202 public readonly ushort XoffLim;
darienf 20:6d2af70c92ab 203 public readonly byte ByteSize;
darienf 20:6d2af70c92ab 204 public readonly byte Parity;
darienf 20:6d2af70c92ab 205 public readonly byte StopBits;
darienf 20:6d2af70c92ab 206 public readonly byte XonChar;
darienf 20:6d2af70c92ab 207 public readonly byte XoffChar;
darienf 20:6d2af70c92ab 208 public readonly byte ErrorChar;
darienf 20:6d2af70c92ab 209 public readonly byte EofChar;
darienf 20:6d2af70c92ab 210 public readonly byte EvtChar;
darienf 20:6d2af70c92ab 211 public readonly ushort wReserved1;
darienf 20:6d2af70c92ab 212 }
darienf 20:6d2af70c92ab 213
darienf 20:6d2af70c92ab 214 #endregion
darienf 20:6d2af70c92ab 215
darienf 20:6d2af70c92ab 216 #endregion
darienf 20:6d2af70c92ab 217 }
darienf 20:6d2af70c92ab 218
darienf 20:6d2af70c92ab 219 internal class Program
darienf 20:6d2af70c92ab 220 {
darienf 20:6d2af70c92ab 221 private static void Main(string[] args)
darienf 20:6d2af70c92ab 222 {
darienf 20:6d2af70c92ab 223 SerialPortFixer.Execute("COM1");
darienf 20:6d2af70c92ab 224 using (SerialPort port = new SerialPort("COM1"))
darienf 20:6d2af70c92ab 225 {
darienf 20:6d2af70c92ab 226 port.Write("test");
darienf 20:6d2af70c92ab 227 }
darienf 20:6d2af70c92ab 228 }
darienf 20:6d2af70c92ab 229 }
darienf 20:6d2af70c92ab 230 }