![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
repo time
Dependencies: mbed MAX14720 MAX30205 USBDevice
Diff: HspGuiSourceV301/GuiDLLs/SerialWrap/SerialPortTester.cs
- Revision:
- 20:6d2af70c92ab
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HspGuiSourceV301/GuiDLLs/SerialWrap/SerialPortTester.cs Tue Apr 06 06:41:40 2021 +0000 @@ -0,0 +1,230 @@ +// Copyright 2010-2014 Zach Saw +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; +using System.IO.Ports; +using System.Runtime.InteropServices; +using System.Text; +using Microsoft.Win32.SafeHandles; + +namespace SerialPortTester +{ + public class SerialPortFixer : IDisposable + { + public static void Execute(string portName) + { + using (new SerialPortFixer(portName)) + { + } + } + #region IDisposable Members + + public void Dispose() + { + if (m_Handle != null) + { + m_Handle.Close(); + m_Handle = null; + } + } + + #endregion + + #region Implementation + + private const int DcbFlagAbortOnError = 14; + private const int CommStateRetries = 10; + private SafeFileHandle m_Handle; + + private SerialPortFixer(string portName) + { + const int dwFlagsAndAttributes = 0x40000000; + const int dwAccess = unchecked((int) 0xC0000000); + + if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase)) + { + throw new ArgumentException("Invalid Serial Port", "portName"); + } + SafeFileHandle hFile = CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes, + IntPtr.Zero); + if (hFile.IsInvalid) + { + WinIoError(); + } + try + { + int fileType = GetFileType(hFile); + if ((fileType != 2) && (fileType != 0)) + { + throw new ArgumentException("Invalid Serial Port", "portName"); + } + m_Handle = hFile; + InitializeDcb(); + } + catch + { + hFile.Close(); + m_Handle = null; + throw; + } + } + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId, + StringBuilder lpBuffer, int nSize, IntPtr arguments); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, + IntPtr securityAttrs, int dwCreationDisposition, + int dwFlagsAndAttributes, IntPtr hTemplateFile); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern int GetFileType(SafeFileHandle hFile); + + private void InitializeDcb() + { + Dcb dcb = new Dcb(); + GetCommStateNative(ref dcb); + dcb.Flags &= ~(1u << DcbFlagAbortOnError); + SetCommStateNative(ref dcb); + } + + private static string GetMessage(int errorCode) + { + StringBuilder lpBuffer = new StringBuilder(0x200); + if ( + FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity, + IntPtr.Zero) != 0) + { + return lpBuffer.ToString(); + } + return "Unknown Error"; + } + + private static int MakeHrFromErrorCode(int errorCode) + { + return (int) (0x80070000 | (uint) errorCode); + } + + private static void WinIoError() + { + int errorCode = Marshal.GetLastWin32Error(); + throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode)); + } + + private void GetCommStateNative(ref Dcb lpDcb) + { + int commErrors = 0; + Comstat comStat = new Comstat(); + + for (int i = 0; i < CommStateRetries; i++) + { + if (!ClearCommError(m_Handle, ref commErrors, ref comStat)) + { + WinIoError(); + } + if (GetCommState(m_Handle, ref lpDcb)) + { + break; + } + if (i == CommStateRetries - 1) + { + WinIoError(); + } + } + } + + private void SetCommStateNative(ref Dcb lpDcb) + { + int commErrors = 0; + Comstat comStat = new Comstat(); + + for (int i = 0; i < CommStateRetries; i++) + { + if (!ClearCommError(m_Handle, ref commErrors, ref comStat)) + { + WinIoError(); + } + if (SetCommState(m_Handle, ref lpDcb)) + { + break; + } + if (i == CommStateRetries - 1) + { + WinIoError(); + } + } + } + + #region Nested type: COMSTAT + + [StructLayout(LayoutKind.Sequential)] + private struct Comstat + { + public readonly uint Flags; + public readonly uint cbInQue; + public readonly uint cbOutQue; + } + + #endregion + + #region Nested type: DCB + + [StructLayout(LayoutKind.Sequential)] + private struct Dcb + { + public readonly uint DCBlength; + public readonly uint BaudRate; + public uint Flags; + public readonly ushort wReserved; + public readonly ushort XonLim; + public readonly ushort XoffLim; + public readonly byte ByteSize; + public readonly byte Parity; + public readonly byte StopBits; + public readonly byte XonChar; + public readonly byte XoffChar; + public readonly byte ErrorChar; + public readonly byte EofChar; + public readonly byte EvtChar; + public readonly ushort wReserved1; + } + + #endregion + + #endregion + } + + internal class Program + { + private static void Main(string[] args) + { + SerialPortFixer.Execute("COM1"); + using (SerialPort port = new SerialPort("COM1")) + { + port.Write("test"); + } + } + } +}