diff --git a/PInvokeSerialPort.sln b/Nefarius.Peripherals.SerialPort.sln
old mode 100755
new mode 100644
similarity index 91%
rename from PInvokeSerialPort.sln
rename to Nefarius.Peripherals.SerialPort.sln
index 1768411..5d37659
--- a/PInvokeSerialPort.sln
+++ b/Nefarius.Peripherals.SerialPort.sln
@@ -1,9 +1,9 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29613.14
+# Visual Studio Version 17
+VisualStudioVersion = 17.3.32825.248
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PInvokeSerialPort", "PInvokeSerialPort\PInvokeSerialPort.csproj", "{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nefarius.Peripherals.SerialPort", "Nefarius.Peripherals.SerialPort\Nefarius.Peripherals.SerialPort.csproj", "{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{99052083-B245-462F-8778-4C94662ABABE}"
ProjectSection(SolutionItems) = preProject
@@ -47,7 +47,6 @@ Global
{928609B4-70AB-4D93-A43E-4BE75C279066}.Release|Any CPU.ActiveCfg = Release|Any CPU
{928609B4-70AB-4D93-A43E-4BE75C279066}.Release|Any CPU.Build.0 = Release|Any CPU
{928609B4-70AB-4D93-A43E-4BE75C279066}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {928609B4-70AB-4D93-A43E-4BE75C279066}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{928609B4-70AB-4D93-A43E-4BE75C279066}.Release|x86.ActiveCfg = Release|Any CPU
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Debug|Any CPU.ActiveCfg = Debug|x86
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
@@ -56,7 +55,6 @@ Global
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Debug|x86.Build.0 = Debug|x86
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Release|Any CPU.ActiveCfg = Release|x86
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Release|Mixed Platforms.ActiveCfg = Release|x86
- {76FAB402-7515-4A9B-8605-4FEC0736C78A}.Release|Mixed Platforms.Build.0 = Release|x86
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Release|x86.ActiveCfg = Release|x86
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Release|x86.Build.0 = Release|x86
EndGlobalSection
diff --git a/Nefarius.Peripherals.SerialPort/ASCII.cs b/Nefarius.Peripherals.SerialPort/ASCII.cs
new file mode 100644
index 0000000..2ff7265
--- /dev/null
+++ b/Nefarius.Peripherals.SerialPort/ASCII.cs
@@ -0,0 +1,41 @@
+namespace Nefarius.Peripherals.SerialPort;
+
+///
+/// Byte type with enumeration constants for ASCII control codes.
+///
+public enum ASCII : byte
+{
+ NULL = 0x00,
+ SOH = 0x01,
+ STH = 0x02,
+ ETX = 0x03,
+ EOT = 0x04,
+ ENQ = 0x05,
+ ACK = 0x06,
+ BELL = 0x07,
+ BS = 0x08,
+ HT = 0x09,
+ LF = 0x0A,
+ VT = 0x0B,
+ FF = 0x0C,
+ CR = 0x0D,
+ SO = 0x0E,
+ SI = 0x0F,
+ DC1 = 0x11,
+ DC2 = 0x12,
+ DC3 = 0x13,
+ DC4 = 0x14,
+ NAK = 0x15,
+ SYN = 0x16,
+ ETB = 0x17,
+ CAN = 0x18,
+ EM = 0x19,
+ SUB = 0x1A,
+ ESC = 0x1B,
+ FS = 0x1C,
+ GS = 0x1D,
+ RS = 0x1E,
+ US = 0x1F,
+ SP = 0x20,
+ DEL = 0x7F
+}
\ No newline at end of file
diff --git a/Nefarius.Peripherals.SerialPort/CommPortException.cs b/Nefarius.Peripherals.SerialPort/CommPortException.cs
new file mode 100644
index 0000000..bb4c8e7
--- /dev/null
+++ b/Nefarius.Peripherals.SerialPort/CommPortException.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Nefarius.Peripherals.SerialPort;
+
+///
+/// Exception used for all errors.
+///
+public class CommPortException : ApplicationException
+{
+ ///
+ /// Constructor for raising direct exceptions
+ ///
+ /// Description of error
+ public CommPortException(string desc) : base(desc)
+ {
+ }
+
+ ///
+ /// Constructor for re-raising exceptions from receive thread
+ ///
+ /// Inner exception raised on receive thread
+ public CommPortException(Exception e) : base("Receive Thread Exception", e)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Nefarius.Peripherals.SerialPort/Handshake.cs b/Nefarius.Peripherals.SerialPort/Handshake.cs
new file mode 100644
index 0000000..ed1bbac
--- /dev/null
+++ b/Nefarius.Peripherals.SerialPort/Handshake.cs
@@ -0,0 +1,27 @@
+namespace Nefarius.Peripherals.SerialPort;
+
+///
+/// Standard handshake methods
+///
+public enum Handshake
+{
+ ///
+ /// No handshaking
+ ///
+ None,
+
+ ///
+ /// Software handshaking using Xon / Xoff
+ ///
+ XonXoff,
+
+ ///
+ /// Hardware handshaking using CTS / RTS
+ ///
+ CtsRts,
+
+ ///
+ /// Hardware handshaking using DSR / DTR
+ ///
+ DsrDtr
+}
\ No newline at end of file
diff --git a/Nefarius.Peripherals.SerialPort/HsOutput.cs b/Nefarius.Peripherals.SerialPort/HsOutput.cs
new file mode 100644
index 0000000..a57434d
--- /dev/null
+++ b/Nefarius.Peripherals.SerialPort/HsOutput.cs
@@ -0,0 +1,27 @@
+namespace Nefarius.Peripherals.SerialPort;
+
+///
+/// Uses for RTS or DTR pins
+///
+public enum HsOutput
+{
+ ///
+ /// Pin is asserted when this station is able to receive data.
+ ///
+ Handshake = 2,
+
+ ///
+ /// Pin is asserted when this station is transmitting data (RTS on NT, 2000 or XP only).
+ ///
+ Gate = 3,
+
+ ///
+ /// Pin is asserted when this station is online (port is open).
+ ///
+ Online = 1,
+
+ ///
+ /// Pin is never asserted.
+ ///
+ None = 0
+}
\ No newline at end of file
diff --git a/Nefarius.Peripherals.SerialPort/ModemStatus.cs b/Nefarius.Peripherals.SerialPort/ModemStatus.cs
new file mode 100644
index 0000000..a7ad443
--- /dev/null
+++ b/Nefarius.Peripherals.SerialPort/ModemStatus.cs
@@ -0,0 +1,36 @@
+using Windows.Win32.Devices.Communication;
+
+namespace Nefarius.Peripherals.SerialPort;
+
+///
+/// Represents the status of the modem control input signals.
+///
+public readonly struct ModemStatus
+{
+ private readonly uint _status;
+
+ internal ModemStatus(uint val)
+ {
+ _status = val;
+ }
+
+ ///
+ /// Condition of the Clear To Send signal.
+ ///
+ public bool Cts => (_status & (uint)MODEM_STATUS_FLAGS.MS_CTS_ON) != 0;
+
+ ///
+ /// Condition of the Data Set Ready signal.
+ ///
+ public bool Dsr => (_status & (uint)MODEM_STATUS_FLAGS.MS_DSR_ON) != 0;
+
+ ///
+ /// Condition of the Receive Line Status Detection signal.
+ ///
+ public bool Rlsd => (_status & (uint)MODEM_STATUS_FLAGS.MS_RLSD_ON) != 0;
+
+ ///
+ /// Condition of the Ring Detection signal.
+ ///
+ public bool Ring => (_status & (uint)MODEM_STATUS_FLAGS.MS_RING_ON) != 0;
+}
\ No newline at end of file
diff --git a/Nefarius.Peripherals.SerialPort/NativeMethods.txt b/Nefarius.Peripherals.SerialPort/NativeMethods.txt
new file mode 100644
index 0000000..15077ca
--- /dev/null
+++ b/Nefarius.Peripherals.SerialPort/NativeMethods.txt
@@ -0,0 +1,17 @@
+CreateFile
+GetHandleInformation
+SetCommState
+SetCommTimeouts
+SetupComm
+WriteFile
+SetCommMask
+WaitCommEvent
+CancelIo
+ReadFile
+TransmitCommChar
+EscapeCommFunction
+GetCommModemStatus
+GetOverlappedResult
+ClearCommError
+GetCommProperties
+WIN32_ERROR
\ No newline at end of file
diff --git a/PInvokeSerialPort/PInvokeSerialPort.csproj b/Nefarius.Peripherals.SerialPort/Nefarius.Peripherals.SerialPort.csproj
old mode 100755
new mode 100644
similarity index 52%
rename from PInvokeSerialPort/PInvokeSerialPort.csproj
rename to Nefarius.Peripherals.SerialPort/Nefarius.Peripherals.SerialPort.csproj
index 6b96489..a071ba9
--- a/PInvokeSerialPort/PInvokeSerialPort.csproj
+++ b/Nefarius.Peripherals.SerialPort/Nefarius.Peripherals.SerialPort.csproj
@@ -3,16 +3,36 @@
netstandard2.0
true
Ebrahim Byagowi, Benjamin Höglinger-Stelzer
+ true
https://github.com/nefarius/PInvokeSerialPort
https://github.com/nefarius/PInvokeSerialPort
- Nefarius.PInvokeSerialPort
+ Nefarius.Peripherals.SerialPort
P/Invoke wrapper for Win32API serial port
- Copyright 2012-2017 Ebrahim Byagowi, 2018 Benjamin Höglinger-Stelzer
+ Copyright 2012-2017 Ebrahim Byagowi, 2018-2022 Benjamin Höglinger-Stelzer
https://raw.githubusercontent.com/Nefarius/PInvokeSerialPort/master/ProjectIcon.png
https://raw.githubusercontent.com/nefarius/PInvokeSerialPort/master/LICENSE
1.0.0
+ $(SolutionDir)bin\
+ NSS-128x128.png
+
+ latest
+
+
+
+
+ True
+
+
+
+
+
+
+
+ all
+
+
\ No newline at end of file
diff --git a/PInvokeSerialPort/Parity.cs b/Nefarius.Peripherals.SerialPort/Parity.cs
old mode 100755
new mode 100644
similarity index 94%
rename from PInvokeSerialPort/Parity.cs
rename to Nefarius.Peripherals.SerialPort/Parity.cs
index 9889b7c..b2130a5
--- a/PInvokeSerialPort/Parity.cs
+++ b/Nefarius.Peripherals.SerialPort/Parity.cs
@@ -1,4 +1,4 @@
-namespace PInvokeSerialPort
+namespace Nefarius.Peripherals.SerialPort
{
///
/// Parity settings
diff --git a/PInvokeSerialPort/QueueStatus.cs b/Nefarius.Peripherals.SerialPort/QueueStatus.cs
old mode 100755
new mode 100644
similarity index 97%
rename from PInvokeSerialPort/QueueStatus.cs
rename to Nefarius.Peripherals.SerialPort/QueueStatus.cs
index 33979c6..69bf8de
--- a/PInvokeSerialPort/QueueStatus.cs
+++ b/Nefarius.Peripherals.SerialPort/QueueStatus.cs
@@ -1,7 +1,7 @@
using System.Text;
-using PInvokeSerialPort.Win32PInvoke;
+using Nefarius.Peripherals.SerialPort.Win32PInvoke;
-namespace PInvokeSerialPort
+namespace Nefarius.Peripherals.SerialPort
{
///
/// Represents the current condition of the port queues.
diff --git a/Nefarius.Peripherals.SerialPort/SerialPort.cs b/Nefarius.Peripherals.SerialPort/SerialPort.cs
new file mode 100644
index 0000000..2ca73fc
--- /dev/null
+++ b/Nefarius.Peripherals.SerialPort/SerialPort.cs
@@ -0,0 +1,870 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using Windows.Win32;
+using Windows.Win32.Devices.Communication;
+using Windows.Win32.Foundation;
+using Windows.Win32.Storage.FileSystem;
+using JetBrains.Annotations;
+
+namespace Nefarius.Peripherals.SerialPort;
+
+///
+/// PInvokeSerialPort main class.
+/// Borrowed from http://msdn.microsoft.com/en-us/magazine/cc301786.aspx ;)
+///
+public class SerialPort : IDisposable
+{
+ ///
+ ///
+ /// For IDisposable
+ ///
+ public void Dispose()
+ {
+ Close();
+ }
+
+ ///
+ /// Opens the com port and configures it with the required settings
+ ///
+ /// false if the port could not be opened
+ [UsedImplicitly]
+ public bool Open()
+ {
+ var portDcb = new DCB();
+ var commTimeouts = new COMMTIMEOUTS();
+
+ if (_online) return false;
+
+ _hPort = PInvoke.CreateFile(
+ PortName,
+ FILE_ACCESS_FLAGS.FILE_GENERIC_READ | FILE_ACCESS_FLAGS.FILE_GENERIC_WRITE,
+ 0,
+ null,
+ FILE_CREATION_DISPOSITION.OPEN_EXISTING, FILE_FLAGS_AND_ATTRIBUTES.FILE_FLAG_OVERLAPPED,
+ null
+ );
+
+ if (_hPort.IsInvalid)
+ {
+ if (Marshal.GetLastWin32Error() == (int)WIN32_ERROR.ERROR_ACCESS_DENIED) return false;
+ throw new CommPortException("Port Open Failure");
+ }
+
+ _online = true;
+
+ commTimeouts.WriteTotalTimeoutConstant = (uint)SendTimeoutConstant;
+ commTimeouts.WriteTotalTimeoutMultiplier = (uint)SendTimeoutMultiplier;
+
+ portDcb.Init(
+ Parity is Parity.Odd or Parity.Even,
+ TxFlowCts,
+ TxFlowDsr,
+ (int)UseDtr,
+ RxGateDsr,
+ !TxWhenRxXoff,
+ TxFlowX,
+ RxFlowX,
+ (int)UseRts
+ );
+ portDcb.BaudRate = (uint)BaudRate;
+ portDcb.ByteSize = (byte)DataBits;
+ portDcb.Parity = (DCB_PARITY)Parity;
+ portDcb.StopBits = (DCB_STOP_BITS)StopBits;
+ portDcb.XoffChar = new CHAR((byte)XoffChar);
+ portDcb.XonChar = new CHAR((byte)XonChar);
+ portDcb.XoffLim = (ushort)RxHighWater;
+ portDcb.XonLim = (ushort)RxLowWater;
+
+ if (RxQueue != 0 || TxQueue != 0)
+ if (!PInvoke.SetupComm(_hPort, (uint)RxQueue, (uint)TxQueue))
+ ThrowException("Bad queue settings");
+
+ if (!PInvoke.SetCommState(_hPort, portDcb)) ThrowException("Bad com settings");
+ if (!PInvoke.SetCommTimeouts(_hPort, commTimeouts)) ThrowException("Bad timeout settings");
+
+ _stateBrk = 0;
+ switch (UseDtr)
+ {
+ case HsOutput.None:
+ _stateDtr = 0;
+ break;
+ case HsOutput.Online:
+ _stateDtr = 1;
+ break;
+ }
+
+ switch (UseRts)
+ {
+ case HsOutput.None:
+ _stateRts = 0;
+ break;
+ case HsOutput.Online:
+ _stateRts = 1;
+ break;
+ }
+
+ _checkSends = CheckAllSends;
+
+ _writeOverlapped = new NativeOverlapped
+ {
+ EventHandle = _checkSends ? _writeEvent.SafeWaitHandle.DangerousGetHandle() : IntPtr.Zero
+ };
+
+ _writeCount = 0;
+
+ _rxException = null;
+ _rxExceptionReported = false;
+
+ _rxThread = new Thread(ReceiveThread)
+ {
+ Name = "CommBaseRx",
+ Priority = ThreadPriority.AboveNormal,
+ IsBackground = true
+ };
+
+ _rxThread.Start();
+ Thread.Sleep(1); //Give rx thread time to start. By documentation, 0 should work, but it does not!
+
+ _auto = false;
+ if (AfterOpen())
+ {
+ _auto = AutoReopen;
+ return true;
+ }
+
+ Close();
+
+ return false;
+ }
+
+ ///
+ /// Closes the com port.
+ ///
+ [UsedImplicitly]
+ public void Close()
+ {
+ if (_online)
+ {
+ _auto = false;
+ BeforeClose(false);
+ InternalClose();
+ _rxException = null;
+ }
+ }
+
+ private void InternalClose()
+ {
+ PInvoke.CancelIo(_hPort);
+ if (_rxThread != null)
+ {
+ _rxThread.Abort();
+ _rxThread = null;
+ }
+
+ _hPort.Close();
+
+ _stateRts = 2;
+ _stateDtr = 2;
+ _stateBrk = 2;
+ _online = false;
+ }
+
+ ///
+ /// Destructor (just in case)
+ ///
+ ~SerialPort()
+ {
+ Close();
+ }
+
+ ///
+ /// Block until all bytes in the queue have been transmitted.
+ ///
+ [UsedImplicitly]
+ public void Flush()
+ {
+ CheckOnline();
+ CheckResult();
+ }
+
+ ///
+ /// Use this to throw exceptions in derived classes. Correctly handles threading issues
+ /// and closes the port if necessary.
+ ///
+ /// Description of fault
+ protected void ThrowException(string reason)
+ {
+ if (Thread.CurrentThread == _rxThread) throw new CommPortException(reason);
+ if (_online)
+ {
+ BeforeClose(true);
+ InternalClose();
+ }
+
+ if (_rxException == null) throw new CommPortException(reason);
+ throw new CommPortException(_rxException);
+ }
+
+ ///
+ /// Queues bytes for transmission.
+ ///
+ /// Array of bytes to be sent
+ [UsedImplicitly]
+ public unsafe void Write(byte[] toSend)
+ {
+ CheckOnline();
+ CheckResult();
+ _writeCount = toSend.GetLength(0);
+
+ fixed (byte* ptr = toSend)
+ fixed (NativeOverlapped* overlapped = &_writeOverlapped)
+ {
+ uint sent;
+ if (PInvoke.WriteFile(_hPort, ptr, (uint)_writeCount, &sent, overlapped))
+ {
+ _writeCount -= (int)sent;
+ }
+ else
+ {
+ if (Marshal.GetLastWin32Error() != (int)WIN32_ERROR.ERROR_IO_PENDING)
+ ThrowException("Unexpected failure");
+ }
+ }
+ }
+
+ ///
+ /// Queues string for transmission.
+ ///
+ /// Array of bytes to be sent
+ [UsedImplicitly]
+ public void Write(string toSend)
+ {
+ Write(new ASCIIEncoding().GetBytes(toSend));
+ }
+
+ ///
+ /// Queues a single byte for transmission.
+ ///
+ /// Byte to be sent
+ [UsedImplicitly]
+ public void Write(byte toSend)
+ {
+ var b = new byte[1];
+ b[0] = toSend;
+ Write(b);
+ }
+
+ ///
+ /// Queues a single char for transmission.
+ ///
+ /// Byte to be sent
+ [UsedImplicitly]
+ public void Write(char toSend)
+ {
+ Write(toSend.ToString());
+ }
+
+ ///
+ /// Queues string with a new line ("\r\n") for transmission.
+ ///
+ /// Array of bytes to be sent
+ [UsedImplicitly]
+ public void WriteLine(string toSend)
+ {
+ Write(new ASCIIEncoding().GetBytes(toSend + Environment.NewLine));
+ }
+
+ private void CheckResult()
+ {
+ if (_writeCount <= 0) return;
+
+ if (PInvoke.GetOverlappedResult(_hPort, _writeOverlapped, out var sent, _checkSends))
+ {
+ _writeCount -= (int)sent;
+ if (_writeCount != 0) ThrowException("Send Timeout");
+ }
+ else
+ {
+ if (Marshal.GetLastWin32Error() != (int)WIN32_ERROR.ERROR_IO_PENDING) ThrowException("Unexpected failure");
+ }
+ }
+
+ ///
+ /// Sends a protocol byte immediately ahead of any queued bytes.
+ ///
+ /// Byte to send
+ /// False if an immediate byte is already scheduled and not yet sent
+ public void SendImmediate(byte toSend)
+ {
+ CheckOnline();
+ if (!PInvoke.TransmitCommChar(_hPort, new CHAR(toSend))) ThrowException("Transmission failure");
+ }
+
+ ///
+ /// Gets the status of the modem control input signals.
+ ///
+ /// Modem status object
+ /*protected ModemStatus GetModemStatus()
+ {
+ CheckOnline();
+ if (!PInvoke.GetCommModemStatus(_hPort, out var f)) ThrowException("Unexpected failure");
+ return new ModemStatus(f);
+ }
+ */
+
+ ///
+ /// Get the status of the queues
+ ///
+ /// Queue status object
+ /*protected QueueStatus GetQueueStatus()
+ {
+ COMSTAT cs;
+ COMMPROP cp;
+ uint er;
+
+ CheckOnline();
+ if (!PInvoke.ClearCommError(_hPort, out er, out cs)) ThrowException("Unexpected failure");
+ if (!PInvoke.GetCommProperties(_hPort, out cp)) ThrowException("Unexpected failure");
+ return new QueueStatus(cs.Flags, cs.cbInQue, cs.cbOutQue, cp.dwCurrentRxQueue, cp.dwCurrentTxQueue);
+ }*/
+
+ ///
+ /// Override this to provide processing after the port is opened (i.e. to configure remote
+ /// device or just check presence).
+ ///
+ /// false to close the port again
+ protected virtual bool AfterOpen()
+ {
+ return true;
+ }
+
+ ///
+ /// Override this to provide processing prior to port closure.
+ ///
+ /// True if closing due to an error
+ protected virtual void BeforeClose(bool error)
+ {
+ }
+
+ public event Action DataReceived;
+
+ ///
+ /// Override this to process received bytes.
+ ///
+ /// The byte that was received
+ protected void OnRxChar(byte ch)
+ {
+ DataReceived?.Invoke(ch);
+ }
+
+ ///
+ /// Override this to take action when transmission is complete (i.e. all bytes have actually
+ /// been sent, not just queued).
+ ///
+ protected virtual void OnTxDone()
+ {
+ }
+
+ ///
+ /// Override this to take action when a break condition is detected on the input line.
+ ///
+ protected virtual void OnBreak()
+ {
+ }
+
+ ///
+ /// Override this to take action when a ring condition is signaled by an attached modem.
+ ///
+ protected virtual void OnRing()
+ {
+ }
+
+ ///
+ /// Override this to take action when one or more modem status inputs change state
+ ///
+ /// The status inputs that have changed state
+ /// The state of the status inputs
+ protected virtual void OnStatusChange(ModemStatus mask, ModemStatus state)
+ {
+ }
+
+ ///
+ /// Override this to take action when the reception thread closes due to an exception being thrown.
+ ///
+ /// The exception which was thrown
+ protected virtual void OnRxException(Exception e)
+ {
+ }
+
+ private unsafe void ReceiveThread()
+ {
+ var buf = new byte[1];
+
+ var sg = new AutoResetEvent(false);
+ var ov = new NativeOverlapped
+ {
+ EventHandle = sg.SafeWaitHandle.DangerousGetHandle()
+ };
+
+ COMM_EVENT_MASK eventMask = 0;
+
+ try
+ {
+ while (true)
+ {
+ if (!PInvoke.SetCommMask(
+ _hPort,
+ COMM_EVENT_MASK.EV_RXCHAR |
+ COMM_EVENT_MASK.EV_TXEMPTY |
+ COMM_EVENT_MASK.EV_CTS |
+ COMM_EVENT_MASK.EV_DSR |
+ COMM_EVENT_MASK.EV_BREAK |
+ COMM_EVENT_MASK.EV_RLSD |
+ COMM_EVENT_MASK.EV_RING |
+ COMM_EVENT_MASK.EV_ERR)
+ )
+ throw new CommPortException("IO Error [001]");
+
+ if (!PInvoke.WaitCommEvent(_hPort, ref eventMask, &ov))
+ {
+ if (Marshal.GetLastWin32Error() == (int)WIN32_ERROR.ERROR_IO_PENDING)
+ sg.WaitOne();
+ else
+ throw new CommPortException("IO Error [002]");
+ }
+
+ if ((eventMask & COMM_EVENT_MASK.EV_ERR) != 0)
+ {
+ CLEAR_COMM_ERROR_FLAGS errs;
+
+ if (PInvoke.ClearCommError(_hPort, &errs, null))
+ {
+ var s = new StringBuilder("UART Error: ", 40);
+ if ((errs & CLEAR_COMM_ERROR_FLAGS.CE_FRAME) != 0) s = s.Append("Framing,");
+ if ((errs & CLEAR_COMM_ERROR_FLAGS.CE_BREAK) != 0) s = s.Append("Break,");
+ if ((errs & CLEAR_COMM_ERROR_FLAGS.CE_OVERRUN) != 0) s = s.Append("Overrun,");
+ if ((errs & CLEAR_COMM_ERROR_FLAGS.CE_RXOVER) != 0) s = s.Append("Receive Overflow,");
+ if ((errs & CLEAR_COMM_ERROR_FLAGS.CE_RXPARITY) != 0) s = s.Append("Parity,");
+
+ s.Length = s.Length - 1;
+
+ throw new CommPortException(s.ToString());
+ }
+
+ throw new CommPortException("IO Error [003]");
+ }
+
+ if ((eventMask & COMM_EVENT_MASK.EV_RXCHAR) != 0)
+ {
+ uint gotBytes;
+ do
+ {
+ fixed (byte* ptrBuffer = buf)
+ {
+ if (!PInvoke.ReadFile(_hPort, ptrBuffer, 1, &gotBytes, &ov))
+ {
+ if (Marshal.GetLastWin32Error() == (int)WIN32_ERROR.ERROR_IO_PENDING)
+ {
+ PInvoke.CancelIo(_hPort);
+ gotBytes = 0;
+ }
+ else
+ {
+ throw new CommPortException("IO Error [004]");
+ }
+ }
+ }
+
+ if (gotBytes == 1) OnRxChar(buf[0]);
+ } while (gotBytes > 0);
+ }
+
+ if ((eventMask & COMM_EVENT_MASK.EV_TXEMPTY) != 0) OnTxDone();
+ if ((eventMask & COMM_EVENT_MASK.EV_BREAK) != 0) OnBreak();
+
+ uint i = 0;
+
+ if ((eventMask & COMM_EVENT_MASK.EV_CTS) != 0) i |= (uint)MODEM_STATUS_FLAGS.MS_CTS_ON;
+ if ((eventMask & COMM_EVENT_MASK.EV_DSR) != 0) i |= (uint)MODEM_STATUS_FLAGS.MS_DSR_ON;
+ if ((eventMask & COMM_EVENT_MASK.EV_RLSD) != 0) i |= (uint)MODEM_STATUS_FLAGS.MS_RLSD_ON;
+ if ((eventMask & COMM_EVENT_MASK.EV_RING) != 0) i |= (uint)MODEM_STATUS_FLAGS.MS_RING_ON;
+
+ if (i != 0)
+ if (!PInvoke.GetCommModemStatus(_hPort, out var f))
+ throw new CommPortException("IO Error [005]");
+ // TODO: fix me! OnStatusChange(new ModemStatus(i), new ModemStatus(f));
+ }
+ }
+ catch (Exception e)
+ {
+ if (e is not ThreadAbortException)
+ {
+ _rxException = e;
+ OnRxException(e);
+ }
+ }
+ }
+
+ private bool CheckOnline()
+ {
+ if (_rxException != null && !_rxExceptionReported)
+ {
+ _rxExceptionReported = true;
+ ThrowException("rx");
+ }
+
+ if (_online)
+ {
+ uint f;
+ if (PInvoke.GetHandleInformation(_hPort, out f)) return true;
+ ThrowException("Offline");
+ return false;
+ }
+
+ if (_auto)
+ if (Open())
+ return true;
+ ThrowException("Offline");
+ return false;
+ }
+
+ #region Private fields
+
+ private readonly ManualResetEvent _writeEvent = new(false);
+ private bool _auto;
+ private bool _checkSends = true;
+
+ private Handshake _handShake;
+ private SafeHandle _hPort;
+ private bool _online;
+ private NativeOverlapped _writeOverlapped;
+ private Exception _rxException;
+ private bool _rxExceptionReported;
+ private Thread _rxThread;
+ private int _stateBrk = 2;
+ private int _stateDtr = 2;
+ private int _stateRts = 2;
+ private int _writeCount;
+
+ #endregion
+
+ #region Public properties
+
+ ///
+ /// Class constructor
+ ///
+ public SerialPort(string portName)
+ {
+ PortName = portName;
+ }
+
+ ///
+ ///
+ /// Class constructor
+ ///
+ public SerialPort(string portName, int baudRate) : this(portName)
+ {
+ BaudRate = baudRate;
+ }
+
+ ///
+ /// If true, the port will automatically re-open on next send if it was previously closed due
+ /// to an error (default: false)
+ ///
+ [UsedImplicitly]
+ public bool AutoReopen { get; set; }
+
+ ///
+ /// Baud Rate (default: 115200)
+ ///
+ /// Unsupported rates will throw "Bad settings".
+ [UsedImplicitly]
+ public int BaudRate { get; set; } = 115200;
+
+ ///
+ /// If true, subsequent Send commands wait for completion of earlier ones enabling the results
+ /// to be checked. If false, errors, including timeouts, may not be detected, but performance
+ /// may be better.
+ ///
+ [UsedImplicitly]
+ public bool CheckAllSends { get; set; } = true;
+
+ ///
+ /// Number of databits 1..8 (default: 8) unsupported values will throw "Bad settings"
+ ///
+ [UsedImplicitly]
+ public int DataBits { get; set; } = 8;
+
+ ///
+ /// The parity checking scheme (default: none)
+ ///
+ [UsedImplicitly]
+ public Parity Parity { get; set; } = Parity.None;
+
+ ///
+ /// If true, Xon and Xoff characters are sent to control the data flow from the remote station (default: false)
+ ///
+ [UsedImplicitly]
+ public bool RxFlowX { get; set; }
+
+ ///
+ /// If true, received characters are ignored unless DSR is asserted by the remote station (default: false)
+ ///
+ [UsedImplicitly]
+ public bool RxGateDsr { get; set; }
+
+ ///
+ /// The number of free bytes in the reception queue at which flow is disabled (default: 2048)
+ ///
+ [UsedImplicitly]
+ public int RxHighWater { get; set; } = 2048;
+
+ ///
+ /// The number of bytes in the reception queue at which flow is re-enabled (default: 512)
+ ///
+ [UsedImplicitly]
+ public int RxLowWater { get; set; } = 512;
+
+ ///
+ /// Requested size for receive queue (default: 0 = use operating system default)
+ ///
+ [UsedImplicitly]
+ public int RxQueue { get; set; }
+
+ ///
+ /// Constant. Max time for Send in ms = (Multiplier * Characters) + Constant (default: 0)
+ ///
+ [UsedImplicitly]
+ public int SendTimeoutConstant { get; set; }
+
+ ///
+ /// Multiplier. Max time for Send in ms = (Multiplier * Characters) + Constant
+ /// (default: 0 = No timeout)
+ ///
+ [UsedImplicitly]
+ public int SendTimeoutMultiplier { get; set; }
+
+ ///
+ /// Number of stop bits (default: one)
+ ///
+ [UsedImplicitly]
+ public StopBits StopBits { get; set; } = StopBits.One;
+
+ ///
+ /// If true, transmission is halted unless CTS is asserted by the remote station (default: false)
+ ///
+ [UsedImplicitly]
+ public bool TxFlowCts { get; set; }
+
+ ///
+ /// If true, transmission is halted unless DSR is asserted by the remote station (default: false)
+ ///
+ [UsedImplicitly]
+ public bool TxFlowDsr { get; set; }
+
+ ///
+ /// If true, transmission is halted when Xoff is received and restarted when Xon is received (default: false)
+ ///
+ [UsedImplicitly]
+ public bool TxFlowX { get; set; }
+
+ ///
+ /// Requested size for transmit queue (default: 0 = use operating system default)
+ ///
+ [UsedImplicitly]
+ public int TxQueue { get; set; }
+
+ ///
+ /// If false, transmission is suspended when this station has sent Xoff to the remote station (default: true)
+ /// Set false if the remote station treats any character as an Xon.
+ ///
+ [UsedImplicitly]
+ public bool TxWhenRxXoff { get; set; } = true;
+
+ ///
+ /// Specidies the use to which the DTR output is put (default: none)
+ ///
+ [UsedImplicitly]
+ public HsOutput UseDtr { get; set; } = HsOutput.None;
+
+ ///
+ /// Specifies the use to which the RTS output is put (default: none)
+ ///
+ [UsedImplicitly]
+ public HsOutput UseRts { get; set; } = HsOutput.None;
+
+ ///
+ /// The character used to signal Xoff for X flow control (default: DC3)
+ ///
+ [UsedImplicitly]
+ public ASCII XoffChar { get; set; } = ASCII.DC3;
+
+ ///
+ /// The character used to signal Xon for X flow control (default: DC1)
+ ///
+ [UsedImplicitly]
+ public ASCII XonChar { get; set; } = ASCII.DC1;
+
+ ///
+ /// True if online.
+ ///
+ [UsedImplicitly]
+ public bool Online => _online && CheckOnline();
+
+ ///
+ /// True if the RTS pin is controllable via the RTS property
+ ///
+ [UsedImplicitly]
+ protected bool RtSavailable => _stateRts < 2;
+
+ ///
+ /// Set the state of the RTS modem control output
+ ///
+ protected bool Rts
+ {
+ set
+ {
+ if (_stateRts > 1) return;
+ CheckOnline();
+ if (value)
+ {
+ if (PInvoke.EscapeCommFunction(_hPort, ESCAPE_COMM_FUNCTION.SETRTS))
+ _stateRts = 1;
+ else
+ ThrowException("Unexpected Failure");
+ }
+ else
+ {
+ if (PInvoke.EscapeCommFunction(_hPort, ESCAPE_COMM_FUNCTION.CLRRTS))
+ _stateRts = 1;
+ else
+ ThrowException("Unexpected Failure");
+ }
+ }
+ get => _stateRts == 1;
+ }
+
+ ///
+ /// True if the DTR pin is controllable via the DTR property
+ ///
+ protected bool DtrAvailable => _stateDtr < 2;
+
+ ///
+ /// The state of the DTR modem control output
+ ///
+ protected bool Dtr
+ {
+ set
+ {
+ if (_stateDtr > 1) return;
+ CheckOnline();
+ if (value)
+ {
+ if (PInvoke.EscapeCommFunction(_hPort, ESCAPE_COMM_FUNCTION.SETDTR))
+ _stateDtr = 1;
+ else
+ ThrowException("Unexpected Failure");
+ }
+ else
+ {
+ if (PInvoke.EscapeCommFunction(_hPort, ESCAPE_COMM_FUNCTION.CLRDTR))
+ _stateDtr = 0;
+ else
+ ThrowException("Unexpected Failure");
+ }
+ }
+ get => _stateDtr == 1;
+ }
+
+ ///
+ /// Assert or remove a break condition from the transmission line
+ ///
+ protected bool Break
+ {
+ set
+ {
+ if (_stateBrk > 1) return;
+ CheckOnline();
+ if (value)
+ {
+ if (PInvoke.EscapeCommFunction(_hPort, ESCAPE_COMM_FUNCTION.SETBREAK))
+ _stateBrk = 0;
+ else
+ ThrowException("Unexpected Failure");
+ }
+ else
+ {
+ if (PInvoke.EscapeCommFunction(_hPort, ESCAPE_COMM_FUNCTION.CLRBREAK))
+ _stateBrk = 0;
+ else
+ ThrowException("Unexpected Failure");
+ }
+ }
+ get => _stateBrk == 1;
+ }
+
+
+ ///
+ /// Port Name
+ ///
+ [UsedImplicitly]
+ public string PortName { get; set; }
+
+ public Handshake Handshake
+ {
+ get => _handShake;
+ set
+ {
+ _handShake = value;
+ switch (_handShake)
+ {
+ case Handshake.None:
+ TxFlowCts = false;
+ TxFlowDsr = false;
+ TxFlowX = false;
+ RxFlowX = false;
+ UseRts = HsOutput.Online;
+ UseDtr = HsOutput.Online;
+ TxWhenRxXoff = true;
+ RxGateDsr = false;
+ break;
+ case Handshake.XonXoff:
+ TxFlowCts = false;
+ TxFlowDsr = false;
+ TxFlowX = true;
+ RxFlowX = true;
+ UseRts = HsOutput.Online;
+ UseDtr = HsOutput.Online;
+ TxWhenRxXoff = true;
+ RxGateDsr = false;
+ XonChar = ASCII.DC1;
+ XoffChar = ASCII.DC3;
+ break;
+ case Handshake.CtsRts:
+ TxFlowCts = true;
+ TxFlowDsr = false;
+ TxFlowX = false;
+ RxFlowX = false;
+ UseRts = HsOutput.Handshake;
+ UseDtr = HsOutput.Online;
+ TxWhenRxXoff = true;
+ RxGateDsr = false;
+ break;
+ case Handshake.DsrDtr:
+ TxFlowCts = false;
+ TxFlowDsr = true;
+ TxFlowX = false;
+ RxFlowX = false;
+ UseRts = HsOutput.Online;
+ UseDtr = HsOutput.Handshake;
+ TxWhenRxXoff = true;
+ RxGateDsr = false;
+ break;
+ }
+ }
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/PInvokeSerialPort/StopBits.cs b/Nefarius.Peripherals.SerialPort/StopBits.cs
old mode 100755
new mode 100644
similarity index 92%
rename from PInvokeSerialPort/StopBits.cs
rename to Nefarius.Peripherals.SerialPort/StopBits.cs
index cb72f33..f59b705
--- a/PInvokeSerialPort/StopBits.cs
+++ b/Nefarius.Peripherals.SerialPort/StopBits.cs
@@ -1,4 +1,4 @@
-namespace PInvokeSerialPort
+namespace Nefarius.Peripherals.SerialPort
{
///
/// Stop bit settings
diff --git a/Nefarius.Peripherals.SerialPort/Util.cs b/Nefarius.Peripherals.SerialPort/Util.cs
new file mode 100644
index 0000000..c0f22b0
--- /dev/null
+++ b/Nefarius.Peripherals.SerialPort/Util.cs
@@ -0,0 +1,23 @@
+using Windows.Win32.Devices.Communication;
+
+namespace Nefarius.Peripherals.SerialPort;
+
+internal static class DCBExtensions
+{
+ public static void Init(this DCB dcb, bool parity, bool outCts, bool outDsr, int dtr, bool inDsr, bool txc,
+ bool xOut,
+ bool xIn, int rts)
+ {
+ dcb.DCBlength = 28;
+ dcb._bitfield = 0x8001;
+ if (parity) dcb._bitfield |= 0x0002;
+ if (outCts) dcb._bitfield |= 0x0004;
+ if (outDsr) dcb._bitfield |= 0x0008;
+ dcb._bitfield |= (uint)((dtr & 0x0003) << 4);
+ if (inDsr) dcb._bitfield |= 0x0040;
+ if (txc) dcb._bitfield |= 0x0080;
+ if (xOut) dcb._bitfield |= 0x0100;
+ if (xIn) dcb._bitfield |= 0x0200;
+ dcb._bitfield |= (uint)((rts & 0x0003) << 12);
+ }
+}
\ No newline at end of file
diff --git a/Nefarius.Peripherals.SerialPort/Win32PInvoke/COMSTAT.cs b/Nefarius.Peripherals.SerialPort/Win32PInvoke/COMSTAT.cs
new file mode 100644
index 0000000..693bae2
--- /dev/null
+++ b/Nefarius.Peripherals.SerialPort/Win32PInvoke/COMSTAT.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Nefarius.Peripherals.SerialPort.Win32PInvoke;
+
+[StructLayout(LayoutKind.Sequential)]
+internal struct COMSTAT
+{
+ internal const uint fCtsHold = 0x1;
+ internal const uint fDsrHold = 0x2;
+ internal const uint fRlsdHold = 0x4;
+ internal const uint fXoffHold = 0x8;
+ internal const uint fXoffSent = 0x10;
+ internal const uint fEof = 0x20;
+ internal const uint fTxim = 0x40;
+ internal UInt32 Flags;
+ internal UInt32 cbInQue;
+ internal UInt32 cbOutQue;
+}
\ No newline at end of file
diff --git a/PInvokeSerialPort.Sample/PInvokeSerialPort.Sample.csproj b/PInvokeSerialPort.Sample/PInvokeSerialPort.Sample.csproj
index e72e1cf..3582d0a 100755
--- a/PInvokeSerialPort.Sample/PInvokeSerialPort.Sample.csproj
+++ b/PInvokeSerialPort.Sample/PInvokeSerialPort.Sample.csproj
@@ -50,7 +50,7 @@
-
+
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}
PInvokeSerialPort
diff --git a/PInvokeSerialPort.Test/PInvokeSerialPort.Test.csproj b/PInvokeSerialPort.Test/PInvokeSerialPort.Test.csproj
index 50a49d4..42f1753 100755
--- a/PInvokeSerialPort.Test/PInvokeSerialPort.Test.csproj
+++ b/PInvokeSerialPort.Test/PInvokeSerialPort.Test.csproj
@@ -53,7 +53,7 @@
-
+
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}
PInvokeSerialPort
diff --git a/PInvokeSerialPort.Test/PInvokeSerialPortTest.cs b/PInvokeSerialPort.Test/PInvokeSerialPortTest.cs
index e1553f5..c0c607f 100755
--- a/PInvokeSerialPort.Test/PInvokeSerialPortTest.cs
+++ b/PInvokeSerialPort.Test/PInvokeSerialPortTest.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO.Ports;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading;
diff --git a/PInvokeSerialPort/ASCII.cs b/PInvokeSerialPort/ASCII.cs
deleted file mode 100755
index 102eb98..0000000
--- a/PInvokeSerialPort/ASCII.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace PInvokeSerialPort
-{
- ///
- /// Byte type with enumeration constants for ASCII control codes.
- ///
- public enum ASCII : byte
- {
- NULL = 0x00, SOH = 0x01, STH = 0x02, ETX = 0x03, EOT = 0x04, ENQ = 0x05, ACK = 0x06, BELL = 0x07,
- BS = 0x08, HT = 0x09, LF = 0x0A, VT = 0x0B, FF = 0x0C, CR = 0x0D, SO = 0x0E, SI = 0x0F, DC1 = 0x11,
- DC2 = 0x12, DC3 = 0x13, DC4 = 0x14, NAK = 0x15, SYN = 0x16, ETB = 0x17, CAN = 0x18, EM = 0x19,
- SUB = 0x1A, ESC = 0x1B, FS = 0x1C, GS = 0x1D, RS = 0x1E, US = 0x1F, SP = 0x20, DEL = 0x7F
- }
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/CommPortException.cs b/PInvokeSerialPort/CommPortException.cs
deleted file mode 100755
index b916f0c..0000000
--- a/PInvokeSerialPort/CommPortException.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-
-namespace PInvokeSerialPort
-{
- ///
- /// Exception used for all errors.
- ///
- public class CommPortException : ApplicationException
- {
- ///
- /// Constructor for raising direct exceptions
- ///
- /// Description of error
- public CommPortException(string desc) : base(desc) { }
-
- ///
- /// Constructor for re-raising exceptions from receive thread
- ///
- /// Inner exception raised on receive thread
- public CommPortException(Exception e) : base("Receive Thread Exception", e) { }
- }
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/Handshake.cs b/PInvokeSerialPort/Handshake.cs
deleted file mode 100755
index 6d76eac..0000000
--- a/PInvokeSerialPort/Handshake.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-namespace PInvokeSerialPort
-{
- ///
- /// Standard handshake methods
- ///
- public enum Handshake
- {
- ///
- /// No handshaking
- ///
- None,
- ///
- /// Software handshaking using Xon / Xoff
- ///
- XonXoff,
- ///
- /// Hardware handshaking using CTS / RTS
- ///
- CtsRts,
- ///
- /// Hardware handshaking using DSR / DTR
- ///
- DsrDtr
- }
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/HsOutput.cs b/PInvokeSerialPort/HsOutput.cs
deleted file mode 100755
index 3d2e742..0000000
--- a/PInvokeSerialPort/HsOutput.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-namespace PInvokeSerialPort
-{
- ///
- /// Uses for RTS or DTR pins
- ///
- public enum HsOutput
- {
- ///
- /// Pin is asserted when this station is able to receive data.
- ///
- Handshake = 2,
- ///
- /// Pin is asserted when this station is transmitting data (RTS on NT, 2000 or XP only).
- ///
- Gate = 3,
- ///
- /// Pin is asserted when this station is online (port is open).
- ///
- Online = 1,
- ///
- /// Pin is never asserted.
- ///
- None = 0
- };
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/ModemStatus.cs b/PInvokeSerialPort/ModemStatus.cs
deleted file mode 100755
index 0daf900..0000000
--- a/PInvokeSerialPort/ModemStatus.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using PInvokeSerialPort.Win32PInvoke;
-
-namespace PInvokeSerialPort
-{
- ///
- /// Represents the status of the modem control input signals.
- ///
- public struct ModemStatus
- {
- private readonly uint _status;
- internal ModemStatus(uint val) { _status = val; }
- ///
- /// Condition of the Clear To Send signal.
- ///
- public bool Cts { get { return ((_status & Win32Com.MS_CTS_ON) != 0); } }
- ///
- /// Condition of the Data Set Ready signal.
- ///
- public bool Dsr { get { return ((_status & Win32Com.MS_DSR_ON) != 0); } }
- ///
- /// Condition of the Receive Line Status Detection signal.
- ///
- public bool Rlsd { get { return ((_status & Win32Com.MS_RLSD_ON) != 0); } }
- ///
- /// Condition of the Ring Detection signal.
- ///
- public bool Ring { get { return ((_status & Win32Com.MS_RING_ON) != 0); } }
- }
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/SerialPort.cs b/PInvokeSerialPort/SerialPort.cs
deleted file mode 100755
index 08b551b..0000000
--- a/PInvokeSerialPort/SerialPort.cs
+++ /dev/null
@@ -1,805 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading;
-using PInvokeSerialPort.Win32PInvoke;
-
-namespace PInvokeSerialPort
-{
- ///
- /// PInvokeSerialPort main class.
- /// Borrowed from http://msdn.microsoft.com/en-us/magazine/cc301786.aspx ;)
- ///
- public class SerialPort : IDisposable
- {
- #region Private fields
-
- private readonly ManualResetEvent _writeEvent = new ManualResetEvent(false);
- private bool _auto;
- private bool _checkSends = true;
-
- private Handshake _handShake;
- private IntPtr _hPort;
- private bool _online;
- private IntPtr _ptrUwo = IntPtr.Zero;
- private Exception _rxException;
- private bool _rxExceptionReported;
- private Thread _rxThread;
- private int _stateBrk = 2;
- private int _stateDtr = 2;
- private int _stateRts = 2;
- private int _writeCount;
-
- #endregion
-
- #region Public properties
-
- ///
- /// Class constructor
- ///
- public SerialPort(string portName)
- {
- PortName = portName;
- }
-
- ///
- ///
- /// Class constructor
- ///
- public SerialPort(string portName, int baudRate) : this(portName)
- {
- BaudRate = baudRate;
- }
-
- ///
- /// If true, the port will automatically re-open on next send if it was previously closed due
- /// to an error (default: false)
- ///
- public bool AutoReopen { get; set; }
-
- ///
- /// Baud Rate (default: 115200)
- ///
- /// Unsupported rates will throw "Bad settings".
- public int BaudRate { get; set; } = 115200;
-
- ///
- /// If true, subsequent Send commands wait for completion of earlier ones enabling the results
- /// to be checked. If false, errors, including timeouts, may not be detected, but performance
- /// may be better.
- ///
- public bool CheckAllSends { get; set; } = true;
-
- ///
- /// Number of databits 1..8 (default: 8) unsupported values will throw "Bad settings"
- ///
- public int DataBits { get; set; } = 8;
-
- ///
- /// The parity checking scheme (default: none)
- ///
- public Parity Parity { get; set; } = Parity.None;
-
- ///
- /// If true, Xon and Xoff characters are sent to control the data flow from the remote station (default: false)
- ///
- public bool RxFlowX { get; set; }
-
- ///
- /// If true, received characters are ignored unless DSR is asserted by the remote station (default: false)
- ///
- public bool RxGateDsr { get; set; }
-
- ///
- /// The number of free bytes in the reception queue at which flow is disabled (default: 2048)
- ///
- public int RxHighWater { get; set; } = 2048;
-
- ///
- /// The number of bytes in the reception queue at which flow is re-enabled (default: 512)
- ///
- public int RxLowWater { get; set; } = 512;
-
- ///
- /// Requested size for receive queue (default: 0 = use operating system default)
- ///
- public int RxQueue { get; set; }
-
- ///
- /// Constant. Max time for Send in ms = (Multiplier * Characters) + Constant (default: 0)
- ///
- public int SendTimeoutConstant { get; set; }
-
- ///
- /// Multiplier. Max time for Send in ms = (Multiplier * Characters) + Constant
- /// (default: 0 = No timeout)
- ///
- public int SendTimeoutMultiplier { get; set; }
-
- ///
- /// Number of stop bits (default: one)
- ///
- public StopBits StopBits { get; set; } = StopBits.One;
-
- ///
- /// If true, transmission is halted unless CTS is asserted by the remote station (default: false)
- ///
- public bool TxFlowCts { get; set; }
-
- ///
- /// If true, transmission is halted unless DSR is asserted by the remote station (default: false)
- ///
- public bool TxFlowDsr { get; set; }
-
- ///
- /// If true, transmission is halted when Xoff is received and restarted when Xon is received (default: false)
- ///
- public bool TxFlowX { get; set; }
-
- ///
- /// Requested size for transmit queue (default: 0 = use operating system default)
- ///
- public int TxQueue { get; set; }
-
- ///
- /// If false, transmission is suspended when this station has sent Xoff to the remote station (default: true)
- /// Set false if the remote station treats any character as an Xon.
- ///
- public bool TxWhenRxXoff { get; set; } = true;
-
- ///
- /// Specidies the use to which the DTR output is put (default: none)
- ///
- public HsOutput UseDtr { get; set; } = HsOutput.None;
-
- ///
- /// Specifies the use to which the RTS output is put (default: none)
- ///
- public HsOutput UseRts { get; set; } = HsOutput.None;
-
- ///
- /// The character used to signal Xoff for X flow control (default: DC3)
- ///
- public ASCII XoffChar { get; set; } = ASCII.DC3;
-
- ///
- /// The character used to signal Xon for X flow control (default: DC1)
- ///
- public ASCII XonChar { get; set; } = ASCII.DC1;
-
- ///
- /// True if online.
- ///
- public bool Online => _online && CheckOnline();
-
- ///
- /// True if the RTS pin is controllable via the RTS property
- ///
- protected bool RtSavailable => _stateRts < 2;
-
- ///
- /// Set the state of the RTS modem control output
- ///
- protected bool Rts
- {
- set
- {
- if (_stateRts > 1) return;
- CheckOnline();
- if (value)
- {
- if (Win32Com.EscapeCommFunction(_hPort, Win32Com.SETRTS))
- _stateRts = 1;
- else
- ThrowException("Unexpected Failure");
- }
- else
- {
- if (Win32Com.EscapeCommFunction(_hPort, Win32Com.CLRRTS))
- _stateRts = 1;
- else
- ThrowException("Unexpected Failure");
- }
- }
- get => _stateRts == 1;
- }
-
- ///
- /// True if the DTR pin is controllable via the DTR property
- ///
- protected bool DtrAvailable => _stateDtr < 2;
-
- ///
- /// The state of the DTR modem control output
- ///
- protected bool Dtr
- {
- set
- {
- if (_stateDtr > 1) return;
- CheckOnline();
- if (value)
- {
- if (Win32Com.EscapeCommFunction(_hPort, Win32Com.SETDTR))
- _stateDtr = 1;
- else
- ThrowException("Unexpected Failure");
- }
- else
- {
- if (Win32Com.EscapeCommFunction(_hPort, Win32Com.CLRDTR))
- _stateDtr = 0;
- else
- ThrowException("Unexpected Failure");
- }
- }
- get => _stateDtr == 1;
- }
-
- ///
- /// Assert or remove a break condition from the transmission line
- ///
- protected bool Break
- {
- set
- {
- if (_stateBrk > 1) return;
- CheckOnline();
- if (value)
- {
- if (Win32Com.EscapeCommFunction(_hPort, Win32Com.SETBREAK))
- _stateBrk = 0;
- else
- ThrowException("Unexpected Failure");
- }
- else
- {
- if (Win32Com.EscapeCommFunction(_hPort, Win32Com.CLRBREAK))
- _stateBrk = 0;
- else
- ThrowException("Unexpected Failure");
- }
- }
- get => _stateBrk == 1;
- }
-
-
- ///
- /// Port Name
- ///
- public string PortName { get; set; }
-
- public Handshake Handshake
- {
- get => _handShake;
- set
- {
- _handShake = value;
- switch (_handShake)
- {
- case Handshake.None:
- TxFlowCts = false;
- TxFlowDsr = false;
- TxFlowX = false;
- RxFlowX = false;
- UseRts = HsOutput.Online;
- UseDtr = HsOutput.Online;
- TxWhenRxXoff = true;
- RxGateDsr = false;
- break;
- case Handshake.XonXoff:
- TxFlowCts = false;
- TxFlowDsr = false;
- TxFlowX = true;
- RxFlowX = true;
- UseRts = HsOutput.Online;
- UseDtr = HsOutput.Online;
- TxWhenRxXoff = true;
- RxGateDsr = false;
- XonChar = ASCII.DC1;
- XoffChar = ASCII.DC3;
- break;
- case Handshake.CtsRts:
- TxFlowCts = true;
- TxFlowDsr = false;
- TxFlowX = false;
- RxFlowX = false;
- UseRts = HsOutput.Handshake;
- UseDtr = HsOutput.Online;
- TxWhenRxXoff = true;
- RxGateDsr = false;
- break;
- case Handshake.DsrDtr:
- TxFlowCts = false;
- TxFlowDsr = true;
- TxFlowX = false;
- RxFlowX = false;
- UseRts = HsOutput.Online;
- UseDtr = HsOutput.Handshake;
- TxWhenRxXoff = true;
- RxGateDsr = false;
- break;
- }
- }
- }
-
- #endregion
-
- ///
- ///
- /// For IDisposable
- ///
- public void Dispose()
- {
- Close();
- }
-
- ///
- /// Opens the com port and configures it with the required settings
- ///
- /// false if the port could not be opened
- public bool Open()
- {
- var portDcb = new DCB();
- var commTimeouts = new COMMTIMEOUTS();
- var wo = new OVERLAPPED();
-
- if (_online) return false;
-
- _hPort = Win32Com.CreateFile(PortName, Win32Com.GENERIC_READ | Win32Com.GENERIC_WRITE, 0, IntPtr.Zero,
- Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero);
- if (_hPort == (IntPtr) Win32Com.INVALID_HANDLE_VALUE)
- {
- if (Marshal.GetLastWin32Error() == Win32Com.ERROR_ACCESS_DENIED) return false;
- throw new CommPortException("Port Open Failure");
- }
-
- _online = true;
-
- commTimeouts.ReadIntervalTimeout = 0;
- commTimeouts.ReadTotalTimeoutConstant = 0;
- commTimeouts.ReadTotalTimeoutMultiplier = 0;
- commTimeouts.WriteTotalTimeoutConstant = SendTimeoutConstant;
- commTimeouts.WriteTotalTimeoutMultiplier = SendTimeoutMultiplier;
- portDcb.Init(Parity == Parity.Odd || Parity == Parity.Even, TxFlowCts, TxFlowDsr,
- (int) UseDtr, RxGateDsr, !TxWhenRxXoff, TxFlowX, RxFlowX, (int) UseRts);
- portDcb.BaudRate = BaudRate;
- portDcb.ByteSize = (byte) DataBits;
- portDcb.Parity = (byte) Parity;
- portDcb.StopBits = (byte) StopBits;
- portDcb.XoffChar = (byte) XoffChar;
- portDcb.XonChar = (byte) XonChar;
- portDcb.XoffLim = (short) RxHighWater;
- portDcb.XonLim = (short) RxLowWater;
- if (RxQueue != 0 || TxQueue != 0)
- if (!Win32Com.SetupComm(_hPort, (uint) RxQueue, (uint) TxQueue))
- ThrowException("Bad queue settings");
- if (!Win32Com.SetCommState(_hPort, ref portDcb)) ThrowException("Bad com settings");
- if (!Win32Com.SetCommTimeouts(_hPort, ref commTimeouts)) ThrowException("Bad timeout settings");
-
- _stateBrk = 0;
- switch (UseDtr)
- {
- case HsOutput.None:
- _stateDtr = 0;
- break;
- case HsOutput.Online:
- _stateDtr = 1;
- break;
- }
-
- switch (UseRts)
- {
- case HsOutput.None:
- _stateRts = 0;
- break;
- case HsOutput.Online:
- _stateRts = 1;
- break;
- }
-
- _checkSends = CheckAllSends;
- wo.Offset = 0;
- wo.OffsetHigh = 0;
- wo.hEvent = _checkSends ? _writeEvent.SafeWaitHandle.DangerousGetHandle() : IntPtr.Zero;
- _ptrUwo = Marshal.AllocHGlobal(Marshal.SizeOf(wo));
- Marshal.StructureToPtr(wo, _ptrUwo, true);
- _writeCount = 0;
-
- _rxException = null;
- _rxExceptionReported = false;
-
- // TODO: utilize Task Parallel Library here
- _rxThread = new Thread(ReceiveThread)
- {
- Name = "CommBaseRx", Priority = ThreadPriority.AboveNormal, IsBackground = true
- };
-
- _rxThread.Start();
- Thread.Sleep(1); //Give rx thread time to start. By documentation, 0 should work, but it does not!
-
- _auto = false;
- if (AfterOpen())
- {
- _auto = AutoReopen;
- return true;
- }
-
- Close();
- return false;
- }
-
- ///
- /// Closes the com port.
- ///
- public void Close()
- {
- if (_online)
- {
- _auto = false;
- BeforeClose(false);
- InternalClose();
- _rxException = null;
- }
- }
-
- private void InternalClose()
- {
- Win32Com.CancelIo(_hPort);
- if (_rxThread != null)
- {
- _rxThread.Abort();
- _rxThread = null;
- }
-
- Win32Com.CloseHandle(_hPort);
- if (_ptrUwo != IntPtr.Zero) Marshal.FreeHGlobal(_ptrUwo);
- _stateRts = 2;
- _stateDtr = 2;
- _stateBrk = 2;
- _online = false;
- }
-
- ///
- /// Destructor (just in case)
- ///
- ~SerialPort()
- {
- Close();
- }
-
- ///
- /// Block until all bytes in the queue have been transmitted.
- ///
- public void Flush()
- {
- CheckOnline();
- CheckResult();
- }
-
- ///
- /// Use this to throw exceptions in derived classes. Correctly handles threading issues
- /// and closes the port if necessary.
- ///
- /// Description of fault
- protected void ThrowException(string reason)
- {
- if (Thread.CurrentThread == _rxThread) throw new CommPortException(reason);
- if (_online)
- {
- BeforeClose(true);
- InternalClose();
- }
-
- if (_rxException == null) throw new CommPortException(reason);
- throw new CommPortException(_rxException);
- }
-
- ///
- /// Queues bytes for transmission.
- ///
- /// Array of bytes to be sent
- public void Write(byte[] toSend)
- {
- uint sent;
- CheckOnline();
- CheckResult();
- _writeCount = toSend.GetLength(0);
- if (Win32Com.WriteFile(_hPort, toSend, (uint) _writeCount, out sent, _ptrUwo))
- {
- _writeCount -= (int) sent;
- }
- else
- {
- if (Marshal.GetLastWin32Error() != Win32Com.ERROR_IO_PENDING) ThrowException("Unexpected failure");
- }
- }
-
- ///
- /// Queues string for transmission.
- ///
- /// Array of bytes to be sent
- public void Write(string toSend)
- {
- Write(new ASCIIEncoding().GetBytes(toSend));
- }
-
- ///
- /// Queues a single byte for transmission.
- ///
- /// Byte to be sent
- public void Write(byte toSend)
- {
- var b = new byte[1];
- b[0] = toSend;
- Write(b);
- }
-
- ///
- /// Queues a single char for transmission.
- ///
- /// Byte to be sent
- public void Write(char toSend)
- {
- Write(toSend.ToString());
- }
-
- ///
- /// Queues string with a new line ("\r\n") for transmission.
- ///
- /// Array of bytes to be sent
- public void WriteLine(string toSend)
- {
- Write(new ASCIIEncoding().GetBytes(toSend + Environment.NewLine));
- }
-
- private void CheckResult()
- {
- if (_writeCount <= 0) return;
- uint sent;
- if (Win32Com.GetOverlappedResult(_hPort, _ptrUwo, out sent, _checkSends))
- {
- _writeCount -= (int) sent;
- if (_writeCount != 0) ThrowException("Send Timeout");
- }
- else
- {
- if (Marshal.GetLastWin32Error() != Win32Com.ERROR_IO_PENDING) ThrowException("Unexpected failure");
- }
- }
-
- ///
- /// Sends a protocol byte immediately ahead of any queued bytes.
- ///
- /// Byte to send
- /// False if an immediate byte is already scheduled and not yet sent
- public void SendImmediate(byte tosend)
- {
- CheckOnline();
- if (!Win32Com.TransmitCommChar(_hPort, tosend)) ThrowException("Transmission failure");
- }
-
- ///
- /// Gets the status of the modem control input signals.
- ///
- /// Modem status object
- protected ModemStatus GetModemStatus()
- {
- uint f;
-
- CheckOnline();
- if (!Win32Com.GetCommModemStatus(_hPort, out f)) ThrowException("Unexpected failure");
- return new ModemStatus(f);
- }
-
-
- ///
- /// Get the status of the queues
- ///
- /// Queue status object
- protected QueueStatus GetQueueStatus()
- {
- COMSTAT cs;
- COMMPROP cp;
- uint er;
-
- CheckOnline();
- if (!Win32Com.ClearCommError(_hPort, out er, out cs)) ThrowException("Unexpected failure");
- if (!Win32Com.GetCommProperties(_hPort, out cp)) ThrowException("Unexpected failure");
- return new QueueStatus(cs.Flags, cs.cbInQue, cs.cbOutQue, cp.dwCurrentRxQueue, cp.dwCurrentTxQueue);
- }
-
- ///
- /// Override this to provide processing after the port is opened (i.e. to configure remote
- /// device or just check presence).
- ///
- /// false to close the port again
- protected virtual bool AfterOpen()
- {
- return true;
- }
-
- ///
- /// Override this to provide processing prior to port closure.
- ///
- /// True if closing due to an error
- protected virtual void BeforeClose(bool error)
- {
- }
-
- public event Action DataReceived;
-
- ///
- /// Override this to process received bytes.
- ///
- /// The byte that was received
- protected void OnRxChar(byte ch)
- {
- DataReceived?.Invoke(ch);
- }
-
- ///
- /// Override this to take action when transmission is complete (i.e. all bytes have actually
- /// been sent, not just queued).
- ///
- protected virtual void OnTxDone()
- {
- }
-
- ///
- /// Override this to take action when a break condition is detected on the input line.
- ///
- protected virtual void OnBreak()
- {
- }
-
- ///
- /// Override this to take action when a ring condition is signaled by an attached modem.
- ///
- protected virtual void OnRing()
- {
- }
-
- ///
- /// Override this to take action when one or more modem status inputs change state
- ///
- /// The status inputs that have changed state
- /// The state of the status inputs
- protected virtual void OnStatusChange(ModemStatus mask, ModemStatus state)
- {
- }
-
- ///
- /// Override this to take action when the reception thread closes due to an exception being thrown.
- ///
- /// The exception which was thrown
- protected virtual void OnRxException(Exception e)
- {
- }
-
- private void ReceiveThread()
- {
- var buf = new byte[1];
-
- var sg = new AutoResetEvent(false);
- var ov = new OVERLAPPED();
- var unmanagedOv = Marshal.AllocHGlobal(Marshal.SizeOf(ov));
- ov.Offset = 0;
- ov.OffsetHigh = 0;
- ov.hEvent = sg.SafeWaitHandle.DangerousGetHandle();
- Marshal.StructureToPtr(ov, unmanagedOv, true);
-
- uint eventMask = 0;
- var uMask = Marshal.AllocHGlobal(Marshal.SizeOf(eventMask));
-
- try
- {
- while (true)
- {
- if (!Win32Com.SetCommMask(_hPort,
- Win32Com.EV_RXCHAR | Win32Com.EV_TXEMPTY | Win32Com.EV_CTS | Win32Com.EV_DSR
- | Win32Com.EV_BREAK | Win32Com.EV_RLSD | Win32Com.EV_RING | Win32Com.EV_ERR))
- throw new CommPortException("IO Error [001]");
- Marshal.WriteInt32(uMask, 0);
- if (!Win32Com.WaitCommEvent(_hPort, uMask, unmanagedOv))
- {
- if (Marshal.GetLastWin32Error() == Win32Com.ERROR_IO_PENDING)
- sg.WaitOne();
- else
- throw new CommPortException("IO Error [002]");
- }
-
- eventMask = (uint) Marshal.ReadInt32(uMask);
- if ((eventMask & Win32Com.EV_ERR) != 0)
- {
- uint errs;
- if (Win32Com.ClearCommError(_hPort, out errs, IntPtr.Zero))
- {
- var s = new StringBuilder("UART Error: ", 40);
- if ((errs & Win32Com.CE_FRAME) != 0) s = s.Append("Framing,");
- if ((errs & Win32Com.CE_IOE) != 0) s = s.Append("IO,");
- if ((errs & Win32Com.CE_OVERRUN) != 0) s = s.Append("Overrun,");
- if ((errs & Win32Com.CE_RXOVER) != 0) s = s.Append("Receive Overflow,");
- if ((errs & Win32Com.CE_RXPARITY) != 0) s = s.Append("Parity,");
- if ((errs & Win32Com.CE_TXFULL) != 0) s = s.Append("Transmit Overflow,");
- s.Length = s.Length - 1;
- throw new CommPortException(s.ToString());
- }
-
- throw new CommPortException("IO Error [003]");
- }
-
- if ((eventMask & Win32Com.EV_RXCHAR) != 0)
- {
- uint gotbytes;
- do
- {
- if (!Win32Com.ReadFile(_hPort, buf, 1, out gotbytes, unmanagedOv))
- {
- if (Marshal.GetLastWin32Error() == Win32Com.ERROR_IO_PENDING)
- {
- Win32Com.CancelIo(_hPort);
- gotbytes = 0;
- }
- else
- {
- throw new CommPortException("IO Error [004]");
- }
- }
-
- if (gotbytes == 1) OnRxChar(buf[0]);
- } while (gotbytes > 0);
- }
-
- if ((eventMask & Win32Com.EV_TXEMPTY) != 0) OnTxDone();
- if ((eventMask & Win32Com.EV_BREAK) != 0) OnBreak();
-
- uint i = 0;
- if ((eventMask & Win32Com.EV_CTS) != 0) i |= Win32Com.MS_CTS_ON;
- if ((eventMask & Win32Com.EV_DSR) != 0) i |= Win32Com.MS_DSR_ON;
- if ((eventMask & Win32Com.EV_RLSD) != 0) i |= Win32Com.MS_RLSD_ON;
- if ((eventMask & Win32Com.EV_RING) != 0) i |= Win32Com.MS_RING_ON;
- if (i != 0)
- {
- uint f;
- if (!Win32Com.GetCommModemStatus(_hPort, out f)) throw new CommPortException("IO Error [005]");
- OnStatusChange(new ModemStatus(i), new ModemStatus(f));
- }
- }
- }
- catch (Exception e)
- {
- if (uMask != IntPtr.Zero) Marshal.FreeHGlobal(uMask);
- if (unmanagedOv != IntPtr.Zero) Marshal.FreeHGlobal(unmanagedOv);
- if (!(e is ThreadAbortException))
- {
- _rxException = e;
- OnRxException(e);
- }
- }
- }
-
- private bool CheckOnline()
- {
- if (_rxException != null && !_rxExceptionReported)
- {
- _rxExceptionReported = true;
- ThrowException("rx");
- }
-
- if (_online)
- {
- uint f;
- if (Win32Com.GetHandleInformation(_hPort, out f)) return true;
- ThrowException("Offline");
- return false;
- }
-
- if (_auto)
- if (Open())
- return true;
- ThrowException("Offline");
- return false;
- }
- }
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/Win32PInvoke/COMMPROP.cs b/PInvokeSerialPort/Win32PInvoke/COMMPROP.cs
deleted file mode 100755
index 2fa0a66..0000000
--- a/PInvokeSerialPort/Win32PInvoke/COMMPROP.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace PInvokeSerialPort.Win32PInvoke
-{
- [StructLayout(LayoutKind.Sequential)]
- internal struct COMMPROP
- {
- internal UInt16 wPacketLength;
- internal UInt16 wPacketVersion;
- internal UInt32 dwServiceMask;
- internal UInt32 dwReserved1;
- internal UInt32 dwMaxTxQueue;
- internal UInt32 dwMaxRxQueue;
- internal UInt32 dwMaxBaud;
- internal UInt32 dwProvSubType;
- internal UInt32 dwProvCapabilities;
- internal UInt32 dwSettableParams;
- internal UInt32 dwSettableBaud;
- internal UInt16 wSettableData;
- internal UInt16 wSettableStopParity;
- internal UInt32 dwCurrentTxQueue;
- internal UInt32 dwCurrentRxQueue;
- internal UInt32 dwProvSpec1;
- internal UInt32 dwProvSpec2;
- internal Byte wcProvChar;
- }
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/Win32PInvoke/COMMTIMEOUTS.cs b/PInvokeSerialPort/Win32PInvoke/COMMTIMEOUTS.cs
deleted file mode 100755
index 506c49a..0000000
--- a/PInvokeSerialPort/Win32PInvoke/COMMTIMEOUTS.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace PInvokeSerialPort.Win32PInvoke
-{
- [StructLayout(LayoutKind.Sequential)]
- internal struct COMMTIMEOUTS
- {
- internal Int32 ReadIntervalTimeout;
- internal Int32 ReadTotalTimeoutMultiplier;
- internal Int32 ReadTotalTimeoutConstant;
- internal Int32 WriteTotalTimeoutMultiplier;
- internal Int32 WriteTotalTimeoutConstant;
- }
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/Win32PInvoke/COMSTAT.cs b/PInvokeSerialPort/Win32PInvoke/COMSTAT.cs
deleted file mode 100755
index c4d5be0..0000000
--- a/PInvokeSerialPort/Win32PInvoke/COMSTAT.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace PInvokeSerialPort.Win32PInvoke
-{
- [StructLayout(LayoutKind.Sequential)]
- internal struct COMSTAT
- {
- internal const uint fCtsHold = 0x1;
- internal const uint fDsrHold = 0x2;
- internal const uint fRlsdHold = 0x4;
- internal const uint fXoffHold = 0x8;
- internal const uint fXoffSent = 0x10;
- internal const uint fEof = 0x20;
- internal const uint fTxim = 0x40;
- internal UInt32 Flags;
- internal UInt32 cbInQue;
- internal UInt32 cbOutQue;
- }
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/Win32PInvoke/DCB.cs b/PInvokeSerialPort/Win32PInvoke/DCB.cs
deleted file mode 100755
index 4ef5aba..0000000
--- a/PInvokeSerialPort/Win32PInvoke/DCB.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace PInvokeSerialPort.Win32PInvoke
-{
- [StructLayout(LayoutKind.Sequential)]
- internal struct DCB
- {
- internal Int32 DCBlength;
- internal Int32 BaudRate;
- internal Int32 PackedValues;
- internal Int16 wReserved;
- internal Int16 XonLim;
- internal Int16 XoffLim;
- internal Byte ByteSize;
- internal Byte Parity;
- internal Byte StopBits;
- internal Byte XonChar;
- internal Byte XoffChar;
- internal Byte ErrorChar;
- internal Byte EofChar;
- internal Byte EvtChar;
- internal Int16 wReserved1;
-
- internal void Init(bool parity, bool outCts, bool outDsr, int dtr, bool inDsr, bool txc, bool xOut,
- bool xIn, int rts)
- {
- DCBlength = 28; PackedValues = 0x8001;
- if (parity) PackedValues |= 0x0002;
- if (outCts) PackedValues |= 0x0004;
- if (outDsr) PackedValues |= 0x0008;
- PackedValues |= ((dtr & 0x0003) << 4);
- if (inDsr) PackedValues |= 0x0040;
- if (txc) PackedValues |= 0x0080;
- if (xOut) PackedValues |= 0x0100;
- if (xIn) PackedValues |= 0x0200;
- PackedValues |= ((rts & 0x0003) << 12);
-
- }
- }
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/Win32PInvoke/OVERLAPPED.cs b/PInvokeSerialPort/Win32PInvoke/OVERLAPPED.cs
deleted file mode 100755
index c26ff13..0000000
--- a/PInvokeSerialPort/Win32PInvoke/OVERLAPPED.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace PInvokeSerialPort.Win32PInvoke
-{
- [StructLayout(LayoutKind.Sequential)]
- internal struct OVERLAPPED
- {
- internal UIntPtr Internal;
- internal UIntPtr InternalHigh;
- internal UInt32 Offset;
- internal UInt32 OffsetHigh;
- internal IntPtr hEvent;
- }
-}
\ No newline at end of file
diff --git a/PInvokeSerialPort/Win32PInvoke/Win32Com.cs b/PInvokeSerialPort/Win32PInvoke/Win32Com.cs
deleted file mode 100755
index 029af99..0000000
--- a/PInvokeSerialPort/Win32PInvoke/Win32Com.cs
+++ /dev/null
@@ -1,155 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace PInvokeSerialPort.Win32PInvoke
-{
- internal class Win32Com
- {
- ///
- /// Opening Testing and Closing the Port Handle.
- ///
- [DllImport("kernel32.dll", SetLastError = true)]
- internal static extern IntPtr CreateFile(String lpFileName, UInt32 dwDesiredAccess, UInt32 dwShareMode,
- IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, UInt32 dwFlagsAndAttributes,
- IntPtr hTemplateFile);
-
- //Constants for errors:
- internal const UInt32 ERROR_FILE_NOT_FOUND = 2;
- internal const UInt32 ERROR_INVALID_NAME = 123;
- internal const UInt32 ERROR_ACCESS_DENIED = 5;
- internal const UInt32 ERROR_IO_PENDING = 997;
-
- //Constants for return value:
- internal const Int32 INVALID_HANDLE_VALUE = -1;
-
- //Constants for dwFlagsAndAttributes:
- internal const UInt32 FILE_FLAG_OVERLAPPED = 0x40000000;
-
- //Constants for dwCreationDisposition:
- internal const UInt32 OPEN_EXISTING = 3;
-
- //Constants for dwDesiredAccess:
- internal const UInt32 GENERIC_READ = 0x80000000;
- internal const UInt32 GENERIC_WRITE = 0x40000000;
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean CloseHandle(IntPtr hObject);
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean GetHandleInformation(IntPtr hObject, out UInt32 lpdwFlags);
-
-
- ///
- /// Manipulating the communications settings.
- ///
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean GetCommState(IntPtr hFile, ref DCB lpDCB);
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean GetCommTimeouts(IntPtr hFile, out COMMTIMEOUTS lpCommTimeouts);
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean BuildCommDCBAndTimeouts(String lpDef, ref DCB lpDCB, ref COMMTIMEOUTS lpCommTimeouts);
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean SetCommState(IntPtr hFile, [In] ref DCB lpDCB);
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean SetCommTimeouts(IntPtr hFile, [In] ref COMMTIMEOUTS lpCommTimeouts);
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean SetupComm(IntPtr hFile, UInt32 dwInQueue, UInt32 dwOutQueue);
-
- ///
- /// Reading and writing.
- ///
- [DllImport("kernel32.dll", SetLastError = true)]
- internal static extern Boolean WriteFile(IntPtr fFile, Byte[] lpBuffer, UInt32 nNumberOfBytesToWrite,
- out UInt32 lpNumberOfBytesWritten, IntPtr lpOverlapped);
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean SetCommMask(IntPtr hFile, UInt32 dwEvtMask);
-
- // Constants for dwEvtMask:
- internal const UInt32 EV_RXCHAR = 0x0001;
- internal const UInt32 EV_RXFLAG = 0x0002;
- internal const UInt32 EV_TXEMPTY = 0x0004;
- internal const UInt32 EV_CTS = 0x0008;
- internal const UInt32 EV_DSR = 0x0010;
- internal const UInt32 EV_RLSD = 0x0020;
- internal const UInt32 EV_BREAK = 0x0040;
- internal const UInt32 EV_ERR = 0x0080;
- internal const UInt32 EV_RING = 0x0100;
- internal const UInt32 EV_PERR = 0x0200;
- internal const UInt32 EV_RX80FULL = 0x0400;
- internal const UInt32 EV_EVENT1 = 0x0800;
- internal const UInt32 EV_EVENT2 = 0x1000;
-
- [DllImport("kernel32.dll", SetLastError = true)]
- internal static extern Boolean WaitCommEvent(IntPtr hFile, IntPtr lpEvtMask, IntPtr lpOverlapped);
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean CancelIo(IntPtr hFile);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- internal static extern Boolean ReadFile(IntPtr hFile, [Out] Byte[] lpBuffer, UInt32 nNumberOfBytesToRead,
- out UInt32 nNumberOfBytesRead, IntPtr lpOverlapped);
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean TransmitCommChar(IntPtr hFile, Byte cChar);
-
- ///
- /// Control port functions.
- ///
- [DllImport("kernel32.dll")]
- internal static extern Boolean EscapeCommFunction(IntPtr hFile, UInt32 dwFunc);
-
- // Constants for dwFunc:
- internal const UInt32 SETXOFF = 1;
- internal const UInt32 SETXON = 2;
- internal const UInt32 SETRTS = 3;
- internal const UInt32 CLRRTS = 4;
- internal const UInt32 SETDTR = 5;
- internal const UInt32 CLRDTR = 6;
- internal const UInt32 RESETDEV = 7;
- internal const UInt32 SETBREAK = 8;
- internal const UInt32 CLRBREAK = 9;
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean GetCommModemStatus(IntPtr hFile, out UInt32 lpModemStat);
-
- // Constants for lpModemStat:
- internal const UInt32 MS_CTS_ON = 0x0010;
- internal const UInt32 MS_DSR_ON = 0x0020;
- internal const UInt32 MS_RING_ON = 0x0040;
- internal const UInt32 MS_RLSD_ON = 0x0080;
-
- ///
- /// Status Functions.
- ///
- [DllImport("kernel32.dll", SetLastError = true)]
- internal static extern Boolean GetOverlappedResult(IntPtr hFile, IntPtr lpOverlapped,
- out UInt32 nNumberOfBytesTransferred, Boolean bWait);
-
- [DllImport("kernel32.dll")]
- internal static extern Boolean ClearCommError(IntPtr hFile, out UInt32 lpErrors, IntPtr lpStat);
- [DllImport("kernel32.dll")]
- internal static extern Boolean ClearCommError(IntPtr hFile, out UInt32 lpErrors, out COMSTAT cs);
-
- //Constants for lpErrors:
- internal const UInt32 CE_RXOVER = 0x0001;
- internal const UInt32 CE_OVERRUN = 0x0002;
- internal const UInt32 CE_RXPARITY = 0x0004;
- internal const UInt32 CE_FRAME = 0x0008;
- internal const UInt32 CE_BREAK = 0x0010;
- internal const UInt32 CE_TXFULL = 0x0100;
- internal const UInt32 CE_PTO = 0x0200;
- internal const UInt32 CE_IOE = 0x0400;
- internal const UInt32 CE_DNS = 0x0800;
- internal const UInt32 CE_OOP = 0x1000;
- internal const UInt32 CE_MODE = 0x8000;
- [DllImport("kernel32.dll")]
- internal static extern Boolean GetCommProperties(IntPtr hFile, out COMMPROP cp);
- }
-}
\ No newline at end of file
diff --git a/README.md b/README.md
old mode 100755
new mode 100644
index 5433b46..bdc731c
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
-# P/Invoke wrapper for Win32API serial port
+
+
+# Nefarius.Peripherals.SerialPort
## About
diff --git a/appveyor.yml b/appveyor.yml
index 960a63b..9cd4246 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,5 +1,5 @@
version: 1.0.{build}
-image: Visual Studio 2019
+image: Visual Studio 2022
configuration:
- Release
install:
diff --git a/assets/NSS-128x128.png b/assets/NSS-128x128.png
new file mode 100644
index 0000000..bf4c391
Binary files /dev/null and b/assets/NSS-128x128.png differ