home *** CD-ROM | disk | FTP | other *** search
/ synchro.net / synchro.net.tar / synchro.net / main / BBS / D32_01.ZIP / OS2COM.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-11-25  |  25.7 KB  |  738 lines

  1. unit OS2COM;
  2. (*
  3. **
  4. ** Serial and TCP/IP communication routines for DOS, OS/2 and Win9x/NT.
  5. ** Tested with: TurboPascal   v7.0,    (DOS)
  6. **              VirtualPascal v2.0,    (OS/2, Win32)
  7. **              FreePascal    v0.99.12 (DOS, Win32)
  8. **              Delphi        v4.0.    (Win32)
  9. **
  10. ** Version : 1.01
  11. ** Created : 21-May-1998
  12. ** Last update : 12-May-1999
  13. **
  14. ** Note: (c) 1998-1999 by Maarten Bekers
  15. **
  16. *)
  17.  
  18. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  19.  INTERFACE
  20. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  21.  
  22. uses Combase, BufUnit, Threads
  23.      {$IFDEF OS2}
  24.        ,Os2Base
  25.      {$ENDIF}
  26.  
  27.      {$IFDEF VirtualPascal}
  28.        ,Use32
  29.      {$ENDIF};
  30.  
  31. Const WriteTimeout   = 20000;                             { Wait max. 20 secs }
  32.       ReadTimeOut    = 20000;                    { General event, 20 secs max }
  33.  
  34.       InBufSize      = 1024 * 32;
  35.       OutBufSize     = 1024 * 32;
  36.  
  37.       ThreadsInitted : Boolean = false;
  38.  
  39. type TOs2Obj = Object(TCommObj)
  40.         constructor Init;
  41.         destructor Done;
  42.  
  43.         function  Com_Open(Comport: Byte; BaudRate: Longint; DataBits: Byte;
  44.                            Parity: Char; StopBits: Byte): Boolean; virtual;
  45.         function  Com_OpenKeep(Comport: Byte): Boolean; virtual;
  46.         function  Com_GetChar: Char; virtual;
  47.         function  Com_CharAvail: Boolean; virtual;
  48.         function  Com_Carrier: Boolean; virtual;
  49.         function  Com_SendChar(C: Char): Boolean; virtual;
  50.         function  Com_ReadyToSend(BlockLen: Longint): Boolean; virtual;
  51.         function  Com_GetBPSrate: Longint; virtual;
  52.         function  Com_GetHandle: Longint; virtual;
  53.  
  54.         procedure Com_OpenQuick(Handle: Longint); virtual;
  55.         procedure Com_Close; virtual;
  56.         procedure Com_SendBlock(var Block; BlockLen: Longint; var Written: Longint); virtual;
  57.         procedure Com_ReadBlock(var Block; BlockLen: Longint; var Reads: Longint); virtual;
  58.         procedure Com_GetBufferStatus(var InFree, OutFree, InUsed, OutUsed: Longint); virtual;
  59.         procedure Com_SetDtr(State: Boolean); virtual;
  60.         procedure Com_GetModemStatus(var LineStatus, ModemStatus: Byte); virtual;
  61.         procedure Com_SetLine(BpsRate: longint; Parity: Char; DataBits, Stopbits: Byte); virtual;
  62.         procedure Com_PurgeInBuffer; virtual;
  63.         procedure Com_PurgeOutBuffer; virtual;
  64.  
  65.         procedure Com_PauseCom(CloseCom: Boolean); virtual;
  66.         procedure Com_ResumeCom(OpenCom: Boolean); virtual;
  67.         procedure Com_SetFlow(SoftTX, SoftRX, Hard: Boolean); virtual;
  68.      end; { object TOs2Obj }
  69.  
  70. Type POs2Obj = ^TOs2Obj;
  71.  
  72. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  73.  IMPLEMENTATION
  74. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  75.  
  76. uses SysUtils;
  77.  
  78. var ClientHandle  : Longint;
  79.  
  80.     InBuffer      : ^BufArrayObj;             { Buffer system internally used }
  81.     OutBuffer     : ^BufArrayObj;
  82.  
  83.     DoTxEvent     : PSysEventObj; { Event manually set when we have to transmit }
  84.     DoRxEvent     : PSysEventObj;      { Event manually set when we need data }
  85.  
  86.     TxClosedEvent : PSysEventObj;    { Event set when the Tx thread is closed }
  87.     RxClosedEvent : PSysEventObj;    { Event set when the Rx thread is closed }
  88.  
  89.     CriticalTx    : PExclusiveObj;                        { Critical sections }
  90.     CriticalRx    : PExclusiveObj;
  91.  
  92.     TxThread      : PThreadsObj;           { The Transmit and Receive threads }
  93.     RxThread      : PThreadsObj;
  94.  
  95.     EndThreads    : Boolean;    { Set to true when we have to end the threads }
  96.  
  97. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  98.  
  99. constructor TOs2Obj.Init;
  100. begin
  101.   inherited Init;
  102. end; { constructor Init }
  103.  
  104. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  105.  
  106. destructor TOs2Obj.Done;
  107. begin
  108.   inherited done;
  109. end; { destructor Done }
  110.  
  111. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  112.  
  113. procedure ComReadProc(var TempPtr: Pointer);
  114. Type TBuffRec = Record
  115.          BytesIn   : SmallWord;               { Number of bytes in the buffer }
  116.          MaxSize   : SmallWord;                     { Full size of the buffer }
  117.      end; { TBuffRec }
  118.  
  119. var Available : Boolean;
  120.     BytesRead : Longint;
  121.     BlockLen  : Longint;
  122.     ReturnCode: Longint;
  123.     BufferRec : TBuffRec;
  124. begin
  125.   repeat
  126.      if DoRxEvent.WaitForEvent(ReadTimeOut) then
  127.       if NOT EndThreads then
  128.        begin
  129.          CriticalRx.EnterExclusive;
  130.          ReturnCode := 0;
  131.          DosDevIoCtl(ClientHandle,                             { File-handle }
  132.                      ioctl_Async,                                 { Category }
  133.                      async_GetInQueCount,                         { Function }
  134.                      nil,                                           { Params }
  135.                      ReturnCode,                          { Max param length }
  136.                      @ReturnCode,                             { Param Length }
  137.                      @BufferRec,                             { Returned data }
  138.                      SizeOf(TBuffRec),                     { Max data length }
  139.                      @ReturnCode);                             { Data length }
  140.  
  141.          Available := (BufferRec.BytesIn > 00);
  142.  
  143.          DoRxEvent.ResetEvent;
  144.  
  145.          if Available then
  146.           begin
  147.             {----------- Start reading the gathered date -------------------}
  148.  
  149.             if InBuffer^.BufRoom > 0 then
  150.               begin
  151.                 BlockLen := BufferRec.BytesIn;
  152.                 if BlockLen > InBuffer^.BufRoom then
  153.                   BlockLen := InBuffer^.BufRoom;
  154.                 if BlockLen > 1024 then
  155.                   BlockLen := 1024;
  156.  
  157.                 if BlockLen > 00 then
  158.                  begin
  159.                    DosRead(ClientHandle,
  160.                            InBuffer^.TmpBuf^,
  161.                            BlockLen,
  162.                            BytesRead);
  163.  
  164.                    InBuffer^.Put(InBuffer^.TmpBuf^, BytesRead);
  165.                  end; { if }
  166.  
  167.               end; { if }
  168.           end; { if available }
  169.  
  170.          CriticalRx.LeaveExclusive;
  171.        end; { if RxEvent }
  172.   until EndThreads;
  173.  
  174.   RxClosedEvent.SignalEvent;
  175.   ExitThisThread;
  176. end; { proc. ComReadProc }
  177.  
  178. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  179.  
  180. procedure ComWriteProc(var TempPtr: Pointer);
  181. var BlockLen    : Longint;
  182.     Written     : Longint;
  183.     ReturnCode  : Longint;
  184.     TempBuf     : ^CharBufType;
  185. begin
  186.   New(TempBuf);
  187.  
  188.   repeat
  189.      if DoTxEvent.WaitForEvent(WriteTimeOut) then
  190.       if NOT EndThreads then
  191.        begin
  192.          CriticalTx.EnterExclusive;
  193.          DoTxEvent.ResetEvent;
  194.  
  195.          if OutBuffer^.BufUsed > 00 then
  196.            begin
  197.              Written := 00;
  198.              BlockLen := OutBuffer^.Get(OutBuffer^.TmpBuf^, OutBuffer^.BufUsed, false);
  199.  
  200.              DosWrite(ClientHandle,
  201.                       OutBuffer^.TmpBuf^,
  202.                       BlockLen,
  203.                       Written);
  204.  
  205.              ReturnCode := OutBuffer^.Get(OutBuffer^.TmpBuf^, Written, true);
  206.              if Written <> BlockLen then
  207.                 DoTxEvent.SignalEvent;
  208.            end; { if }
  209.  
  210.          CriticalTx.LeaveExclusive;
  211.        end; { if }
  212.  
  213.   until EndThreads;
  214.  
  215.   Dispose(TempBuf);
  216.   TxClosedEvent.SignalEvent;
  217.   ExitThisThread;
  218. end; { proc. ComWriteProc }
  219.  
  220. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  221.  
  222. function Com_StartThread: Boolean;
  223. begin
  224.   Result := false;
  225.   EndThreads := false;
  226.   if ThreadsInitted then EXIT;
  227.   ThreadsInitted := true;
  228.  
  229.   {----------------------- Create all the events ----------------------------}
  230.   New(DoTxEvent, Init);
  231.   if NOT DoTxEvent.CreateEvent(true) then EXIT;
  232.  
  233.   New(DoRxEvent, Init);
  234.   if NOT DoRxEvent.CreateEvent(true) then EXIT;
  235.  
  236.   New(RxClosedEvent, Init);
  237.   if NOT RxClosedEvent.CreateEvent(false) then EXIT;
  238.  
  239.   New(TxClosedEvent, Init);
  240.   if NOT TxClosedEvent.CreateEvent(false) then EXIT;
  241.  
  242.  
  243.   {-------------- Startup the buffers and overlapped events -----------------}
  244.   New(InBuffer, Init(InBufSize));
  245.   New(OutBuffer, Init(OutBufSize));
  246.  
  247.   if (InBuffer^.TxtArr=nil) OR (InBuffer^.TmpBuf=nil) then EXIT;
  248.   if (OutBuffer^.TxtArr=nil) OR (OutBuffer^.TmpBuf=nil) then EXIT;
  249.  
  250.   {-------------------- Startup a seperate write thread ---------------------}
  251.   New(CriticalTx, Init);
  252.   CriticalTx.CreateExclusive;
  253.  
  254.   New(TxThread, Init);
  255.   if NOT TxThread.CreateThread(16384,                            { Stack size }
  256.                                @ComWriteProc,              { Actual procedure }
  257.                                nil,                              { Parameters }
  258.                                0)                            { Creation flags }
  259.                                  then EXIT;
  260.  
  261.   {-------------------- Startup a seperate read thread ----------------------}
  262.   New(CriticalRx, Init);
  263.   CriticalRx.CreateExclusive;
  264.  
  265.   New(RxThread, Init);
  266.   if NOT RxThread.CreateThread(16384,                            { Stack size }
  267.                                @ComReadProc,               { Actual procedure }
  268.                                nil,                              { Parameters }
  269.                                0)                            { Creation flags }
  270.                                  then EXIT;
  271.  
  272.   Result := true;
  273. end; { proc. Com_StartThread }
  274.  
  275. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  276.  
  277. procedure Com_InitVars;
  278. begin
  279.   DoTxEvent := nil;
  280.   DoRxEvent := nil;
  281.   RxClosedEvent := nil;
  282.   TxClosedEvent := nil;
  283.   TxThread := nil;
  284.   RxThread := nil;
  285.  
  286.   InBuffer := nil;
  287.   OutBuffer := nil;
  288.   CriticalRx := nil;
  289.   CriticalTx := nil;
  290. end; { proc. Com_InitVars }
  291.  
  292. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  293.  
  294. procedure Com_StopThread;
  295. begin
  296.   EndThreads := true;
  297.   ThreadsInitted := false;
  298.  
  299.   if DoTxEvent <> nil then DoTxEvent.SignalEvent;
  300.   if DoTxEvent <> nil then DoRxEvent.SignalEvent;
  301.  
  302.  
  303.   if TxThread <> nil then TxThread.CloseThread;
  304.   if RxThread <> nil then RxThread.CloseThread;
  305.  
  306.   if TxClosedEvent <> nil then
  307.    if NOT TxClosedEvent^.WaitForEvent(1000) then
  308.      TxThread.TerminateThread(0);
  309.  
  310.   if RxClosedEvent <> nil then
  311.    if NOT RxClosedEvent^.WaitForEvent(1000) then
  312.      RxThread.TerminateThread(0);
  313.  
  314.   if TxThread <> nil then TxThread.Done;
  315.   if RxThread <> nil then RxThread.Done;
  316.  
  317.   if DoTxEvent <> nil then Dispose(DoTxEvent, Done);
  318.   if DoRxEvent <> nil then Dispose(DoRxEvent, Done);
  319.   if RxClosedEvent <> nil then Dispose(RxClosedEvent, Done);
  320.   if TxClosedEvent <> nil then Dispose(TxClosedEvent, Done);
  321.  
  322.   if CriticalTx <> nil then Dispose(CriticalTx, Done);
  323.   if CriticalRx <> nil then Dispose(CriticalRx, Done);
  324.  
  325.   if InBuffer <> nil then Dispose(InBuffer, Done);
  326.   if OutBuffer <> nil then Dispose(OutBuffer, Done);
  327.  
  328.   Com_InitVars;
  329. end; { proc. Com_StopThread }
  330.  
  331. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  332.  
  333. function TOs2Obj.Com_GetHandle: Longint;
  334. begin
  335.   Result := ClientHandle;
  336. end; { func. Com_GetHandle }
  337.  
  338. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  339.  
  340. procedure TOs2Obj.Com_OpenQuick(Handle: Longint);
  341. begin
  342.   ClientHandle := Handle;
  343.  
  344.   InitFailed := NOT Com_StartThread;
  345. end; { proc. TOs2Obj.Com_OpenQuick }
  346.  
  347. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  348.  
  349. function TOs2Obj.Com_OpenKeep(Comport: Byte): Boolean;
  350. var ReturnCode: Longint;
  351.     OpenAction: Longint;
  352.     Temp       : Array[0..15] of Char;
  353. begin
  354.   InitFailed := NOT Com_StartThread;
  355.  
  356.   if NOT InitFailed then
  357.     begin
  358.       OpenAction := file_Open;
  359.       StrpCopy(Temp, 'COM' + IntToStr(ComPort));
  360.  
  361.       ReturnCode :=
  362.         DosOpen(Temp,                                    { Filename, eg: COM2 }
  363.                 ClientHandle,
  364.                 OpenAction,
  365.                 0,                                                 { Filesize }
  366.                 0,                                               { Attributes }
  367.                 FILE_OPEN or OPEN_ACTION_OPEN_IF_EXISTS,         { Open flags }
  368.                 OPEN_ACCESS_READWRITE or OPEN_SHARE_DENYNONE or    { OpenMode }
  369.                 OPEN_FLAGS_FAIL_ON_ERROR,
  370.                 nil);                                   { Extended attributes }
  371.  
  372.       InitFailed := (ReturnCode <> 0);
  373.     end; { if }
  374.  
  375.   Com_OpenKeep := NOT InitFailed;
  376. end; { func. Com_OpenKeep }
  377.  
  378. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  379.  
  380. function TOs2Obj.Com_Open(Comport: Byte; BaudRate: Longint; DataBits: Byte;
  381.                             Parity: Char; StopBits: Byte): Boolean;
  382. begin
  383.   InitFailed := true;
  384.  
  385.   if Com_OpenKeep(Comport) then
  386.     begin
  387.       Com_SetLine(BaudRate, Parity, DataBits, StopBits);
  388.  
  389.       InitFailed := false;
  390.     end; { if }
  391.  
  392.   Com_Open := NOT InitFailed;
  393. end; { func. TOs2Obj.Com_OpenCom }
  394.  
  395. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  396.  
  397. procedure TOs2Obj.Com_SetLine(BpsRate: longint; Parity: Char; DataBits, Stopbits: Byte);
  398. type TBpsRec = Record
  399.          Rate  : Longint;
  400.          Frac  : Byte;
  401.       end; { record }
  402.  
  403. var TempRec      : Array[1..3] of Byte;
  404.     BpsRec       : TBpsRec;
  405.     RetLength    : Longint;
  406.     Temp_Parity  : Byte;
  407.     Temp_StopBits: Byte;
  408. begin
  409.   if NOT (DataBits in [5,7,8]) then DataBits := 8;
  410.   if NOT (Parity in ['O', 'E', 'N', 'M', 'S']) then Parity := 'N';
  411.   if NOT (StopBits in [0..2]) then StopBits := 1;
  412.  
  413.   Temp_Parity := 00;
  414.   Case Parity of
  415.     'N' : Temp_Parity := 00;
  416.     'O' : Temp_Parity := 01;
  417.     'E' : Temp_Parity := 02;
  418.     'M' : Temp_Parity := 03;
  419.     'S' : Temp_Parity := 04;
  420.   end; { case }
  421.  
  422.   Temp_Stopbits := 00;
  423.   Case StopBits of
  424.      1  : StopBits := 0;
  425.      2  : StopBits := 2;
  426.   end; { case }
  427.  
  428.   Fillchar(TempRec, SizeOf(TempRec), 00);
  429.   TempRec[01] := DataBits;
  430.   TempRec[02] := Temp_Parity;
  431.   TempRec[03] := Temp_StopBits;
  432.  
  433.   {------------------------- Set line parameters ----------------------------}
  434.   DosDevIoCtl(ClientHandle,                                    { File-handle }
  435.               ioctl_Async,                                        { Category }
  436.               async_SetLineCtrl,                                  { Function }
  437.               @TempRec,                                             { Params }
  438.               SizeOf(TempRec),                            { Max param length }
  439.               @RetLength,                                     { Param Length }
  440.               @TempRec,                                      { Returned data }
  441.               SizeOf(TempRec),                             { Max data length }
  442.               @RetLength);                                     { Data length }
  443.  
  444.   {------------------------- Set speed parameters ---------------------------}
  445.   BpsRec.Rate := BpsRate;
  446.   BpsRec.Frac := 00;
  447.   DosDevIoCtl(ClientHandle,                                     { File-handle }
  448.               ioctl_Async,                                         { Category }
  449.               async_ExtSetBaudRate,                                { Function }
  450.               @BpsRec,                                               { Params }
  451.               SizeOf(BpsRec),                              { Max param length }
  452.               @RetLength,                                      { Param Length }
  453.               @BpsRec,                                        { Returned data }
  454.               SizeOf(BpsRec),                               { Max data length }
  455.               @RetLength);                                      { Data length }
  456. end; { proc. TOs2Obj.Com_SetLine }
  457.  
  458. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  459.  
  460. procedure TOs2Obj.Com_Close;
  461. begin
  462.   if DontClose then EXIT;
  463.  
  464.   if ClientHandle <> -1 then
  465.     begin
  466.       Com_StopThread;
  467.       DosClose(ClientHandle);
  468.  
  469.       ClientHandle := -1;
  470.     end; { if }
  471.  
  472. end; { func. TOs2Obj.Com_CloseCom }
  473.  
  474. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  475.  
  476. function TOs2Obj.Com_SendChar(C: Char): Boolean;
  477. var Written: Longint;
  478. begin
  479.   Com_SendBlock(C, SizeOf(C), Written);
  480.   Com_SendChar := (Written = SizeOf(c));
  481. end; { proc. TOs2Obj.Com_SendChar }
  482.  
  483. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  484.  
  485. function TOs2Obj.Com_GetChar: Char;
  486. var Reads: Longint;
  487. begin
  488.   Com_ReadBlock(Result, SizeOf(Result), Reads);
  489. end; { func. TOs2Obj.Com_GetChar }
  490.  
  491. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  492.  
  493. procedure TOs2Obj.Com_SendBlock(var Block; BlockLen: Longint; var Written: Longint);
  494. begin
  495.   if OutBuffer^.BufRoom < BlockLen then
  496.    repeat
  497.      {$IFDEF OS2}
  498.        DosSleep(1);
  499.      {$ENDIF}
  500.    until (OutBuffer^.BufRoom >= BlockLen) OR (NOT Com_Carrier);
  501.  
  502.   CriticalTx.EnterExclusive;
  503.     Written := OutBuffer^.Put(Block, BlockLen);
  504.   CriticalTx.LeaveExclusive;
  505.  
  506.   DoTxEvent.SignalEvent;
  507. end; { proc. TOs2Obj.Com_SendBlock }
  508.  
  509. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  510.  
  511. procedure TOs2Obj.Com_ReadBlock(var Block; BlockLen: Longint; var Reads: Longint);
  512. begin
  513.   if InBuffer^.BufUsed < BlockLen then
  514.     begin
  515.       DoRxEvent.SignalEvent;
  516.  
  517.       repeat
  518.         DosSleep(1);
  519.       until (InBuffer^.BufUsed >= BlockLen) OR (NOT Com_Carrier);
  520.     end; { if }
  521.  
  522.   CriticalRx.EnterExclusive;
  523.     Reads := InBuffer^.Get(Block, BlockLen, true);
  524.   CriticalRx.LeaveExclusive;
  525. end; { proc. TOs2Obj.Com_ReadBlock }
  526.  
  527. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  528.  
  529. function TOs2Obj.Com_CharAvail: Boolean;
  530. begin
  531.   if InBuffer^.BufUsed < 1 then DoRxEvent.SignalEvent;
  532.  
  533.   Result := (InBuffer^.BufUsed > 0);
  534. end; { func. TOs2Obj.Com_CharAvail }
  535.  
  536. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  537.  
  538. function TOs2Obj.Com_Carrier: Boolean;
  539. var Status    : Byte;
  540.     RetLength : Longint;
  541. begin
  542.   DosDevIoCtl(ClientHandle,                                     { File-handle }
  543.               ioctl_Async,                                         { Category }
  544.               async_GetModemInput,                                 { Function }
  545.               nil,                                                   { Params }
  546.               00,                                          { Max param length }
  547.               @RetLength,                                      { Param Length }
  548.               @Status,                                        { Returned data }
  549.               SizeOf(Status),                               { Max data length }
  550.               @RetLength);                                      { Data length }
  551.  
  552.   Com_Carrier := Status AND 128 <> 00;
  553. end; { func. TOs2Obj.Com_Carrier }
  554.  
  555. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  556.  
  557. procedure TOs2Obj.Com_GetModemStatus(var LineStatus, ModemStatus: Byte);
  558. begin
  559.   LineStatus := 00;
  560.   ModemStatus := 08;
  561.  
  562.   if Com_Carrier then ModemStatus := ModemStatus OR (1 SHL 7);
  563. end; { proc. TOs2Obj.Com_GetModemStatus }
  564.  
  565. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  566.  
  567. procedure TOs2Obj.Com_SetDtr(State: Boolean);
  568. type
  569.    TRtsDtrRec = record
  570.       Onmask,
  571.       Offmask : Byte;
  572.    end; { record }
  573.  
  574. var MaskRec   : TRtsDtrRec;
  575.     RetLength : Longint;
  576. begin
  577.   if State then
  578.     begin
  579.       MaskRec.OnMask   := $01;
  580.       MaskRec.OffMask  := $FF;
  581.     end
  582.       else begin
  583.              MaskRec.OnMask   := $00;
  584.              MaskRec.OffMask  := $FE;
  585.            end; { if }
  586.  
  587.   DosDevIoCtl(ClientHandle,                                     { File-handle }
  588.               ioctl_Async,                                         { Category }
  589.               async_SetModemCtrl,                                  { Function }
  590.               @MaskRec,                                              { Params }
  591.               SizeOf(MaskRec),                             { Max param length }
  592.               @RetLength,                                      { Param Length }
  593.               @MaskRec,                                       { Returned data }
  594.               SizeOf(MaskRec),                              { Max data length }
  595.               @RetLength);                                      { Data length }
  596. end; { proc. TOs2Obj.Com_SetDtr }
  597.  
  598. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  599.  
  600. function TOs2Obj.Com_GetBpsRate: Longint;
  601. type
  602.    TBpsRec = record
  603.       CurBaud  : Longint;                                  { Current BaudRate }
  604.       CurFrac  : Byte;                                     { Current Fraction }
  605.       MinBaud  : Longint;                                  { Minimum BaudRate }
  606.       MinFrac  : Byte;                                     { Minimum Fraction }
  607.       MaxBaud  : Longint;                                  { Maximum BaudRate }
  608.       MaxFrac  : Byte;                                     { Maximum Fraction }
  609.    end; { TBpsRec }
  610.  
  611. var BpsRec   : TBpsRec;
  612.     Status   : Byte;
  613.     RetLength: Longint;
  614. begin
  615.   DosDevIoCtl(ClientHandle,                                     { File-handle }
  616.               ioctl_Async,                                         { Category }
  617.               async_ExtGetBaudRate,                                { Function }
  618.               nil,                                                   { Params }
  619.               00,                                          { Max param length }
  620.               @RetLength,                                      { Param Length }
  621.               @BpsRec,                                        { Returned data }
  622.               SizeOf(BpsRec),                               { Max data length }
  623.               @RetLength);                                      { Data length }
  624.  
  625.   Com_GetBpsRate := BpsRec.CurBaud;
  626. end; { func. TOs2Obj.Com_GetBpsRate }
  627.  
  628. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  629.  
  630. procedure TOs2Obj.Com_GetBufferStatus(var InFree, OutFree, InUsed, OutUsed: Longint);
  631. begin
  632.   DoRxEvent.SignalEvent;
  633.   DoTxEvent.SignalEvent;
  634.  
  635.   InFree := InBuffer^.BufRoom;
  636.   OutFree := OutBuffer^.BufRoom;
  637.   InUsed := InBuffer^.BufUsed;
  638.   OutUsed := OutBuffer^.BufUsed;
  639. end; { proc. TOs2Obj.Com_GetBufferStatus }
  640.  
  641. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  642.  
  643. procedure TOs2Obj.Com_PurgeInBuffer;
  644. begin
  645.   CriticalRx.EnterExclusive;
  646.  
  647.   InBuffer^.Clear;
  648.  
  649.   CriticalRx.LeaveExclusive;
  650. end; { proc. TOs2Obj.Com_PurgeInBuffer }
  651.  
  652. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  653.  
  654. procedure TOs2Obj.Com_PurgeOutBuffer;
  655. begin
  656.   CriticalTx.EnterExclusive;
  657.  
  658.   OutBuffer^.Clear;
  659.  
  660.   CriticalTx.LeaveExclusive;
  661. end; { proc. TOs2Obj.Com_PurgeInBuffer }
  662.  
  663. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  664.  
  665. function TOs2Obj.Com_ReadyToSend(BlockLen: Longint): Boolean;
  666. begin
  667.   Result := OutBuffer^.BufRoom >= BlockLen;
  668. end; { func. ReadyToSend }
  669.  
  670. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  671.  
  672. procedure TOs2Obj.Com_PauseCom(CloseCom: Boolean);
  673. begin
  674.   if CloseCom then Com_Close
  675.     else Com_StopThread;
  676. end; { proc. Com_PauseCom }
  677.  
  678. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  679.  
  680. procedure TOs2Obj.Com_ResumeCom(OpenCom: Boolean);
  681. begin
  682.   if OpenCom then Com_OpenKeep(0)
  683.     else Com_StartThread;
  684. end; { proc. Com_ResumeCom }
  685.  
  686. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  687.  
  688. procedure TOs2Obj.Com_SetFlow(SoftTX, SoftRX, Hard: Boolean);
  689. var Dcb      : DCBINFO;
  690.     RetLength: Longint;
  691. begin
  692.   FillChar(Dcb, SizeOF(Dcb), 0);
  693.  
  694.   DosDevIoCtl(ClientHandle,                                     { File-handle }
  695.               ioctl_Async,                                         { Category }
  696.               async_GetDcbInfo,                                    { Function }
  697.               nil,                                                   { Params }
  698.               00,                                          { Max param length }
  699.               @RetLength,                                      { Param Length }
  700.               @Dcb,                                           { Returned data }
  701.               SizeOf(DcbInfo),                              { Max data length }
  702.               @RetLength);                                      { Data length }
  703.  
  704.   if (SoftTX) or (SoftRX) then
  705.     begin
  706.       dcb.fbFlowReplace := dcb.fbFlowReplace + MODE_AUTO_RECEIVE + MODE_AUTO_TRANSMIT;
  707.     end
  708.       else begin
  709.              dcb.fbFlowReplace := MODE_RTS_HANDSHAKE;
  710.              dcb.fbCtlHndShake := dcb.fbCtlHndShake + MODE_CTS_HANDSHAKE;
  711.            end; { if }
  712.  
  713.   dcb.fbTimeout := MODE_NO_WRITE_TIMEOUT + MODE_WAIT_READ_TIMEOUT;
  714.   dcb.bXONChar := $11;
  715.   dcb.bXOFFChar := $13;
  716.  
  717.   RetLength := SizeOf(DcbInfo);
  718.   DosDevIoCtl(ClientHandle,                                     { File-handle }
  719.               ioctl_Async,                                         { Category }
  720.               async_SetDcbInfo,                                    { Function }
  721.               @Dcb,                                                  { Params }
  722.               SizeOf(DcbInfo),                             { Max param length }
  723.               @RetLength,                                      { Param Length }
  724.               nil,                                            { Returned data }
  725.               RetLength,                                    { Max data length }
  726.               @RetLength);                                      { Data length }
  727.  
  728. end; { proc. Com_SetFlow }
  729.  
  730. (*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-+-*-*)
  731.  
  732. initialization
  733.   Com_Initvars;
  734.  
  735. finalization
  736.   Com_StopThread;
  737. end. { unit OS2COM }
  738.