Fixed a base class of serial communication under several bugs .NET

zhaozj2021-02-16  54

Fixed a base class of serial communication under several bugs .NET

Using system;

Using system.runtime.interopservices; using system.threading; using system.io; using system.xml.serialization;

Namespace xst.xstcomm.base {////

/// Lowest Level COM Driver Handling All Win32 API Calls and Processing Send and received in Terms of /// Individual Bytes. Used as a base class for higher level drivers. ///

Public Abstract Class CommBase: IDisposable

{

PRIVATE INTPTR HPORT;

PRIVATE INTPTR PTRUWO = INTPTR.ZERO;

Private thread rxthread = null;

PRIVATE BOOL online = false;

PRIVATE BOOL Auto = FALSE;

Private bool checksends = true;

PRIVATE EXCETION RXEXCEPTION = NULL;

Private bool rxExceptionReported = false;

PRIVATE INT WRITECOUNT = 0;

Private manualReveTevent WriteEvent = New ManualReveTevent (false);

// JH 1.2: Added Below To Improve Robustness of Thread Start-Up.

Private manualReveTevent Startevent = New ManualReveTevent (false);

Private int staterts = 2;

Private int stat = 2;

Private Int Statebrk = 2;

// JH 1.3: Added to support The New Congestion Detection Scheme (FOLLOWING TWO "):

Private bool [] EMPTY = New bool [1];

PRIVATE BOOL DATAQUED = FALSE;

///

/// Parity Settings ////

Public Enum Parity

{

///

/// Characters Do Not Have a Parity Bit. ///

None = 0,

///

///Iff there 1s in the data bits, The Parity Bit IS 1. ///

ODD = 1,

///

/// if there is an evenu number of 1s in the data bits, the parity bit is ////

Even = 2,

///

/// The parity bit is always 1. ///

Mark = 3,

///

/// The parity bit is always 0. ////

Space = 4

}

///

/// stop bit settings ////

Public Enum Stopbits

{

///

/// line is asserted for 1 bit duration at end of each character /// one = 0,

///

/// line is asked for 1.5 bit duration at end of each character ////////

OnePointFive = 1,

///

/// line is asked for 2 bit duration at end of each character ///

TWO = 2

}

///

/// Uses for rts or dtr pins ////

Public Enum HSOUTPUT

{

///

/// pin is asserted when this station is able to remove data. ///

Handshake = 2,

///

/// pin is asserted when this station is transmitting data (rts on nt, 2000 or xp "///

Gate = 3,

///

/// pin is asserted when this station is open (port is open). ///

ONLINE = 1,

///

/// pin is never asserted. ///

None = 0

}

///

/// standard handshake methods ///

Public Enum Handshake

{

///

/// no Handshaking ///

None,

///

/// Software Handshaking Using XON / XOFF ///

Xonxoff,

///

/// Hardware Handshaking Using CTS / RTS /////

CTSRTS,

///

/// Hardware Handshaking Using DSR / DTR / / / /

DSRDTR

}

///

/// set the public fields to supply settings to commit. ///

Public class commbasesettings

{

///

/// port name (Default: "COM1:") ///

Public String Port = "COM1";

///

/// baud Rate (Default: 2400) Unsupported Rates Will Throw "Bad Settings" /////

Public int baudrate = 19200;

///

/// The Parity Checking Scheme (Default: none) ///

Public Parity Parity = Parity.none;

///

/// Number of DataBits 1..8 (Default: 8) Unsupported Values ​​Will Throw "Bad Settings" ///

Public int DATABITS = 8;

///

/// Number of Stop Bits (Default: One) ///

Public stopbits stopbits = stopbits.one;

///

/// if true, transmission is halted unless cts is asserted by the remote station (default: false) /// public bool txflowcts = false

///

/// if true, transmission is halted unless dsr is asserted by The Remote Station (Default: false) ///

Public bool txflowdsr = false;

///

/// if true, transmission is halted when Xoff is recection and restarted WHEN XON IS Rece: false ///

Public bool txflowx = false;

///

/// if false, Transmission is suspended gen this station skill: true) /// set false if the remote station treats any character as an xon. ///

Public bool txwhenrxxoff = true;

///

/// if true, receivated characters area ignored unless dsr is asked by the remote station (default: false) ///

Public bool rxgatedsr = false;

///

/// if true, Xon and Xoff Characters Are Sent To Control The Data Flow from The Remote Station (Default: false) ///

Public bool rxflowx = false;

///

/// specifies the use to which the RTS Output is Put (Default: None) ///

Public hsideput utes = hsoutput.none;

///

/// Specidies the Use to which the DTR OUTPUT IS PUT (DEFAULT: NONE) ///

Public hsideput usedtr = hsoutput.none;

///

/// the character used to signal xon for x flow control (default: dc1) ////

Public ascii xonchar = asCII.NULL; // ascii.dc1;

///

/// The character used to signal Xoff for x flow control (default: DC3) /////

Public ascii xoffchar = ascii.null; // ascii.dc3;

// JH 1.2: Next Two defaults change to 0 to use new defaulting mechanism dependant on queue size.

///

//////////// (default: 0 = set to 1 / 10th of actual rxqueue size) /// public int rxhighwater = 0;

///

////////// (Default: 0 = set to 1 / 10th of actual rxqueue size) ///

Public int rXlowwater = 0;

///

/// Multiplier. Max Time for send in ms = (multiplier * characters) constant /// (Default: 0 = no timeout) ///

Public uint sendtimeoutmultiPlier = 0;

///

/// constant. Max time for send in ms = (multiplier * characters) Constant (default: 0) ///

Public uint sendtimeoutConstant = 0;

///

/// Requested Size for Receive Queue (Default: 0 = Use Operating System Default) ///

Public int rxqueue = 0;

///

/// Requested Size for Transmit Queue (Default: 0 = Use Operating System Default) ///

Public int TXQUE = 0;

///

/// if true, the port will automaticly re-open next sendness due /// to an error: false ////

Public Bool Autoreopen = False;

///

/// 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. ///

Public Bool Checkallsends = true;

///

/// pre-configures settings for MOST MODERN Devices: 8 Database, 1 Stop Bit, No Parity and /// One of the common handshake protocols. Change Individual Settings Later if Necessary. ///

///

The port to use (i.e. "COM1:")

///

The baud rate

///

The Handshake Protocol

Public Void SetStandard (String Port, Int Baud, Handshake HS)

{

Database = 8; stopbits = stopbits.one; PARITY = PARITY.NONE; port = port; baudrate = baud;

Switch (HS)

{

Case Handshake.none:

Txflowcts = false; txflowdsr = false; txflowx = false;

Rxflowx = false; useerts = 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.cts:

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;

}

}

///

/// Save the Object in XML Format to a stream ///

///

Street to save the object to save

Public void saveasxml (stream s)

{

XMLSERIALIZER SR = New XmlSerializer (this.gettype ());

Sr.Serialize (s, this);

}

///

/// Create a new commbasesettings object initialised from xml data ////

///

Stream to loading the xml from

///

CommBasesettings Object

Public Static CommBasesettings LoadFromxml (Stream S)

{

Return LoadFromxml (S, TypeOf (CommBaseTings));

}

///

/// Create a new object loading members from the stream in XML format /// Derived class should call this from a static method ie:. /// return (ComDerivedSettings) LoadFromXML (s, typeof (ComDerivedSettings)); /// ///

Stream to loading the object from

///

Type of the derived object

///

Protected Static Commbasesettings LoadFromxml (Street S, Type T)

{

XMLSERIALIZER SR = New XMLSERIALIZER (T);

Try

{

Return (CommBasesettings) Sr.Deselialize (s);

}

Catch

{

Return NULL;

}

}

}

#Region "ASCII Defense" // JH 1.3: Corrected Sth -> StX (THANKS - Johan Thelin!) ///

/// Byte Type with Enumeration Constants for ASCII Control Codes. ///

Public Enum ascii: byte

{

///

/// null /////

NULL = 0x00,

///

/// SOH //////

SOH = 0x01,

///

/// stx /////

STX = 0x02,

///

/// etX /////

ETX = 0x03,

///

/// Eot ////

Eot = 0x04,

///

/// ////

ENQ = 0x05,

///

/// ////

ACK = 0x06,

///

/// ////

Bell = 0x07,

///

/// ////

BS = 0x08,

///

/// ////

HT = 0x09,

///

/// ////

LF = 0x0a,

///

/// ////

Vt = 0x0b,

///

/// ////

FF = 0x0c,

///

/// ////

Cr = 0x0d,

///

/// ////

SO = 0x0E,

///

/// ////

Si = 0x0f,

///

/// ////

DC1 = 0x11,

///

/// ////

DC2 = 0x12,

///

/// ////

DC3 = 0x13,

///

/// ////

DC4 = 0x14,

///

/// ////

NAK = 0x15,

///

/// ////

SYN = 0x16,

///

/// ////

ETB = 0x17,

///

/// ////

CAN = 0x18,

///

/// ////

EM = 0x19,

///

/// ////

Sub = 0x1a,

///

/// ////

ESC = 0x1b,

///

/// ////

FS = 0x1c,

///

/// ////

GS = 0x1d,

///

/// ////

RS = 0x1e,

///

/// ////

US = 0x1f,

////// ////

Sp = 0x20,

///

/// ////

Del = 0x7f

}

#ndregion

// jh 1.3: Added AltName Function, Portstatus Enum and isportavailable function.

///

/// Returns the alternative name of a com port i.e. ///com1 for com1: /// Some Systems Require this form number ost p p

///

Name in form com1 or com1:

///

Name in form

//./Com1

> private string altname (string s) {string r = s.trim (); if (s.endswith (":"))) s = s.Substring (0, S.Length - 1); if (S .Startswith (@ "/")) Return S; return @ "

//./ " S;

}

///

/// Availability Status of a port /////

Public Enum Portstatus

{

///

/// port exissrs but is unavailable (may be open to noother program) ///

Unavailable = 0,

///

/// Available for USE /////

AVAILABLE = 1,

///

/// port does not exist ///

ABSENT = -1

}

///

/// Tests the availability of a named comm port. ///

///

Name of port

///

Availability of Port

Public portstatus isportavailable (String s)

{

INTPTR H;

h = Win32Com.CreateFile (s, Win32Com.GENERIC_READ | Win32Com.GENERIC_WRITE, 0, IntPtr.Zero, Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero); if (== h (IntPtr) Win32Com.INVALID_HANDLE_VALUE) {if ( Marshal.GetLastWin32Error () == Win32Com.ERROR_ACCESS_DENIED) {return PortStatus.unavailable;} else {// JH 1.3: Automatically try AltName if supplied name fails: h = Win32Com.CreateFile (AltName (s), Win32Com.GENERIC_READ | win32Com. GENERIC_WRITE, 0, IntPtr.Zero, Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero); if (== h (IntPtr) Win32Com.INVALID_HANDLE_VALUE) {if (Marshal.GetLastWin32Error () == Win32Com.ERROR_ACCESS_DENIED) {return PortStatus .unavailable;}}} win32com.closehandle (h); return portstatus.available;} ///

/// Opens the com port and configures it with the required settings //////

///

False if the port could not be opened

Public bool open ()

{

Win32com.dcb portdcb = new win32com.dcb ();

Win32com.commtimeouts Commtimeouts = New Win32com.commtimeouts ();

CommBasetdtings CS;

Win32com.Overlapped wo = new win32com.overlapped ();

Win32com.commprop CP;

IF (Online) Return False; CS = CommSttings ();

hPort = Win32Com.CreateFile (cs.port, Win32Com.GENERIC_READ | Win32Com.GENERIC_WRITE, 0, IntPtr.Zero, Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero); if (hPort == (IntPtr) Win32Com.INVALID_HANDLE_VALUE) { if (Marshal.GetLastWin32Error () == Win32Com.ERROR_ACCESS_DENIED) {return false;} else {// JH 1.3: Try alternative name form if main one fails: hPort = Win32Com.CreateFile (AltName (cs.port), Win32Com.GENERIC_READ | Win32Com.GENERIC_WRITE, 0, IntPtr.Zero, Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero); if (hPort == (IntPtr) Win32Com.INVALID_HANDLE_VALUE) {if (Marshal.GetLastWin32Error () == Win32Com.ERROR_ACCESS_DENIED) {RETURN FALSE;} else {throw new commportException ("Port Open Failure");}}}} online = true;

//JH1.1: Changed from 0 to "magic number" to give instant return on ReadFile: CommTimeouts.ReadIntervalTimeout = Win32Com.MAXDWORD; CommTimeouts.ReadTotalTimeoutConstant = 0; CommTimeouts.ReadTotalTimeoutMultiplier = 0;

//JH1.2: 0 Does Not Seem To Mean Infinite on Non-NT Platforms, So Default It To 10 // Seconds Per Byte Which Should Be Enough for anyone. If (cs.sendtimeoutmultiplier == 0) {IF (System. Environment.OSVersion.Platform == System.PlatformID.Win32NT) {CommTimeouts.WriteTotalTimeoutMultiplier = 0;} else {CommTimeouts.WriteTotalTimeoutMultiplier = 10000;}} else {CommTimeouts.WriteTotalTimeoutMultiplier = cs.sendTimeoutMultiplier;} CommTimeouts.WriteTotalTimeoutConstant = cs.sendTimeoutConstant; Portdcb.init ((cs.parity == parity.od) || (cs.parity == parity.even)), cs.txflowcts, cs.txflowdsr, (int) cs.usedtr, cs.rxgatedsr,! Cs .txwhenrxxoff, cs.txflowx, cs.rxflowx, (int) cs.userts; portdcb.baudrate = cs.baudrate; portdcb.bytesize = (byte) cs.database; portdcb.parity = (byte) cs.parity; portdcb .Stopbits = (byte) cs.stopbits; portdcb.xoffchar = (byte) cs.xOffchar; portdcb.xonchar = (byte) cs.xonchar; if ((cs.rxqueue! = 0) || (CS) .txqueue! = 0))) IF (! Win32com.Setupcomm (hport, (uint) cs.rxqueue, (uint) cs.txqueue) throwexception ("Bad Queue Settings");

// JH 1.2:. Defaulting mechanism for handshake thresholds - prevents problems of setting specific // defaults which may violate the size of the actually granted queue If the user specifically sets // these values, it's their problem if ((cs.rxLowWater! == 0) || (cs.rxhighwater == 0)) {if (! Win32com.getCommproperties (HPORT, OUT CP)) cp.dwcurrentrxqueue = 0; if (cp.dwcurrentrxqueue> 0) {// if we can determine The Queue Size, Default To 1 / 10th, 8 / 10th, 1 / 10th. // Note That Highwater Is Measured from Top of Queue. Portdcb.xOfflim = Portdcb.xonlim = (Short) ((int) cp.dwcurrentrxqueue / 10 } Else {// if we do not know the queue size, set value low defaults for safety. Portdcb.xofflim = portdcb.xonlim = 8;}} else {portdcb.xofflim = (short) cs.RxHighwater; portdcb. Xonlim = (short) cs.rxlowwater;} if (! Win32com.setcommstate (HPORT, REF portdcb)) throwexception ("Bad CoM Settings"); if (! Win32com.setcommtimeout) (Hport, Ref Comm THROWEXCEPTION ("Bad Timeout Settings"); statebrk = 0; if (cs.usedtr == hsoutput.none) statedtr = 0; if (cs.usedtr == hsoutput.online) StatedTR = 1; IF (CS. Userts == hsoutput.none) staterts = 0; if (cs.userts == hsoutput.online) staterts = 1;

Checksends = cs.checkallsends; wo.offset = 0; wo.offsetHigh = 0; if (checksends) hevent = writeevent.handle; else wo.Hevent = INTPTR.ZERO;

Ptruwo = Marshal.allochglobal (Marshal.SizeOf (WO));

Marshal.StructureToPtr (wo, ptrUWO, true); writeCount = 0; //JH1.3: empty [0] = true; dataQueued = false; rxException = null; rxExceptionReported = false; rxThread = new Thread (new ThreadStart (this. ReceiveThread)); rxThread.Name = "CommBaseRx"; rxThread.Priority = ThreadPriority.AboveNormal; rxThread.Start (); // JH1.2:. More robust thread start-up wait startEvent.WaitOne (500, false);

Auto = false; if (afteropen ()) {auto = cs.autoreopen; return true;} else {close (); return false;}

}

///

/// Adder: SYMA Date: 2004-06-07 // Open the serial port /// according to the port and baud rate set

///

///

///

Public Bool Open (String Port, Int Baud)

{

Win32com.dcb portdcb = new win32com.dcb ();

Win32com.commtimeouts Commtimeouts = New Win32com.commtimeouts ();

CommBasetdtings CS;

Win32com.Overlapped wo = new win32com.overlapped ();

Win32com.commprop CP;

IF (Online) Return False; CS = CommSettings (); cs.port = port; cs.baudrate = baud;

hPort = Win32Com.CreateFile (cs.port, Win32Com.GENERIC_READ | Win32Com.GENERIC_WRITE, 0, IntPtr.Zero, Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero); if (hPort == (IntPtr) Win32Com.INVALID_HANDLE_VALUE) { if (Marshal.GetLastWin32Error () == Win32Com.ERROR_ACCESS_DENIED) {return false;} else {// JH 1.3: Try alternative name form if main one fails: hPort = Win32Com.CreateFile (AltName (cs.port), Win32Com.GENERIC_READ | Win32Com.GENERIC_WRITE, 0, IntPtr.Zero, Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero); if (hPort == (IntPtr) Win32Com.INVALID_HANDLE_VALUE) {if (Marshal.GetLastWin32Error () == Win32Com.ERROR_ACCESS_DENIED) {RETURN FALSE;} else {throw new commportException ("Port Open Failure");}}}} online = true;

//JH1.1: Changed from 0 to "magic number" to give instant return on ReadFile: CommTimeouts.ReadIntervalTimeout = Win32Com.MAXDWORD; CommTimeouts.ReadTotalTimeoutConstant = 0; CommTimeouts.ReadTotalTimeoutMultiplier = 0;

//JH1.2: 0 Does Not Seem To Mean Infinite on Non-NT Platforms, So Default It To 10 // Seconds Per Byte Which Should Be Enough for anyone. If (cs.sendtimeoutmultiplier == 0) {IF (System. Environment.OSVersion.Platform == System.PlatformID.Win32NT) {CommTimeouts.WriteTotalTimeoutMultiplier = 0;} else {CommTimeouts.WriteTotalTimeoutMultiplier = 10000;}} else {CommTimeouts.WriteTotalTimeoutMultiplier = cs.sendTimeoutMultiplier;} CommTimeouts.WriteTotalTimeoutConstant = cs.sendTimeoutConstant; Portdcb.init ((cs.parity == parity.od) || (cs.parity == parity.even)), cs.txflowcts, cs.txflowdsr, (int) cs.usedtr, cs.rxgatedsr,! Cs .txwhenrxxoff, cs.txflowx, cs.rxflowx, (int) cs.userts; portdcb.baudrate = cs.baudrate; portdcb.bytesize = (byte) cs.database; portdcb.parity = (byte) cs.parity; portdcb .Stopbits = (byte) cs.stopbits; portdcb.xoffchar = (byte) cs.xOffchar; portdcb.xonchar = (byte) cs.xonchar; if ((cs.rxqueue! = 0) || (CS) .txqueue! = 0))) IF (! Win32com.Setupcomm (hport, (uint) cs.rxqueue, (uint) cs.txqueue) throwexception ("Bad Queue Settings");

// JH 1.2:. Defaulting mechanism for handshake thresholds - prevents problems of setting specific // defaults which may violate the size of the actually granted queue If the user specifically sets // these values, it's their problem if ((cs.rxLowWater! == 0) || (cs.rxhighwater == 0)) {if (! Win32com.getCommproperties (HPORT, OUT CP)) cp.dwcurrentrxqueue = 0; if (cp.dwcurrentrxqueue> 0) {// if we can determine The Queue Size, Default To 1 / 10th, 8 / 10th, 1 / 10th. // Note That Highwater Is Measured from Top of Queue. Portdcb.xOfflim = Portdcb.xonlim = (Short) ((int) cp.dwcurrentrxqueue / 10 } Else {// if we do not know the queue size, set value low defaults for safety. Portdcb.xofflim = portdcb.xonlim = 8;}} else {portdcb.xofflim = (short) cs.RxHighwater; portdcb. Xonlim = (short) cs.rxlowwater;} if (! Win32com.setcommstate (HPORT, REF portdcb)) throwexception ("Bad CoM Settings"); if (! Win32com.setcommtimeout) (Hport, Ref Comm THROWEXCEPTION ("Bad Timeout Settings"); statebrk = 0; if (cs.usedtr == hsoutput.none) statedtr = 0; if (cs.usedtr == hsoutput.online) StatedTR = 1; IF (CS. Userts == hsoutput.none) staterts = 0; if (cs.userts == hsoutput.online) staterts = 1;

Checksends = cs.checkallsends; wo.offset = 0; wo.offsetHigh = 0; if (checksends) hevent = writeevent.handle; else wo.Hevent = INTPTR.ZERO;

Ptruwo = Marshal.allochglobal (Marshal.SizeOf (WO));

Marshal.StructureToPtr (wo, ptrUWO, true); writeCount = 0; //JH1.3: empty [0] = true; dataQueued = false; rxException = null; rxExceptionReported = false; rxThread = new Thread (new ThreadStart (this. ReceiveThread)); rxThread.Name = "CommBaseRx"; rxThread.Priority = ThreadPriority.AboveNormal; rxThread.Start (); // JH1.2:. More robust thread start-up wait startEvent.WaitOne (500, false);

Auto = false; if (afteropen ()) {auto = cs.autoreopen; return true;} else {close (); return false;}

}

///

/// Closes the COM port. ///

Public void close ()

{

IF (Online)

{

Auto = FALSE;

BeforeClose (false);

INTERNALCLOSE ();

RxException = NULL;

}

}

Private void internalclose ()

{

Win32com.cancelio (HPORT);

IF (RXTHREAD! = NULL)

{

Rxthread.abort ();

// jh 1.3: Improve Robustness of Close In Case Were Followed by Open:

Rxthread.join (100);

Rxthread = NULL;

}

Win32com.closehandle (HPORT);

IF (Ptruwo! = INTPTR.ZERO) Marshal.Freehglobal (Ptruwo);

STATERTS = 2;

StateDTR = 2;

Statebrk = 2;

ONLINE = FALSE;

}

///

/// for idisposable ///

Public void dispose () {close ();

///

/// destructor (just in case) //////

~ Commbase () {close ();

///

/// true ife. ///

Public Bool Online {Get {if (! Online) Return False; else returnch checkonline ();}}

///

/// block unsil alltes in the queue have been transmitted. ///

Public void flush ()

{

Checkonline ();

CheckResult ();

}

///

/// Set the baud rate ///

///

Public Void ResetBaudrate (int BDR)

{

Win32com.dcb dcb = new xst.xstcomm.base.win32com.dcb ();

Win32com.getCommState (HPORT, REF DCB);

Dcb.baudrate = BDR;

Win32com.Setcommstate (HPORT, REF DCB); purgein ();

Purgeout ();

}

///

/// Remove the read buffer content ///

Private void purgein ()

{

//Win32com.purgecomm (Hport ,Win32com.purge_rxabort | Win32com.purge_rxclear);

CANCELREAD ();

Purgeread ();

}

///

/// Clear write buffer content ///

Private void purgeout ()

{

//Win32com.purgecomm (Hport ,win32com.purge_txabort | win32com.purge_txclear);

CANCELWRITE ();

Purgewrite ();

}

private bool PurgeRead () {return (Win32Com.PurgeComm (hPort, Win32Com.PURGE_RXCLEAR));} private bool PurgeWrite () {return (Win32Com.PurgeComm (hPort, Win32Com.PURGE_TXCLEAR));} private bool CancelRead () {return ( Win32com.purgecomm (hport, win32com.purge_rxabort);} private bool can Cancelwrite () {return (Win32com.purgecomm (hport, win32com.purge_txabort);}

///

/// Use this to throw exceptionins in derived classes. CORRECTLY HANDLES THREADING ISSUES /// and closs the port if neseary. ///

///

Description of fault

Protected void throwexception (String REASON)

{

IF (thread.currentthread == rxthread)

{

Throw new commportException (REASON);

}

Else

{

IF (Online)

{

BeforeClose (True);

INTERNALCLOSE ();

}

IF (rxException == null)

{

Throw new commportException (REASON);

}

Else

{

Throw new commitexception (rxexception);

}

}

}

///

/// Queues BYTES for Transmission. ///

///

Array of Bytes to Be Sent

protected void send (byte [] tosend)

{

Uint Sent = 0;

Checkonline ();

CheckResult ();

Writecount = tosend.getLength (0);

IF (Win32com.Writefile (Hport, Tosend, (UINT) WRITECUNT, OUT SENT, PTRUWO)

{

Writecount - = (int) SENT;

}

Else

{

IF (Marshal.getlastwin32error ()! = Win32com.ErroROR_IO_PENDING) ThrowException ("Send Failed");

//JH1.3:

Dataqueued = True;

}

}

///

/// queues a single byte for transmission. //////

Byte to be Sent

Protected Void Send (Byte Tosend)

{

Byte [] b = new byte [1];

B [0] = TOSEND;

Send (b);

}

Private void checkresult () {uint Sent = 0;

// JH 1.3:. Fixed a number of problems working with checkSends == false Byte counting was unreliable because // occasionally GetOverlappedResult would return true with a completion having missed one or more previous // completions The test for ERROR_IO_INCOMPLETE was incorrectly for ERROR_IO_PENDING. INSTEAD.

if (writeCount> 0) {if (Win32Com.GetOverlappedResult (hPort, ptrUWO, out sent, checkSends)) {if (checkSends) {writeCount - = (int) sent; if (writeCount = 0!) ThrowException ( "Send Timeout" ); Writecount = 0;}} else {if (Marshal.getlastwin32ERROR ()! = Win32com.error_io_incumplete) throwexception ("Write Error");}}}

///

/// sends a protocol byte immediely ahead of any queued bytes. ///

///

Byte To Send

Protected void sendimmediate (byte tosend)

{

Checkonline ();

IF (! Win32com.TransmitCommchar (HPORT, TOSEND)) ThrowException ("Transmission Failure);

}

///

/// DELAY processing. ///

///

Milliseconds to delay by

Protected Void Sleep (Int MilliseConds)

{

Thread.sleep (MilliseConds);

}

///

/// REPRESENTS The Status of the MODEM Control InputiGnals. ///

Public struct modemstatus

{

Private uint status;

INTERNAL MODEMSTATUS (UINT VAL) {status = val;}

///

/// Condition of the clear to send signal. ///

Public Bool CTS {Get {Return (status & win32com.ms_cts_on)! = 0);}}

///

/// Condition of the data set ready signal. ///

Public Bool DSR {Get {Return (status & win32com.ms_dsr_on)! = 0);}} ///

/// Condition of the receive line status detection signal. ///

Public Bool rlsd {get {return (status & win32com.ms_rlsd_on)! = 0);}}

///

/// Condition of the Ring Detection signal. ///

Public Bool Ring {Get {Return ((status & win32com.ms_ring_on)! = 0);}}

}

///

/// Gets The Status of the MODEM Control Input Signals. ///

///

Modem Status Object

Protected ModemStatus getModemStatus ()

{

UINT F;

Checkonline (); if (! Win32com.getCommodemStatus (HPORT, OUT F)) throwexception ("Unexpected Failure"); Return New ModemStatus (f);}

///

/// REPRESENTS The Current Condition of The Port Queues. ///

Public struct queuesttus

{

Private uint status;

PRIVATE UINT INQUEUE;

PRIVATE uint Outqueue;

Private uint inqueueSize;

PRIVATE UINT OUTQUEESIZE;

INTERNAL Queuesttus (uint stat, uint inq, uint outq, uint inqs, uint out {status = stat; inqueue = inq; outqueue = Outq; inQueueSize = inqs; outqueueesize = Outqs;} ///

/// output is blocked by CTS Handshaking. ///

Public bool ctshold {get {return (status & win32com.comstat.fctshold)! = 0);}}

///

/// output is blocked by DRS HANDSHAKING. ///

Public Bool DSRHOLD {Get {Return ((status & win32com.comstat.fdsrhold)! = 0);}}

///

/// output is blocked by rlsd haandshaking. ///

Public Bool rlsdhold {get {return ((status & win32com.comstat.frlsdhold)! = 0);}}

///

/// output is blocked Because Software Handshaking IS enabled and xoff Was received. ///

Public Bool Xoffhold {Get {Return ((Status & Win32com.comstat.fxoffhold)! = 0);}}

///

/// Output WAS Blocked Because Xoff WAS Sent and this station station station} (status & win32com.comstat.fxoffsent)! = 0);}}

///

//////////////////////////////////////////////////////////>

Public bool immediatewaiting {get {return ((status & win32com.comstat.ftxim)! = 0);}}

///

/// Number of bytes waiting in the input queue. ///

PUBLIC Long Inqueue {Get {Return (Long) Incueue;}}

///

/// Number of bytes waiting for transmission. ///

PUBLIC Long Outqueue {Get {Return (long) Outqueue;}}

///

/// Total Size of INPUT Queue (0 means information unavailable) ///

PUBLIC Long InqueueSize {Get {Return (long) inQueueSize;}}

///

/// Total Size of Output Queue (0 means Information unavailable) ///

Public long outqueesize {get {return (long) OutqueueSize;}}

///

/// ////

///

Public override string toString ()

{

StringBuilder M = New StringBuilder ("The Reception Queue IS", 60);

IF (InqueueSize == 0)

{

M.Append ("of unknown size and");

}

Else

{

M.Append (InqueueSize.toString () "BYTES long and");

}

IF (inqueue == 0)

{

M.APpend ("IS Empty.");

}

Else if (inqueue == 1)

{

M.apore ("Contains 1 Byte.");

}

Else

{

M.Append ("contains");

M.Append (Inqueue.toString ());

M.Append ("bytes.");

}

M.Append ("THE Transmission Queue IS";

IF (OutqueueSize == 0)

{

M.Append ("of unknown size and");

}

Else

{

M.Append (OutqueueSize.toString () "BYTES long and");

}

IF (Outqueue == 0)

{

M.Append ("is empty");

}

Else if (Outqueue == 1)

{

M.Append ("Contains 1 Byte. IT IS");

Else

{

M.Append ("contains");

M.Append (Outqueue.toString ());

M.Append ("Bytes. IT IS");

}

IF (Outqueue> 0)

{

IF (CTShold || DSRhold || rlsdhold || Xoffhold || Xoffsent)

{

M.Append ("Holding On");

IF (CTSHOLD) M.APpend ("CTS");

IF (DSRHOLD) M.APpend ("DSR");

IF (rlsdhold) M.Append ("rlsd");

IF (Xoffhold) M.Append ("RX XOFF");

IF (XOFFSENT) M.APpend ("TX Xoff");

}

Else

{

M.Append ("Pumping Data");

}

}

M.Append (". The immediate buffer is");

IF (immediatewaiting)

M.Append ("full.");

Else

M.APpend ("Empty.");

Return m.toString ();

}

}

///

/// Get the status of the queues ///

///

Queue Status Object

protected queuestatus getQueuesttatus ()

{

Win32com.comstat CS;

Win32com.commprop CP;

UINT ER;

CheckOnline (); if (Win32Com.ClearCommError (hPort, out er, out cs)!) ThrowException ( "Unexpected failure"); if (Win32Com.GetCommProperties (hPort, out cp)!) ThrowException ( "Unexpected failure"); return New queuesttus (cs.flags, cs.cbinque, cs.cboutque, cp.dwcurrentrxqueue, cp.dwcurrenttxqueue);}

// jh 1.3. Added for this version. ///

/// Test if the line is congested (data being queued for send faster than it is being dequeued) /// This detects if baud rate is too slow or if handshaking is not allowing enough transmission /// time. It should be called AT REASONABLY Long Fixed Intervals. If Data Has Been Sent During /// The Interval, Congest IS Reported If The Queue Was Never Empty During The Interval. ///

///

True if congsted

protected bool iscongested ()

{

BOOL E;

IF (! Dataqueue) Return False;

Lock (EMPTY) {E = Empty [0]; EMPTY [0] = false;} Dataqueueue

Return! E;

}

///

/// true if the rts pin is controllable via the rts printy ///

Protected Bool RTSAVAILABLE {Get {Return (Staterts <2);}}

///

/// set the state of the rts modem control output ///

Protected Bool RTS

{

set

{

IF (Staterts> 1) Return;

Checkonline ();

IF (Value)

{

IF (Win32com.escapecommfunction (hport, win32com.setrs)

STATERTS = 1;

Else

ThrowException ("Unexpected Failure";

}

Else

{

IF (Win32com.escapecommfunction))

// JH 1.3: WAS 1, Should BE 0:

STATERTS = 0;

Else

ThrowException ("Unexpected Failure";

}

}

get

{

Return (staterts == 1);

}

}

///

/// true if the dtr pin is controllable via the DTR Property ///

Protected Bool DTRAVAILABLE {Get {Return (StateDtr <2);}}

///

//////////////////

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);

}

}

///

/// assert or remove a break condition from the transmission line ///

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);

}

}

///

/// Override this to provide settings. (NB this is caled during open method) ///

///

Commbasesettings, or derived Object with required settings initialia

Protected Virtual CommBasesettings CommSettings () {Return New CommbaseSettings ();

///

/// Override this to provide processing after the port is openned (i.e. To configure recee /// device or just check presence). ///

///

False to close the port again

Protected Virtual Bool afterOpen () {Return True;}

///

/// Override this to provide processing prior to port closure. ///

///

True if closing due to an error

Protected Virtual Void BeforeClose (Bool Error) {}

///

/// Override this to process received Bytes. ///

///

The byte tria tas received

Protected Virtual Void OnRxchar (Byte Ch) {}

///

/// Override this to take action means (i.e. alltes have actual "/// been sample, not just queued). ///

Protected Virtual Void ONTXDODONE () {}

///

//////////////////////////>

Protected virtual void onbreak () {}

// jh 1.3: Deleted Onring () Which Was Never Called: Use onstatuschange INSTEAD (THANKS JIM FOSTER)

///

/////////////////////////////////>

///

The Status Inputs That Have Changed State

///

The State of The Status Inputs

Protected Virtual Void OnStatusChange (ModemStatus Mask, Modemstatus State) {}

///

/// Override this to take a the action thread closes due to an exception being thrown. ///

///

The Exception Which Was Thrown

Protected Virtual Void OnRxexception (Exception E) {}

private void ReceiveThread () {byte [] buf = new Byte [1]; uint gotbytes; bool starting; starting = true; AutoResetEvent sg = new AutoResetEvent (false); Win32Com.OVERLAPPED ov = new Win32Com.OVERLAPPED ();

INTPTR UNMANAGED; INTPTR umask; uint eventmask = 0; unmanagedov = Marshal.allochglobal (Marshal.SizeOf (OV)); umask = marshal.allochglobal (Marshal.Sizeof (eventmask);

Ov.offset = 0; ov.offsethiGH = 0; ov.hevent = sg.handle; Marshal.StructureToptr (OV, Unmanagedov, True);

try {while (true) {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)) { Throw new commitException ("IO Error [001]");} Marshal.writeInt32 (Umask, 0); // JH 1.2: Tells the main thread That Thread is Ready for action. If (starting) {Startevent.Set () ; starting = false;} if (! Win32Com.WaitCommEvent (hPort, uMask, unmanagedOv)) {if (Marshal.GetLastWin32Error () == Win32Com.ERROR_IO_PENDING) {sg.WaitOne ();} else {throw new CommPortException ( "IO Error [002] ");}} EventMask = (uint) Marshal.Readint32 (umask); if (EventMask & Win32com.ev_err)! = 0) {uint32 errs; if (Win32com.clearcommorror (Hport, Out Errs, INTPTR) . Zero) {// jh 1.2: Break condition Has An Error flag and and an Event flag. Not Sure IF Both // Are ALWAY s raised, so if CE_BREAK is only error flag ignore it and set the EV_BREAK // flag for normal handling. Also made more robust by handling case were no recognised // error was present in the flags. (Thanks to Fred Pittroff for finding this Problem!) int EC = 0; StringBuilder S = New StringBuilder ("UART Error:", 40); if ((Errs & Win32com.ce_frame)! = 0) {s = S.Append ("framing,"); EC } IF ((Errs & Win32com.ce_ioe)! = 0) {s = S.Append ("IO,"); EC ;} f ((Errs & Win32com.ce_Overrun)! = 0) {s = S.Append ("Overrun,"); EC ;} IF ((Errs &)

Win32com.ce_rxover)! = 0) {S = S.Append ("Receive Cverflow,"); EC ;} if ((Errs & Win32com.ce_RXPARITY)! = 0) {s = S.Append ("Parity,") ; EC ;} if ((errs & win32com.ce_txfull! = 0) {s = S.Append ("Transmit overflow,"); EC ;} if (EC> 0) {s.ley = S.LENGTH - 1 Throw new commportException (S.ToString ());} else {if (errs == win32com.ce_break) {eventmask | = Win32com.ev_break;} else {throw new commportException ("IO Error [003]);}} } Else {throw new commportException ("IO Error [003]");}}} f ((EventMask & Win32com.ev_rxchar)! = 0) {DO {gotbytes = 0; if (! Win32com.readfile (Hport, BUF, 1 Out gotbytes, unmanagedov) {// jh 1.1: removed error_IO_PENDING HANDLING As Comm Timeouts Have Now // Been Set So Readfile Returns Immediately, this Avoids Use of Cancelio // Which Was Caus ING LOSS of Data. Thanks To Daniel Moth for Suggesting this // Might Be a problem, and to many Others for Reporting That It was! int x = marshal.getlastwin32error ();

Throw new commportException ("IO Error [004]");} if (gotbytes == 1) OnRxChar (BUF [0]);} while (gotbytes> 0);} if ((EventMask & Win32com.ev_txempty)! = 0 ) {//JH1.3: Lock (EMPTY) EMPTY [0] = true; ONTXDONE ();} IF ((Eventmask & Win32com.ev_break)! = 0) Onbreak (); uint i = 0; if ((Eventmask) & Win32com.ev_cts)! = 0) I | = WIN32COM.MS_CTS_ON; IF ((EventMask & Win32com.ev_dsr)! = 0) i | = Win32com.ms_DSR_ON; IF ((Eventmask & Win32com.ev_rlsd)! = 0) i | = WIN32COM.MS_RLSD_ON; IF ((EventMask & Win32Com.ev_ring)! = 0) i | = Win32com.ms_ring_on; if (i! = 0) {uint f; if (! Win32com.getcommodemstatus (Hport, Out F)) throw new CommPortException ( "IO Error [005]"); OnStatusChange (new ModemStatus (i), new ModemStatus (f));}}} catch (Exception e) {// JH 1.3: Added for shutdown robustness (Thanks to Fred PitTroff, Mark Behner and Kevin Williamson!),. Win32com.cancelio (HPORT); IF (Umask ! = IntPtr.Zero) Marshal.FreeHGlobal (uMask); if (unmanagedOv = IntPtr.Zero) Marshal.FreeHGlobal (unmanagedOv);! If ((e is ThreadAbortException!)) {RxException = e; OnRxException (e);}} }

private bool CheckOnline () {if (!! (rxException = null) && (rxExceptionReported)) {rxExceptionReported = true; ThrowException ( "rx");} if (online) {// JH 1.1: Avoid use of GetHandleInformation for W98 compatability . if (hPort = (System.IntPtr) Win32Com.INVALID_HANDLE_VALUE!) return true; ThrowException ( "Offline"); return false;} else {if (auto) {if (Open ()) return true;} ThrowException ( "Offline "); Return false;}}}

///

/// Overlays CommBase to provide line or packet oriented communications to derived classes. Strings /// are sent and received and the Transact method is added which transmits a string and then blocks until /// a reply string has been received (subject to a timeout). ///

Public Abstract Class Comline: CommBase

{

Private byte [] rxbuffer;

Private uint rxbufferp = 0;

Private ASCII RXTERM;

PRIVATE ASCII [] TXTERM;

Private ascii [] rxfilter;

Private string rxstring = ""

Private manualReveTevent Transflag = New ManualReveTevent (TRUE);

PRIVATE UINT TRANSTIMEOUT;

///

/// Extends Commbasesettings to add the settings buy by circline. ////

Public Class CommLinesettings: commit.commbasesettings

{

///

/// Maximum size of review string (Default: 256) //////

Public int rxstringBuffersize = 256;

///

/// ASCII Code That Terminates A Received String (Default: CR) ///

Public ascii rxterminator = ascii.cr;

///

/// ASCII Codes That Will BE ignored in received string (Default: null) ///

Public ASCII [] RXFilter;

///

/// Maximum Time (MS) for the Transact Method to Complete (Default: 500) ///

Public int transacttimeout = 500;

///

/// ASCII Codes Transmitted After Each Send String /// Public ASCII [] TXTERMINATOR;

///

/// Get setting information from the XML file ///

///

///

Public Static New CommlineSettings LoadFromXML (stream s)

{

Return (CommLinesettings) LoadFromxml (S, TypeOf (CommLineSetting));

}

}

///

/// Queue the ascii representation of a string and then the set terminator bytes for sending. ///

///

String to bas.

Protected Void Send (String Tosend)

{

// jh 1.1: Use static encoder for effect. Thanks to PROF. Dr. Peter Jesorsky!

UINT L = (uint) Encoding.ascii.getbytecount (TOSEND);

IF (txterm! = null) L = (uint) TXTERM.GETLENGTH (0);

Byte [] b = new byte [l];

Byte [] s = encoding.ascii.getbytes (TOSEND);

INT I;

For (i = 0; (i <= s.getupperbound (0)); i ) b [i] = s [i];

IF (TXTERM! = NULL) for (int J = 0; (j <= txterm.getupperbound (0)); J , i ) B [i] = (byte) TXTERM [J];

Send (b);

}

///

/// transmits the ascii representation of a string followed by the set terminator bytes and life /// awaits a response string. ///

///

The string to be slow.

///

The response string.

Protected string transact (String Tosend)

{

Send (tosend);

Transflag.reset ();

IF (! Transflag.waitone ((int) TRANSTIMEOUT, FALSE)) ThrowException ("Timeout");

String S;

Lock (rxstring) {s = rxstring;}

Return S;

}

///

/// if a derived class overrides comsettings (), IT Must Call this prior to return the settings to ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///

Class Containing the appropriate settings.

Protected Void Setup (Commlinesettings S)

{

Rxbuffer = new byte [s.rxstringbuffersize];

RXTERM = S.Rxterminator;

Rxfilter = s.rxfilter;

TRANSTIMEOUT = (uint) S.TransActTimeout; TXTERM = S.TXTERMINATOR;

}

///

/// Override this to process unsolicited Input Lines (not a result of transact). ///

///

String containing the receivated ascii text.

Protected Virtual Void OnRxline (String s) {}

///

/// According to the byte acceptance data ///

///

Protected Override Void OnRxchar (Byte Ch)

{

ASCII CA = (ASCII) CH;

IF ((CA == RXTERM) || (RxBufferp> rxbuffer.getupperbound (0)))

{

// jh 1.1: Use static encoder for effect. Thanks to PROF. Dr. Peter Jesorsky!

Lock (rxstring) {rxstring = encoding.ascii.getstring (rxbuffer, 0, (int) rxbufferp);}

RxBufferp = 0;

IF (Transflag.Waitone (0, FALSE))

{

OnRxline (rxstring);

}

Else

{

Transflag.set ();

}

}

Else

{

BOOL WR = True;

IF (RxFilter! = NULL)

{

For (int i = 0; i <= rxfilter.getupperbound (0); i ) IF (RxFilter [i] == ca) WR = FALSE;

}

IF (WR)

{

RxBuffer [rxbufferp] = ch;

RxBufferp ;

}

}

}

}

///

/// Exception use for all errors. /////

Public Class CommPortext: ApplicationException

{

///

/// constructor for raising direct exceptions //////

///

Description of error

Public CommPortexception (String DESC): Base (DESC) {}

///

/// Constructor for Re-raising Exceptions from receive thread ///

///

Inner Exception Raised on Receive Thread

Public CommPortexception (Exception E): BASE ("Receive Thread Exception", E) {}

}

INTERNAL CLASS WIN32COM {

///

/// Opening Testing and Closing The port handle. ///

[DLLIMPORT ("kernel32.dll", setLastError = true)]

INTERNAL Static Extern INTPTR CREATEFILE (STRING LPFILENAME, UINT32 DWDESIREDACCESS, UINT32 DWSHAREMODE,

INTPTR LPSECurityAttributes, uint32 dwcreationdisposition, uint32 dwflagsandattributes, intptr htemplatefile;

// Constants for errors: internal const UInt32 ERROR_FILE_NOT_FOUND = 2; internal const UInt32 ERROR_INVALID_NAME = 123; internal const UInt32 ERROR_ACCESS_DENIED = 5; internal const UInt32 ERROR_IO_PENDING = 997; internal const UInt32 ERROR_IO_INCOMPLETE = 996;

// Constants for return value: INTERNAL const INT32 invalid_handle_value = -1;

// Constants for dwflagsandattributes: internal const uint32 file_flag_overlapped = 0x40000000;

// constants for dwcreationdisposition: internal const uint32 open_exiSTING = 3;

// constants for dwdesiredaccess: internal const uint32 generic_read = 0x80000000; INTERNAL const uint32 generic_write = 0x40000000;

[DLLIMPORT ("kernel32.dll")] INTERNAL Static Extern Boolean CloseHandle (INTPTR HOBJECT);

///

/// manipulating the communications settings. ///

[DLLIMPORT ("kernel32.dll")] INTERNAL Static Extern Boolean getcommstate (INTPTR HFILE, REF DCB LPDCB);

[DLLIMPORT ("kernel32.dll")] INTERNAL Static Extern Boolean getcommtimeouts (INTPTR HFILE, OUT COMMTIMEOUTS LPCOMMTIMEOUTS);

[DLLIMPORT ("kernel32.dll")] INTERNAL Static Extern Boolean BuildcommdcBandTimeouts (String LPDEF, REF DCB LPDCB, Ref Commtimeouts LPCommtimeout);

[DLLIMPORT ("kernel32.dll")] INTERNAL Static Extern Boolean SetCommState (INTPTR HFILE, [IN] REF DCB LPDCB);

[DLLIMPORT ("kernel32.dll")] INTERNAL Static Extern Boolean setcommtimeouts (INTPTR HFILE, [IN] Ref strtimeouts lpcommtimeout;

[DllImport ( "kernel32.dll")] internal static extern Boolean SetupComm (IntPtr hFile, UInt32 dwInQueue, UInt32 dwOutQueue); [StructLayout (LayoutKind.Sequential)] internal struct COMMTIMEOUTS {// JH 1.1: Changed Int32 to UInt32 to allow setting to MAXDWORD internal UInt32 ReadIntervalTimeout; internal UInt32 ReadTotalTimeoutMultiplier; internal UInt32 ReadTotalTimeoutConstant; internal UInt32 WriteTotalTimeoutMultiplier; internal UInt32 WriteTotalTimeoutConstant;} // JH 1.1: Added to enable use of "return immediately" timeout internal const UInt32 MAXDWORD = 0xffffffff;.

[StructLayout (LayoutKind.Sequential)] internal struct DCB {internal Int32 DCBlength; internal Int32 BaudRate; internal Int32 PackedValues; internal Int16 wReserved; internal Int16 XonLim; internal Int16 XoffLim; internal Byte ByteSize; internal Byte Parity; internal Byte StopBits; internal Byte INTERNAL BYTE ERRORCHAR; Internal Byte EOFCHAR; Internal Byte Evtchar; Internal INT16 WRESERVED1;

internal void init (bool parity, bool outCTS, bool outDSR, int dtr, bool inDSR, bool txc, bool xOut, bool xIn, int rts) {// JH 1.3:! Was 0x8001 ans so not setting fAbortOnError - Thanks Larry Delby DCBlength = 28; packedvalues ​​= 0x4001; if (Parity) PackedValues ​​| = 0x0002; if (outcts) packedValues ​​| = 0x0004; if (outdsr) PackedValues ​​| = 0x0008; PackedValues ​​| = ((DTR & 0x0003) << 4); IF INDSR) PackedValues ​​| = 0x0040; IF (TXC) PackedValues ​​| = 0x0080; if (xout) PackedValues ​​| = 0x0100; if (xin) PackedValues ​​| = 0x0200; PackedValues ​​| = ((RTS & 0x0003) << 12);

}

///

/// reading and Writing. ///

[DLLIMPORT ("kernel32.dll", setLastError = true)]

INTERNAL Static Extern Boolean Writefile (INTPTR FFILE, BYTE [] lpbuffer, uint32 nnumberofbytestowrite,

OUT uint32 lpnumberofbyteswritten, intptr lpoverlapped;

[StructLayout (LayoutKind.Sequential)] internal struct OVERLAPPED {internal UIntPtr Internal; internal UIntPtr InternalHigh; internal UInt32 Offset; internal UInt32 OffsetHigh; internal IntPtr hEvent;}

[DLLIMPORT ("kernel32.dll")] INTERNAL Static Extern Boolean SetCommmask (INTPTR HFILE, UINT32 DWEVTMASK);

// Constants for dwEvtMask: internal const UInt32 EV_RXCHAR = 0x0001; internal const UInt32 EV_RXFLAG = 0x0002; internal const UInt32 EV_TXEMPTY = 0x0004; internal const UInt32 EV_CTS = 0x0008; internal const UInt32 EV_DSR = 0x0010; internal const UInt32 EV_RLSD = 0x0020; internal const UInt32 EV_BREAK = 0x0040; internal const UInt32 EV_ERR = 0x0080; internal const UInt32 EV_RING = 0x0100; internal const UInt32 EV_PERR = 0x0200; internal const UInt32 EV_RX80FULL = 0x0400; internal const UInt32 EV_EVENT1 = 0x0800; internal const UInt32 EV_EVENT2 = 0x1000;

[DLLIMPORT ("kernel32.dll", setlasterror = true)] INTERNAL Static Extern Boolean Waitcommmevent (INTPTR HFILE, INTPTR LPEVTMASK, INTPTR LPOVERLAPPED);

[DllImport ( "kernel32.dll")] internal static extern Boolean CancelIo (IntPtr hFile); [DllImport ( "kernel32.dll", SetLastError = true)] internal static extern Boolean ReadFile (IntPtr hFile, [Out] Byte [] lpBuffer , Uint32 nnumberofbytestoread, out uint32 nNumberofbytesRead, INTPTR LPOVERLAPPED;

[DLLIMPORT ("kernel32.dll")] INTERNAL Static Extern Boolean Transmitcommchar (INTPTR HFILE, BYTE CCHAR); ///

/// Control port functions. ///

[DLLIMPORT ("kernel32.dll")]]]]

INTERNAL Static Extern Boolean EscapeCommfunction (INTPTR HFILE, UINT32 DWFUNC);

// Constants for dwFunc: internal const UInt32 SETXOFF = 1; internal const UInt32 SETXON = 2; internal const UInt32 SETRTS = 3; internal const UInt32 CLRRTS = 4; internal const UInt32 SETDTR = 5; internal const UInt32 CLRDTR = 6; internal const UInt32 RESETDEV = 7; internal const UInt32 SETBREAK = 8; internal const UInt32 CLRBREAK = 9; [DllImport ( "kernel32.dll")] internal static extern Boolean GetCommModemStatus (IntPtr hFile, out UInt32 lpModemStat);

// constants for lpmodemstat: INTERNAL const uint32 ms_cts_on = 0x0010; INTERNAL const uint32 ms_dsr_on = 0x0020; INTERNAL const UINT32 ms_ring_on = 0x0040; Internal const uint32 ms_rlsd_on = 0x0080;

///

/// status functions. ///

[DLLIMPORT ("kernel32.dll", setLastError = true)]

INTERNAL Static Extern Boolean GetoverlappedResult (INTPTR HFILE, INTPTR LPOVERLAPPED,

Out uint32 nnumberofbytestransferred, boolean bwait;

[DLLIMPORT ("kernel32.dll", setlasterror = true)] INTERNAL Static Extern Boolean PurgeComm (INTPTR HFILE, UINT DWFLAGS);

internal const uint PURGE_TXABORT = 0x0001; // Kill the pending / current writes to the comm port internal const uint PURGE_RXABORT = 0x0002;. // Kill the pending / current reads to the comm port internal const uint PURGE_TXCLEAR = 0x0004;. // Kill INTERNAL CONST UINT PURGE_RXCLEAR = 0x0008; // Kill The Typeahead Buffer if There.

[DllImport ( "kernel32.dll")] internal static extern Boolean ClearCommError (IntPtr hFile, out UInt32 lpErrors, IntPtr lpStat); [DllImport ( "kernel32.dll")] internal static extern Boolean ClearCommError (IntPtr hFile, out UInt32 lpErrors, out COMSTAT cs); // Constants for lpErrors: internal const UInt32 CE_RXOVER = 0x0001; internal const UInt32 CE_OVERRUN = 0x0002; internal const UInt32 CE_RXPARITY = 0x0004; internal const UInt32 CE_FRAME = 0x0008; internal const UInt32 CE_BREAK = 0x0010; internal const UInt32 CE_TXFULL = 0x0100; internal const UInt32 CE_PTO = 0x0200; internal const UInt32 CE_IOE = 0x0400; internal const UInt32 CE_DNS = 0x0800; internal const UInt32 CE_OOP = 0x1000; internal const UInt32 CE_MODE = 0x8000;

[StructLayout (LayoutKind.Sequential)] internal struct COMSTAT {internal const uint fCtsHold = 0x1; internal const uint fDsrHold = 0x2; internal const uint fRlsdHold = 0x4; internal const uint fXoffHold = 0x8; internal const uint fXoffSent = 0x10; internal const uint fEof = 0x20; internal const uint fTxim = 0x40; internal UInt32 Flags; internal UInt32 cbInQue; internal UInt32 cbOutQue;} [DllImport ( "kernel32.dll")] internal static extern Boolean GetCommProperties (IntPtr hFile, out COMMPROP cp);

[StructLayout (LayoutKind.Sequential)] internal struct COMMPROP {internal UInt16 wPacketLength; internal UInt16 wPacketVersion; internal UInt32 dwServiceMask; internal UInt32 dwReserved1; internal UInt32 dwMaxTxQueue; internal UInt32 dwMaxRxQueue; internal UInt32 dwMaxBaud; internal UInt32 dwProvSubType; internal UInt32 dwProvCapabilities; internal UInt32 dwSettableParams; internal UInt32 dwSettableBaud; internal UInt16 wSettableData; internal UInt16 wSettableStopParity; internal UInt32 dwCurrentTxQueue; internal UInt32 dwCurrentRxQueue; internal UInt32 dwProvSpec1; internal UInt32 dwProvSpec2; internal Byte wcProvChar;}}}


New Post(0)