Files
Nefarius.Peripherals.Serial…/Nefarius.Peripherals.SerialPort/SerialPort.cs
T

648 lines
18 KiB
C#
Raw Normal View History

2012-03-03 13:20:54 +03:30
using System;
2024-07-13 14:59:01 +02:00
using System.Diagnostics.CodeAnalysis;
2012-03-03 13:20:54 +03:30
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
2024-07-13 14:59:01 +02:00
2022-10-03 17:36:44 +02:00
using Windows.Win32;
2022-10-03 17:58:42 +02:00
using Windows.Win32.Devices.Communication;
using Windows.Win32.Foundation;
2022-10-03 17:36:44 +02:00
using Windows.Win32.Storage.FileSystem;
2024-07-13 14:59:01 +02:00
2022-10-03 17:36:44 +02:00
using Microsoft.Win32.SafeHandles;
2024-07-13 14:59:01 +02:00
2022-10-03 19:09:40 +02:00
namespace Nefarius.Peripherals.SerialPort;
/// <summary>
2022-10-03 20:21:52 +02:00
/// Wrapper class around a serial (COM, RS-232) port.
2022-10-03 19:09:40 +02:00
/// </summary>
2024-07-13 14:59:01 +02:00
[SuppressMessage("ReSharper", "UnusedMember.Global")]
2022-10-03 19:23:48 +02:00
public partial class SerialPort : IDisposable
2012-03-03 13:20:54 +03:30
{
2022-10-03 19:23:48 +02:00
private readonly ManualResetEvent _writeEvent = new(false);
private bool _auto;
private bool _checkSends = true;
2024-07-14 10:57:12 +02:00
private CancellationTokenSource _cts;
2022-10-03 19:23:48 +02:00
private Handshake _handShake;
private SafeFileHandle _hPort;
private bool _online;
private NativeOverlapped _ptrUwo;
private Exception _rxException;
private bool _rxExceptionReported;
private Thread _rxThread;
private int _stateBrk = 2;
private int _stateDtr = 2;
private int _stateRts = 2;
private int _writeCount;
2022-10-03 20:21:52 +02:00
2022-10-03 19:23:48 +02:00
/// <summary>
/// Class constructor
/// </summary>
public SerialPort(string portName)
{
PortName = portName;
}
/// <inheritdoc />
public SerialPort(string portName, int baudRate) : this(portName)
{
BaudRate = baudRate;
}
2022-10-03 19:09:40 +02:00
/// <inheritdoc />
public void Dispose()
2012-03-03 13:20:54 +03:30
{
2022-10-03 19:09:40 +02:00
Close();
}
2018-11-22 21:35:11 +01:00
2022-10-03 19:09:40 +02:00
/// <summary>
2024-07-13 15:53:59 +02:00
/// Opens the com port and configures it with the required settings.
2022-10-03 19:09:40 +02:00
/// </summary>
2024-07-13 15:53:59 +02:00
/// <returns>false if the port could not be opened due to missing permissions.</returns>
2022-10-03 19:09:40 +02:00
public bool Open()
{
2024-07-13 14:59:01 +02:00
DCB portDcb = new();
COMMTIMEOUTS commTimeouts = new();
2018-11-22 21:35:11 +01:00
2024-07-13 14:59:01 +02:00
if (_online)
{
return false;
}
2018-11-25 14:34:11 +01:00
2022-10-03 19:09:40 +02:00
_hPort = PInvoke.CreateFile(PortName,
2024-07-13 17:20:18 +02:00
(uint)(FILE_ACCESS_RIGHTS.FILE_GENERIC_READ | FILE_ACCESS_RIGHTS.FILE_GENERIC_WRITE),
0,
null,
FILE_CREATION_DISPOSITION.OPEN_EXISTING, FILE_FLAGS_AND_ATTRIBUTES.FILE_FLAG_OVERLAPPED,
null
);
2018-11-22 21:35:11 +01:00
2022-10-03 19:09:40 +02:00
if (_hPort.IsInvalid)
2018-11-25 14:25:25 +01:00
{
2024-07-13 14:59:01 +02:00
if (Marshal.GetLastWin32Error() == (int)WIN32_ERROR.ERROR_ACCESS_DENIED)
{
return false;
}
2024-07-13 17:20:18 +02:00
throw new CommPortException("Port Open Failure", Marshal.GetLastWin32Error());
2018-11-25 14:25:25 +01:00
}
2022-10-03 19:09:40 +02:00
_online = true;
2018-11-25 14:25:25 +01:00
2022-10-03 19:09:40 +02:00
commTimeouts.ReadIntervalTimeout = 0;
commTimeouts.ReadTotalTimeoutConstant = 0;
commTimeouts.ReadTotalTimeoutMultiplier = 0;
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;
2024-07-13 14:59:01 +02:00
portDcb.XoffChar = new CHAR((sbyte)XoffChar);
portDcb.XonChar = new CHAR((sbyte)XonChar);
2022-10-03 19:09:40 +02:00
portDcb.XoffLim = (ushort)RxHighWater;
portDcb.XonLim = (ushort)RxLowWater;
if (RxQueue != 0 || TxQueue != 0)
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:09:40 +02:00
if (!PInvoke.SetupComm(_hPort, (uint)RxQueue, (uint)TxQueue))
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:09:40 +02:00
ThrowException("Bad queue settings");
2024-07-13 14:59:01 +02:00
}
}
2018-11-22 21:35:11 +01:00
2022-10-03 19:09:40 +02:00
if (!PInvoke.SetCommState(_hPort, portDcb))
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:09:40 +02:00
ThrowException("Bad com settings");
2024-07-13 14:59:01 +02:00
}
2018-11-22 21:35:11 +01:00
2022-10-03 19:09:40 +02:00
if (!PInvoke.SetCommTimeouts(_hPort, commTimeouts))
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:09:40 +02:00
ThrowException("Bad timeout settings");
2024-07-13 14:59:01 +02:00
}
2022-10-03 19:09:40 +02:00
_stateBrk = 0;
switch (UseDtr)
2018-11-22 21:35:11 +01:00
{
2022-10-03 19:09:40 +02:00
case HsOutput.None:
_stateDtr = 0;
break;
case HsOutput.Online:
_stateDtr = 1;
break;
2018-11-22 21:35:11 +01:00
}
2022-10-03 19:09:40 +02:00
switch (UseRts)
2018-11-22 21:35:11 +01:00
{
2022-10-03 19:09:40 +02:00
case HsOutput.None:
_stateRts = 0;
break;
case HsOutput.Online:
_stateRts = 1;
break;
2018-11-22 21:35:11 +01:00
}
2022-10-03 19:09:40 +02:00
_checkSends = CheckAllSends;
_ptrUwo.EventHandle = _checkSends ? _writeEvent.SafeWaitHandle.DangerousGetHandle() : IntPtr.Zero;
_writeCount = 0;
2018-11-22 21:35:11 +01:00
2022-10-03 19:09:40 +02:00
_rxException = null;
_rxExceptionReported = false;
2018-11-22 21:35:11 +01:00
_cts = new CancellationTokenSource();
2022-10-03 19:09:40 +02:00
_rxThread = new Thread(ReceiveThread)
2018-11-22 21:35:11 +01:00
{
2024-07-13 14:59:01 +02:00
Name = "CommBaseRx", Priority = ThreadPriority.AboveNormal, IsBackground = true
2022-10-03 19:09:40 +02:00
};
2018-11-22 21:35:11 +01:00
2022-10-03 19:09:40 +02:00
_rxThread.Start();
Thread.Sleep(1); //Give rx thread time to start. By documentation, 0 should work, but it does not!
2018-11-25 14:34:11 +01:00
2022-10-03 19:09:40 +02:00
_auto = false;
if (AfterOpen())
2018-11-22 21:35:11 +01:00
{
2022-10-03 19:09:40 +02:00
_auto = AutoReopen;
return true;
2018-11-22 21:35:11 +01:00
}
2022-10-03 19:09:40 +02:00
Close();
return false;
}
2012-03-03 13:20:54 +03:30
2022-10-03 19:09:40 +02:00
/// <summary>
/// Closes the com port.
/// </summary>
public void Close()
{
2024-07-14 10:57:12 +02:00
if (!_online)
2022-10-03 19:09:40 +02:00
{
2024-07-14 10:57:12 +02:00
return;
2012-03-03 13:20:54 +03:30
}
2024-07-14 10:57:12 +02:00
_auto = false;
BeforeClose(false);
InternalClose();
_rxException = null;
2022-10-03 19:09:40 +02:00
}
2012-03-03 13:20:54 +03:30
2022-10-03 19:09:40 +02:00
private void InternalClose()
{
2024-07-13 15:19:51 +02:00
PInvoke.CancelIo(_hPort);
2022-10-03 19:09:40 +02:00
if (_rxThread != null)
2012-03-03 13:20:54 +03:30
{
2024-07-14 10:57:12 +02:00
_cts.Cancel();
_rxThread.Join();
2022-10-03 19:09:40 +02:00
_rxThread = null;
2012-03-03 13:20:54 +03:30
}
2022-10-03 19:09:40 +02:00
_hPort.Dispose();
_stateRts = 2;
_stateDtr = 2;
_stateBrk = 2;
_online = false;
}
2018-11-22 21:35:11 +01:00
2022-10-03 19:09:40 +02:00
/// <summary>
/// Destructor (just in case)
/// </summary>
~SerialPort()
{
Close();
}
2012-03-03 13:20:54 +03:30
2022-10-03 19:09:40 +02:00
/// <summary>
/// Block until all bytes in the queue have been transmitted.
/// </summary>
public void Flush()
{
CheckOnline();
CheckResult();
}
2012-03-03 13:20:54 +03:30
2022-10-03 19:09:40 +02:00
/// <summary>
/// Use this to throw exceptions in derived classes. Correctly handles threading issues
/// and closes the port if necessary.
/// </summary>
/// <param name="reason">Description of fault</param>
protected void ThrowException(string reason)
{
2024-07-13 14:59:01 +02:00
if (Thread.CurrentThread == _rxThread)
{
throw new CommPortException(reason);
}
2022-10-03 19:09:40 +02:00
if (_online)
2012-03-03 13:20:54 +03:30
{
2022-10-03 19:09:40 +02:00
BeforeClose(true);
InternalClose();
2012-03-03 13:20:54 +03:30
}
2024-07-13 14:59:01 +02:00
if (_rxException == null)
{
throw new CommPortException(reason);
}
2022-10-03 19:09:40 +02:00
throw new CommPortException(_rxException);
}
2018-11-22 21:35:11 +01:00
2022-10-03 19:09:40 +02:00
/// <summary>
/// Queues bytes for transmission.
/// </summary>
/// <param name="toSend">Array of bytes to be sent</param>
public unsafe void Write(byte[] toSend)
{
CheckOnline();
CheckResult();
_writeCount = toSend.GetLength(0);
2012-03-03 13:20:54 +03:30
2022-10-03 19:09:40 +02:00
fixed (NativeOverlapped* ptrOl = &_ptrUwo)
2012-03-03 13:20:54 +03:30
{
2024-07-13 14:59:01 +02:00
uint sent;
2024-07-13 15:07:34 +02:00
if (PInvoke.WriteFile(_hPort, toSend.AsSpan(), &sent, ptrOl))
2012-03-03 13:20:54 +03:30
{
2022-10-03 17:58:42 +02:00
_writeCount -= (int)sent;
2012-03-03 13:20:54 +03:30
}
else
{
2022-10-03 19:23:48 +02:00
if (Marshal.GetLastWin32Error() != (int)WIN32_ERROR.ERROR_IO_PENDING)
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:20:01 +02:00
ThrowException("Unexpected failure");
2024-07-13 14:59:01 +02:00
}
2012-03-03 13:20:54 +03:30
}
}
2022-10-03 19:09:40 +02:00
}
2012-03-03 13:20:54 +03:30
2022-10-03 19:09:40 +02:00
/// <summary>
/// Queues string for transmission.
/// </summary>
/// <param name="toSend">Array of bytes to be sent</param>
public void Write(string toSend)
{
Write(new ASCIIEncoding().GetBytes(toSend));
}
2012-03-03 13:20:54 +03:30
2022-10-03 19:09:40 +02:00
/// <summary>
/// Queues a single byte for transmission.
/// </summary>
/// <param name="toSend">Byte to be sent</param>
public void Write(byte toSend)
{
2024-07-13 14:59:01 +02:00
byte[] b = new byte[1];
2022-10-03 19:09:40 +02:00
b[0] = toSend;
Write(b);
}
2012-03-03 13:20:54 +03:30
2022-10-03 19:09:40 +02:00
/// <summary>
/// Queues a single char for transmission.
/// </summary>
/// <param name="toSend">Byte to be sent</param>
public void Write(char toSend)
{
Write(toSend.ToString());
}
/// <summary>
/// Queues string with a new line ("\r\n") for transmission.
/// </summary>
/// <param name="toSend">Array of bytes to be sent</param>
public void WriteLine(string toSend)
{
Write(new ASCIIEncoding().GetBytes(toSend + Environment.NewLine));
}
private void CheckResult()
{
2024-07-13 14:59:01 +02:00
if (_writeCount <= 0)
{
return;
}
if (PInvoke.GetOverlappedResult(_hPort, _ptrUwo, out uint sent, _checkSends))
2012-03-03 13:20:54 +03:30
{
2022-10-03 19:09:40 +02:00
_writeCount -= (int)sent;
2024-07-13 14:59:01 +02:00
if (_writeCount != 0)
{
ThrowException("Send Timeout");
}
2012-03-03 13:20:54 +03:30
}
2022-10-03 19:09:40 +02:00
else
2012-03-03 13:20:54 +03:30
{
2024-07-13 14:59:01 +02:00
if (Marshal.GetLastWin32Error() != (int)WIN32_ERROR.ERROR_IO_PENDING)
{
ThrowException("Unexpected failure");
}
2012-03-03 13:20:54 +03:30
}
2022-10-03 19:09:40 +02:00
}
2012-03-03 13:20:54 +03:30
2022-10-03 19:09:40 +02:00
/// <summary>
/// Sends a protocol byte immediately ahead of any queued bytes.
/// </summary>
/// <param name="tosend">Byte to send</param>
/// <returns>False if an immediate byte is already scheduled and not yet sent</returns>
public void SendImmediate(byte tosend)
{
CheckOnline();
2024-07-13 15:28:19 +02:00
if (!PInvoke.TransmitCommChar(_hPort, new CHAR((sbyte)tosend)))
2024-07-13 14:59:01 +02:00
{
ThrowException("Transmission failure");
}
2022-10-03 19:09:40 +02:00
}
/// <summary>
/// Gets the status of the modem control input signals.
/// </summary>
/// <returns>Modem status object</returns>
protected ModemStatus GetModemStatus()
{
CheckOnline();
2024-07-13 15:28:19 +02:00
if (!PInvoke.GetCommModemStatus(_hPort, out MODEM_STATUS_FLAGS f))
2024-07-13 14:59:01 +02:00
{
ThrowException("Unexpected failure");
}
2024-07-13 15:28:19 +02:00
return new ModemStatus(f);
2022-10-03 19:09:40 +02:00
}
2022-10-03 20:21:52 +02:00
2022-10-03 19:09:40 +02:00
/// <summary>
/// Get the status of the queues
/// </summary>
/// <returns>Queue status object</returns>
2022-10-03 19:16:35 +02:00
protected unsafe QueueStatus GetQueueStatus()
2022-10-03 19:09:40 +02:00
{
COMSTAT cs;
2024-07-13 14:59:01 +02:00
COMMPROP cp = new();
2022-10-03 19:16:35 +02:00
CLEAR_COMM_ERROR_FLAGS er;
2022-10-03 19:09:40 +02:00
CheckOnline();
2022-10-03 19:16:35 +02:00
if (!PInvoke.ClearCommError(_hPort, &er, &cs))
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:16:35 +02:00
ThrowException("Unexpected failure");
2024-07-13 14:59:01 +02:00
}
2022-10-03 19:16:35 +02:00
2024-07-13 14:59:01 +02:00
if (!PInvoke.GetCommProperties(_hPort, &cp))
{
2022-10-03 19:16:35 +02:00
ThrowException("Unexpected failure");
2024-07-13 14:59:01 +02:00
}
2022-10-03 19:16:35 +02:00
return new QueueStatus(cs._bitfield, cs.cbInQue, cs.cbOutQue, cp.dwCurrentRxQueue, cp.dwCurrentTxQueue);
2022-10-03 19:09:40 +02:00
}
/// <summary>
/// Override this to provide processing after the port is opened (i.e. to configure remote
/// device or just check presence).
/// </summary>
/// <returns>false to close the port again</returns>
protected virtual bool AfterOpen()
{
return true;
}
/// <summary>
/// Override this to provide processing prior to port closure.
/// </summary>
/// <param name="error">True if closing due to an error</param>
protected virtual void BeforeClose(bool error)
{
}
2024-07-14 10:57:12 +02:00
/// <summary>
/// Invoked when a single character has been received.
/// </summary>
2022-10-03 19:09:40 +02:00
public event Action<byte> DataReceived;
/// <summary>
/// Override this to process received bytes.
/// </summary>
/// <param name="ch">The byte that was received</param>
protected void OnRxChar(byte ch)
{
DataReceived?.Invoke(ch);
}
/// <summary>
/// Override this to take action when transmission is complete (i.e. all bytes have actually
/// been sent, not just queued).
/// </summary>
protected virtual void OnTxDone()
{
}
/// <summary>
/// Override this to take action when a break condition is detected on the input line.
/// </summary>
protected virtual void OnBreak()
{
}
/// <summary>
/// Override this to take action when a ring condition is signaled by an attached modem.
/// </summary>
protected virtual void OnRing()
{
}
/// <summary>
/// Override this to take action when one or more modem status inputs change state
/// </summary>
/// <param name="mask">The status inputs that have changed state</param>
/// <param name="state">The state of the status inputs</param>
protected virtual void OnStatusChange(ModemStatus mask, ModemStatus state)
{
}
/// <summary>
/// Override this to take action when the reception thread closes due to an exception being thrown.
/// </summary>
/// <param name="e">The exception which was thrown</param>
protected virtual void OnRxException(Exception e)
{
}
2022-10-03 19:16:35 +02:00
private unsafe void ReceiveThread()
2022-10-03 19:09:40 +02:00
{
2024-07-13 15:07:34 +02:00
byte[] buffer = new byte[1];
2024-07-13 14:59:01 +02:00
AutoResetEvent sg = new(false);
NativeOverlapped ov = new() { EventHandle = sg.SafeWaitHandle.DangerousGetHandle() };
2022-10-03 19:09:40 +02:00
try
2012-03-03 13:20:54 +03:30
{
while (!_cts.IsCancellationRequested)
2012-03-03 13:20:54 +03:30
{
2024-07-13 15:07:34 +02:00
COMM_EVENT_MASK eventMask = 0;
2022-10-03 20:21:52 +02:00
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))
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:09:40 +02:00
throw new CommPortException("IO Error [001]");
2024-07-13 14:59:01 +02:00
}
2022-10-03 20:21:52 +02:00
if (!PInvoke.WaitCommEvent(_hPort, ref eventMask, &ov))
2022-10-03 19:09:40 +02:00
{
2022-10-03 19:20:01 +02:00
if (Marshal.GetLastWin32Error() == (int)WIN32_ERROR.ERROR_IO_PENDING)
2024-07-13 14:59:01 +02:00
{
2024-07-14 10:57:12 +02:00
WaitHandle.WaitAny(new[] { sg, _cts.Token.WaitHandle });
2024-07-13 14:59:01 +02:00
}
2022-10-03 19:09:40 +02:00
else
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:09:40 +02:00
throw new CommPortException("IO Error [002]");
2024-07-13 14:59:01 +02:00
}
2022-10-03 19:09:40 +02:00
}
2022-10-03 20:21:52 +02:00
if ((eventMask & COMM_EVENT_MASK.EV_ERR) != 0)
2022-10-03 19:09:40 +02:00
{
2022-10-03 19:16:35 +02:00
CLEAR_COMM_ERROR_FLAGS errs;
if (PInvoke.ClearCommError(_hPort, &errs, null))
2022-10-03 19:09:40 +02:00
{
2024-07-13 14:59:01 +02:00
StringBuilder s = new("UART Error: ", 40);
2024-07-13 15:22:16 +02:00
if (((uint)errs & (uint)CLEAR_COMM_ERROR_FLAGS.CE_FRAME) != 0)
2024-07-13 14:59:01 +02:00
{
s = s.Append("Framing,");
}
2024-07-13 15:24:30 +02:00
if (((uint)errs & PInvoke.CE_IOE) != 0)
2024-07-13 14:59:01 +02:00
{
s = s.Append("IO,");
}
2024-07-13 15:22:16 +02:00
if (((uint)errs & (uint)CLEAR_COMM_ERROR_FLAGS.CE_OVERRUN) != 0)
2024-07-13 14:59:01 +02:00
{
s = s.Append("Overrun,");
}
2024-07-13 15:22:16 +02:00
if (((uint)errs & (uint)CLEAR_COMM_ERROR_FLAGS.CE_RXOVER) != 0)
2024-07-13 14:59:01 +02:00
{
s = s.Append("Receive Overflow,");
}
2024-07-13 15:22:16 +02:00
if (((uint)errs & (uint)CLEAR_COMM_ERROR_FLAGS.CE_RXPARITY) != 0)
2024-07-13 14:59:01 +02:00
{
s = s.Append("Parity,");
}
2024-07-13 15:24:30 +02:00
if (((uint)errs & PInvoke.CE_TXFULL) != 0)
2024-07-13 14:59:01 +02:00
{
s = s.Append("Transmit Overflow,");
}
2022-10-03 19:20:01 +02:00
s.Length -= 1;
2022-10-03 19:09:40 +02:00
throw new CommPortException(s.ToString());
}
throw new CommPortException("IO Error [003]");
}
2022-10-03 20:21:52 +02:00
if ((eventMask & COMM_EVENT_MASK.EV_RXCHAR) != 0)
2022-10-03 19:09:40 +02:00
{
2024-07-13 14:59:01 +02:00
uint gotBytes;
2022-10-03 19:09:40 +02:00
do
{
2024-07-13 15:07:34 +02:00
if (!PInvoke.ReadFile(_hPort, buffer, &gotBytes, &ov))
2022-10-03 19:09:40 +02:00
{
2022-10-03 19:20:01 +02:00
if (Marshal.GetLastWin32Error() == (int)WIN32_ERROR.ERROR_IO_PENDING)
2022-10-03 19:09:40 +02:00
{
2024-07-13 15:19:51 +02:00
PInvoke.CancelIo(_hPort);
2024-07-13 14:59:01 +02:00
gotBytes = 0;
2022-10-03 19:09:40 +02:00
}
else
{
throw new CommPortException("IO Error [004]");
}
}
2024-07-13 14:59:01 +02:00
if (gotBytes == 1)
{
2024-07-13 15:07:34 +02:00
OnRxChar(buffer[0]);
2024-07-13 14:59:01 +02:00
}
} while (gotBytes > 0);
}
if ((eventMask & COMM_EVENT_MASK.EV_TXEMPTY) != 0)
{
OnTxDone();
2022-10-03 19:09:40 +02:00
}
2024-07-13 14:59:01 +02:00
if ((eventMask & COMM_EVENT_MASK.EV_BREAK) != 0)
{
OnBreak();
}
2022-10-03 19:09:40 +02:00
2024-07-13 15:12:45 +02:00
MODEM_STATUS_FLAGS i = 0;
2024-07-13 14:59:01 +02:00
if ((eventMask & COMM_EVENT_MASK.EV_CTS) != 0)
{
2024-07-13 15:12:45 +02:00
i |= MODEM_STATUS_FLAGS.MS_CTS_ON;
2024-07-13 14:59:01 +02:00
}
if ((eventMask & COMM_EVENT_MASK.EV_DSR) != 0)
{
2024-07-13 15:12:45 +02:00
i |= MODEM_STATUS_FLAGS.MS_DSR_ON;
2024-07-13 14:59:01 +02:00
}
if ((eventMask & COMM_EVENT_MASK.EV_RLSD) != 0)
{
2024-07-13 15:12:45 +02:00
i |= MODEM_STATUS_FLAGS.MS_RLSD_ON;
2024-07-13 14:59:01 +02:00
}
if ((eventMask & COMM_EVENT_MASK.EV_RING) != 0)
{
2024-07-13 15:12:45 +02:00
i |= MODEM_STATUS_FLAGS.MS_RING_ON;
2024-07-13 14:59:01 +02:00
}
2022-10-03 19:09:40 +02:00
if (i != 0)
{
2024-07-13 15:28:19 +02:00
if (!PInvoke.GetCommModemStatus(_hPort, out MODEM_STATUS_FLAGS f))
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:09:40 +02:00
throw new CommPortException("IO Error [005]");
2024-07-13 14:59:01 +02:00
}
2024-07-13 15:28:19 +02:00
OnStatusChange(new ModemStatus(i), new ModemStatus(f));
2022-10-03 19:09:40 +02:00
}
2012-03-03 13:20:54 +03:30
}
2022-10-03 19:09:40 +02:00
}
catch (Exception e)
{
2024-07-13 14:59:01 +02:00
if (e is not ThreadAbortException)
2012-03-03 13:20:54 +03:30
{
2022-10-03 19:09:40 +02:00
_rxException = e;
OnRxException(e);
2012-03-03 13:20:54 +03:30
}
}
2022-10-03 19:09:40 +02:00
}
2012-03-03 13:20:54 +03:30
2022-10-03 19:09:40 +02:00
private bool CheckOnline()
{
if (_rxException != null && !_rxExceptionReported)
2012-03-03 13:20:54 +03:30
{
2022-10-03 19:09:40 +02:00
_rxExceptionReported = true;
ThrowException("rx");
2012-03-03 13:20:54 +03:30
}
2022-10-03 19:09:40 +02:00
if (_online)
2012-03-03 13:20:54 +03:30
{
2024-07-13 15:28:19 +02:00
if (PInvoke.GetHandleInformation(_hPort, out uint _))
2024-07-13 14:59:01 +02:00
{
return true;
}
2022-10-03 19:09:40 +02:00
ThrowException("Offline");
return false;
2012-03-03 13:20:54 +03:30
}
2022-10-03 19:09:40 +02:00
if (_auto)
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:09:40 +02:00
if (Open())
2024-07-13 14:59:01 +02:00
{
2022-10-03 19:09:40 +02:00
return true;
2024-07-13 14:59:01 +02:00
}
}
2022-10-03 19:09:40 +02:00
ThrowException("Offline");
return false;
}
2024-07-13 15:07:34 +02:00
}