Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System; using System.Text; using System.Collections.Generic;
- using System.IO; using System.IO.Ports; using System.Runtime.InteropServices;
- using Microsoft.Win32.SafeHandles; using System.Threading;
- namespace Fire { public class ComStream: Stream {
- //##################################################################################################
- public enum IMPL {
- [Display("P/Invoke", XX="native")] NATIVE,
- [Display("FileStream", XX="stream")] STREAM,
- [Display("SerialPort", XX="serial")] SERIAL }
- #if MONO
- public static IMPL Implementation = IMPL.SERIAL;
- #else
- public static IMPL Implementation = IMPL.STREAM;
- #endif
- public static bool UseAsync = Environment.OSVersion.Platform != PlatformID.Win32Windows;
- //[Obsolete]
- public static bool UseFileStream { get { return Implementation == IMPL.STREAM; }
- set { Implementation = value ? IMPL.STREAM : IMPL.NATIVE; } }
- public static bool UseSerialPort { get { return Implementation == IMPL.SERIAL; }
- set { Implementation = value ? IMPL.SERIAL : IMPL.STREAM; } }
- //==================================================================================================
- protected byte port;
- protected SerialPort serport;
- #if !MONO
- protected FileStream fstream;
- protected SafeFileHandle handle;
- protected WinApi.DCB dcb;
- protected WinApi.COMMTIMEOUTS tmos;
- #endif
- protected void SafeClearHandle() {
- #if MONO
- try { serport.Close(); } catch { }
- serport = null;
- #else
- if(serport != null) {
- try { serport.Close(); } catch { }
- serport = null; return; }
- SafeFileHandle toClose = handle;
- this.handle = null;
- if(toClose == null) return;
- if(fstream != null) {
- try { fstream.Close(); } catch { }
- fstream = null; }
- try { toClose.Close(); } catch { }
- #endif
- }
- protected override void Dispose(bool disposing) {
- if(disposing) try { Flush(); } catch { }
- SafeClearHandle();
- base.Dispose(disposing); }
- protected ComStream(byte port) {
- this.port = port;
- #if !MONO
- if(Implementation != IMPL.SERIAL) {
- handle = WinApi.OpenFile(@"\\.\COM" + port.ToString(), WinApi.OPEN_EXISTING,
- UseAsync ? WinApi.FILE_FLAG_OVERLAPPED : WinApi.FILE_ATTRIBUTE_NORMAL);
- if(handle.IsInvalid) {
- handle = null; Throw.WinIO("COM{0} open", port); }
- try {
- tmos.ReadIntervalTimeout = 1; // 1ms max between bytes
- tmos.ReadTotalTimeoutMultiplier = 0; // don't use - big buffers ;)
- tmos.ReadTotalTimeoutConstant = 333; // 1/3s max for read
- tmos.WriteTotalTimeoutConstant = 1000; // 1s max for write
- tmos.WriteTotalTimeoutMultiplier = 2; // add max 2ms per byte write
- dcb.DCBlength = (uint)Marshal.SizeOf(dcb);
- if(!WinApi.GetCommState(handle, ref dcb)) Throw.WinIO("COM{0} get settings", port);
- dcb.DCBlength = (uint)Marshal.SizeOf(dcb);
- dcb.Flags = WinApi.DCB.fBinary|WinApi.DCB.fCtsFlow|WinApi.DCB.fDtrOn|WinApi.DCB.fRtsOn|WinApi.DCB.fAbort;
- dcb.ByteSize = 8;
- dcb.Parity = 0;
- dcb.StopBits = 0;
- } catch { SafeClearHandle(); throw; } return; }
- #endif
- string name = WinApi.WinVer != WinVer.Unix ? "COM" + port.ToString()
- : port < 20 ? "/dev/ttyS" + port.ToString()
- : port < 50 ? "/dev/ttyACM" + (port-20).ToString()
- : "/dev/ttyUSB" + (port-50).ToString();
- if(WinApi.WinVer == WinVer.Unix && !File.Exists(name))
- Throw.IO("{0} does not exist", name);
- serport = new SerialPort(name, 115200) {
- DtrEnable = true, RtsEnable = true };
- }
- protected void SetCommState() {
- #if !MONO
- if(serport != null) return;
- if(!WinApi.SetCommState(handle, ref dcb)) Throw.WinIO("COM{0} set settings", port);
- #endif
- }
- protected void SetCommTimeouts() {
- #if !MONO
- if(serport != null) return;
- if(!WinApi.SetCommTimeouts(handle, ref tmos)) Throw.WinIO("COM{0} set timeouts", port);
- #endif
- }
- protected void Init() {
- try {
- #if MONO
- serport.Open();
- #else
- if(UseSerialPort)
- serport.Open();
- else {
- SetCommState();
- SetCommTimeouts();
- if(UseFileStream) fstream = new FileStream(handle, FileAccess.ReadWrite, 0x1000, UseAsync);
- }
- #endif
- } catch { SafeClearHandle(); throw; }}
- protected static byte CheckPortNumber(int port) {
- if(port < 0 || port > 99) Throw.Range("port");
- return (byte)port; }
- public ComStream(int port) : this(CheckPortNumber(port)) { Init(); }
- public ComStream(int port, uint rate) : this(CheckPortNumber(port)) {
- #if MONO
- serport.BaudRate = rate > 0 ? (int)rate : 115200;
- #else
- dcb.BaudRate = rate;
- #endif
- Init(); }
- public ComStream(int port, uint rate, Handshake flow) : this(CheckPortNumber(port)) {
- #if MONO
- serport.BaudRate = rate > 0? (int)rate : 115200;
- serport.Handshake = flow;
- #else
- dcb.Flags &=~(WinApi.DCB.fRtsMask|WinApi.DCB.fXIn|WinApi.DCB.fXOut);
- dcb.Flags |= (flow & Handshake.RequestToSend) != Handshake.None ? WinApi.DCB.fRtsFlow : WinApi.DCB.fRtsOn;
- if((flow & Handshake.XOnXOff) != Handshake.None) dcb.Flags |= WinApi.DCB.fXOut|WinApi.DCB.fXIn;
- dcb.BaudRate = rate;
- #endif
- Init(); }
- //--------------------------------------------------------------------------------------------------
- public int BytesToRead { get {
- if(serport != null) return serport.BytesToRead;
- WinApi.COMSTAT stat = new WinApi.COMSTAT();
- WinApi.ClearCommError(handle, IntPtr.Zero, out stat);
- return (int)stat.cbInQue; } }
- #if !MONO
- private int read(byte[] buffer, int offset, int count) {
- if(serport != null) return serport.Read(buffer, offset, count);
- if(fstream != null) return fstream.Read(buffer, offset, count);
- return WinApi.ReadFile(handle, buffer, offset, count); }
- #endif
- public override int Read(byte[] buffer, int offset, int count) {
- if(count <= 0) return 0;
- #if MONO
- int inq = serport.BytesToRead;
- if(inq <= 0) return inq;
- if(count > inq) count = inq;
- return serport.Read(buffer, offset, count);
- #else
- int inq = BytesToRead;
- if(inq > 0) {
- if(count > inq) count = inq;
- return read(buffer, offset, count); }
- int num = read(buffer, offset, 1);
- if(num <= 0) return num;
- offset += num;
- count -= num;
- inq = BytesToRead;
- if(count > inq) count = inq;
- return num + read(buffer, offset, count);
- #endif
- }
- public override void Write(byte[] buffer, int offset, int count) {
- #if MONO
- serport.Write(buffer, offset, count);
- #else
- if(serport != null) { serport.Write(buffer, offset, count); }
- else if(fstream != null) { fstream.Write(buffer, offset, count); fstream.Flush(); }
- else WinApi.WriteFile(handle, buffer, offset, count);
- #endif
- }
- public override void Flush() {
- #if !MONO
- // can result in lockdown on win7
- // if(handle != null) WinApi.FlushFileBuffers(handle);
- if(fstream != null) fstream.Flush();
- #endif
- }
- //--------------------------------------------------------------------------------------------------
- public byte Port {
- get { return port; } }
- public Handshake Handshake {
- get {
- #if MONO
- return serport.Handshake;
- #else
- if(serport != null) return serport.Handshake;
- Handshake flow = Handshake.None;
- if((dcb.Flags & WinApi.DCB.fRtsFlow) != 0) flow |= Handshake.RequestToSend;
- if((dcb.Flags & WinApi.DCB.fXIn) != 0) flow |= Handshake.XOnXOff;
- return flow;
- #endif
- }
- set {
- #if MONO
- serport.Handshake = value;
- #else
- if(serport != null) {
- serport.Handshake = value; return; }
- uint flags = dcb.Flags;
- try {
- dcb.Flags &=~(WinApi.DCB.fRtsMask|WinApi.DCB.fXIn|WinApi.DCB.fXOut);
- dcb.Flags |= (value & Handshake.RequestToSend) != Handshake.None ? WinApi.DCB.fRtsFlow : WinApi.DCB.fRtsOn;
- if((value & Handshake.XOnXOff) != Handshake.None) dcb.Flags |= WinApi.DCB.fXOut|WinApi.DCB.fXIn;
- if(!WinApi.SetCommState(handle, ref dcb)) Throw.WinIO("COM{0} set settings", port);
- } catch {
- dcb.Flags = flags;
- throw; }
- #endif
- }}
- public uint BaudRate {
- get {
- #if MONO
- return (uint)serport.BaudRate;
- #else
- return dcb.BaudRate;
- #endif
- }
- set {
- #if MONO
- serport.BaudRate = (int)value;
- #else
- uint rate = dcb.BaudRate;
- try {
- dcb.BaudRate = value;
- SetCommState();
- } catch {
- dcb.BaudRate = rate;
- throw; }
- #endif
- }}
- //--------------------------------------------------------------------------------------------------
- #if MONO
- public override bool CanRead { get { return serport != null; } }
- public override bool CanWrite { get { return serport != null; } }
- #else
- public override bool CanRead { get { return handle != null || serport != null; } }
- public override bool CanWrite { get { return handle != null || serport != null; } }
- #endif
- public override bool CanTimeout { get { return false; /* TODO */ } }
- public override bool CanSeek { get { return false; } }
- public override long Length { get { throw new NotImplementedException(); } }
- public override void SetLength(long value) { throw new NotImplementedException(); }
- public override long Position {
- get { throw new NotImplementedException(); }
- set { throw new NotImplementedException(); } }
- public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); }
- }}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement