Renegade-1.19/SOURCE/ELECOM/OS2COM.PAS

787 lines
27 KiB
Plaintext
Raw Permalink Normal View History

2022-06-21 17:11:35 -07:00
unit OS2COM;
(*
**
** Serial and TCP/IP communication routines for DOS, OS/2 and Win9x/NT.
** Tested with: TurboPascal v7.0, (DOS)
** VirtualPascal v2.1, (OS/2, Win32)
** FreePascal v0.99.12 (DOS, Win32)
** Delphi v4.0. (Win32)
**
** Version : 1.01
** Created : 21-May-1998
** Last update : 12-May-1999
**
** Note: (c) 1998-1999 by Maarten Bekers
**
*)
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
INTERFACE
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
uses Combase, BufUnit, Threads,
{$IFDEF OS2}
Os2Base
{$ENDIF}
{$IFDEF VirtualPascal}
,Use32
{$ENDIF};
Const WriteTimeout = 20000; { Wait max. 20 secs }
ReadTimeOut = 5000; { General event, 5 secs max }
InBufSize = 1024 * 32;
OutBufSize = 1024 * 32;
type TOs2Obj = Object(TCommObj)
ReadProcPtr: Pointer; { Pointer to TX/RX handler (thread) }
WriteProcPtr: Pointer; { Pointer to TX/RX handler (thread) }
ThreadsInitted: Boolean; { Are the thread(s) up and running? }
ClientHandle : Longint;
InBuffer : ^BufArrayObj; { Buffer system internally used }
OutBuffer : ^BufArrayObj;
DoTxEvent : PSysEventObj; { Event manually set when we have to transmit }
DoRxEvent : PSysEventObj; { Event manually set when we need data }
TxClosedEvent : PSysEventObj; { Event set when the Tx thread is closed }
RxClosedEvent : PSysEventObj; { Event set when the Rx thread is closed }
CriticalTx : PExclusiveObj; { Critical sections }
CriticalRx : PExclusiveObj;
TxThread : PThreadsObj; { The Transmit and Receive threads }
RxThread : PThreadsObj;
EndThreads : Boolean; { Set to true when we have to end the threads }
constructor Init;
destructor Done;
function Com_Open(Comport: Byte; BaudRate: Longint; DataBits: Byte;
Parity: Char; StopBits: Byte): Boolean; virtual;
function Com_OpenKeep(Comport: Byte): Boolean; virtual;
function Com_GetChar: Char; virtual;
function Com_CharAvail: Boolean; virtual;
function Com_Carrier: Boolean; virtual;
function Com_SendChar(C: Char): Boolean; virtual;
function Com_ReadyToSend(BlockLen: Longint): Boolean; virtual;
function Com_GetBPSrate: Longint; virtual;
function Com_GetHandle: Longint; virtual;
procedure Com_OpenQuick(Handle: Longint); virtual;
procedure Com_Close; virtual;
procedure Com_SendBlock(var Block; BlockLen: Longint; var Written: Longint); virtual;
procedure Com_ReadBlock(var Block; BlockLen: Longint; var Reads: Longint); virtual;
procedure Com_GetBufferStatus(var InFree, OutFree, InUsed, OutUsed: Longint); virtual;
procedure Com_SetDtr(State: Boolean); virtual;
procedure Com_GetModemStatus(var LineStatus, ModemStatus: Byte); virtual;
procedure Com_SetLine(BpsRate: longint; Parity: Char; DataBits, Stopbits: Byte); virtual;
procedure Com_PurgeInBuffer; virtual;
procedure Com_PurgeOutBuffer; virtual;
procedure Com_FlushOutBuffer(Slice: SliceProc); virtual;
procedure Com_PauseCom(CloseCom: Boolean); virtual;
procedure Com_ResumeCom(OpenCom: Boolean); virtual;
procedure Com_SetFlow(SoftTX, SoftRX, Hard: Boolean); virtual;
procedure Com_SetDataProc(ReadPtr, WritePtr: Pointer); virtual;
procedure Com_ReadProc(var TempPtr: Pointer);
procedure Com_WriteProc(var TempPtr: Pointer);
function Com_StartThread: Boolean;
procedure Com_InitVars;
procedure Com_StopThread;
end; { object TOs2Obj }
Type POs2Obj = ^TOs2Obj;
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
IMPLEMENTATION
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
uses SysUtils;
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
constructor TOs2Obj.Init;
begin
inherited Init;
Com_InitVars;
ThreadsInitted := FALSE;
end; { constructor Init }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
destructor TOs2Obj.Done;
begin
inherited done;
end; { destructor Done }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_ReadProc(var TempPtr: Pointer);
Type TBuffRec = Record
BytesIn : SmallWord; { Number of bytes in the buffer }
MaxSize : SmallWord; { Full size of the buffer }
end; { TBuffRec }
var Available : Boolean;
BytesRead : Longint;
BlockLen : Longint;
ReturnCode: Longint;
BufferRec : TBuffRec;
begin
repeat
if DoRxEvent.WaitForEvent(ReadTimeOut) then
if NOT EndThreads then
begin
CriticalRx.EnterExclusive;
ReturnCode := 0;
DosDevIoCtl(ClientHandle, { File-handle }
ioctl_Async, { Category }
async_GetInQueCount, { Function }
nil, { Params }
ReturnCode, { Max param length }
@ReturnCode, { Param Length }
@BufferRec, { Returned data }
SizeOf(TBuffRec), { Max data length }
@ReturnCode); { Data length }
Available := (BufferRec.BytesIn > 00);
DoRxEvent.ResetEvent;
if Available then
begin
{----------- Start reading the gathered date -------------------}
if InBuffer^.BufRoom > 0 then
begin
BlockLen := BufferRec.BytesIn;
if BlockLen > InBuffer^.BufRoom then
BlockLen := InBuffer^.BufRoom;
if BlockLen > 1024 then
BlockLen := 1024;
if BlockLen > 00 then
begin
DosRead(ClientHandle,
InBuffer^.TmpBuf,
BlockLen,
BytesRead);
InBuffer^.Put(InBuffer^.TmpBuf, BytesRead);
end; { if }
end; { if }
end; { if available }
CriticalRx.LeaveExclusive;
end; { if RxEvent }
until EndThreads;
RxClosedEvent.SignalEvent;
ExitThisThread;
end; { proc. ComReadProc }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_WriteProc(var TempPtr: Pointer);
var BlockLen : Longint;
Written : Longint;
ReturnCode : Longint;
TempBuf : ^CharBufType;
begin
New(TempBuf);
repeat
if DoTxEvent.WaitForEvent(WriteTimeOut) then
if NOT EndThreads then
begin
CriticalTx.EnterExclusive;
DoTxEvent.ResetEvent;
if OutBuffer^.BufUsed > 00 then
begin
Written := 00;
BlockLen := OutBuffer^.Get(OutBuffer^.TmpBuf, OutBuffer^.BufUsed, false);
DosWrite(ClientHandle,
OutBuffer^.TmpBuf,
BlockLen,
Written);
ReturnCode := OutBuffer^.Get(OutBuffer^.TmpBuf, Written, true);
if Written <> BlockLen then
DoTxEvent.SignalEvent;
end; { if }
CriticalTx.LeaveExclusive;
end; { if }
until EndThreads;
Dispose(TempBuf);
TxClosedEvent.SignalEvent;
ExitThisThread;
end; { proc. ComWriteProc }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
function TOs2Obj.Com_StartThread: Boolean;
begin
Result := false;
EndThreads := false;
if ThreadsInitted then EXIT;
ThreadsInitted := true;
{----------------------- Create all the events ----------------------------}
New(DoTxEvent, Init);
if NOT DoTxEvent.CreateEvent(false) then EXIT;
New(DoRxEvent, Init);
if NOT DoRxEvent.CreateEvent(false) then EXIT;
New(RxClosedEvent, Init);
if NOT RxClosedEvent.CreateEvent(false) then EXIT;
New(TxClosedEvent, Init);
if NOT TxClosedEvent.CreateEvent(false) then EXIT;
{-------------- Startup the buffers and overlapped events -----------------}
New(InBuffer, Init(InBufSize));
New(OutBuffer, Init(OutBufSize));
{-------------------- Startup a seperate write thread ---------------------}
New(CriticalTx, Init);
CriticalTx.CreateExclusive;
New(TxThread, Init);
if NOT TxThread.CreateThread(16384, { Stack size }
WriteProcPtr, { Actual procedure }
nil, { Parameters }
0) { Creation flags }
then EXIT;
{-------------------- Startup a seperate read thread ----------------------}
New(CriticalRx, Init);
CriticalRx.CreateExclusive;
New(RxThread, Init);
if NOT RxThread.CreateThread(16384, { Stack size }
ReadProcPtr, { Actual procedure }
nil, { Parameters }
0) { Creation flags }
then EXIT;
Result := true;
end; { proc. Com_StartThread }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_InitVars;
begin
DoTxEvent := nil;
DoRxEvent := nil;
RxClosedEvent := nil;
TxClosedEvent := nil;
TxThread := nil;
RxThread := nil;
InBuffer := nil;
OutBuffer := nil;
CriticalRx := nil;
CriticalTx := nil;
end; { proc. Com_InitVars }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_StopThread;
begin
EndThreads := true;
ThreadsInitted := false;
if DoTxEvent <> nil then DoTxEvent.SignalEvent;
if DoTxEvent <> nil then DoRxEvent.SignalEvent;
if TxThread <> nil then TxThread.CloseThread;
if RxThread <> nil then RxThread.CloseThread;
if TxClosedEvent <> nil then
if NOT TxClosedEvent^.WaitForEvent(1000) then
TxThread.TerminateThread(0);
if RxClosedEvent <> nil then
if NOT RxClosedEvent^.WaitForEvent(1000) then
RxThread.TerminateThread(0);
if TxThread <> nil then TxThread.Done;
if RxThread <> nil then RxThread.Done;
if DoTxEvent <> nil then Dispose(DoTxEvent, Done);
if DoRxEvent <> nil then Dispose(DoRxEvent, Done);
if RxClosedEvent <> nil then Dispose(RxClosedEvent, Done);
if TxClosedEvent <> nil then Dispose(TxClosedEvent, Done);
if CriticalTx <> nil then Dispose(CriticalTx, Done);
if CriticalRx <> nil then Dispose(CriticalRx, Done);
if InBuffer <> nil then Dispose(InBuffer, Done);
if OutBuffer <> nil then Dispose(OutBuffer, Done);
Com_InitVars;
end; { proc. Com_StopThread }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
function TOs2Obj.Com_GetHandle: Longint;
begin
Result := ClientHandle;
end; { func. Com_GetHandle }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_OpenQuick(Handle: Longint);
begin
ClientHandle := Handle;
InitFailed := NOT Com_StartThread;
end; { proc. TOs2Obj.Com_OpenQuick }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
function TOs2Obj.Com_OpenKeep(Comport: Byte): Boolean;
var ReturnCode: Longint;
OpenAction: Longint;
Temp : Array[0..15] of Char;
begin
InitFailed := NOT Com_StartThread;
if NOT InitFailed then
begin
OpenAction := file_Open;
StrpCopy(Temp, 'COM' + IntToStr(ComPort));
ReturnCode :=
DosOpen(Temp, { Filename, eg: COM2 }
ClientHandle,
OpenAction,
0, { Filesize }
0, { Attributes }
FILE_OPEN or OPEN_ACTION_OPEN_IF_EXISTS, { Open flags }
OPEN_ACCESS_READWRITE or OPEN_SHARE_DENYNONE or { OpenMode }
OPEN_FLAGS_FAIL_ON_ERROR,
nil); { Extended attributes }
InitFailed := (ReturnCode <> 0);
end; { if }
Com_OpenKeep := NOT InitFailed;
end; { func. Com_OpenKeep }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
function TOs2Obj.Com_Open(Comport: Byte; BaudRate: Longint; DataBits: Byte;
Parity: Char; StopBits: Byte): Boolean;
begin
InitFailed := true;
if Com_OpenKeep(Comport) then
begin
Com_SetLine(BaudRate, Parity, DataBits, StopBits);
InitFailed := false;
end; { if }
Com_Open := NOT InitFailed;
end; { func. TOs2Obj.Com_OpenCom }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_SetLine(BpsRate: longint; Parity: Char; DataBits, Stopbits: Byte);
type TBpsRec = Record
Rate : Longint;
Frac : Byte;
end; { record }
var TempRec : Array[1..3] of Byte;
BpsRec : TBpsRec;
RetLength : Longint;
Temp_Parity : Byte;
Temp_StopBits: Byte;
begin
if NOT (DataBits in [5,7,8]) then DataBits := 8;
if NOT (Parity in ['O', 'E', 'N', 'M', 'S']) then Parity := 'N';
if NOT (StopBits in [0..2]) then StopBits := 1;
Temp_Parity := 00;
Case Parity of
'N' : Temp_Parity := 00;
'O' : Temp_Parity := 01;
'E' : Temp_Parity := 02;
'M' : Temp_Parity := 03;
'S' : Temp_Parity := 04;
end; { case }
Temp_Stopbits := 00;
Case StopBits of
1 : StopBits := 0;
2 : StopBits := 2;
end; { case }
Fillchar(TempRec, SizeOf(TempRec), 00);
TempRec[01] := DataBits;
TempRec[02] := Temp_Parity;
TempRec[03] := Temp_StopBits;
{------------------------- Set line parameters ----------------------------}
DosDevIoCtl(ClientHandle, { File-handle }
ioctl_Async, { Category }
async_SetLineCtrl, { Function }
@TempRec, { Params }
SizeOf(TempRec), { Max param length }
@RetLength, { Param Length }
@TempRec, { Returned data }
SizeOf(TempRec), { Max data length }
@RetLength); { Data length }
{------------------------- Set speed parameters ---------------------------}
BpsRec.Rate := BpsRate;
BpsRec.Frac := 00;
DosDevIoCtl(ClientHandle, { File-handle }
ioctl_Async, { Category }
async_ExtSetBaudRate, { Function }
@BpsRec, { Params }
SizeOf(BpsRec), { Max param length }
@RetLength, { Param Length }
@BpsRec, { Returned data }
SizeOf(BpsRec), { Max data length }
@RetLength); { Data length }
end; { proc. TOs2Obj.Com_SetLine }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_Close;
begin
if DontClose then EXIT;
if ClientHandle <> -1 then
begin
Com_StopThread;
DosClose(ClientHandle);
ClientHandle := -1;
end; { if }
end; { func. TOs2Obj.Com_CloseCom }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
function TOs2Obj.Com_SendChar(C: Char): Boolean;
var Written: Longint;
begin
Com_SendBlock(C, SizeOf(C), Written);
Com_SendChar := (Written = SizeOf(c));
end; { proc. TOs2Obj.Com_SendChar }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
function TOs2Obj.Com_GetChar: Char;
var Reads: Longint;
begin
Com_ReadBlock(Result, SizeOf(Result), Reads);
end; { func. TOs2Obj.Com_GetChar }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_SendBlock(var Block; BlockLen: Longint; var Written: Longint);
begin
if OutBuffer^.BufRoom < BlockLen then
repeat
{$IFDEF OS2}
DosSleep(1);
{$ENDIF}
until (OutBuffer^.BufRoom >= BlockLen) OR (NOT Com_Carrier);
CriticalTx.EnterExclusive;
Written := OutBuffer^.Put(Block, BlockLen);
CriticalTx.LeaveExclusive;
DoTxEvent.SignalEvent;
end; { proc. TOs2Obj.Com_SendBlock }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_ReadBlock(var Block; BlockLen: Longint; var Reads: Longint);
begin
if InBuffer^.BufUsed < BlockLen then
begin
repeat
if Com_CharAvail then
DoRxEvent.SignalEvent;
DosSleep(1);
until (InBuffer^.BufUsed >= BlockLen) OR (NOT Com_Carrier);
end; { if }
CriticalRx.EnterExclusive;
Reads := InBuffer^.Get(Block, BlockLen, true);
CriticalRx.LeaveExclusive;
end; { proc. TOs2Obj.Com_ReadBlock }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
function TOs2Obj.Com_CharAvail: Boolean;
Type TBuffRec = Record
BytesIn : SmallWord; { Number of bytes in the buffer }
MaxSize : SmallWord; { Full size of the buffer }
end; { TBuffRec }
var ReturnCode: Longint;
BufferRec : TBuffRec;
begin
if InBuffer^.BufUsed < 1 then
begin
ReturnCode := 0;
DosDevIoCtl(ClientHandle, { File-handle }
ioctl_Async, { Category }
async_GetInQueCount, { Function }
nil, { Params }
ReturnCode, { Max param length }
@ReturnCode, { Param Length }
@BufferRec, { Returned data }
SizeOf(TBuffRec), { Max data length }
@ReturnCode); { Data length }
if (BufferRec.BytesIn > 0) then
DoRxEvent.SignalEvent;
end; { if }
Result := (InBuffer^.BufUsed > 0);
end; { func. TOs2Obj.Com_CharAvail }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
function TOs2Obj.Com_Carrier: Boolean;
var Status : Byte;
RetLength : Longint;
begin
DosDevIoCtl(ClientHandle, { File-handle }
ioctl_Async, { Category }
async_GetModemInput, { Function }
nil, { Params }
00, { Max param length }
@RetLength, { Param Length }
@Status, { Returned data }
SizeOf(Status), { Max data length }
@RetLength); { Data length }
Com_Carrier := Status AND 128 <> 00;
end; { func. TOs2Obj.Com_Carrier }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_GetModemStatus(var LineStatus, ModemStatus: Byte);
begin
LineStatus := 00;
ModemStatus := 08;
if Com_Carrier then ModemStatus := ModemStatus OR (1 SHL 7);
end; { proc. TOs2Obj.Com_GetModemStatus }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_SetDtr(State: Boolean);
type
TRtsDtrRec = record
Onmask,
Offmask : Byte;
end; { record }
var MaskRec : TRtsDtrRec;
RetLength : Longint;
begin
if State then
begin
MaskRec.OnMask := $01;
MaskRec.OffMask := $FF;
end
else begin
MaskRec.OnMask := $00;
MaskRec.OffMask := $FE;
end; { if }
DosDevIoCtl(ClientHandle, { File-handle }
ioctl_Async, { Category }
async_SetModemCtrl, { Function }
@MaskRec, { Params }
SizeOf(MaskRec), { Max param length }
@RetLength, { Param Length }
@MaskRec, { Returned data }
SizeOf(MaskRec), { Max data length }
@RetLength); { Data length }
end; { proc. TOs2Obj.Com_SetDtr }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
function TOs2Obj.Com_GetBpsRate: Longint;
type
TBpsRec = record
CurBaud : Longint; { Current BaudRate }
CurFrac : Byte; { Current Fraction }
MinBaud : Longint; { Minimum BaudRate }
MinFrac : Byte; { Minimum Fraction }
MaxBaud : Longint; { Maximum BaudRate }
MaxFrac : Byte; { Maximum Fraction }
end; { TBpsRec }
var BpsRec : TBpsRec;
Status : Byte;
RetLength: Longint;
begin
DosDevIoCtl(ClientHandle, { File-handle }
ioctl_Async, { Category }
async_ExtGetBaudRate, { Function }
nil, { Params }
00, { Max param length }
@RetLength, { Param Length }
@BpsRec, { Returned data }
SizeOf(BpsRec), { Max data length }
@RetLength); { Data length }
Com_GetBpsRate := BpsRec.CurBaud;
end; { func. TOs2Obj.Com_GetBpsRate }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_GetBufferStatus(var InFree, OutFree, InUsed, OutUsed: Longint);
begin
DoRxEvent.SignalEvent;
DoTxEvent.SignalEvent;
InFree := InBuffer^.BufRoom;
OutFree := OutBuffer^.BufRoom;
InUsed := InBuffer^.BufUsed;
OutUsed := OutBuffer^.BufUsed;
end; { proc. TOs2Obj.Com_GetBufferStatus }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_PurgeInBuffer;
begin
CriticalRx.EnterExclusive;
InBuffer^.Clear;
CriticalRx.LeaveExclusive;
end; { proc. TOs2Obj.Com_PurgeInBuffer }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_PurgeOutBuffer;
begin
CriticalTx.EnterExclusive;
OutBuffer^.Clear;
CriticalTx.LeaveExclusive;
end; { proc. TOs2Obj.Com_PurgeInBuffer }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_FlushOutBuffer(Slice: SliceProc);
begin
DosResetBuffer(ClientHandle);
inherited Com_FlushOutBuffer(Slice);
end; { proc. Com_FlushOutBuffer }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
function TOs2Obj.Com_ReadyToSend(BlockLen: Longint): Boolean;
begin
Result := OutBuffer^.BufRoom >= BlockLen;
end; { func. ReadyToSend }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_PauseCom(CloseCom: Boolean);
begin
if CloseCom then Com_Close
else Com_StopThread;
end; { proc. Com_PauseCom }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_ResumeCom(OpenCom: Boolean);
begin
if OpenCom then Com_OpenKeep(0)
else Com_StartThread;
end; { proc. Com_ResumeCom }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_SetFlow(SoftTX, SoftRX, Hard: Boolean);
var Dcb : DCBINFO;
RetLength: Longint;
begin
FillChar(Dcb, SizeOF(Dcb), 0);
DosDevIoCtl(ClientHandle, { File-handle }
ioctl_Async, { Category }
async_GetDcbInfo, { Function }
nil, { Params }
00, { Max param length }
@RetLength, { Param Length }
@Dcb, { Returned data }
SizeOf(DcbInfo), { Max data length }
@RetLength); { Data length }
if (SoftTX) or (SoftRX) then
begin
dcb.fbFlowReplace := dcb.fbFlowReplace + MODE_AUTO_RECEIVE + MODE_AUTO_TRANSMIT;
end
else begin
dcb.fbFlowReplace := MODE_RTS_HANDSHAKE;
dcb.fbCtlHndShake := dcb.fbCtlHndShake + MODE_CTS_HANDSHAKE;
end; { if }
dcb.fbTimeout := MODE_NO_WRITE_TIMEOUT + MODE_WAIT_READ_TIMEOUT;
dcb.bXONChar := $11;
dcb.bXOFFChar := $13;
RetLength := SizeOf(DcbInfo);
DosDevIoCtl(ClientHandle, { File-handle }
ioctl_Async, { Category }
async_SetDcbInfo, { Function }
@Dcb, { Params }
SizeOf(DcbInfo), { Max param length }
@RetLength, { Param Length }
nil, { Returned data }
RetLength, { Max data length }
@RetLength); { Data length }
end; { proc. Com_SetFlow }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
procedure TOs2Obj.Com_SetDataProc(ReadPtr, WritePtr: Pointer);
begin
ReadProcPtr := ReadPtr;
WriteProcPtr := WritePtr;
end; { proc. Com_SetDataProc }
(*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
end.