/* *Author:MarcusLorentzon,2001 * d98m
强烈推介IDEA2020.2破解激活,IntelliJ IDEA 注册码,2020.2 IDEA 激活码
/* * Author: Marcus Lorentzon, 2001 * d98malor@dtek.chalmers.se * * Freeware: Please do not remove this header * * File: SerialStream.cs * * Description: Implements a Stream for asynchronous * transfers and COMM. Stream version. * * Version: 2.4 * */
#region Using
using System; using System.IO; using System.Threading; using System.Runtime.InteropServices; using System.ComponentModel;
#endregion Using
namespace LoMaN.IO {
public class SerialStream : Stream { #region Attributes
private IOCompletionCallback m_IOCompletionCallback; private IntPtr m_hFile = IntPtr.Zero; private string m_sPort; private bool m_bRead; private bool m_bWrite;
#endregion Attributes
#region Properties
public string Port { get { return m_sPort; } set { if (m_sPort != value) { Close(); Open(value); } } }
public override bool CanRead { get { return m_bRead; } }
public override bool CanWrite { get { return m_bWrite; } }
public override bool CanSeek { get { return false; } }
public bool Closed { get { return m_hFile.ToInt32() <= 0; } }
public override long Length { get { throw new NotSupportedException("Length isn't supported on serial ports."); } }
public override long Position { get { throw new NotSupportedException("Seek isn't supported on serial ports."); } set { throw new NotSupportedException("Seek isn't supported on serial ports."); } }
public bool Dtr { set { if (!EscapeCommFunction(m_hFile, value ? SETDTR : CLRDTR)) { throw new Win32Exception(); } } }
public bool Rts { set { if (!EscapeCommFunction(m_hFile, value ? SETRTS : CLRRTS)) { throw new Win32Exception(); } } }
public bool Break { set { if (!EscapeCommFunction(m_hFile, value ? SETBREAK : CLRBREAK)) { throw new Win32Exception(); } } }
public bool Cts { get { uint status; if (!GetCommModemStatus(m_hFile, out status)) { throw new Win32Exception(); } return (status & MS_CTS_ON) > 0; } }
public bool Dsr { get { uint status; if (!GetCommModemStatus(m_hFile, out status)) { throw new Win32Exception(); } return (status & MS_DSR_ON) > 0; } }
public bool Ring { get { uint status; if (!GetCommModemStatus(m_hFile, out status)) { throw new Win32Exception(); } return (status & MS_RING_ON) > 0; } }
public bool Rlsd { get { uint status; if (!GetCommModemStatus(m_hFile, out status)) { throw new Win32Exception(); } return (status & MS_RLSD_ON) > 0; } }
#endregion Properties
#region Constructors
public SerialStream() : this(FileAccess.ReadWrite) { }
public SerialStream(FileAccess access) { m_bRead = ((int)access & (int)FileAccess.Read) != 0; m_bWrite = ((int)access & (int)FileAccess.Write) != 0; unsafe { m_IOCompletionCallback = new IOCompletionCallback(AsyncFSCallback); } }
public SerialStream(string port) : this(FileAccess.ReadWrite) { Open(port); }
public SerialStream(string port, FileAccess access) : this(access) { Open(port); }
#endregion Constructors
#region Methods
public void Open(string port) { if (m_hFile != IntPtr.Zero) { throw new IOException("Stream already opened."); } m_sPort = port; m_hFile = CreateFile(port, (uint)((m_bRead?GENERIC_READ:0)|(m_bWrite?GENERIC_WRITE:0)), 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (m_hFile.ToInt32() == INVALID_HANDLE_VALUE) { m_hFile = IntPtr.Zero; throw new FileNotFoundException("Unable to open " + port); }
ThreadPool.BindHandle(m_hFile);
SetTimeouts(0, 0, 0, 0, 0); }
public override void Close() { CloseHandle(m_hFile); m_hFile = IntPtr.Zero; m_sPort = null; }
public IAsyncResult BeginRead(byte[] buffer) { return BeginRead(buffer, 0, buffer.Length, null, null); }
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { GCHandle gchBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); SerialAsyncResult sar = new SerialAsyncResult(this, state, callback, true, gchBuffer); Overlapped ov = new Overlapped(0, 0, sar.AsyncWaitHandle.Handle.ToInt32(), sar); unsafe { NativeOverlapped* nov = ov.Pack(m_IOCompletionCallback); byte* data = (byte*)((int)gchBuffer.AddrOfPinnedObject() + offset);
uint read = 0; if (ReadFile(m_hFile, data, (uint)count, out read, nov)) { sar.m_bCompletedSynchronously = true; return sar; } else if (GetLastError() == ERROR_IO_PENDING) { return sar; } else throw new Exception("Unable to initialize read. Errorcode: " + GetLastError().ToString()); } }
public IAsyncResult BeginWrite(byte[] buffer) { return BeginWrite(buffer, 0, buffer.Length, null, null); }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { GCHandle gchBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); SerialAsyncResult sar = new SerialAsyncResult(this, state, callback, false, gchBuffer); Overlapped ov = new Overlapped(0, 0, sar.AsyncWaitHandle.Handle.ToInt32(), sar); unsafe { NativeOverlapped* nov = ov.Pack(m_IOCompletionCallback); byte* data = (byte*)((int)gchBuffer.AddrOfPinnedObject() + offset);
uint written = 0; if (WriteFile(m_hFile, data, (uint)count, out written, nov)) { sar.m_bCompletedSynchronously = true; return sar; } else if (GetLastError() == ERROR_IO_PENDING) { return sar; } else throw new Exception("Unable to initialize write. Errorcode: " + GetLastError().ToString()); } }
private int EndOperation(IAsyncResult asyncResult, bool isRead) { SerialAsyncResult sar = (SerialAsyncResult)asyncResult; if (sar.m_bIsRead != isRead) throw new IOException("Invalid parameter: IAsyncResult is not from a " + (isRead ? "read" : "write")); if (sar.EndOperationCalled) { throw new IOException("End" + (isRead ? "Read" : "Write") + " called twice for the same operation."); } else { sar.m_bEndOperationCalled = true; }
while (!sar.m_bCompleted) { sar.AsyncWaitHandle.WaitOne(); }
sar.Dispose();
if (sar.m_nErrorCode != ERROR_SUCCESS && sar.m_nErrorCode != ERROR_OPERATION_ABORTED) { throw new IOException("Operation finished with errorcode: " + sar.m_nErrorCode); }
return sar.m_nReadWritten; } public override int EndRead(IAsyncResult asyncResult) { return EndOperation(asyncResult, true); } public override void EndWrite(IAsyncResult asyncResult) { EndOperation(asyncResult, false); }
public int EndWriteEx(IAsyncResult asyncResult) { return EndOperation(asyncResult, false); }
public override int Read(byte[] buffer, int offset, int count) { return EndRead(BeginRead(buffer, offset, count, null, null)); }
public override void Write(byte[] buffer, int offset, int count) { EndWrite(BeginWrite(buffer, offset, count, null, null)); }
public int WriteEx(byte[] buffer, int offset, int count) { return EndWriteEx(BeginWrite(buffer, offset, count, null, null)); }
public int Read(byte[] buffer) { return EndRead(BeginRead(buffer, 0, buffer.Length, null, null)); }
public int Write(byte[] buffer) { return EndOperation(BeginWrite(buffer, 0, buffer.Length, null, null), false); }
public override void Flush() { FlushFileBuffers(m_hFile); }
public bool PurgeRead() { return PurgeComm(m_hFile, PURGE_RXCLEAR); }
public bool PurgeWrite() { return PurgeComm(m_hFile, PURGE_TXCLEAR); }
public bool Purge() { return PurgeRead() && PurgeWrite(); }
public bool CancelRead() { return PurgeComm(m_hFile, PURGE_RXABORT); }
public bool CancelWrite() { return PurgeComm(m_hFile, PURGE_TXABORT); }
public bool CancelAll() { return CancelRead() && CancelWrite(); }
public override void SetLength(long nLength) { throw new NotSupportedException("SetLength isn't supported on serial ports."); }
public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException("Seek isn't supported on serial ports."); }
public void SetTimeouts(int ReadIntervalTimeout, int ReadTotalTimeoutMultiplier, int ReadTotalTimeoutConstant, int WriteTotalTimeoutMultiplier, int WriteTotalTimeoutConstant) { SerialTimeouts Timeouts = new SerialTimeouts(ReadIntervalTimeout, ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant, WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant); unsafe { SetCommTimeouts(m_hFile, ref Timeouts); } }
public bool SetPortSettings(uint baudrate) { return SetPortSettings(baudrate, FlowControl.Hardware); }
public bool SetPortSettings(uint baudrate, FlowControl flowControl) { return SetPortSettings(baudrate, flowControl, Parity.None); }
public bool SetPortSettings(uint baudrate, FlowControl flowControl, Parity parity) { return SetPortSettings(baudrate, flowControl, parity, 8, StopBits.One); }
public bool SetPortSettings(uint baudrate, FlowControl flowControl, Parity parity, byte databits, StopBits stopbits) { unsafe { DCB dcb = new DCB(); dcb.DCBlength = sizeof(DCB); dcb.BaudRate = baudrate; dcb.ByteSize = databits; dcb.StopBits = (byte)stopbits; dcb.Parity = (byte)parity; dcb.fParity = (parity > 0)? 1U : 0U; dcb.fBinary = dcb.fDtrControl = dcb.fTXContinueOnXoff = 1; dcb.fOutxCtsFlow = dcb.fAbortOnError = (flowControl == FlowControl.Hardware)? 1U : 0U; dcb.fOutX = dcb.fInX = (flowControl == FlowControl.XOnXOff)? 1U : 0U; dcb.fRtsControl = (flowControl == FlowControl.Hardware)? 2U : 1U; dcb.XonLim = 2048; dcb.XoffLim = 512; dcb.XonChar = 0x11; // Ctrl-Q dcb.XoffChar = 0x13; // Ctrl-S return SetCommState(m_hFile, ref dcb); } }
public bool SetPortSettings(DCB dcb) { return SetCommState(m_hFile, ref dcb); }
public bool GetPortSettings(out DCB dcb) { unsafe { DCB dcb2 = new DCB(); dcb2.DCBlength = sizeof(DCB); bool ret = GetCommState(m_hFile, ref dcb2); dcb = dcb2; return ret; } }
public bool SetXOn() { return EscapeCommFunction(m_hFile, SETXON); }
public bool SetXOff() { return EscapeCommFunction(m_hFile, SETXOFF); }
private unsafe void AsyncFSCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped) { SerialAsyncResult sar = (SerialAsyncResult)Overlapped.Unpack(pOverlapped).AsyncResult;
sar.m_nErrorCode = errorCode; sar.m_nReadWritten = (int)numBytes; sar.m_bCompleted = true;
if (sar.Callback != null) sar.Callback.Invoke(sar);
Overlapped.Free(pOverlapped); }
#endregion Methods
#region Constants
private const uint PURGE_TXABORT = 0x0001; // Kill the pending/current writes to the comm port. private const uint PURGE_RXABORT = 0x0002; // Kill the pending/current reads to the comm port. private const uint PURGE_TXCLEAR = 0x0004; // Kill the transmit queue if there. private const uint PURGE_RXCLEAR = 0x0008; // Kill the typeahead buffer if there.
private const uint SETXOFF = 1; // Simulate XOFF received private const uint SETXON = 2; // Simulate XON received private const uint SETRTS = 3; // Set RTS high private const uint CLRRTS = 4; // Set RTS low private const uint SETDTR = 5; // Set DTR high private const uint CLRDTR = 6; // Set DTR low private const uint SETBREAK = 8; // Set the device break line. private const uint CLRBREAK = 9; // Clear the device break line.
private const uint MS_CTS_ON = 0x0010; private const uint MS_DSR_ON = 0x0020; private const uint MS_RING_ON = 0x0040; private const uint MS_RLSD_ON = 0x0080;
private const uint FILE_FLAG_OVERLAPPED = 0x40000000;
private const uint OPEN_EXISTING = 3;
private const int INVALID_HANDLE_VALUE = -1;
private const uint GENERIC_READ = 0x80000000; private const uint GENERIC_WRITE = 0x40000000;
private const uint ERROR_SUCCESS = 0; private const uint ERROR_OPERATION_ABORTED = 995; private const uint ERROR_IO_PENDING = 997;
#endregion Constants
#region Enums
public enum Parity {None, Odd, Even, Mark, Space}; public enum StopBits {One, OneAndHalf, Two}; public enum FlowControl {None, XOnXOff, Hardware};
#endregion Enums
#region Classes
[StructLayout(LayoutKind.Sequential)] public struct DCB {
#region Attributes
public int DCBlength; public uint BaudRate; public uint Flags; public ushort wReserved; public ushort XonLim; public ushort XoffLim; public byte ByteSize; public byte Parity; public byte StopBits; public sbyte XonChar; public sbyte XoffChar; public sbyte ErrorChar; public sbyte EofChar; public sbyte EvtChar; public ushort wReserved1;
#endregion Attributes
#region Properties
public uint fBinary { get { return Flags&0x0001; } set { Flags = Flags & ~1U | value; } } public uint fParity { get { return (Flags>>1)&1; } set { Flags = Flags & ~(1U << 1) | (value << 1); } } public uint fOutxCtsFlow { get { return (Flags>>2)&1; } set { Flags = Flags & ~(1U << 2) | (value << 2); } } public uint fOutxDsrFlow { get { return (Flags>>3)&1; } set { Flags = Flags & ~(1U << 3) | (value << 3); } } public uint fDtrControl { get { return (Flags>>4)&3; } set { Flags = Flags & ~(3U << 4) | (value << 4); } } public uint fDsrSensitivity { get { return (Flags>>6)&1; } set { Flags = Flags & ~(1U << 6) | (value << 6); } } public uint fTXContinueOnXoff { get { return (Flags>>7)&1; } set { Flags = Flags & ~(1U << 7) | (value << 7); } } public uint fOutX { get { return (Flags>>8)&1; } set { Flags = Flags & ~(1U << 8) | (value << 8); } } public uint fInX { get { return (Flags>>9)&1; } set { Flags = Flags & ~(1U << 9) | (value << 9); } } public uint fErrorChar { get { return (Flags>>10)&1; } set { Flags = Flags & ~(1U << 10) | (value << 10); } } public uint fNull { get { return (Flags>>11)&1; } set { Flags = Flags & ~(1U << 11) | (value << 11); } } public uint fRtsControl { get { return (Flags>>12)&3; } set { Flags = Flags & ~(3U << 12) | (value << 12); } } public uint fAbortOnError { get { return (Flags>>14)&1; } set { Flags = Flags & ~(1U << 14) | (value << 14); } }
#endregion Properties
#region Methods
public override string ToString() { return "DCBlength: " + DCBlength + "/r/n" + "BaudRate: " + BaudRate + "/r/n" + "fBinary: " + fBinary + "/r/n" + "fParity: " + fParity + "/r/n" + "fOutxCtsFlow: " + fOutxCtsFlow + "/r/n" + "fOutxDsrFlow: " + fOutxDsrFlow + "/r/n" + "fDtrControl: " + fDtrControl + "/r/n" + "fDsrSensitivity: " + fDsrSensitivity + "/r/n" + "fTXContinueOnXoff: " + fTXContinueOnXoff + "/r/n" + "fOutX: " + fOutX + "/r/n" + "fInX: " + fInX + "/r/n" + "fErrorChar: " + fErrorChar + "/r/n" + "fNull: " + fNull + "/r/n" + "fRtsControl: " + fRtsControl + "/r/n" + "fAbortOnError: " + fAbortOnError + "/r/n" + "XonLim: " + XonLim + "/r/n" + "XoffLim: " + XoffLim + "/r/n" + "ByteSize: " + ByteSize + "/r/n" + "Parity: " + Parity + "/r/n" + "StopBits: " + StopBits + "/r/n" + "XonChar: " + XonChar + "/r/n" + "XoffChar: " + XoffChar + "/r/n" + "EofChar: " + EofChar + "/r/n" + "EvtChar: " + EvtChar + "/r/n"; }
#endregion Methods }
private class SerialAsyncResult : IAsyncResult, IDisposable {
#region Attributes
internal bool m_bEndOperationCalled = false; internal bool m_bIsRead; internal int m_nReadWritten = 0; internal bool m_bCompleted = false; internal bool m_bCompletedSynchronously = false; internal uint m_nErrorCode = ERROR_SUCCESS;
private object m_AsyncObject; private object m_StateObject; private ManualResetEvent m_WaitHandle = new ManualResetEvent(false); private AsyncCallback m_Callback; private GCHandle m_gchBuffer;
#endregion Attributes
#region Properties
internal bool EndOperationCalled { get { return m_bEndOperationCalled; } }
public bool IsCompleted { get { return m_bCompleted; } }
public bool CompletedSynchronously { get { return m_bCompletedSynchronously; } }
public object AsyncObject { get { return m_AsyncObject; } }
public object AsyncState { get { return m_StateObject; } }
public WaitHandle AsyncWaitHandle { get { return m_WaitHandle; } } internal ManualResetEvent WaitHandle { get { return m_WaitHandle; } }
public AsyncCallback Callback { get { return m_Callback; } }
#endregion Properties
#region Constructors
public SerialAsyncResult(object asyncObject, object stateObject, AsyncCallback callback, bool bIsRead, GCHandle gchBuffer) {
m_AsyncObject = asyncObject; m_StateObject = stateObject; m_Callback = callback; m_bIsRead = bIsRead; m_gchBuffer = gchBuffer; }
#endregion Constructors
#region Methods
public void Dispose() { m_WaitHandle.Close(); m_gchBuffer.Free(); }
#endregion Methods }
#endregion Classes
#region Imports
[DllImport("kernel32.dll", EntryPoint="CreateFileW", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true)] static extern IntPtr CreateFile(string filename, uint access, uint sharemode, uint security_attributes, uint creation, uint flags, uint template);
[DllImport("kernel32.dll", SetLastError=true)] static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32.dll", SetLastError=true)] static extern unsafe bool ReadFile(IntPtr hFile, byte* lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, NativeOverlapped* lpOverlapped);
[DllImport("kernel32.dll", SetLastError=true)] static extern unsafe bool WriteFile(IntPtr hFile, byte* lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, NativeOverlapped* lpOverlapped);
[DllImport("kernel32.dll", SetLastError=true)] static extern bool SetCommTimeouts(IntPtr hFile, ref SerialTimeouts lpCommTimeouts);
[DllImport("kernel32.dll", SetLastError=true)] static extern bool SetCommState(IntPtr hFile, ref DCB lpDCB);
[DllImport("kernel32.dll", SetLastError=true)] static extern bool GetCommState(IntPtr hFile, ref DCB lpDCB);
[DllImport("kernel32.dll", SetLastError=true)] static extern bool BuildCommDCB(string def, ref DCB lpDCB);
[DllImport("kernel32.dll", SetLastError=true)] static extern int GetLastError();
[DllImport("kernel32.dll", SetLastError=true)] static extern bool FlushFileBuffers(IntPtr hFile);
[DllImport("kernel32.dll", SetLastError=true)] static extern bool PurgeComm(IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", SetLastError=true)] static extern bool EscapeCommFunction(IntPtr hFile, uint dwFunc);
[DllImport("kernel32.dll", SetLastError=true)] static extern bool GetCommModemStatus(IntPtr hFile, out uint modemStat);
#endregion Imports }
[StructLayout(LayoutKind.Sequential)] public struct SerialTimeouts {
#region Attributes
public int ReadIntervalTimeout; public int ReadTotalTimeoutMultiplier; public int ReadTotalTimeoutConstant; public int WriteTotalTimeoutMultiplier; public int WriteTotalTimeoutConstant;
#endregion Attributes
#region Constructors
public SerialTimeouts(int r1, int r2, int r3, int w1, int w2) { ReadIntervalTimeout = r1; ReadTotalTimeoutMultiplier = r2; ReadTotalTimeoutConstant = r3; WriteTotalTimeoutMultiplier = w1; WriteTotalTimeoutConstant = w2; }
#endregion Constructors
#region Methods
public override string ToString() { return "ReadIntervalTimeout: " + ReadIntervalTimeout + "/r/n" + "ReadTotalTimeoutMultiplier: " + ReadTotalTimeoutMultiplier + "/r/n" + "ReadTotalTimeoutConstant: " + ReadTotalTimeoutConstant + "/r/n" + "WriteTotalTimeoutMultiplier: " + WriteTotalTimeoutMultiplier + "/r/n" + "WriteTotalTimeoutConstant: " + WriteTotalTimeoutConstant + "/r/n"; }
#endregion Methods } }
本文由来源 21aspnet,由 system_mush 整理编辑,其版权均为 21aspnet 所有,文章内容系作者个人观点,不代表 Java架构师必看 对观点赞同或支持。如需转载,请注明文章来源。