More refactoring

This commit is contained in:
Benjamin Höglinger-Stelzer 2018-11-22 21:35:11 +01:00
parent 55c3aefa2d
commit 33e68a0745

View File

@ -12,19 +12,136 @@ namespace PInvokeSerialPort
/// </summary> /// </summary>
public class SerialPort : IDisposable public class SerialPort : IDisposable
{ {
private IntPtr _hPort; private readonly ManualResetEvent _writeEvent = new ManualResetEvent(false);
private IntPtr _ptrUwo = IntPtr.Zero;
private Thread _rxThread;
private bool _online;
private bool _auto; private bool _auto;
private bool _checkSends = true; private bool _checkSends = true;
private Handshake _handShake;
private IntPtr _hPort;
private bool _online;
private IntPtr _ptrUwo = IntPtr.Zero;
private Exception _rxException; private Exception _rxException;
private bool _rxExceptionReported; private bool _rxExceptionReported;
private int _writeCount; private Thread _rxThread;
private readonly ManualResetEvent _writeEvent = new ManualResetEvent(false);
private int _stateRts = 2;
private int _stateDtr = 2;
private int _stateBrk = 2; private int _stateBrk = 2;
private int _stateDtr = 2;
private int _stateRts = 2;
private int _writeCount;
/// <summary>
/// If true, the port will automatically re-open on next send if it was previously closed due
/// to an error (default: false)
/// </summary>
public bool AutoReopen;
/// <summary>
/// Baud Rate (default: 2400) unsupported rates will throw "Bad settings"
/// </summary>
public int BaudRate = 115200;
/// <summary>
/// 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.
/// </summary>
public bool CheckAllSends = true;
/// <summary>
/// Number of databits 1..8 (default: 8) unsupported values will throw "Bad settings"
/// </summary>
public int DataBits = 8;
/// <summary>
/// The parity checking scheme (default: none)
/// </summary>
public Parity Parity = Parity.None;
/// <summary>
/// If true, Xon and Xoff characters are sent to control the data flow from the remote station (default: false)
/// </summary>
public bool RxFlowX;
/// <summary>
/// If true, received characters are ignored unless DSR is asserted by the remote station (default: false)
/// </summary>
public bool RxGateDsr;
/// <summary>
/// The number of free bytes in the reception queue at which flow is disabled (default: 2048)
/// </summary>
public int RxHighWater = 2048;
/// <summary>
/// The number of bytes in the reception queue at which flow is re-enabled (default: 512)
/// </summary>
public int RxLowWater = 512;
/// <summary>
/// Requested size for receive queue (default: 0 = use operating system default)
/// </summary>
public int RxQueue;
/// <summary>
/// Constant. Max time for Send in ms = (Multiplier * Characters) + Constant (default: 0)
/// </summary>
public int SendTimeoutConstant;
/// <summary>
/// Multiplier. Max time for Send in ms = (Multiplier * Characters) + Constant
/// (default: 0 = No timeout)
/// </summary>
public int SendTimeoutMultiplier;
/// <summary>
/// Number of stop bits (default: one)
/// </summary>
public StopBits StopBits = StopBits.One;
/// <summary>
/// If true, transmission is halted unless CTS is asserted by the remote station (default: false)
/// </summary>
public bool TxFlowCts;
/// <summary>
/// If true, transmission is halted unless DSR is asserted by the remote station (default: false)
/// </summary>
public bool TxFlowDsr;
/// <summary>
/// If true, transmission is halted when Xoff is received and restarted when Xon is received (default: false)
/// </summary>
public bool TxFlowX;
/// <summary>
/// Requested size for transmit queue (default: 0 = use operating system default)
/// </summary>
public int TxQueue;
/// <summary>
/// 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.
/// </summary>
public bool TxWhenRxXoff = true;
/// <summary>
/// Specidies the use to which the DTR output is put (default: none)
/// </summary>
public HsOutput UseDtr = HsOutput.None;
/// <summary>
/// Specifies the use to which the RTS output is put (default: none)
/// </summary>
public HsOutput UseRts = HsOutput.None;
/// <summary>
/// The character used to signal Xoff for X flow control (default: DC3)
/// </summary>
public ASCII XoffChar = ASCII.DC3;
/// <summary>
/// The character used to signal Xon for X flow control (default: DC1)
/// </summary>
public ASCII XonChar = ASCII.DC1;
/// <summary> /// <summary>
/// Class contructor /// Class contructor
@ -43,6 +160,170 @@ namespace PInvokeSerialPort
BaudRate = baudRate; BaudRate = baudRate;
} }
/// <summary>
/// True if online.
/// </summary>
public bool Online => _online && CheckOnline();
/// <summary>
/// True if the RTS pin is controllable via the RTS property
/// </summary>
protected bool RtSavailable => _stateRts < 2;
/// <summary>
/// Set the state of the RTS modem control output
/// </summary>
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;
}
/// <summary>
/// True if the DTR pin is controllable via the DTR property
/// </summary>
protected bool DtrAvailable => _stateDtr < 2;
/// <summary>
/// The state of the DTR modem control output
/// </summary>
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;
}
/// <summary>
/// Assert or remove a break condition from the transmission line
/// </summary>
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;
}
/// <summary>
/// Port Name
/// </summary>
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;
}
}
}
/// <summary>
/// For IDisposable
/// </summary>
public void Dispose()
{
Close();
}
/// <summary> /// <summary>
/// Opens the com port and configures it with the required settings /// Opens the com port and configures it with the required settings
/// </summary> /// </summary>
@ -59,10 +340,7 @@ namespace PInvokeSerialPort
Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero); Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero);
if (_hPort == (IntPtr) Win32Com.INVALID_HANDLE_VALUE) if (_hPort == (IntPtr) Win32Com.INVALID_HANDLE_VALUE)
{ {
if (Marshal.GetLastWin32Error() == Win32Com.ERROR_ACCESS_DENIED) if (Marshal.GetLastWin32Error() == Win32Com.ERROR_ACCESS_DENIED) return false;
{
return false;
}
throw new CommPortException("Port Open Failure"); throw new CommPortException("Port Open Failure");
} }
@ -73,7 +351,7 @@ namespace PInvokeSerialPort
commTimeouts.ReadTotalTimeoutMultiplier = 0; commTimeouts.ReadTotalTimeoutMultiplier = 0;
commTimeouts.WriteTotalTimeoutConstant = SendTimeoutConstant; commTimeouts.WriteTotalTimeoutConstant = SendTimeoutConstant;
commTimeouts.WriteTotalTimeoutMultiplier = SendTimeoutMultiplier; commTimeouts.WriteTotalTimeoutMultiplier = SendTimeoutMultiplier;
portDcb.Init(((Parity == Parity.Odd) || (Parity == Parity.Even)), TxFlowCts, TxFlowDsr, portDcb.Init(Parity == Parity.Odd || Parity == Parity.Even, TxFlowCts, TxFlowDsr,
(int) UseDtr, RxGateDsr, !TxWhenRxXoff, TxFlowX, RxFlowX, (int) UseRts); (int) UseDtr, RxGateDsr, !TxWhenRxXoff, TxFlowX, RxFlowX, (int) UseRts);
portDcb.BaudRate = BaudRate; portDcb.BaudRate = BaudRate;
portDcb.ByteSize = (byte) DataBits; portDcb.ByteSize = (byte) DataBits;
@ -83,8 +361,9 @@ namespace PInvokeSerialPort
portDcb.XonChar = (byte) XonChar; portDcb.XonChar = (byte) XonChar;
portDcb.XoffLim = (short) RxHighWater; portDcb.XoffLim = (short) RxHighWater;
portDcb.XonLim = (short) RxLowWater; portDcb.XonLim = (short) RxLowWater;
if ((RxQueue != 0) || (TxQueue != 0)) if (RxQueue != 0 || TxQueue != 0)
if (!Win32Com.SetupComm(_hPort, (uint)RxQueue, (uint)TxQueue)) ThrowException("Bad queue settings"); if (!Win32Com.SetupComm(_hPort, (uint) RxQueue, (uint) TxQueue))
ThrowException("Bad queue settings");
if (!Win32Com.SetCommState(_hPort, ref portDcb)) ThrowException("Bad com settings"); if (!Win32Com.SetCommState(_hPort, ref portDcb)) ThrowException("Bad com settings");
if (!Win32Com.SetCommTimeouts(_hPort, ref commTimeouts)) ThrowException("Bad timeout settings"); if (!Win32Com.SetCommTimeouts(_hPort, ref commTimeouts)) ThrowException("Bad timeout settings");
@ -120,6 +399,7 @@ namespace PInvokeSerialPort
_auto = AutoReopen; _auto = AutoReopen;
return true; return true;
} }
Close(); Close();
return false; return false;
} }
@ -146,6 +426,7 @@ namespace PInvokeSerialPort
_rxThread.Abort(); _rxThread.Abort();
_rxThread = null; _rxThread = null;
} }
Win32Com.CloseHandle(_hPort); Win32Com.CloseHandle(_hPort);
if (_ptrUwo != IntPtr.Zero) Marshal.FreeHGlobal(_ptrUwo); if (_ptrUwo != IntPtr.Zero) Marshal.FreeHGlobal(_ptrUwo);
_stateRts = 2; _stateRts = 2;
@ -154,20 +435,13 @@ namespace PInvokeSerialPort
_online = false; _online = false;
} }
/// <summary>
/// For IDisposable
/// </summary>
public void Dispose() { Close(); }
/// <summary> /// <summary>
/// Destructor (just in case) /// Destructor (just in case)
/// </summary> /// </summary>
~SerialPort() { Close(); } ~SerialPort()
{
/// <summary> Close();
/// True if online. }
/// </summary>
public bool Online { get { return _online && CheckOnline(); } }
/// <summary> /// <summary>
/// Block until all bytes in the queue have been transmitted. /// Block until all bytes in the queue have been transmitted.
@ -185,19 +459,14 @@ namespace PInvokeSerialPort
/// <param name="reason">Description of fault</param> /// <param name="reason">Description of fault</param>
protected void ThrowException(string reason) protected void ThrowException(string reason)
{ {
if (Thread.CurrentThread == _rxThread) if (Thread.CurrentThread == _rxThread) throw new CommPortException(reason);
{
throw new CommPortException(reason);
}
if (_online) if (_online)
{ {
BeforeClose(true); BeforeClose(true);
InternalClose(); InternalClose();
} }
if (_rxException == null)
{ if (_rxException == null) throw new CommPortException(reason);
throw new CommPortException(reason);
}
throw new CommPortException(_rxException); throw new CommPortException(_rxException);
} }
@ -324,120 +593,26 @@ namespace PInvokeSerialPort
return new QueueStatus(cs.Flags, cs.cbInQue, cs.cbOutQue, cp.dwCurrentRxQueue, cp.dwCurrentTxQueue); return new QueueStatus(cs.Flags, cs.cbInQue, cs.cbOutQue, cp.dwCurrentRxQueue, cp.dwCurrentTxQueue);
} }
/// <summary>
/// True if the RTS pin is controllable via the RTS property
/// </summary>
protected bool RtSavailable { get { return (_stateRts < 2); } }
/// <summary>
/// Set the state of the RTS modem control output
/// </summary>
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
{
return (_stateRts == 1);
}
}
/// <summary>
/// True if the DTR pin is controllable via the DTR property
/// </summary>
protected bool DtrAvailable { get { return (_stateDtr < 2); } }
/// <summary>
/// The state of the DTR modem control output
/// </summary>
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
{
return (_stateDtr == 1);
}
}
/// <summary>
/// Assert or remove a break condition from the transmission line
/// </summary>
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
{
return (_stateBrk == 1);
}
}
/// <summary> /// <summary>
/// Override this to provide processing after the port is openned (i.e. to configure remote /// Override this to provide processing after the port is openned (i.e. to configure remote
/// device or just check presence). /// device or just check presence).
/// </summary> /// </summary>
/// <returns>false to close the port again</returns> /// <returns>false to close the port again</returns>
protected virtual bool AfterOpen() { return true; } protected virtual bool AfterOpen()
{
return true;
}
/// <summary> /// <summary>
/// Override this to provide processing prior to port closure. /// Override this to provide processing prior to port closure.
/// </summary> /// </summary>
/// <param name="error">True if closing due to an error</param> /// <param name="error">True if closing due to an error</param>
protected virtual void BeforeClose(bool error) { } protected virtual void BeforeClose(bool error)
{
}
public event Action<byte> DataReceived; public event Action<byte> DataReceived;
/// <summary> /// <summary>
/// Override this to process received bytes. /// Override this to process received bytes.
/// </summary> /// </summary>
@ -452,39 +627,50 @@ namespace PInvokeSerialPort
/// Override this to take action when transmission is complete (i.e. all bytes have actually /// Override this to take action when transmission is complete (i.e. all bytes have actually
/// been sent, not just queued). /// been sent, not just queued).
/// </summary> /// </summary>
protected virtual void OnTxDone() { } protected virtual void OnTxDone()
{
}
/// <summary> /// <summary>
/// Override this to take action when a break condition is detected on the input line. /// Override this to take action when a break condition is detected on the input line.
/// </summary> /// </summary>
protected virtual void OnBreak() { } protected virtual void OnBreak()
{
}
/// <summary> /// <summary>
/// Override this to take action when a ring condition is signalled by an attached modem. /// Override this to take action when a ring condition is signalled by an attached modem.
/// </summary> /// </summary>
protected virtual void OnRing() { } protected virtual void OnRing()
{
}
/// <summary> /// <summary>
/// Override this to take action when one or more modem status inputs change state /// Override this to take action when one or more modem status inputs change state
/// </summary> /// </summary>
/// <param name="mask">The status inputs that have changed state</param> /// <param name="mask">The status inputs that have changed state</param>
/// <param name="state">The state of the status inputs</param> /// <param name="state">The state of the status inputs</param>
protected virtual void OnStatusChange(ModemStatus mask, ModemStatus state) { } protected virtual void OnStatusChange(ModemStatus mask, ModemStatus state)
{
}
/// <summary> /// <summary>
/// Override this to take action when the reception thread closes due to an exception being thrown. /// Override this to take action when the reception thread closes due to an exception being thrown.
/// </summary> /// </summary>
/// <param name="e">The exception which was thrown</param> /// <param name="e">The exception which was thrown</param>
protected virtual void OnRxException(Exception e) { } protected virtual void OnRxException(Exception e)
{
}
private void ReceiveThread() private void ReceiveThread()
{ {
var buf = new Byte[1]; var buf = new byte[1];
var sg = new AutoResetEvent(false); var sg = new AutoResetEvent(false);
var ov = new OVERLAPPED(); var ov = new OVERLAPPED();
var unmanagedOv = Marshal.AllocHGlobal(Marshal.SizeOf(ov)); var unmanagedOv = Marshal.AllocHGlobal(Marshal.SizeOf(ov));
ov.Offset = 0; ov.OffsetHigh = 0; ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = sg.Handle; ov.hEvent = sg.Handle;
Marshal.StructureToPtr(ov, unmanagedOv, true); Marshal.StructureToPtr(ov, unmanagedOv, true);
@ -495,27 +681,23 @@ namespace PInvokeSerialPort
{ {
while (true) while (true)
{ {
if (!Win32Com.SetCommMask(_hPort, Win32Com.EV_RXCHAR | Win32Com.EV_TXEMPTY | Win32Com.EV_CTS | Win32Com.EV_DSR 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)) | Win32Com.EV_BREAK | Win32Com.EV_RLSD | Win32Com.EV_RING | Win32Com.EV_ERR))
{
throw new CommPortException("IO Error [001]"); throw new CommPortException("IO Error [001]");
}
Marshal.WriteInt32(uMask, 0); Marshal.WriteInt32(uMask, 0);
if (!Win32Com.WaitCommEvent(_hPort, uMask, unmanagedOv)) if (!Win32Com.WaitCommEvent(_hPort, uMask, unmanagedOv))
{ {
if (Marshal.GetLastWin32Error() == Win32Com.ERROR_IO_PENDING) if (Marshal.GetLastWin32Error() == Win32Com.ERROR_IO_PENDING)
{
sg.WaitOne(); sg.WaitOne();
}
else else
{
throw new CommPortException("IO Error [002]"); throw new CommPortException("IO Error [002]");
} }
}
eventMask = (uint) Marshal.ReadInt32(uMask); eventMask = (uint) Marshal.ReadInt32(uMask);
if ((eventMask & Win32Com.EV_ERR) != 0) if ((eventMask & Win32Com.EV_ERR) != 0)
{ {
UInt32 errs; uint errs;
if (Win32Com.ClearCommError(_hPort, out errs, IntPtr.Zero)) if (Win32Com.ClearCommError(_hPort, out errs, IntPtr.Zero))
{ {
var s = new StringBuilder("UART Error: ", 40); var s = new StringBuilder("UART Error: ", 40);
@ -528,8 +710,10 @@ namespace PInvokeSerialPort
s.Length = s.Length - 1; s.Length = s.Length - 1;
throw new CommPortException(s.ToString()); throw new CommPortException(s.ToString());
} }
throw new CommPortException("IO Error [003]"); throw new CommPortException("IO Error [003]");
} }
if ((eventMask & Win32Com.EV_RXCHAR) != 0) if ((eventMask & Win32Com.EV_RXCHAR) != 0)
{ {
uint gotbytes; uint gotbytes;
@ -547,14 +731,12 @@ namespace PInvokeSerialPort
throw new CommPortException("IO Error [004]"); throw new CommPortException("IO Error [004]");
} }
} }
if (gotbytes == 1) OnRxChar(buf[0]);
if (gotbytes == 1) OnRxChar(buf[0]);
} while (gotbytes > 0); } while (gotbytes > 0);
} }
if ((eventMask & Win32Com.EV_TXEMPTY) != 0)
{ if ((eventMask & Win32Com.EV_TXEMPTY) != 0) OnTxDone();
OnTxDone();
}
if ((eventMask & Win32Com.EV_BREAK) != 0) OnBreak(); if ((eventMask & Win32Com.EV_BREAK) != 0) OnBreak();
uint i = 0; uint i = 0;
@ -584,11 +766,12 @@ namespace PInvokeSerialPort
private bool CheckOnline() private bool CheckOnline()
{ {
if ((_rxException != null) && (!_rxExceptionReported)) if (_rxException != null && !_rxExceptionReported)
{ {
_rxExceptionReported = true; _rxExceptionReported = true;
ThrowException("rx"); ThrowException("rx");
} }
if (_online) if (_online)
{ {
uint f; uint f;
@ -596,147 +779,12 @@ namespace PInvokeSerialPort
ThrowException("Offline"); ThrowException("Offline");
return false; return false;
} }
if (_auto) if (_auto)
{ if (Open())
if (Open()) return true; return true;
}
ThrowException("Offline"); ThrowException("Offline");
return false; return false;
} }
/// <summary>
/// Port Name
/// </summary>
public string PortName { get; set; }
/// <summary>
/// Baud Rate (default: 2400) unsupported rates will throw "Bad settings"
/// </summary>
public int BaudRate = 115200;
/// <summary>
/// The parity checking scheme (default: none)
/// </summary>
public Parity Parity = Parity.None;
/// <summary>
/// Number of databits 1..8 (default: 8) unsupported values will throw "Bad settings"
/// </summary>
public int DataBits = 8;
/// <summary>
/// Number of stop bits (default: one)
/// </summary>
public StopBits StopBits = StopBits.One;
/// <summary>
/// If true, transmission is halted unless CTS is asserted by the remote station (default: false)
/// </summary>
public bool TxFlowCts;
/// <summary>
/// If true, transmission is halted unless DSR is asserted by the remote station (default: false)
/// </summary>
public bool TxFlowDsr;
/// <summary>
/// If true, transmission is halted when Xoff is received and restarted when Xon is received (default: false)
/// </summary>
public bool TxFlowX;
/// <summary>
/// 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.
/// </summary>
public bool TxWhenRxXoff = true;
/// <summary>
/// If true, received characters are ignored unless DSR is asserted by the remote station (default: false)
/// </summary>
public bool RxGateDsr;
/// <summary>
/// If true, Xon and Xoff characters are sent to control the data flow from the remote station (default: false)
/// </summary>
public bool RxFlowX;
/// <summary>
/// Specifies the use to which the RTS output is put (default: none)
/// </summary>
public HsOutput UseRts = HsOutput.None;
/// <summary>
/// Specidies the use to which the DTR output is put (default: none)
/// </summary>
public HsOutput UseDtr = HsOutput.None;
/// <summary>
/// The character used to signal Xon for X flow control (default: DC1)
/// </summary>
public ASCII XonChar = ASCII.DC1;
/// <summary>
/// The character used to signal Xoff for X flow control (default: DC3)
/// </summary>
public ASCII XoffChar = ASCII.DC3;
/// <summary>
/// The number of free bytes in the reception queue at which flow is disabled (default: 2048)
/// </summary>
public int RxHighWater = 2048;
/// <summary>
/// The number of bytes in the reception queue at which flow is re-enabled (default: 512)
/// </summary>
public int RxLowWater = 512;
/// <summary>
/// Multiplier. Max time for Send in ms = (Multiplier * Characters) + Constant
/// (default: 0 = No timeout)
/// </summary>
public int SendTimeoutMultiplier;
/// <summary>
/// Constant. Max time for Send in ms = (Multiplier * Characters) + Constant (default: 0)
/// </summary>
public int SendTimeoutConstant;
/// <summary>
/// Requested size for receive queue (default: 0 = use operating system default)
/// </summary>
public int RxQueue;
/// <summary>
/// Requested size for transmit queue (default: 0 = use operating system default)
/// </summary>
public int TxQueue;
/// <summary>
/// If true, the port will automatically re-open on next send if it was previously closed due
/// to an error (default: false)
/// </summary>
public bool AutoReopen;
/// <summary>
/// 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.
/// </summary>
public bool CheckAllSends = true;
private Handshake _handShake;
public Handshake Handshake
{
get { return _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;
}
}
}
} }
} }