//
using System;
-using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace System.IO.Ports
{
- public class WinSerialStream : Stream, IDisposable
+ class WinSerialStream : Stream, ISerialStream, IDisposable
{
// Windows API Constants
const uint GenericRead = 0x80000000;
const uint WinInfiniteTimeout = 0xFFFFFFFF;
const uint FileIOPending = 997;
+ // Signal constants
+ const uint SetRts = 3;
+ const uint ClearRts = 4;
+ const uint SetDtr = 5;
+ const uint ClearDtr = 6;
+ const uint SetBreak = 8;
+ const uint ClearBreak = 9;
+ const uint CtsOn = 0x0010;
+ const uint DsrOn = 0x0020;
+ const uint RsldOn = 0x0080;
+
+ // Event constants
+ const uint EvRxChar = 0x0001;
+ const uint EvCts = 0x0008;
+ const uint EvDsr = 0x0010;
+ const uint EvRlsd = 0x0020;
+ const uint EvBreak = 0x0040;
+ const uint EvErr = 0x0080;
+ const uint EvRing = 0x0100;
+
int handle;
int read_timeout;
int write_timeout;
[DllImport("kernel32", SetLastError = true)]
static extern bool SetCommTimeouts(int handle, Timeouts timeouts);
- public unsafe WinSerialStream (string port_name, int baud_rate, int data_bits, Parity parity,
- StopBits sb, Handshake hs, int read_timeout, int write_timeout,
+ public WinSerialStream (string port_name, int baud_rate, int data_bits, Parity parity, StopBits sb,
+ bool dtr_enable, bool rts_enable, Handshake hs, int read_timeout, int write_timeout,
int read_buffer_size, int write_buffer_size)
{
handle = CreateFile (port_name, GenericRead | GenericWrite, 0, 0, OpenExisting,
FileFlagOverlapped, 0);
if (handle == -1)
- ReportIOError(port_name);
+ ReportIOError (port_name);
// Set port low level attributes
SetAttributes (baud_rate, parity, data_bits, sb, hs);
if (!SetCommTimeouts(handle, timeouts))
ReportIOError (null);
+ /// Set DTR and RTS
+ SetSignal(SerialSignal.Dtr, dtr_enable);
+
+ if (hs != Handshake.RequestToSend &&
+ hs != Handshake.RequestToSendXOnXOff)
+ SetSignal(SerialSignal.Rts, rts_enable);
+
// Init overlapped structures
NativeOverlapped wo = new NativeOverlapped ();
write_event = new ManualResetEvent (false);
+#if NET_2_0
+ wo.EventHandle = write_event.Handle;
+#else
wo.EventHandle = (int) write_event.Handle;
+#endif
write_overlapped = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (NativeOverlapped)));
Marshal.StructureToPtr (wo, write_overlapped, true);
NativeOverlapped ro = new NativeOverlapped ();
read_event = new ManualResetEvent (false);
+#if NET_2_0
+ ro.EventHandle = read_event.Handle;
+#else
ro.EventHandle = (int) read_event.Handle;
+#endif
read_overlapped = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (NativeOverlapped)));
Marshal.StructureToPtr (ro, read_overlapped, true);
}
throw new NotSupportedException();
}
+#if !TARGET_JVM
[DllImport("kernel32", SetLastError = true)]
static extern unsafe bool ReadFile (int handle, byte* buffer, int bytes_to_read,
out int bytes_read, IntPtr overlapped);
[DllImport("kernel32", SetLastError = true)]
static extern unsafe bool GetOverlappedResult (int handle, IntPtr overlapped,
ref int bytes_transfered, bool wait);
+#endif
- public override unsafe int Read ([In, Out] byte [] buffer, int offset, int count)
+ public override int Read ([In, Out] byte [] buffer, int offset, int count)
{
CheckDisposed ();
if (buffer == null)
throw new ArgumentNullException ("buffer");
- if (offset < 0 || offset >= buffer.Length)
- throw new ArgumentOutOfRangeException ("offset");
- if (count < 0 || count > buffer.Length)
- throw new ArgumentOutOfRangeException ("count");
- if (count > buffer.Length - offset)
- throw new ArgumentException ();
-
- int bytes_read;
+ if (offset < 0 || count < 0)
+ throw new ArgumentOutOfRangeException ("offset or count less than zero.");
- fixed (byte* ptr = buffer) {
- if (ReadFile (handle, ptr + offset, count, out bytes_read, read_overlapped))
- return bytes_read;
+ if (buffer.Length - offset < count )
+ throw new ArgumentException ("offset+count",
+ "The size of the buffer is less than offset + count.");
- // Test for overlapped behavior
- if (Marshal.GetLastWin32Error () != FileIOPending)
- ReportIOError (null);
+ int bytes_read;
- if (!GetOverlappedResult (handle, read_overlapped, ref bytes_read, true))
- ReportIOError (null);
+ unsafe {
+ fixed (byte* ptr = buffer) {
+ if (ReadFile (handle, ptr + offset, count, out bytes_read, read_overlapped))
+ return bytes_read;
+
+ // Test for overlapped behavior
+ if (Marshal.GetLastWin32Error () != FileIOPending)
+ ReportIOError (null);
+
+ if (!GetOverlappedResult (handle, read_overlapped, ref bytes_read, true))
+ ReportIOError (null);
+
+ }
}
if (bytes_read == 0)
return bytes_read;
}
+#if !TARGET_JVM
[DllImport("kernel32", SetLastError = true)]
static extern unsafe bool WriteFile (int handle, byte* buffer, int bytes_to_write,
out int bytes_written, IntPtr overlapped);
+#endif
- public override unsafe void Write (byte [] buffer, int offset, int count)
+ public override void Write (byte [] buffer, int offset, int count)
{
CheckDisposed ();
if (buffer == null)
throw new ArgumentNullException ("buffer");
- if (offset < 0 || offset >= buffer.Length)
- throw new ArgumentOutOfRangeException ("offset");
- if (count < 0 || count > buffer.Length)
- throw new ArgumentOutOfRangeException ("count");
- if (count > buffer.Length - offset)
- throw new ArgumentException ("count > buffer.Length - offset");
- int bytes_written = 0;
+ if (offset < 0 || count < 0)
+ throw new ArgumentOutOfRangeException ();
- fixed (byte* ptr = buffer) {
- if (WriteFile (handle, ptr + offset, count, out bytes_written, write_overlapped))
- return;
+ if (buffer.Length - offset < count)
+ throw new ArgumentException ("offset+count",
+ "The size of the buffer is less than offset + count.");
- if (Marshal.GetLastWin32Error() != FileIOPending)
- ReportIOError (null);
+ int bytes_written = 0;
- if (!GetOverlappedResult(handle, write_overlapped, ref bytes_written, true))
- ReportIOError (null);
+ unsafe {
+ fixed (byte* ptr = buffer) {
+ if (WriteFile (handle, ptr + offset, count, out bytes_written, write_overlapped))
+ return;
+ if (Marshal.GetLastWin32Error() != FileIOPending)
+ ReportIOError (null);
+
+ if (!GetOverlappedResult(handle, write_overlapped, ref bytes_written, true))
+ ReportIOError (null);
+ }
}
// If the operation timed out, then
[DllImport ("kernel32", SetLastError=true)]
static extern bool SetCommState (int handle, DCB dcb);
- void SetAttributes (int baud_rate, Parity parity, int data_bits, StopBits bits, Handshake hs)
+ public void SetAttributes (int baud_rate, Parity parity, int data_bits, StopBits bits, Handshake hs)
{
DCB dcb = new DCB ();
if (!GetCommState (handle, dcb))
throw new ObjectDisposedException (GetType ().FullName);
}
+ // ISerialStream members
+ public void DiscardInBuffer ()
+ {
+ if (!PurgeComm (handle, PurgeRxClear))
+ ReportIOError (null);
+ }
+
+ public void DiscardOutBuffer ()
+ {
+ if (!PurgeComm (handle, PurgeRxClear))
+ ReportIOError (null);
+ }
+
+ [DllImport ("kernel32", SetLastError=true)]
+ static extern bool ClearCommError (int handle, out CommStat stat);
+
+ public int BytesToRead {
+ get {
+ CommStat stat;
+ if (!ClearCommError (handle, out stat))
+ ReportIOError (null);
+
+ return (int)stat.BytesIn;
+ }
+ }
+
+ public int BytesToWrite {
+ get {
+ CommStat stat;
+ if (!ClearCommError (handle, out stat))
+ ReportIOError (null);
+
+ return (int)stat.BytesOut;
+ }
+ }
+
+ [DllImport ("kernel32", SetLastError=true)]
+ static extern bool GetCommModemStatus (int handle, out uint flags);
+
+ public SerialSignal GetSignals ()
+ {
+ uint flags;
+ if (!GetCommModemStatus (handle, out flags))
+ ReportIOError (null);
+
+ SerialSignal signals = SerialSignal.None;
+ if ((flags & RsldOn) != 0)
+ signals |= SerialSignal.Cd;
+ if ((flags & CtsOn) != 0)
+ signals |= SerialSignal.Cts;
+ if ((flags & DsrOn) != 0)
+ signals |= SerialSignal.Dsr;
+
+ return signals;
+ }
+
+ [DllImport ("kernel32", SetLastError=true)]
+ static extern bool EscapeCommFunction (int handle, uint flags);
+
+ public void SetSignal (SerialSignal signal, bool value)
+ {
+ if (signal != SerialSignal.Rts && signal != SerialSignal.Dtr)
+ throw new Exception ("Wrong internal value");
+
+ uint flag;
+ if (signal == SerialSignal.Rts)
+ if (value)
+ flag = SetRts;
+ else
+ flag = ClearRts;
+ else
+ if (value)
+ flag = SetDtr;
+ else
+ flag = ClearDtr;
+
+ if (!EscapeCommFunction (handle, flag))
+ ReportIOError (null);
+ }
+
+ public void SetBreakState (bool value)
+ {
+ if (!EscapeCommFunction (handle, value ? SetBreak : ClearBreak))
+ ReportIOError (null);
+ }
+
}
[StructLayout (LayoutKind.Sequential)]
public byte evt_char;
public short w_reserved1;
+ // flags:
+ //const int fBinary = 0x0001;
+ //const int fParity = 0x0002;
+ const int fOutxCtsFlow = 0x0004;
+ //const int fOutxDsrFlow1 = 0x0008;
+ //const int fOutxDsrFlow2 = 0x0010;
+ //const int fDtrControl = 0x00020;
+ //const int fDsrSensitivity = 0x0040;
+ //const int fTXContinueOnXoff = 0x0080;
+ const int fOutX = 0x0100;
+ const int fInX = 0x0200;
+ //const int fErrorChar = 0x0400;
+ //const int fNull = 0x0800;
+ //const int fRtsControl1 = 0x1000;
+ const int fRtsControl2 = 0x2000;
+ //const int fAbortOnError = 0x4000;
+
public void SetValues (int baud_rate, Parity parity, int byte_size, StopBits sb, Handshake hs)
{
switch (sb) {
}
this.baud_rate = baud_rate;
- this.parity = (byte) parity;
- this.byte_size = (byte) byte_size;
- }
+ this.parity = (byte)parity;
+ this.byte_size = (byte)byte_size;
+
+ // Clear Handshake flags
+ flags &= ~(fOutxCtsFlow | fOutX | fInX | fRtsControl2);
+ // Set Handshake flags
+ switch (hs)
+ {
+ case Handshake.None:
+ break;
+ case Handshake.XOnXOff:
+ flags |= fOutX | fInX;
+ break;
+ case Handshake.RequestToSend:
+ flags |= fOutxCtsFlow | fRtsControl2;
+ break;
+ case Handshake.RequestToSendXOnXOff:
+ flags |= fOutxCtsFlow | fOutX | fInX | fRtsControl2;
+ break;
+ default: // Shouldn't happen
+ break;
+ }
+ }
}
[StructLayout (LayoutKind.Sequential)]
}
}
+
+ [StructLayout (LayoutKind.Sequential)]
+ class CommStat
+ {
+ public uint flags;
+ public uint BytesIn;
+ public uint BytesOut;
+ }
}
#endif