{============================================================================== WCSC COMM/LIB Multi-port RS232 Communications Component ============================================================================== TO USERS OF THIS COMPONENT This Delphi component was developed and is copyrighted by Ken Sizer, II and Dan River, Inc. If you would like to use this component, we ask only that you let us know what you're doing and how it is working for you. Bug reports and bug fixes are especially appreciated. If you find this component to be truly wonderful, you may show your appreciation by buying some of our sheets, comforters or famous Bed-in-a-Bag ensembles! ACKNOWLEDGMENTS * Borland International -- for developing the slickest development tool around * Willies Computer Software Company -- for their solid communications products and unbeatable technical support * Jeff Steele of Dart Communications -- for working out the details of Delphi wrappers and DLL callbacks (and taking the time to write it all down) THE FINE PRINT The user of this component assumes full responsibility for any loss or damage resulting from its use. In no event shall Dan River or its employees be liable for any damages, lost profits or other consequences of the use of this product. ============================================================================== Tools: Borland Delphi 1.0, MS-Windows 3.11 Author: Ken Sizer, II (kbsizer@ns.gamewood.net) Start: 4/22/96 Mods: 4/22/96--kbs--initial implementation (bare bones) 5/19/96--kbs--added event handlers for interrupt-driven I/O 6/05/96--kbs--streamlined and generalized interrupt handler ----------------------------------------------------------------------------- Notes: 1) The data retrieval functions (Get*) return the number of characters successfully read, not an RS232 error code. 2) This implementation limits GetString to 255 characters and PutString to 254 characters. 3) The C DLL's used by this wrapper do not allow GetString and PutString to handle embedded NULL characters. 4) This wrapper requires that port numbers be within the range [0..7] when event handlers are used. (port number acts as the index into the event handler address array) ----------------------------------------------------------------------------- Usage Tips: 1) All "Trigger Properties", e.g. RecChar0, must be initialized at run- time, after a successful call to InitializePort. This is one of the "rough edges" of this component. 2) To make life with InitializePort and SetPortCharacteristics easier, the TWCSCConfig record type may be used. (I typically read all the fields in from an INI file and call these functions in an OnCreate method) ----------------------------------------------------------------------------- Future development items: 1) Make "Trigger Properties" array properties! This would include the creation of an array property editor. 2) Add support for more events. This would be easy in itself, but tedious until (1) has been addressed. 3) General removal of rough edges associated with initialization. =============================================================================} unit WCSCComm; interface {====================================================================} uses SysUtils, WinTypes, WinProcs, Classes, Forms, Dialogs, Messages; const {--- some ASCII character definitions ---} NUL = #$00; STX = #$02; ETX = #$03; ENQ = #$05; CAN = #$18; ESC = #$1B; XON = #$0B; XOF = #$0D; CR = #$0D; LF = #$0A; {--- I/O Card Specific Stuff ---} BOCA_PORTS = 8; { available ports are 0,1,2,3,4,5,6,7 } BOCA_LASTPORT = 7; BOCA_CARD_OFFSET = $40; { port blocks are 40h or 64d bytes in length } BOCA_PORT_OFFSET = $08; { each port's data area occupies 8 bytes } {--- Comm Settings ---} BAUD110 = 0; {110 baud} BAUD150 = 1; {150 baud} BAUD300 = 2; {300 baud} BAUD600 = 3; {600 baud} BAUD1200 = 4; {1200 baud} BAUD2400 = 5; {2400 baud} BAUD4800 = 6; {4800 baud} BAUD9600 = 7; {9600 baud} BAUD19200 = 8; {19200 baud} BAUD38400 = 9; {38400 baud} BAUD57600 = 10; {57600 baud} BAUD115200 = 11; {115.2 kbaud} PARITY_NONE = 0; {No parity} PARITY_ODD = 1; {ODD parity} PARITY_EVEN = 2; {Even parity} PARITY_SODD = 3; {Sticky ODD parity} PARITY_SEVEN = 4; {Sticky Even parity} LENGTH_5 = 0; {5 bits} LENGTH_6 = 1; {6 bits} LENGTH_7 = 2; {7 bits} LENGTH_8 = 3; {8 bits} STOPBIT_1 = 0; {1 Stop bit} STOPBIT_2 = 1; {2 Stop bit} BREAK_OFF = 0; {Break off} BREAK_ON = 1; {Break on} {--- Protocols ---} PROT_RTSRTS = 0; {Local CTS/RTS Remote CTS/RTS} PROT_RTSXON = 1; {Local CTS/RTS Remote XON/XOFF} PROT_RTSDTR = 2; {Local CTS/RTS Remote DSR/DTR} PROT_RTSNON = 3; {Local CTS/RTS Remote no protocol} PROT_NONNON = 4; {Local no prot Remote no protocol} PROT_NONXON = 5; {Local no prot Remote XOFF/XON} PROT_XONNON = 6; {Local XOFF/XON Remote no protocol} PROT_XONXON = 7; {Local XON/XOFF Remote XON/XOFF} PROT_DTRNON = 8; {Local DSR/DTR Remote no protocol} PROT_DTRRTS = 9; {Local DSR/DTR Remote CTS/RTS} PROT_DTRDTR = 10; {Local DSR/DTR Remote DSR/DTR} PROT_DTRXON = 11; {Local DSR/DTR Remote XON/XOFF} PROT_NONRTS = 12; {Local no prot Remote CTS/RTS} PROT_NONDTR = 13; {Local no prot Remote DSR/DTR} PROT_XONRTS = 14; {Local XOFF/XON Remote CTS/RTS} PROT_XONDTR = 15; {Local XOFF/XON Remote DSR/DTR} {--- Serial Cards Supported ---} CARD_NORMAL = 0; { Normal cards } CARD_INTELH = 1; { Intel HUB card } CARD_DIGCXI = 2; { Digiboard COMXI } CARD_ARNETSPLUS = 3; { Arnet Smartplus } CARD_BOCA1610 = 4; { BOCA 1610 } CARD_DIGPCX = 5; { Digiboard PCX } CARD_GTEK = 6; { GTEK board } CARD_INT14 = 7; { 3rd party INT14H board } CARD_WCSCVXD = 8; { WCSC high speed VxD for 8250 family } CARD_WINAPI = 9; { Uses Windows API } {--- Miscellaneous Function Sub-commands ---} WAITCDON = $0000; { Waitfor CD on } WAITCDOFF = $0001; { Waitfor CD off } WAITCTSON = $0002; { Waitfor RTS on } WAITCTSOFF = $0003; { Waitfor RTS off } WAITDSRON = $0004; { Waitfor DSR on } WAITDSROFF = $0005; { Waitfor DSR off } WAITRION = $0006; { Waitfor RI on } WAITRIOFF = $0007; { Waitfor RI off } WAITXEMPTY = $0008; { Waitfor xmit buf empty } WAITXNOTEMPTY = $0009; { Waitfor xmit buf not empty } WAITREMPTY = $000A; { Waitfor receive buf empty } WAITRNOTEMPTY = $000B; { Waitfor receive buf not empty } SETRCVCHR = $000C; { Set receive character comparator } SETXMTCHR = $000D; { Set transmit character comparator } SETIBFDCNT = $000E; { Set input buffer down count threshold } SETIBFICNT = $000F; { Set input buffer up count threshold } SETOBFDCNT = $0010; { Set output buffer down count threshold } SETOBFICNT = $0011; { Set output buffer up count threshold } WAITTIME = $0012; { Waitfor time } WAITRCOUNT = $0013; { Waitfor at least RCV buffer count } WAITXCOUNT = $0014; { Waitfor at least XMT buffer count } SETRCOUNT = $0015; { Waitfor at least RCV buffer count } SETXCOUNT = $0016; { Waitfor at least XMT buffer count } SENDNOW = $0017; { Send a string ahead of buffered area } {--- Line and Modem Status ---} LSR_DATA = $01; { Data Ready bit } LSR_OVERRUN = $02; { Overrun error bit } LSR_PARITY = $04; { Parity error bit } LSR_FRAMING = $08; { Framing error bit } LSR_BREAK = $10; { Break Detect } LSR_THRE = $20; { Transmit Holding Register Empty } LSR_TSRE = $40; { Transmit Shift Register Empty } MSR_CTS = $10; { Clear To Send } MSR_DSR = $20; { Data Set Ready } MSR_RI = $40; { Ring Indicator - during entire ring } MSR_DCD = $80; { Data Carrier Detect - on line } {--- Callback Events ---} { Activation Trigger Mask Settings } INTFUNC_MODEM = $0008; { Set = Exec modem intrpt func } INTFUNC_STAT = $0010; { Set = Exec status intrpt func } INTFUNC_RCV = $0020; { Set = Exec receive intrpt func } INTFUNC_XMIT = $0040; { Set = Exec xmit interpt func } INTFUNC_AVAIL = $0080; { Set = } INTFUNC_RCVCHR = $0100; { Set = Exec specific char rcv intrpt func } INTFUNC_IBFDCNT = $0200; { Set = Exec inbuf dec to val intrpt func } INTFUNC_IBFICNT = $0400; { Set = Exec inbuf inc to val intrpt func } INTFUNC_OBFDCNT = $0800; { Set = Exec outbuf dec to val intrpt func } INTFUNC_OBFICNT = $1000; { Set = Exec outbuf inc to val intrpt func } INTFUNC_XMTCHR = $2000; { Set = Exec if about to xmit chr intrpt fnc } INTFUNC_X = $4000; { Set = Use extended masks } INTFUNC_OTHER = $8000; { Set = Exec by other conditions } INTFUNC_X_BREAK = $0001; { Set = Exec on Break intrpt func } INTFUNC_X_FRAME = $0002; { Set = Exec on7 Frame intrpt func } INTFUNC_X_OVRUN = $0004; { Set = Exec on Parity intrpt func } INTFUNC_X_PARER = $0008; { Set = Exec on Frame intrpt func } INTFUNC_X_CTS = $0010; { Set = Exec on CTS intrpt func } INTFUNC_X_DSR = $0020; { Set = Exec on DSR intrpt func } INTFUNC_X_CD = $0040; { Set = Exec on CD intrpt func } INTFUNC_X_RING = $0080; { Set = Exec on RING intrpt func } { Activation ID's passed to Interrupt Handler } INTFUNC_VMODEM = $0000; { Modem intrpt } INTFUNC_VSTAT = $0001; { Status intrpt } INTFUNC_VRCV = $0002; { Receive intrpt } INTFUNC_VXMIT = $0003; { Xmit interpt } INTFUNC_VAVAIL = $0004; { } INTFUNC_VRCVCHR = $0005; { Specific char rcv intrpt } INTFUNC_VIBFDCNT = $0006; { Inbuf dec to val intrpt } INTFUNC_VIBFICNT = $0007; { Inbuf inc to val intrpt } INTFUNC_VOBFDCNT = $0008; { Outbuf dec to val intrpt } INTFUNC_VOBFICNT = $0009; { Outbuf inc to val intrpt } INTFUNC_VXMTCHR = $000a; { XMIT specific char int } INTFUNC_VWAITCDON = $000b; { Waitfor CD on int } INTFUNC_VWAITCDOFF = $000c; { Waitfor CD off int } INTFUNC_VWAITCTSON = $000d; { Waitfor CTS on int } INTFUNC_VWAITCTSOFF = $000e; { Waitfor CTS off int } INTFUNC_VWAITDSRON = $000f; { Waitfor DSR on int } INTFUNC_VWAITDSROFF = $0010; { Waitfor DSR off int } INTFUNC_VWAITRION = $0011; { Waitfor RI on int } INTFUNC_VWAITRIOFF = $0012; { Waitfor RI off int } INTFUNC_VWAITXEMPTY = $0013; { Waitfor xmit empty int } INTFUNC_VWAITXNOTEMPTY = $0014; { Waitfor xmit not empty int } INTFUNC_VWAITREMPTY = $0015; { Waitfor receive empty int } INTFUNC_VWAITRNOTEMPTY = $0016; { Waitfor receive not empty int } INTFUNC_VWAITTIME = $0017; { Waitfor time int } INTFUNC_VX_BREAK = $0018; { Break intrpt } INTFUNC_VX_FRAME = $0019; { Frame intrpt } INTFUNC_VX_OVRUN = $001a; { Overrun intrpt } INTFUNC_VX_PARER = $001b; { Parity intrpt } INTFUNC_VX_CTS = $001c; { CTS intrpt } INTFUNC_VX_DSR = $001d; { DSR intrpt } INTFUNC_VX_CD = $001e; { CD intrpt } INTFUNC_VX_RING = $001f; { RING intrpt } INTFUNC_VWAITRCOUNT = $0020; { RCV Count intrpt } INTFUNC_VWAITXCOUNT = $0021; { XMT Count intrpt } INTFUNC_VSENDNOWDONE = $0022; { Send now done } {--- Timer Tick Resolution ---} TICKS_PER_SECOND = 18; { Interrupt 08h ticks come every 1/18 sec } {--- Error Codes ---} RS232ERR_NONE = 0; {RS232 no error} RS232ERR_NOINIT = -1; {RS232 port not initialized} RS232ERR_BUFFER = 1; {RS232 buffer not set or buff changed} RS232ERR_ACTIVE = 2; {RS232 port not active} RS232ERR_XMTBUF = 3; {RS232 xmit buffer full} RS232ERR_RCVBUF = 4; {RS232 recv buffer empty} RS232ERR_SYNTAX = 5; {RS232 port syntax error} RS232ERR_BUFSIZ = 6; {RS232 invalid buffer size} RS232ERR_PORT = 7; {RS232 invalid port} RS232ERR_HANDLR = 8; {RS232 handler changed} RS232ERR_BAUD = 9; {RS232 invalid baud rate} RS232ERR_PARITY = 10; {RS232 invalid parity} RS232ERR_LNGTH = 11; {RS232 invalid data length} RS232ERR_STOPBIT = 12; {RS232 invalid # stopbits} RS232ERR_PROTOCOL = 13; {RS232 invalid protocol} RS232ERR_IRQCHANGED = 14; {RS232 IRQ changed} RS232ERR_PORTCHANGED = 15; {RS232 port changed} RS232ERR_THRESHOLD = 16; {RS232 invalid threshold} RS232ERR_INVIRQ = 17; {RS232 invalid IRQ} RS232ERR_INTOFF = 18; {RS232 interrupts not enabled} RS232ERR_BREAK = 19; {RS232 invalid break syntax} RS232ERR_FATAL = 20; {RS232 fatal error} RS232ERR_DSR = 21; {RS232 CTS error} RS232ERR_INVADR = 22; {RS232 Invalid RS232 address} RS232ERR_ENVIRON = 23; {Environment variable not set} RS232ERR_IOCTL = 24; {Error issuing IOCTL call} RS232ERR_ATEXIT = 25; {Error issuing atexit cleanup} RS232ERR_DEVINIT = 26; {Error mapping for dir calls} RS232ERR_DOSOPEN = 27; {Error opening Device} RS232ERR_MALLOC = 28; {Error allocating memory} RS232ERR_EXTMICRO = 29; {Error on external micro} RS232ERR_CARDCHANGED = 30; {Card changed error} RS232ERR_CARDTYPE = 31; {Card type error} RS232ERR_NOSUPPORT = 32; {Not supported} RS232ERR_CMDBUFFULL = 33; {Card command buffer full} RS232ERR_PPORT = 34; {Invalid parent PCB} RS232ERR_NODEVICE = 35; {No device for this port} RS232ERR_UNKNOWN = 36; {Unknow error} RS232ERR_BUSY = 37; {Busy} RS232ERR_NOTIMER = 38; {No more timers available} RS232ERR_INT14VEC = 39; {INT 14H vector changed} RS232ERR_INT1CVEC = 40; {Timer vector changed} RS232ERR_DPMI = 41; {DPMI error} RS232ERR_WINBUF = 42; {No windows buffer or too small} RS232ERR_NOASYNCRES = 43; {No asynchronous resources left} RS232ERR_NOTIMERRES = 44; {No timer resources left} RS232ERR_NOOTHERES = 45; {Out of other resources} RS232ERR_FILEIO = 46; {File I/O error} RS232ERR_HMEMG64 = 47; {Hardware memory exceeded 64K} RS232ERR_MAPVXD = 48; {VxD not present/other VxD error} {--- Define our own Windows messages ---} WM_WCSC_NOTIFY = WM_USER + $0100; WM_WCSC_DEBUG = WM_USER + $0101; type { === WCSC COMM-DRV/LIB Serial Communications API Function Signatures === } TWCSC_InitializePort = function( port, subport : Integer; addr, irq, cardtype, cardseg, inbuflen, outbuflen, flag : word ) : Integer; TWCSC_UnInitializePort = function ( port : Integer ) : Integer; TWCSC_SetPortCharacteristics = function ( port : Integer; baud, parity, length, stopBits, protocol : word ) : Integer; TWCSC_SetTimeout = function ( port, nTicks : Integer ) : Integer; TWCSC_PutByte = function ( port : Integer; ch : char ) : Integer; TWCSC_PutPacket = function ( port, length : Integer; pkt : PChar ) : Integer; TWCSC_PutString = function ( port : Integer; str : PChar ) : Integer; TWCSC_IsReceiveBufferEmpty = function ( port : Integer ) : Integer; TWCSC_GetByte = function ( port : Integer ) : Integer; TWCSC_GetPacket = function ( port, length : Integer; pkt : PChar ) : Integer; TWCSC_GetString = function ( port, length : Integer; str : PChar ) : Integer; TWCSC_WaitFor = function ( port, timeout : Integer; outstr, instr : PChar ) : Integer; TWCSC_WaitForPeek = function ( port, timeout : Integer; outstr, instr : PChar ) : Integer; TWCSC_Flush = function ( port : Integer; arg : Integer ) : Integer; TWCSC_GetStatus = function ( port : Integer; status : PChar ) : Integer; TWCSC_MiscFunction = function ( port : Integer; cmd : Word; arg : LongInt ) : Integer; TWCSC_SetIntFunc = function ( port : Integer; func : Pointer;{addr of pntr to fun addr} imask : Integer ) : Integer; { === Event Types === } TOnRecAny = procedure( Sender : TObject; ch : Char ) of Object; TOnRecChar = procedure( Sender : TObject ) of Object; TOnRecCount = procedure( Sender : TObject ) of Object; { === Enumerated Types === } { === Other Useful Types === } TPortNumber = 0..BOCA_LASTPORT; {standard Pascal subrange type} {--- Port Control Block structure (PCB) ---} TPWCSC_PortParam = ^TWCSC_PortParam; TWCSC_PortParam = record portAddr : Word; { Base address of this port } irq : Word; { Interrupt number } baud : Word; { baud rate index } parity : Word; { parity index } lngth : Word; { length index } stopbit : Word; { stopbit index } brk : Word; { Break } protocol : Word; { protocol index } ticksLo : Byte; { # of 1/18.2 secs count } ticksHi : Byte; inbuf_low : Word; { Low threshold of recv buffer } inbuf_high : Word; { High threshold of xmit buffer } buffer_seg : Word; { Segment to start of buffer } buffer_off : Word; { Offset to start of buffer } inbuf_len : Word; { Input buffer length } outbuf_len : Word; { Output buffer length } aux_addr1 : Byte; { Auxiliary Address } sflag : Byte; { System flag } cardseg : Word; { Memory card segment } cardtype : Word; { Card Type } intFunc : TFarProc; { Addr of Interrupt Function } error : Word; { Error flag } flag : Word; { general purpose flag } inbuf_count : Word; { # bytes in input buf } outbuf_count : Word; { # of bytes in ouput } lost_ichar : LongInt; { Lost inputted bytes } lost_ochar : LongInt; { Lost outputted bytes } total_ichar : LongInt; { Total attempted bytes in } total_ochar : LongInt; { Total attempted bytes out } devfuncs : Pointer; { Pntr to table of pntr to dev funcs } msr_reg : Byte; { Current modem status register} lsr_reg : Byte; { Current line status register} ddata : Word; { Data that sub-device driver may use } inbuf_start : Word; { Input buffer control block} outbuf_start : Word; { Output buffer control block} irqp : Pointer; { Pointer to irq parameter block } port : Word; { Port number } flag2 : Word; { Secondary flag } obufoff : Word; { Output buf off if DIFFXBUF set } obufseg : Word; { Output buf seg if DIFFXBUF set } pport : Word; { Parent port } ppcb : Word; { Parent pcb } timer_iblk : Word; { Timer block.} timer_oblk : Word; { Timer block.} hblockHi : Byte; { Hi byte of input/output timeouts } hblockLo : Byte; { Lo byte of input/output timouts } char_xon : Byte; { XON character } char_xoff : Byte; { XOFF character } char_xxon : Byte; { XON xmit character } char_xxoff : Byte; { XOFF xmit character } auxpcb : Pointer; { Pointer to auxiliary PCB} prot_local : Word; { Local protocol } prot_remote : Word; { Remote protocol } opcb : TPWCSC_PortParam; { Pointer to this PCB} dflag : Word; { Subdevice specific flag } o_baud_regLo : Byte; { Old baud rate} o_baud_regHi : Byte; o_lcr_reg : Byte; { Old line control register} o_mcr_reg : Byte; { Old modem control register} o_ier_reg : Byte; { Old Interrupt enable register} tuart : Byte; { Type of UART} next_pcb : Word; { Pointer to next } end; {--- Event Trigger Data ---} TWCSC_PortTriggers = record iMask : Integer; { "iMask" passed to ser_rs232_set_intfunc } recAny : Boolean; { Trigger an event on EVERY character } recChar : Char; { Trigger if "recChar" is received } recCount : Word; { Trigger if "recCount" chars are received } end; {--- A record for the user... to simplify initializing WCSC ports ---} TWCSCConfig = record { Port Settings } port : TPortNumber; subPort : Integer; baseAddr : Word; UARTOffset : Word; IRQ : Word; cardType : Word; cardSeg : Word; inBufLen : Word; outBufLen : Word; flag : Word; { Comm Settings } baud : Integer; parity : Word; dataBits : Word; stopBits : Word; protocol : Word; end; { === WCSC Multiple RS232 I/O Port Control Class ===} TWCSCComm = class(TComponent) private HLF_library : THandle; { Handle of High-level function DLL } LLF_library : THandle; { Handle of Low-level function DLL } {---- Pointers to DLL entry points ----} WCSC_InitializePort : TWCSC_InitializePort; WCSC_UnInitializePort : TWCSC_UnInitializePort; WCSC_SetPortCharacteristics : TWCSC_SetPortCharacteristics; WCSC_SetTimeout : TWCSC_SetTimeout; WCSC_Flush : TWCSC_Flush; WCSC_GetStatus : TWCSC_GetStatus; WCSC_PutByte : TWCSC_PutByte; WCSC_PutPacket : TWCSC_PutPacket; WCSC_PutString : TWCSC_PutString; WCSC_IsReceiveBufferEmpty : TWCSC_IsReceiveBufferEmpty; WCSC_GetByte : TWCSC_GetByte; WCSC_GetPacket : TWCSC_GetPacket; WCSC_GetString : TWCSC_GetString; WCSC_WaitFor : TWCSC_WaitFor; WCSC_WaitForPeek : TWCSC_WaitForPeek; WCSC_MiscFunction : TWCSC_MiscFunction; WCSC_SetIntFunc : TWCSC_SetIntFunc; {------ Internal state variables ------} WCSC_TestMode : Boolean; { Diagnostic Message Flag } WCSC_portTriggers : array [0..BOCA_LASTPORT] of TWCSC_portTriggers; {---- Pointers to event handlers ---} FOnRecAny : array [0..BOCA_LASTPORT] of TOnRecAny; FOnRecChar : array [0..BOCA_LASTPORT] of TOnRecChar; FOnRecCount : array [0..BOCA_LASTPORT] of TOnRecCount; {---- Private methods used by Property Access Methods ----} procedure SetRecAny( port : TPortNumber; any : Boolean ); procedure SetRecChar( port : TPortNumber; ch : Char ); procedure SetRecCount( port : TPortNumber; count : Word ); {---- Property Access Methods (three for each port) ----} procedure SetRecAny0( any : Boolean ); procedure SetRecChar0( ch : Char ); procedure SetRecCount0( count : Word ); procedure SetRecAny1( any : Boolean ); procedure SetRecChar1( ch : Char ); procedure SetRecCount1( count : Word ); procedure SetRecAny2( any : Boolean ); procedure SetRecChar2( ch : Char ); procedure SetRecCount2( count : Word ); procedure SetRecAny3( any : Boolean ); procedure SetRecChar3( ch : Char ); procedure SetRecCount3( count : Word ); procedure SetRecAny4( any : Boolean ); procedure SetRecChar4( ch : Char ); procedure SetRecCount4( count : Word ); procedure SetRecAny5( any : Boolean ); procedure SetRecChar5( ch : Char ); procedure SetRecCount5( count : Word ); procedure SetRecAny6( any : Boolean ); procedure SetRecChar6( ch : Char ); procedure SetRecCount6( count : Word ); procedure SetRecAny7( any : Boolean ); procedure SetRecChar7( ch : Char ); procedure SetRecCount7( count : Word ); {---- Windows Message Dispatcher for Callbacks ---} procedure WndProc( var winMsg : TMessage ); protected public {====================== BEGIN COMPONENT INTERFACE =======================} constructor Create(AOwner : TComponent); override; destructor Destroy; override; {--------------- WCSC Comm Component Methods ----------------------------} {--- High-level Functions ---} function InitializePort( port : TPortNumber; subport : Integer; addr, irq, cardtype, cardseg, inbuflen, outbuflen, flag : word ) : Integer; function UnInitializePort( port : Integer ) : Integer; function SetPortCharacteristics( port : Integer; baud, parity, length, stopBits, protocol : word ) : Integer; function SetTimeout( port, nTicks : Integer ) : Integer; function PutByte( port : Integer; ch : char ) : Integer; function PutPacket( port, length : Integer; pkt : PChar ) : Integer; function PutString( port : TPortNumber; str : string ) : Integer; function InputBufferEmpty( port : Integer ) : boolean; function GetByte( port : Integer; var ch : char ) : Integer; function GetPacket( port, length : Integer; pkt : PChar ) : Integer; function GetString( port : TPortNumber; var str : string ) : Integer; function WaitFor( port, timeout : Integer; outstr, instr : string ) : Integer; function WaitForPeek( port, timeout : Integer; outstr, instr : string ) : Integer; {--- Low-level Functions ---} function GetStatus( port : TPortNumber; var modemStat : byte; var lineStat : byte ) : Integer; function Flush ( port : TPortNumber) : Integer; {--- Diagnostic Functions ---} function GetErrorMsg : String; published {--------------- WCSC Comm Component Properties -------------------------} property TestMode : Boolean read WCSC_TestMode write WCSC_TestMode; property RecAny0 : Boolean read WCSC_portTriggers[0].recAny write SetRecAny0; property RecChar0 : Char read WCSC_portTriggers[0].recChar write SetRecChar0; property RecCount0 : Word read WCSC_portTriggers[0].recCount write SetRecCount0; property RecAny1 : Boolean read WCSC_portTriggers[1].recAny write SetRecAny1; property RecChar1 : Char read WCSC_portTriggers[1].recChar write SetRecChar1; property RecCount1 : Word read WCSC_portTriggers[1].recCount write SetRecCount1; property RecAny2 : Boolean read WCSC_portTriggers[2].recAny write SetRecAny2; property RecChar2 : Char read WCSC_portTriggers[2].recChar write SetRecChar2; property RecCount2 : Word read WCSC_portTriggers[2].recCount write SetRecCount2; property RecAny3 : Boolean read WCSC_portTriggers[3].recAny write SetRecAny3; property RecChar3 : Char read WCSC_portTriggers[3].recChar write SetRecChar3; property RecCount3 : Word read WCSC_portTriggers[3].recCount write SetRecCount3; property RecAny4 : Boolean read WCSC_portTriggers[4].recAny write SetRecAny4; property RecChar4 : Char read WCSC_portTriggers[4].recChar write SetRecChar4; property RecCount4 : Word read WCSC_portTriggers[4].recCount write SetRecCount4; property RecAny5 : Boolean read WCSC_portTriggers[5].recAny write SetRecAny5; property RecChar5 : Char read WCSC_portTriggers[5].recChar write SetRecChar5; property RecCount5 : Word read WCSC_portTriggers[5].recCount write SetRecCount5; property RecAny6 : Boolean read WCSC_portTriggers[6].recAny write SetRecAny6; property RecChar6 : Char read WCSC_portTriggers[6].recChar write SetRecChar6; property RecCount6 : Word read WCSC_portTriggers[6].recCount write SetRecCount6; property RecAny7 : Boolean read WCSC_portTriggers[7].recAny write SetRecAny7; property RecChar7 : Char read WCSC_portTriggers[7].recChar write SetRecChar7; property RecCount7 : Word read WCSC_portTriggers[7].recCount write SetRecCount7; {--------------- WCSC Comm Component Events -----------------------------} property OnRecAny0 : TOnRecAny read FOnRecAny[0] write FOnRecAny[0]; property OnRecChar0 : TOnRecChar read FOnRecChar[0] write FOnRecChar[0]; property OnRecCount0 : TOnRecCount read FOnRecCount[0] write FOnRecCount[0]; property OnRecAny1 : TOnRecAny read FOnRecAny[1] write FOnRecAny[1]; property OnRecChar1 : TOnRecChar read FOnRecChar[1] write FOnRecChar[1]; property OnRecCount1 : TOnRecCount read FOnRecCount[1] write FOnRecCount[1]; property OnRecAny2 : TOnRecAny read FOnRecAny[2] write FOnRecAny[2]; property OnRecChar2 : TOnRecChar read FOnRecChar[2] write FOnRecChar[2]; property OnRecCount2 : TOnRecCount read FOnRecCount[2] write FOnRecCount[2]; property OnRecAny3 : TOnRecAny read FOnRecAny[3] write FOnRecAny[3]; property OnRecChar3 : TOnRecChar read FOnRecChar[3] write FOnRecChar[3]; property OnRecCount3 : TOnRecCount read FOnRecCount[3] write FOnRecCount[3]; property OnRecAny4 : TOnRecAny read FOnRecAny[4] write FOnRecAny[4]; property OnRecChar4 : TOnRecChar read FOnRecChar[4] write FOnRecChar[4]; property OnRecCount4 : TOnRecCount read FOnRecCount[4] write FOnRecCount[4]; property OnRecAny5 : TOnRecAny read FOnRecAny[5] write FOnRecAny[5]; property OnRecChar5 : TOnRecChar read FOnRecChar[5] write FOnRecChar[5]; property OnRecCount5 : TOnRecCount read FOnRecCount[5] write FOnRecCount[5]; property OnRecAny6 : TOnRecAny read FOnRecAny[6] write FOnRecAny[6]; property OnRecChar6 : TOnRecChar read FOnRecChar[6] write FOnRecChar[6]; property OnRecCount6 : TOnRecCount read FOnRecCount[6] write FOnRecCount[6]; property OnRecAny7 : TOnRecAny read FOnRecAny[7] write FOnRecAny[7]; property OnRecChar7 : TOnRecChar read FOnRecChar[7] write FOnRecChar[7]; property OnRecCount7 : TOnRecCount read FOnRecCount[7] write FOnRecCount[7]; {====================== END COMPONENT INTERFACE =========================} end; { === These procedures and functions are not part of the object model === } { Callback function -- this function must use the C calling convention } { and its definition must match what the caller is expecting: } { "short (FAR *(FAR *callback))(short c,struct port_param FAR *p);" } { DO NOT use the EXPORT directive with this function, since the WCSC DLL } { uses the pointer we pass to it to set the DS for us! } function CallbackProc( v : Integer; p : TPWCSC_PortParam ) : Integer; cdecl; {export;} { Required by Delphi for component installation } procedure Register; implementation {===============================================================} const DLL_NOT_LOADED = $7FFF; {My own signal, for DLL problems} var ReturnCode : Integer; WCSC_hwnd : HWnd; WndProcHndl : HWnd; WCSC_callbackProc : TFarProc; { Address of instance of callback } { Registration procedure, used by Delphi to install the component } procedure Register; begin RegisterComponents('RS232', [TWCSCComm]); end; {----------------------------------------------------------------------------} { CALLBACK FUNCTION whose address is given to the WCSC DLL } {----------------------------------------------------------------------------} { Usage Notes: } { 1) This function is called when an interrupt is triggered. This } { routine can be called AT ANY TIME and must therefore be fully } { reentrant. One of the consequences of this requirement is that } { our compiler's STACK CHECKING option must be DISABLED. } { 2) The WCSC DLL requires that we pass "ser_rs232_set_intfunc" the } { address of a pointer variable which holds the address of this } { callback function. The extra level of indirection allows the DLL } { caller to set the data segment (DS) register to our global variable } { segment before handing over control. If they didn't do us this } { little favor, this callback could not access any of our program's } { global data, e.g., it couldn't even know the HWND of the window to } { which it is supposed to send messages! } {----------------------------------------------------------------------------} { Parameters: } { Hi(v) == Event ID (INTFUNC_VMODEM, INTFUNC_VRCV, etc.) } { Lo(v) == Optional byte of data associated with event, e.g., } { INTFUNC_MODEM ==> Lo(v) = modem status register } { INTFUNC_STAT ==> Lo(v) = line status register } { INTFUNC_RCV ==> Lo(v) = received character, etc. } { p == Pointer to the port parameter structure which contains } { everything we could ever want to know about our port } {----------------------------------------------------------------------------} function CallbackProc( v : Integer; p : TPWCSC_PortParam ) : Integer; begin PostMessage( WndProcHndl, WM_WCSC_NOTIFY, v, LongInt(p) ); { Depending on performance tests, we may want to change this to a SendMessage, which requires that the receiver get and act on the message IMMEDIATELY. } if Hi(v) = INTFUNC_VRCV then { Don't buffer if this is a RCV message } Result := -1 else Result := v; end; {----------------------------------------------------------------------------} { WINDOWS MESSAGE HANDLER } {----------------------------------------------------------------------------} { This Windows message handler is responsible for catching messages thrown } { to the WCSCComm object by the Windows environment. } { The only messages truly "handled" by this method are those sent to it by } { the above callback function, i.e., WM_WCSC_NOTIFY. All others are simply } { passed along to the default handler. } { NOTE: } { In order to have event handlers for the ports trigger correctly, this } { routine requires that port numbers be within the range [0..7] } {----------------------------------------------------------------------------} procedure TWCSCComm.WndProc( var winMsg : TMessage ); var portNo : TPortNumber; begin with winMsg do begin if Msg = WM_WCSC_NOTIFY then begin portNo := TPWCSC_PortParam(lParam)^.port; case Hi(wParam) of INTFUNC_VRCV : if Assigned( FOnRecAny[portNo] ) then FOnRecAny[portNo]( self, Char(Lo(wParam))); INTFUNC_VRCVCHR : if Assigned( FOnRecChar[portNo] ) then FOnRecChar[portNo]( self ); INTFUNC_VIBFICNT : if Assigned( FOnRecCount[portNo] ) then FOnRecCount[portNo]( self ); else if WCSC_TestMode then MessageDlg( 'WCSC Component, Message Handler' + #13 + 'Received unexpected INTFUNC message ' + IntToHex(Hi(wParam),4) + #13 + 'from port ' + IntToStr(portNo), mtError, [mbOK], 0 ); end; end else Result := DefWindowProc( WCSC_hwnd, Msg, wParam, lParam ); end; end; { A dummy stub used to render DLL functions harmless when DLL cannot be found } function NullProc : Integer; far; begin ReturnCode := DLL_NOT_LOADED; result := DLL_NOT_LOADED end; {=== CONSTRUCTOR & DESTRUCTOR ==================================} constructor TWCSCComm.Create(AOwner : TComponent); {private function, accessible only from within this method} Function AcquireFun( lib : THandle; funName : PChar ) : Pointer; begin result := GetProcAddress( lib, funName ); if result = NIL then begin result := @NullProc; {point to NullProc if we can't find the real addr} if WCSC_TestMode then MessageDlg('GetProcAddress failed,' + CR + 'assigning ' + StrPas(funName) + ' to NULL.', mtError, [mbOK], 0 ); end; end; begin inherited Create(AOwner); WCSC_hwnd := (AOwner as TForm).Handle; {Get handle of my owner} (* Willies' DLL doesn't need this extra step... { create instance of CallbackProc to handle interrupts by sending msgs } WCSC_callbackProc := MakeProcInstance( @CallbackProc, HInstance ); *) WCSC_callbackProc := @CallbackProc; if WCSC_TestMode then begin MessageDlg('WCSC_callbackProc = ' + IntToHex(Seg(CallbackProc),4) + ':' + IntToHex(Ofs(CallbackProc),4), mtInformation, [mbOK], 0 ); MessageDlg('WCSC_callbackProc is stored at' + IntToHex(Seg(WCSC_callbackProc),4) + ':' + IntToHex(Ofs(WCSC_callbackProc),4), mtInformation, [mbOK], 0 ); end; { create invisible window to receive Windows messages } WndProcHndl := AllocateHWnd( WndProc ); {--- Load the High-level DLL functions ---} HLF_library := LoadLibrary( 'CDRVHF.DLL' ); if HLF_library < HINSTANCE_ERROR then MessageDlg( 'The WCSC High Level Function DLL (CDRVHF.DLL)' + CR + 'could not be loaded. The file is probably missing or' + CR + 'its location is not on the current PATH.', mtError, [mbOK], 0 ); @WCSC_InitializePort := AcquireFun( HLF_library, 'InitializePort'); @WCSC_UnInitializePort := AcquireFun( HLF_library, 'UnInitializePort'); @WCSC_SetPortCharacteristics := AcquireFun( HLF_library, 'SetPortCharacteristics'); @WCSC_SetTimeout := AcquireFun( HLF_library, 'SetTimeout'); @WCSC_PutByte := AcquireFun( HLF_library, 'PutByte'); @WCSC_PutPacket := AcquireFun( HLF_library, 'PutPacket'); @WCSC_PutString := AcquireFun( HLF_library, 'PutString'); @WCSC_IsReceiveBufferEmpty := AcquireFun( HLF_library, 'IsReceiveBufferEmpty'); @WCSC_GetByte := AcquireFun( HLF_library, 'GetByte'); @WCSC_GetPacket := AcquireFun( HLF_library, 'GetPacket'); @WCSC_GetString := AcquireFun( HLF_library, 'GetString'); @WCSC_WaitFor := AcquireFun( HLF_library, 'WaitFor'); @WCSC_WaitForPeek := AcquireFun( HLF_library, 'WaitForPeek'); {--- Load the low-level DLL functions ---} LLF_library := LoadLibrary( 'CDRVDLL.DLL' ); if LLF_library < HINSTANCE_ERROR then MessageDlg( 'The WCSC Low Level Function DLL (CDRVDLL.DLL)' + CR + 'could not be loaded. The file is probably missing or' + CR + 'its location is not on the current PATH.', mtError, [mbOK], 0 ); @WCSC_GetStatus := AcquireFun( LLF_library, 'ser_rs232_getstatus' ); @WCSC_Flush := AcquireFun( LLF_library, 'ser_rs232_fush' ); @WCSC_MiscFunction := AcquireFun( LLF_library, 'ser_rs232_misc_func'); @WCSC_SetIntFunc := AcquireFun( LLF_library, 'ser_rs232_set_intfunc'); end; destructor TWCSCComm.Destroy; begin FreeLibrary( HLF_library ); { Unload the High-level DLL } FreeLibrary( LLF_library ); { Unload the Low-level DLL } DeallocateHWnd(WndProcHndl); { kill invisible window } (* Willies' DLL doesn't need this... FreeProcInstance( WCSC_callbackProc ); { free callback instance } *) inherited Destroy; end; {=== PRIMARY METHODS ===========================================} function TWCSCComm.InitializePort( port : TPortNumber; subport : Integer; addr, irq, cardtype, cardseg, inbuflen, outbuflen, flag : word ) : Integer; begin result := WCSC_InitializePort( port, subport, addr, irq, cardtype, cardseg, inbuflen, outbuflen, flag ); ReturnCode := result; if result = RS232ERR_NONE then { once initialized, set any triggers } with WCSC_portTriggers[port] do { indicated by our properties } begin SetRecAny( port, recAny ); SetRecChar( port, recChar ); SetRecCount( port, recCount ) end; end; function TWCSCComm.UnInitializePort( port : Integer ) : Integer; begin WCSC_SetIntFunc( port, NIL, 0 ); { reset interrupt triggers } result := WCSC_UnInitializePort( port ); ReturnCode := result; end; function TWCSCComm.SetPortCharacteristics( port : Integer; baud, parity, length, stopBits, protocol : word ) : Integer; begin { We subtract 5 from length and 1 from stopBits in order to match the DLL's conventions, e.g., LENGTH_8 = 3; (8 bits) } result := WCSC_SetPortCharacteristics( port, baud, parity, length - 5, stopBits - 1, protocol ); ReturnCode := result; end; function TWCSCComm.SetTimeout( port, nTicks : Integer ) : Integer; begin result := WCSC_SetTimeout( port, nTicks ); ReturnCode := result; end; function TWCSCComm.PutByte( port : Integer; ch : char ) : Integer; begin result := WCSC_PutByte( port, ch ); end; function TWCSCComm.PutPacket( port, length : Integer; pkt : PChar ) : Integer; begin result := WCSC_PutPacket( port, length, pkt ); end; function TWCSCComm.PutString( port : TPortNumber; str : string ) : Integer; begin str[length(str)+1] := #0; {make a null-terminated string; NO SPACE CHECK} result := WCSC_PutString( port, @str[1] ); if result < 0 then {all characters were written, so just say so} result := length(str); end; function TWCSCComm.InputBufferEmpty( port : Integer ) : boolean; begin result := WCSC_IsReceiveBufferEmpty( port ) <> 0; end; function TWCSCComm.GetByte( port : Integer; var ch : char ) : Integer; begin result := WCSC_GetByte( port ); if result < 0 then { DLL return val < 0 indicates error} ch := #0 else begin ch := char(lo(result)); {low-order byte is the character read} result := 1 {number of chars read} end; end; function TWCSCComm.GetPacket( port, length : Integer; pkt : PChar ) : Integer; begin result := WCSC_GetPacket( port, length, pkt ); end; function TWCSCComm.GetString( port : TPortNumber; var str : string ) : Integer; var nullStr : array[0..255] of char; begin result := WCSC_GetString( port, sizeOf(nullStr), @nullStr ); if result < 0 then str := '' else str := StrPas( nullStr ); end; function TWCSCComm.WaitFor( port, timeout : Integer; outstr, instr : string ) : Integer; begin outstr[length(outstr)+1] := #0; {give'em null terminators} instr[length(instr)+1] := #0; result := WCSC_WaitFor( port, timeout, @outstr[1], @instr[1] ); ReturnCode := result; end; function TWCSCComm.WaitForPeek( port, timeout : Integer; outstr, instr : string ) : Integer; begin outstr[length(outstr)+1] := #0; {give'em null terminators} instr[length(instr)+1] := #0; result := WCSC_WaitForPeek( port, timeout, @outstr[1], @instr[1] ); ReturnCode := result; end; {--- Low-level Functions ---} function TWCSCComm.GetStatus( port : TPortNumber; var modemStat : byte; var lineStat : byte ) : Integer; var statusBuf : array[0..1] of char; begin result := WCSC_GetStatus( port, @statusBuf ); ReturnCode := result; if result = RS232ERR_NONE then begin modemStat := byte(statusBuf[0]); lineStat := byte(statusBuf[1]); end else begin modemStat := 0; lineStat := 0 end; end; function TWCSCComm.Flush( port : TPortNumber ) : Integer; begin Result := WCSC_Flush( port, 2 ); { code 2 = clear input and output buffers } end; { Return descriptive string corresponding to last error code } function TWCSCComm.GetErrorMsg : String; var msg : String; begin case ReturnCode of RS232ERR_NOINIT : msg := 'Port not initialized'; RS232ERR_NONE : msg := 'No error'; RS232ERR_BUFFER : msg := 'RS232, buffer not set or buff changed'; RS232ERR_ACTIVE : msg := 'RS232, port not active'; RS232ERR_XMTBUF : msg := 'RS232, xmit buffer full'; RS232ERR_RCVBUF : msg := 'RS232, recv buffer empty'; RS232ERR_SYNTAX : msg := 'RS232, port syntax error'; RS232ERR_BUFSIZ : msg := 'RS232, invalid buffer size'; RS232ERR_PORT : msg := 'RS232, invalid port'; RS232ERR_HANDLR : msg := 'RS232, handler changed'; RS232ERR_BAUD : msg := 'RS232, invalid baud rate'; RS232ERR_PARITY : msg := 'RS232, invalid parity'; RS232ERR_LNGTH : msg := 'RS232, invalid data length'; RS232ERR_STOPBIT : msg := 'RS232, invalid # stopbits'; RS232ERR_PROTOCOL : msg := 'RS232, invalid protocol'; RS232ERR_IRQCHANGED : msg := 'RS232, IRQ changed'; RS232ERR_PORTCHANGED : msg := 'RS232, port changed'; RS232ERR_THRESHOLD : msg := 'RS232, invalid threshold'; RS232ERR_INVIRQ : msg := 'RS232, invalid IRQ'; RS232ERR_INTOFF : msg := 'RS232, interrupts not enabled'; RS232ERR_BREAK : msg := 'RS232, invalid break syntax'; RS232ERR_FATAL : msg := 'RS232, fatal error'; RS232ERR_DSR : msg := 'RS232, CTS error'; RS232ERR_INVADR : msg := 'RS232, Invalid RS232 address'; RS232ERR_ENVIRON : msg := 'Environment variable not set'; RS232ERR_IOCTL : msg := 'Error issuing IOCTL call'; RS232ERR_ATEXIT : msg := 'Error issuing atexit cleanup'; RS232ERR_DEVINIT : msg := 'Error mapping for dir calls'; RS232ERR_DOSOPEN : msg := 'Error opening Device'; RS232ERR_MALLOC : msg := 'Error allocating memory'; RS232ERR_EXTMICRO : msg := 'Error on external micro'; RS232ERR_CARDCHANGED : msg := 'Card changed error'; RS232ERR_CARDTYPE : msg := 'Card type error'; RS232ERR_NOSUPPORT : msg := 'Not supported'; RS232ERR_CMDBUFFULL : msg := 'Card command buffer full'; RS232ERR_PPORT : msg := 'Invalid parent PCB'; RS232ERR_NODEVICE : msg := 'No device for this port'; RS232ERR_UNKNOWN : msg := 'Unknown error'; RS232ERR_BUSY : msg := 'Busy'; RS232ERR_NOTIMER : msg := 'No more timers available'; RS232ERR_INT14VEC : msg := 'INT 14H vector changed'; RS232ERR_INT1CVEC : msg := 'Timer vector changed'; RS232ERR_DPMI : msg := 'DPMI error'; RS232ERR_WINBUF : msg := 'No windows buffer or too small'; RS232ERR_NOASYNCRES : msg := 'No asynchronous resources left'; RS232ERR_NOTIMERRES : msg := 'No timer resources left'; RS232ERR_NOOTHERES : msg := 'Out of other resources'; RS232ERR_FILEIO : msg := 'File I/O error'; RS232ERR_HMEMG64 : msg := 'Hardware memory exceeded 64K'; RS232ERR_MAPVXD : msg := 'VxD not present/other VxD error'; DLL_NOT_LOADED : msg := 'DLL functions are not available'; else msg := 'No message text available'; end; result := '[' + IntToStr(ReturnCode) + '] ' + msg; end; {--- Private methods used by property setting methods which follow ---} procedure TWCSCComm.SetRecAny( port : TPortNumber; any : Boolean ); begin with WCSC_PortTriggers[port] do if any <> recAny then begin recAny := any; if any then iMask := iMask or INTFUNC_RCV else iMask := iMask and ( not INTFUNC_RCV ); ReturnCode := WCSC_SetIntFunc( port, @WCSC_callbackProc, iMask ); if ReturnCode <> RS232ERR_NONE then MessageDlg('Procedure SetRecAny reports' + #13 + GetErrorMsg, mtError, [mbOK], 0); end; end; procedure TWCSCComm.SetRecChar( port : TPortNumber; ch : Char ); begin with WCSC_PortTriggers[port] do if ch <> recChar then begin recChar := ch; if ch = #0 then { use NUL char to disable this trigger } iMask := iMask and ( not INTFUNC_RCVCHR ) else begin iMask := iMask or INTFUNC_RCVCHR; ReturnCode := WCSC_MiscFunction( port, SETRCVCHR, ord(ch) ); if ReturnCode <> RS232ERR_NONE then MessageDlg('Procedure SetRecChar reports' + #13 + GetErrorMsg + #13 + '(on execution of MiscFunction)', mtError, [mbOK], 0); end; ReturnCode := WCSC_SetIntFunc( port, @WCSC_callbackProc, iMask ); if ReturnCode <> RS232ERR_NONE then MessageDlg('Procedure SetRecChar reports' + #13 + GetErrorMsg + #13 + '(on execution of SetIntFunc)', mtError, [mbOK], 0); end; end; procedure TWCSCComm.SetRecCount( port : TPortNumber; count : Word ); begin with WCSC_PortTriggers[port] do if count <> recCount then begin recCount := count; if count = 0 then { use a count of zero to disable this trigger } iMask := iMask and ( not INTFUNC_IBFICNT ) else begin iMask := iMask or INTFUNC_IBFICNT; ReturnCode := WCSC_MiscFunction( port, SETIBFICNT, count ); if ReturnCode <> RS232ERR_NONE then MessageDlg('Procedure SetRecCount reports' + #13 + GetErrorMsg + #13 + '(on execution of MiscFunction)', mtError, [mbOK], 0); end; ReturnCode := WCSC_SetIntFunc( port, @WCSC_callbackProc, iMask ); if ReturnCode <> RS232ERR_NONE then MessageDlg('Procedure SetRecCount reports' + #13 + GetErrorMsg + #13 + '(on execution of SetIntFunc)', mtError, [mbOK], 0); end; end; {--- Private methods for setting properties ---} procedure TWCSCComm.SetRecAny0( any : Boolean ); begin SetRecAny( 0, any ) end; procedure TWCSCComm.SetRecChar0( ch : Char ); begin SetRecChar( 0, ch ) end; procedure TWCSCComm.SetRecCount0( count : Word ); begin SetRecCount( 0, count ) end; procedure TWCSCComm.SetRecAny1( any : Boolean ); begin SetRecAny( 1, any ) end; procedure TWCSCComm.SetRecChar1( ch : Char ); begin SetRecChar( 1, ch ) end; procedure TWCSCComm.SetRecCount1( count : Word ); begin SetRecCount( 1, count ) end; procedure TWCSCComm.SetRecAny2( any : Boolean ); begin SetRecAny( 2, any ) end; procedure TWCSCComm.SetRecChar2( ch : Char ); begin SetRecChar( 2, ch ) end; procedure TWCSCComm.SetRecCount2( count : Word ); begin SetRecCount( 2, count ) end; procedure TWCSCComm.SetRecAny3( any : Boolean ); begin SetRecAny( 3, any ) end; procedure TWCSCComm.SetRecChar3( ch : Char ); begin SetRecChar( 3, ch ) end; procedure TWCSCComm.SetRecCount3( count : Word ); begin SetRecCount( 3, count ) end; procedure TWCSCComm.SetRecAny4( any : Boolean ); begin SetRecAny( 4, any ) end; procedure TWCSCComm.SetRecChar4( ch : Char ); begin SetRecChar( 4, ch ) end; procedure TWCSCComm.SetRecCount4( count : Word ); begin SetRecCount( 4, count ) end; procedure TWCSCComm.SetRecAny5( any : Boolean ); begin SetRecAny( 5, any ) end; procedure TWCSCComm.SetRecChar5( ch : Char ); begin SetRecChar( 5, ch ) end; procedure TWCSCComm.SetRecCount5( count : Word ); begin SetRecCount( 5, count ) end; procedure TWCSCComm.SetRecAny6( any : Boolean ); begin SetRecAny( 6, any ) end; procedure TWCSCComm.SetRecChar6( ch : Char ); begin SetRecChar( 6, ch ) end; procedure TWCSCComm.SetRecCount6( count : Word ); begin SetRecCount( 6, count ) end; procedure TWCSCComm.SetRecAny7( any : Boolean ); begin SetRecAny( 7, any ) end; procedure TWCSCComm.SetRecChar7( ch : Char ); begin SetRecChar( 7, ch ) end; procedure TWCSCComm.SetRecCount7( count : Word ); begin SetRecCount( 7, count ) end; end. {========================= End of Component ==============================}