📄 serialstream.cs
字号:
{
if(value != parityReplace)
{
byte parityReplaceOld = parityReplace;
byte errorCharOld = dcb.ErrorChar;
int fErrorCharOld = GetDcbFlag(NativeMethods.FERRORCHAR);
parityReplace = value;
if (GetDcbFlag(NativeMethods.FPARITY) == 1)
{
SetDcbFlag(NativeMethods.FERRORCHAR, (parityReplace != '\0')? 1 : 0);
dcb.ErrorChar = parityReplace;
}
else
{
SetDcbFlag(NativeMethods.FERRORCHAR, 0);
dcb.ErrorChar = (byte) '\0';
}
if (UnsafeNativeMethods.SetCommState(_handleProtector.Handle, ref dcb) == false)
{
parityReplace = parityReplaceOld;
SetDcbFlag(NativeMethods.FERRORCHAR, fErrorCharOld);
dcb.ErrorChar = errorCharOld;
InternalResources.WinIOError();
}
}
}
}
// Timeouts are considered to be TOTAL time for the Read/Write operation and to be in milliseconds.
// Timeouts are translated into DCB structure as follows:
// Desired timeout => ReadTotalTimeoutConstant ReadTotalTimeoutMultiplier ReadIntervalTimeout
// 0 0 0 MAXDWORD
// 0 < n < infinity n MAXDWORD MAXDWORD
// infinity Int32.MaxValue MAXDWORD MAXDWORD
//
// rationale for "infinity": There does not exist in the COMMTIMEOUTS structure a way to
// *wait indefinitely for any byte, return when found*. Instead, if we set ReadTimeout
// to infinity, SerialStream's EndRead loops if Int32.MaxValue mills have elapsed
// without a byte received. Note that this is approximately 24 days, so essentially
// most practical purposes effectively equate 24 days with an infinite amount of time
// on a serial port connection.
internal int ReadTimeout
{
get
{
int constant = commTimeouts.ReadTotalTimeoutConstant;
// any time user sets timeout to Int32.MaxValue, timeout is assumed
// to be infinite, and not 2^31 - 1 milliseconds ~= 24 days
if (constant == Int32.MaxValue) return SerialPort.InfiniteTimeout;
else return constant;
}
set
{
if (value < 0 && value != SerialPort.InfiniteTimeout)
throw new ArgumentOutOfRangeException("readTimeout", InternalResources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
int oldReadConstant = commTimeouts.ReadTotalTimeoutConstant;
int oldReadInterval = commTimeouts.ReadIntervalTimeout;
int oldReadMultipler = commTimeouts.ReadTotalTimeoutMultiplier;
if (value == 0) {
commTimeouts.ReadTotalTimeoutConstant = commTimeouts.ReadTotalTimeoutMultiplier = 0;
commTimeouts.ReadIntervalTimeout = NativeMethods.MAXDWORD;
} else if (value == SerialPort.InfiniteTimeout) {
commTimeouts.ReadTotalTimeoutConstant = Int32.MaxValue;
commTimeouts.ReadTotalTimeoutMultiplier = commTimeouts.ReadIntervalTimeout = NativeMethods.MAXDWORD;
} else {
commTimeouts.ReadTotalTimeoutConstant = value;
commTimeouts.ReadTotalTimeoutMultiplier = commTimeouts.ReadIntervalTimeout = NativeMethods.MAXDWORD;
}
if (UnsafeNativeMethods.SetCommTimeouts(_handleProtector.Handle, ref commTimeouts) == false)
{
commTimeouts.ReadTotalTimeoutConstant = oldReadConstant;
commTimeouts.ReadTotalTimeoutMultiplier = oldReadMultipler;
commTimeouts.ReadIntervalTimeout = oldReadInterval;
InternalResources.WinIOError();
}
}
}
internal bool RtsEnable
{
get { return rtsEnable; }
set
{
if(value != rtsEnable)
{
bool rtsEnableOld = rtsEnable;
int fRtsControlOld = GetDcbFlag(NativeMethods.FRTSCONTROL);
rtsEnable = value;
if ((handshake == Handshake.RequestToSend ||
handshake == Handshake.RequestToSendXOnXOff))
{
SetDcbFlag(NativeMethods.FRTSCONTROL, NativeMethods.RTS_CONTROL_HANDSHAKE);
}
else if(rtsEnable)
{
SetDcbFlag(NativeMethods.FRTSCONTROL, NativeMethods.RTS_CONTROL_ENABLE);
}
else
{
SetDcbFlag(NativeMethods.FRTSCONTROL, NativeMethods.RTS_CONTROL_DISABLE);
}
if (UnsafeNativeMethods.SetCommState(_handleProtector.Handle, ref dcb) == false)
{
rtsEnable = rtsEnableOld;
SetDcbFlag(NativeMethods.FRTSCONTROL, fRtsControlOld);
InternalResources.WinIOError();
}
}
}
}
// StopBits represented in C# as StopBits enum type and in Win32 as an integer 1, 2, or 3.
internal StopBits StopBits
{
get
{
switch(dcb.StopBits)
{
case NativeMethods.ONESTOPBIT:
return StopBits.One;
case NativeMethods.ONE5STOPBITS:
return StopBits.OnePointFive;
case NativeMethods.TWOSTOPBITS:
return StopBits.Two;
default:
Debug.Assert(true, "Invalid Stopbits value " + dcb.StopBits);
return StopBits.One;
}
}
set
{
if(value < StopBits.One || value > StopBits.OnePointFive)
throw new ArgumentOutOfRangeException("stopBits", InternalResources.GetResourceString("ArgumentOutOfRange_Enum"));
byte nativeValue = 0;
if (value == StopBits.One) nativeValue = (byte) NativeMethods.ONESTOPBIT;
else if (value == StopBits.OnePointFive) nativeValue = (byte) NativeMethods.ONE5STOPBITS;
else if (value == StopBits.Two) nativeValue = (byte) NativeMethods.TWOSTOPBITS;
else Debug.Assert(true, "Invalid Stopbits value " + value);
if(nativeValue != dcb.StopBits)
{
byte stopBitsOld = dcb.StopBits;
if (UnsafeNativeMethods.SetCommState(_handleProtector.Handle, ref dcb) == false)
{
dcb.StopBits = stopBitsOld;
InternalResources.WinIOError();
}
}
}
}
// note: WriteTimeout must be either SerialPort.InfiniteTimeout or POSITIVE.
// a timeout of zero implies that every Write call throws an exception.
internal int WriteTimeout
{
get
{
int timeout = commTimeouts.WriteTotalTimeoutConstant;
return (timeout == 0) ? SerialPort.InfiniteTimeout : timeout;
}
set
{
if (value <= 0 && value != SerialPort.InfiniteTimeout)
throw new ArgumentOutOfRangeException("WriteTimeout", InternalResources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
int oldWriteConstant = commTimeouts.WriteTotalTimeoutConstant;
commTimeouts.WriteTotalTimeoutConstant = ((value == SerialPort.InfiniteTimeout) ? 0 : value);
if (UnsafeNativeMethods.SetCommTimeouts(_handleProtector.Handle, ref commTimeouts) == false)
{
commTimeouts.WriteTotalTimeoutConstant = oldWriteConstant;
InternalResources.WinIOError();
}
}
}
// CDHolding, CtsHolding, DsrHolding query the current state of each of the carrier, the CTS pin,
// and the DSR pin, respectively. Read-only.
// All will throw exceptions if the port is not open.
internal bool CDHolding
{
get
{
int pinStatus = 0;
if (UnsafeNativeMethods.GetCommModemStatus(_handleProtector.Handle, ref pinStatus) == false)
InternalResources.WinIOError();
return (NativeMethods.MS_RLSD_ON & pinStatus) != 0;
}
}
internal bool CtsHolding
{
get
{
int pinStatus = 0;
if (UnsafeNativeMethods.GetCommModemStatus(_handleProtector.Handle, ref pinStatus) == false)
InternalResources.WinIOError();
return (NativeMethods.MS_CTS_ON & pinStatus) != 0;
}
}
internal bool DsrHolding
{
get
{
int pinStatus = 0;
if (UnsafeNativeMethods.GetCommModemStatus(_handleProtector.Handle, ref pinStatus) == false)
InternalResources.WinIOError();
return (NativeMethods.MS_DSR_ON & pinStatus) != 0;
}
}
// Fills comStat structure from an unmanaged function
// to determine the number of bytes waiting in the serial driver's internal receive buffer.
internal int InBufferBytes
{
get
{
int errorCode = 0; // "ref" arguments need to have values, as opposed to "out" arguments
if (UnsafeNativeMethods.ClearCommError(_handleProtector.Handle, ref errorCode, ref comStat) == false)
{
InternalResources.WinIOError();
}
return (int) comStat.cbInQue;
}
}
// Fills comStat structure from an unmanaged function
// to determine the number of bytes waiting in the serial driver's internal transmit buffer.
internal int OutBufferBytes
{
get
{
int errorCode = 0; // "ref" arguments need to be set before method invocation, as opposed to "out" arguments
if (UnsafeNativeMethods.ClearCommError(_handleProtector.Handle, ref errorCode, ref comStat) == false)
InternalResources.WinIOError();
return (int) comStat.cbOutQue;
}
}
// -----------SECTION: constructor --------------------------*
// this method is used by SerialPort upon SerialStream's creation
internal SerialStream(string resource, int baudRate, Parity parity, int dataBits, StopBits stopBits, int readTimeout, int writeTimeout, Handshake handshake,
bool dtrEnable, bool rtsEnable, bool discardNull, byte parityReplace)
{
//Error checking done in SerialPort.
IntPtr tempHandle = UnsafeNativeMethods.CreateFile("\\\\.\\" + resource,
NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE,
0, // comm devices must be opened w/exclusive-access
NativeMethods.NULL, // no security attributes
UnsafeNativeMethods.OPEN_EXISTING, // comm devices must use OPEN_EXISTING
UnsafeNativeMethods.FILE_FLAG_OVERLAPPED |
UnsafeNativeMethods.FILE_ATTRIBUTE_NORMAL, // async I/O
NativeMethods.NULL // hTemplate must be NULL for comm devices
);
if (tempHandle == NativeMethods.INVALID_HANDLE_VALUE)
{
int errorCode = Marshal.GetLastWin32Error();
switch(errorCode)
{
case NativeMethods.ERROR_FILE_NOT_FOUND:
throw new FileNotFoundException("resource", InternalResources.GetResourceString("IO.FileNotFound_FileName", resource));
case NativeMethods.ERROR_ACCESS_DENIED:
throw new UnauthorizedAccessException(InternalResources.GetResourceString("UnauthorizedAccess_IODenied_Path", resource));
default:
InternalResources.WinIOError();
break;
}
}
if (UnsafeNativeMethods.GetFileType(tempHandle) != UnsafeNativeMethods.FILE_TYPE_CHAR)
throw new ArgumentException("resource", InternalResources.GetResourceString("Arg_InvalidResourceFile"));
_handleProtector = new __HandleProtector(tempHandle, true);
// set properties of the stream that exist as members in SerialStream
this.portName = resource;
this.handshake = handshake;
this.dtrEnable = dtrEnable;
this.rtsEnable = rtsEnable;
this.parityReplace = parityReplace;
tempBuf = new byte[1]; // used in ReadByte()
// fill COMMPROPERTIES struct, which has our maximum allowed baud rate
commProp = new UnsafeNativeMethods.COMMPROP();
if (UnsafeNativeMethods.GetCommProperties(_handleProtector.Handle, ref commProp) == false)
{
UnsafeNativeMethods.CloseHandle(_handleProtector.Handle);
InternalResources.WinIOError();
}
if (baudRate > commProp.dwMaxBaud)
throw new ArgumentOutOfRangeException("baudRate", "Requested baud greater than maximum for this device driver = " + commProp.dwMaxBaud);
comStat = new UnsafeNativeMethods.COMSTAT();
// create internal DCB structure, initialize according to Platform SDK
// standard: ms-help://MS.MSNDNQTR.2002APR.1003/hardware/commun_965u.htm
dcb = new UnsafeNativeMethods.DCB();
// set constant properties of the DCB
InitializeDCB(baudRate, parity, dataBits, stopBits, discardNull);
// set timeout defaults
commTimeouts.ReadIntervalTimeout = (readTimeout == SerialPort.InfiniteTimeout) ? 0 : NativeMethods.MAXDWORD;
commTimeouts.ReadTotalTimeoutMultiplier = (readTimeout > 0 && readTimeout != SerialPort.InfiniteTimeout)
? NativeMethods.MAXDWORD : 0;
commTimeouts.ReadTotalTimeoutConstant = (readTimeout > 0 && readTimeout != SerialPort.InfiniteTimeout) ?
readTimeout : 0;
commTimeouts.WriteTotalTimeoutMultiplier = 0;
commTimeouts.WriteTotalTimeoutConstant = ((writeTimeout == SerialPort.InfiniteTimeout) ?
0 : writeTimeout);
// note - we cannot have a meaningful conception of a 0 write timeout, since every write takes at
// least 0 mills.
// set unmanaged timeout structure
if (UnsafeNativeMethods.SetCommTimeouts(_handleProtector.Handle, ref commTimeouts) == false)
{
UnsafeNativeMethods.CloseHandle(_handleProtector.Handle);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -