787 lines
27 KiB
Plaintext
787 lines
27 KiB
Plaintext
|
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.
|