home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / comos2.zip / COMMOS2.CPP < prev    next >
C/C++ Source or Header  |  1993-02-21  |  22KB  |  888 lines

  1. /**************************************************************************
  2.  *
  3.  *  COMMOS2.CPP
  4.  *
  5.  *  This file contains the 32-bit routines which provide the CommPort
  6.  *  class methods
  7.  *
  8.  *  This file was compiled with the IBM C/C++ beta compiler using the
  9.  *  following flags:
  10.  *
  11.  *      /Fd /Tdp /G3m+s-d-e+ /O /Re /C /W3gen+ppc+enu+par+
  12.  *_________________________________________________________________________
  13.  *
  14.  *  Copyright (c) 1992 by ASH Software, Inc.
  15.  *
  16.  *  Update History
  17.  *
  18.  *    11/28/1992 - Module created
  19.  *
  20.  **************************************************************************/
  21.  
  22. #include "COMM.HPP"
  23.  
  24. /*------------------------------------------------------------------------*
  25.  *  CommPort
  26.  *
  27.  *  This is the class constructor which initializes each instance of the
  28.  *  class.
  29.  *------------------------------------------------------------------------*/
  30.  
  31. CommPort::CommPort(VOID)
  32. {
  33.  
  34. //
  35. // Initialize the Comm data
  36. //
  37.  
  38. ulCommError = COMM_ERROR_NOERROR;
  39. ulDosError  = NO_ERROR;
  40. hCommPort   = 0;
  41. ulCommMode  = COMM_MODE_NOTSTARTED;
  42. fPortOpen   = FALSE;
  43. fPortOpened = FALSE;
  44.  
  45. return;
  46. }
  47.  
  48. /*------------------------------------------------------------------------*
  49.  *  ~CommPort
  50.  *
  51.  *  This is the class destructor.
  52.  *------------------------------------------------------------------------*/
  53.  
  54. CommPort::~CommPort(VOID)
  55. {
  56. if (fPortOpen)
  57.   Close();
  58.  
  59. return;
  60. }
  61.  
  62. /*------------------------------------------------------------------------*
  63.  *  GetLastError
  64.  *
  65.  *  This method returns information concerning the last error for the
  66.  *  port.
  67.  *------------------------------------------------------------------------*/
  68.  
  69. ULONG CommPort::GetLastError(PULONG pulCommError,PULONG pulDosError,
  70.                              PULONG pulCommMode)
  71. {
  72. if (!fPortOpen)
  73.   return COMM_ERROR_PORTNOTFOUND;   // Unable to locate comm port
  74.  
  75. (*pulCommError) = ulCommError;
  76. (*pulDosError)  = ulDosError;
  77. (*pulCommMode)  = ulCommMode;
  78.  
  79. return COMM_ERROR_NOERROR;
  80. }
  81.  
  82. /*------------------------------------------------------------------------*
  83.  *  Open
  84.  *
  85.  *  This method invokes DosOpen to open the specified serial comm port.
  86.  *------------------------------------------------------------------------*/
  87.  
  88. ULONG CommPort::Open(INT iCommPort)
  89. {
  90. INT
  91.   iLoop,
  92.   fKeepLooping;
  93.  
  94. ULONG
  95.   ulParmLength,
  96.   ulAction,
  97.   ulRC;
  98.  
  99. CHAR
  100.   cPortName[21];
  101.  
  102. LINECONTROL
  103.   COMParams;
  104.  
  105. fPortOpened=TRUE;
  106. sprintf(cPortName,"COM%d",iCommPort);
  107. ulRC=DosOpen(cPortName,&hCommPort,&ulAction,0L,
  108.              FILE_NORMAL,FILE_OPEN,
  109.              OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
  110.              NULL);
  111.  
  112. if (ulRC)
  113.   {
  114.   fPortOpen   = FALSE;
  115.   ulCommError = COMM_ERROR_OPENFAILED;
  116.   ulDosError  = ulRC;
  117.   ulCommMode  = COMM_MODE_OPEN;
  118.   return COMM_ERROR_OPENFAILED;
  119.   }
  120. else
  121.   {
  122.   ulCommError = COMM_ERROR_NOERROR;
  123.   ulDosError  = NO_ERROR;
  124.   ulCommMode  = COMM_MODE_OPEN;
  125.   fPortOpen   = TRUE;
  126.   }
  127.  
  128. //
  129. // Create/Initialize the read & write semaphores
  130. //
  131.  
  132. ulRC=DosCreateMutexSem(NULL,&hCommWriteSem,0L,FALSE);
  133. if (ulRC)
  134.   return COMM_ERROR_SEMAPHOREFAILED;
  135. ulRC=DosCreateMutexSem(NULL,&hCommReadSem,0L,FALSE);
  136. if (ulRC)
  137.   return COMM_ERROR_SEMAPHOREFAILED;
  138.  
  139. //
  140. // Initialize the DCB structure
  141. //
  142.  
  143. ulRC=GetDCBInfo();
  144. if (ulRC)
  145.   return COMM_ERROR_DCBINFOFAILED;
  146. DCBOriginal=DCBInfo;
  147.  
  148. //
  149. // Initialize other parameters
  150. //
  151.  
  152. ulParmLength=sizeof(LINECONTROL);
  153. ulRC=DosDevIOCtl(hCommPort,IOCTL_ASYNC,ASYNC_GETLINECTRL,
  154.   NULL,0L,NULL,&COMParams,ulParmLength,&ulParmLength);
  155. usDataBits = COMParams.bDataBits;
  156. usParity   = COMParams.bParity;
  157. usStopBits = COMParams.bStopBits;
  158. usTxBreak  = COMParams.fTransBreak;
  159. if (ulRC)
  160.   return COMM_ERROR_BAUDFAILED;
  161.  
  162. ulParmLength=sizeof(short);
  163. ulRC=DosDevIOCtl(hCommPort,IOCTL_ASYNC,ASYNC_GETBAUDRATE,
  164.    NULL,0L,NULL,&usBaudRate,ulParmLength,&ulParmLength);
  165. if (ulRC)
  166.   return COMM_ERROR_BAUDFAILED;
  167.  
  168. return COMM_ERROR_NOERROR;
  169. }
  170.  
  171. /*------------------------------------------------------------------------*
  172.  *  Initialize
  173.  *
  174.  *  This method initializes a serial comm port by calling the
  175.  *  DosDevIOCtl routine with the proper parameters.
  176.  *------------------------------------------------------------------------*/
  177.  
  178. ULONG CommPort::Initialize(USHORT usBaudRate,USHORT usParity,
  179.                            USHORT usDataBits,USHORT usStopBits,
  180.                            USHORT usTxBreak)
  181. {
  182. USHORT
  183.   usErrorCode;
  184.  
  185. ULONG
  186.   ulParmLength,
  187.   ulDataLength,
  188.   ulRC;
  189.  
  190. LINECONTROL
  191.   COMParams;
  192.  
  193. //
  194. // Set the baud rate
  195. //
  196.  
  197. ulParmLength=sizeof(USHORT);
  198. ulRC=DosDevIOCtl(hCommPort,IOCTL_ASYNC,ASYNC_SETBAUDRATE,
  199.                  &usBaudRate,ulParmLength,&ulParmLength,
  200.                  NULL,0L,NULL);
  201. if (ulRC)
  202.   {
  203.   ulCommError = COMM_ERROR_BAUDFAILED;
  204.   ulDosError  = ulRC;
  205.   ulCommMode  = COMM_MODE_SETBAUD;
  206.   return COMM_ERROR_BAUDFAILED;
  207.   }
  208.  
  209. //
  210. // Set the number of bits, parity, stop bits, and Transmit break
  211. //
  212.  
  213. COMParams.bDataBits  =(unsigned char)usDataBits;  // Set data bits
  214. COMParams.bParity    =(unsigned char)usParity;    // Set parity
  215. COMParams.bStopBits  =(unsigned char)usStopBits;  // Set stop bits
  216. COMParams.fTransBreak=(unsigned char)usTxBreak;   // Set Transmit break
  217. ulParmLength=sizeof(LINECONTROL);
  218.   
  219. ulRC=DosDevIOCtl(hCommPort,IOCTL_ASYNC,ASYNC_SETLINECTRL,
  220.                  &COMParams,ulParmLength,&ulParmLength,
  221.                  NULL,0L,NULL);
  222. if (ulRC)
  223.   {
  224.   ulCommError = COMM_ERROR_LINECNTRLFAILED;
  225.   ulDosError  = ulRC;
  226.   ulCommMode  = COMM_MODE_SETLINECNTRL;
  227.   return COMM_ERROR_LINECNTRLFAILED;
  228.   }
  229.  
  230. return COMM_ERROR_NOERROR;
  231. }
  232.  
  233. /*------------------------------------------------------------------------*
  234.  *  ClearBuffers
  235.  *
  236.  *  This method clears both the transmit and receive buffers for the
  237.  *  com port.
  238.  *------------------------------------------------------------------------*/
  239.  
  240. ULONG CommPort::ClearBuffers(VOID)
  241. {
  242. ULONG
  243.   ulRC;
  244.  
  245. ulRC=ClearTxBuffer();
  246. if (!ulRC)
  247.   ulRC=ClearRxBuffer();
  248.  
  249. return ulRC;
  250. }
  251.  
  252. /*------------------------------------------------------------------------*
  253.  *  ClearTxBuffer
  254.  *
  255.  *  This method clears the transmit buffer for the com port.
  256.  *------------------------------------------------------------------------*/
  257.  
  258. ULONG CommPort::ClearTxBuffer(VOID)
  259. {
  260. UCHAR
  261.   ucZero;
  262.  
  263. ULONG
  264.   ulRC,
  265.   ulParmLength;
  266.  
  267. ucZero=0;
  268. ulParmLength=sizeof(UCHAR);
  269.  
  270. ulRC=DosDevIOCtl(hCommPort,IOCTL_GENERAL,DEV_FLUSHOUTPUT,
  271.                  &ucZero,ulParmLength,&ulParmLength,
  272.                  NULL,0L,NULL);
  273. if (ulRC)
  274.   {
  275.   ulCommError = COMM_ERROR_CLEARBUFFERFAILED;
  276.   ulDosError  = ulRC;
  277.   ulCommMode  = COMM_MODE_CLEARTXBUFFER;
  278.   return COMM_ERROR_CLEARBUFFERFAILED;
  279.   }
  280.  
  281. return COMM_ERROR_NOERROR;
  282. }
  283.  
  284. /*------------------------------------------------------------------------*
  285.  *  ClearRxBuffer
  286.  *
  287.  *  This methoc clears receive buffer for the com port
  288.  *------------------------------------------------------------------------*/
  289.  
  290. ULONG CommPort::ClearRxBuffer(VOID)
  291. {
  292. UCHAR
  293.   ucZero;
  294.  
  295. ULONG
  296.   ulRC,
  297.   ulParmLength;
  298.  
  299. ucZero=0;
  300. ulParmLength=sizeof(UCHAR);
  301.  
  302. ulRC=DosDevIOCtl(hCommPort,IOCTL_GENERAL,DEV_FLUSHINPUT,
  303.                  &ucZero,ulParmLength,&ulParmLength,
  304.                  NULL,0L,NULL);
  305. if (ulRC)
  306.   {
  307.   ulCommError = COMM_ERROR_CLEARBUFFERFAILED;
  308.   ulDosError  = ulRC;
  309.   ulCommMode  = COMM_MODE_CLEARRXBUFFER;
  310.   return COMM_ERROR_CLEARBUFFERFAILED;
  311.   }
  312.  
  313. return COMM_ERROR_NOERROR;
  314. }
  315.  
  316. /*------------------------------------------------------------------------*
  317.  *  Close
  318.  *
  319.  *  This method invokes DosClose to close a serial comm port.
  320.  *------------------------------------------------------------------------*/
  321.  
  322. ULONG CommPort::Close(VOID)
  323. {
  324. ULONG
  325.   ulDCBSize;
  326.  
  327. if (!fPortOpened)
  328.   return COMM_ERROR_PORTNOTFOUND;   // Unable to locate comm port
  329.  
  330. if (fPortOpen)
  331.   {
  332.   ulDCBSize=sizeof(DCBINFO);
  333.   DosDevIOCtl(hCommPort,IOCTL_ASYNC,ASYNC_SETDCBINFO,
  334.     &DCBOriginal,ulDCBSize,&ulDCBSize,NULL,0L,NULL);
  335.   Initialize(usBaudRate,usParity,usDataBits,usStopBits,usTxBreak);
  336.   DosClose(hCommPort);
  337.   }
  338.  
  339. DosCloseMutexSem(hCommReadSem);
  340. DosCloseMutexSem(hCommWriteSem);
  341.  
  342. ulCommError = COMM_ERROR_NOERROR;
  343. ulDosError  = NO_ERROR;
  344. ulCommMode  = COMM_MODE_NOTSTARTED;
  345. fPortOpen   = FALSE;
  346. fPortOpened = FALSE;
  347.  
  348. return COMM_ERROR_NOERROR;
  349. }
  350.  
  351. /*------------------------------------------------------------------------*
  352.  *  Write
  353.  *
  354.  *  This method invokes DosWrite to write the data to the serial comm
  355.  *  port.
  356.  *------------------------------------------------------------------------*/
  357.  
  358. ULONG CommPort::Write(PUCHAR pucDataArea,ULONG ulDataAreaSize,
  359.                       PULONG pulWritten)
  360. {
  361. ULONG
  362.   ulRC;
  363.  
  364. ulRC=DosRequestMutexSem(hCommWriteSem,COMMOS2_RESOURCE_SEM_WAIT);
  365. if (ulRC)
  366.   {
  367.   ulCommError = COMM_ERROR_SEMAPHOREFAILED;
  368.   ulDosError  = ulRC;
  369.   ulCommMode  = COMM_MODE_WRITE;
  370.   return COMM_ERROR_SEMAPHOREFAILED;
  371.   }
  372.  
  373. ulRC=DosWrite(hCommPort,pucDataArea,ulDataAreaSize,pulWritten);
  374.  
  375. DosReleaseMutexSem(hCommWriteSem);
  376.  
  377. if (ulRC)
  378.   {
  379.   ulCommError = COMM_ERROR_WRITEFAILED;
  380.   ulDosError  = ulRC;
  381.   ulCommMode  = COMM_MODE_WRITE;
  382.   return COMM_ERROR_WRITEFAILED;
  383.   }
  384.  
  385. return COMM_ERROR_NOERROR;
  386. }
  387.  
  388. /*------------------------------------------------------------------------*
  389.  *  Read
  390.  *
  391.  *  This method invokes DosRead to read the data from the serial comm
  392.  *  port.  This routine reads whatever data is currently available from
  393.  *  the port buffer.  It does not wait for information to arrive.
  394.  *------------------------------------------------------------------------*/
  395.  
  396. ULONG CommPort::Read(PUCHAR pucDataArea,ULONG ulDataAreaSize,
  397.                      PULONG pulRead)
  398. {
  399. ULONG
  400.   ulRC;
  401.  
  402. ulRC=DosRequestMutexSem(hCommReadSem,COMMOS2_RESOURCE_SEM_WAIT);
  403. if (ulRC)
  404.   {
  405.   ulCommError = COMM_ERROR_SEMAPHOREFAILED;
  406.   ulDosError  = ulRC;
  407.   ulCommMode  = COMM_MODE_READ;
  408.   return COMM_ERROR_SEMAPHOREFAILED;
  409.   }
  410.  
  411. ulRC=DosRead(hCommPort,pucDataArea,ulDataAreaSize,pulRead);
  412.  
  413. DosReleaseMutexSem(hCommReadSem);
  414.  
  415. if (ulRC)
  416.   {
  417.   ulCommError = COMM_ERROR_READFAILED;
  418.   ulDosError  = ulRC;
  419.   ulCommMode  = COMM_MODE_READ;
  420.   return COMM_ERROR_WRITEFAILED;
  421.   }
  422.  
  423. return COMM_ERROR_NOERROR;
  424. }
  425.  
  426. /*------------------------------------------------------------------------*
  427.  *  ReadTimeOut
  428.  *
  429.  *  This method invokes DosRead and DosDevIOCtl to either read the
  430.  *  specified number of characters or to return once the timeout specified
  431.  *  has elapsed.
  432.  *------------------------------------------------------------------------*/
  433.  
  434. ULONG CommPort::ReadTimeOut(PUCHAR pucDataArea,ULONG ulDataAreaSize,
  435.                             PULONG pulRead,LONG lTimeOutmSec)
  436. {
  437. INT
  438.   fCheck,
  439.   fKeepWaiting;
  440.  
  441. ULONG
  442.   ulStartTime,
  443.   ulTimeOut,
  444.   ulCharCount,
  445.   ulSleepTime,
  446.   ulReadRC,
  447.   ulRC;
  448.  
  449. ulRC=DosRequestMutexSem(hCommReadSem,COMMOS2_RESOURCE_SEM_WAIT);
  450. if (ulRC)
  451.   {
  452.   ulCommError = COMM_ERROR_SEMAPHOREFAILED;
  453.   ulDosError  = ulRC;
  454.   ulCommMode  = COMM_MODE_READTIMEOUT;
  455.   return COMM_ERROR_SEMAPHOREFAILED;
  456.   }
  457.  
  458. ulStartTime=TimerValue();
  459. ulTimeOut=lTimeOutmSec/10L;
  460. ulSleepTime=1L;
  461. fKeepWaiting=TRUE;
  462. if (lTimeOutmSec == TIMEOUT_INDEFINITE)
  463.   fCheck=FALSE;
  464. else
  465.   fCheck=TRUE;
  466. ulReadRC=COMM_ERROR_NOERROR;
  467. do
  468.   {
  469.   ulRC=QueryQueue(COMM_QUERY_RXCOUNT,&ulCharCount);
  470.   if (ulRC)
  471.     {
  472.     ulCommError = COMM_ERROR_IOCTLFAILED;
  473.     ulDosError  = ulRC;
  474.     ulCommMode = COMM_MODE_READTIMEOUT;
  475.     DosReleaseMutexSem(hCommReadSem);
  476.     return COMM_ERROR_IOCTLFAILED;
  477.     }
  478.  
  479.   if (ulCharCount >= ulDataAreaSize) 
  480.     {
  481.  
  482.     //
  483.     // The number of characters requested are available.  Read the data
  484.     // and return to the calling program.
  485.     //
  486.  
  487.     fKeepWaiting=FALSE;
  488.     ulReadRC=Read(pucDataArea,ulDataAreaSize,pulRead);
  489.     }
  490.   else
  491.     {
  492.  
  493.     //
  494.     // The requested number of characters are not available at this
  495.     // time.  Test to see if the specified time has elapsed and return
  496.     // to the calling program if it has.
  497.     //
  498.  
  499.     if (fCheck && (TimerDifference(ulStartTime) > ulTimeOut))
  500.       {
  501.       fKeepWaiting=FALSE;
  502.       (*pulRead)=0;
  503.       ulCommError = COMM_ERROR_TIMEOUTEXCEEDED;
  504.       ulDosError  = NO_ERROR;
  505.       ulCommMode  = COMM_MODE_READTIMEOUT;
  506.       ulReadRC=COMM_ERROR_TIMEOUTEXCEEDED;
  507.       }
  508.     }
  509.   if (fKeepWaiting)
  510.     {
  511.     DosSleep(ulSleepTime);
  512.  
  513.     //
  514.     // If port is not responding, slowly increase sleep interval.  Do
  515.     // not exceed 256 (approximately 1/4 second).
  516.     //
  517.  
  518.     if (ulSleepTime < 256L)
  519.       ulSleepTime *= 2L;
  520.     }
  521.   } while (fKeepWaiting);
  522.  
  523. DosReleaseMutexSem(hCommReadSem);
  524. return ulReadRC;
  525. }
  526.  
  527. /*------------------------------------------------------------------------*
  528.  *  ReadUntilByte
  529.  *
  530.  *  This method invokes DosRead and DosDevIOCtl to either read either the
  531.  *  specified number of characters or to return once the character
  532.  *  specified has been read.  The routine will also return if the timeout
  533.  *  specified has elapsed.
  534.  *------------------------------------------------------------------------*/
  535.  
  536. ULONG CommPort::ReadUntilByte(PUCHAR pucDataArea,ULONG ulDataAreaSize,
  537.                               PULONG pulRead,UCHAR ucWaitByte,
  538.                               LONG lTimeOutmSec)
  539. {
  540. ULONG 
  541.   ulStartTime,
  542.   ulTimeOut,
  543.   ulSleepTime,
  544.   ulCharCount,
  545.   ulReadRC,
  546.   ulRC,
  547.   ulDataPosition;
  548.  
  549. UCHAR
  550.   ucNextChar;
  551.  
  552. INT
  553.   fCheck,
  554.   fKeepWaiting;
  555.  
  556. ulRC=DosRequestMutexSem(hCommReadSem,COMMOS2_RESOURCE_SEM_WAIT);
  557. if (ulRC)
  558.   {
  559.   ulCommError = COMM_ERROR_SEMAPHOREFAILED;
  560.   ulDosError  = ulRC;
  561.   ulCommMode  = COMM_MODE_READUNTILBYTE;
  562.   return COMM_ERROR_SEMAPHOREFAILED;
  563.   }
  564.  
  565. ulStartTime=TimerValue();
  566. ulTimeOut=lTimeOutmSec/10L;
  567. ulSleepTime=1L;
  568. fKeepWaiting=TRUE;
  569. if (lTimeOutmSec == TIMEOUT_INDEFINITE)
  570.   fCheck=FALSE;
  571. else
  572.   fCheck=TRUE;
  573. ulReadRC=COMM_ERROR_NOERROR;
  574. ulDataPosition=0;
  575. (*pulRead)=0;
  576. do
  577.   {
  578.   ulRC=QueryQueue(COMM_QUERY_RXCOUNT,&ulCharCount);
  579.   if (ulRC)
  580.     {
  581.     ulCommError = COMM_ERROR_IOCTLFAILED;
  582.     ulDosError  = ulRC;
  583.     ulCommMode = COMM_MODE_READUNTILBYTE;
  584.     DosReleaseMutexSem(hCommReadSem);
  585.     return COMM_ERROR_IOCTLFAILED;
  586.     }
  587.  
  588.   if (ulCharCount > 0) 
  589.     {
  590.  
  591.     //
  592.     // Some characters are available.  Read them one by one checking
  593.     // to see if the termination character is present or the maximum
  594.     // number of characters have been read.
  595.     //
  596.  
  597.     do
  598.       {
  599.       ulReadRC=Read(&ucNextChar,1,pulRead);
  600.       if (ulReadRC)
  601.         fKeepWaiting=FALSE;
  602.       if (fKeepWaiting)
  603.         {
  604.         pucDataArea[ulDataPosition]=ucNextChar;
  605.         ulDataPosition++;
  606.         ulCharCount--;
  607.         if (ucNextChar == ucWaitByte)
  608.           fKeepWaiting=FALSE;
  609.         if (ulDataPosition >= ulDataAreaSize)
  610.           fKeepWaiting=FALSE;
  611.         }
  612.       } while (fKeepWaiting && (ulCharCount > 0));
  613.     (*pulRead)=ulDataPosition;
  614.     }
  615.   else
  616.     {
  617.  
  618.     //
  619.     // The requested number of characters are not available at this
  620.     // time.  Test to see if the specified time has elapsed and return
  621.     // to the calling program if it has.
  622.     //
  623.  
  624.     if (fCheck && (TimerDifference(ulStartTime) > ulTimeOut))
  625.       {
  626.       fKeepWaiting=FALSE;
  627.       ulCommError = COMM_ERROR_TIMEOUTEXCEEDED;
  628.       ulDosError  = NO_ERROR;
  629.       ulCommMode  = COMM_MODE_READUNTILBYTE;
  630.       ulReadRC=COMM_ERROR_TIMEOUTEXCEEDED;
  631.       }
  632.     }
  633.   if (fKeepWaiting)
  634.     {
  635.     DosSleep(ulSleepTime);
  636.  
  637.     //
  638.     // If port is not responding, slowly increase sleep interval.  Do
  639.     // not exceed 256 (approximately 1/4 second).
  640.     //
  641.  
  642.     if (ulSleepTime < 256L)
  643.       ulSleepTime *= 2L;
  644.     }
  645.   } while (fKeepWaiting);
  646.  
  647. DosReleaseMutexSem(hCommReadSem);
  648. return ulReadRC;
  649. }
  650.  
  651. /*------------------------------------------------------------------------*
  652.  *  QueryQueue
  653.  *
  654.  *  This method queries the values of count and size for both the
  655.  *  receive and transmit buffers.
  656.  *------------------------------------------------------------------------*/
  657.  
  658. ULONG CommPort::QueryQueue(USHORT usMode,PULONG pulValue)
  659. {
  660. RXQUEUE
  661.   RxQueue;
  662.  
  663. ULONG
  664.   ulRC,
  665.   ulRxQueue,
  666.   ulFunction;
  667.  
  668. switch (usMode)
  669.   {
  670.   case COMM_QUERY_RXCOUNT:  // Query Rx character count
  671.   case COMM_QUERY_RXBUFFER: // Query Rx buffer size
  672.     ulFunction=ASYNC_GETINQUECOUNT;
  673.     break;
  674.  
  675.   case COMM_QUERY_TXCOUNT:  // Query Tx character count
  676.   case COMM_QUERY_TXBUFFER: // Query Tx buffer size
  677.     ulFunction=ASYNC_GETOUTQUECOUNT;
  678.     break;
  679.   }
  680.  
  681. ulRxQueue=sizeof(RXQUEUE);
  682. (*pulValue)=0;
  683. ulRC=(unsigned long)DosDevIOCtl(hCommPort,IOCTL_ASYNC,
  684.   ulFunction,NULL,0L,NULL,
  685.   &RxQueue,ulRxQueue,&ulRxQueue);
  686.  
  687. if (ulRC)
  688.   {  
  689.   ulCommError = COMM_ERROR_IOCTLFAILED;
  690.   ulDosError  = ulRC;
  691.   return COMM_ERROR_IOCTLFAILED;
  692.   }
  693.  
  694. switch (usMode)
  695.   {
  696.   case COMM_QUERY_RXCOUNT:  // Return Rx buffer count
  697.   case COMM_QUERY_TXCOUNT:  // Return Tx buffer count
  698.     (*pulValue)=RxQueue.cch;
  699.     break;
  700.  
  701.   case COMM_QUERY_RXBUFFER: // Return Rx buffer size
  702.   case COMM_QUERY_TXBUFFER: // Return Tx buffer size
  703.     (*pulValue)=RxQueue.cb;
  704.     break;
  705.   }
  706.  
  707. return COMM_ERROR_NOERROR;
  708. }
  709.  
  710. /*------------------------------------------------------------------------*
  711.  *  QueryRxCount
  712.  *
  713.  *  This method returns the number of characters in the receiver buffer.
  714.  *------------------------------------------------------------------------*/
  715.  
  716. ULONG CommPort::QueryRxCount(PULONG pulCount)
  717. {
  718. ULONG
  719.   ulRC;
  720.  
  721. ulRC=QueryQueue(COMM_QUERY_RXCOUNT,pulCount);
  722. if (ulRC)
  723.   {
  724.   ulCommMode = COMM_MODE_QUERYRXCOUNT;
  725.   }
  726.  
  727. return ulRC;
  728. }
  729.  
  730. /*------------------------------------------------------------------------*
  731.  *  QueryRxBufSize
  732.  *
  733.  *  This method returns the size of the receiver buffer.
  734.  *------------------------------------------------------------------------*/
  735.  
  736. ULONG CommPort::QueryRxBufferSize(PULONG pulSize)
  737. {
  738. ULONG
  739.   ulRC;
  740.  
  741. ulRC=QueryQueue(COMM_QUERY_RXBUFFER,pulSize);
  742. if (ulRC)
  743.   {
  744.   ulCommMode = COMM_MODE_QUERYRXBUFSIZE;
  745.   }
  746.  
  747. return ulRC;
  748. }
  749.  
  750. /*------------------------------------------------------------------------*
  751.  *  QueryTxCount
  752.  *
  753.  *  This method returns the number of characters in the transmit buffer.
  754.  *------------------------------------------------------------------------*/
  755.  
  756. ULONG CommPort::QueryTxCount(PULONG pulCount)
  757. {
  758. ULONG
  759.   ulRC;
  760.  
  761. ulRC=QueryQueue(COMM_QUERY_TXCOUNT,pulCount);
  762. if (ulRC)
  763.   {
  764.   ulCommMode = COMM_MODE_QUERYTXCOUNT;
  765.   }
  766.  
  767. return ulRC;
  768. }
  769.  
  770. /*------------------------------------------------------------------------*
  771.  *  QueryTxBufSize
  772.  *
  773.  *  This method returns the size of the transmit buffer.
  774.  *------------------------------------------------------------------------*/
  775.  
  776. ULONG CommPort::QueryTxBufferSize(PULONG pulSize)
  777. {
  778. ULONG
  779.   ulRC;
  780.  
  781. ulRC=QueryQueue(COMM_QUERY_TXBUFFER,pulSize);
  782. if (ulRC)
  783.   {
  784.   ulCommMode = COMM_MODE_QUERYTXBUFSIZE;
  785.   }
  786.  
  787. return ulRC;
  788. }
  789.  
  790. /*------------------------------------------------------------------------*
  791.  *  GetDCBInfo
  792.  *
  793.  *  This method gets the DCB information for the comm port.
  794.  *------------------------------------------------------------------------*/
  795.  
  796. ULONG CommPort::GetDCBInfo(VOID)
  797. {
  798. ULONG
  799.   ulRC,
  800.   ulDCBSize;
  801.  
  802. ulDCBSize=sizeof(DCBINFO);
  803. ulRC=(unsigned long)DosDevIOCtl(hCommPort,IOCTL_ASYNC,ASYNC_GETDCBINFO,
  804.   NULL,0L,NULL,&DCBInfo,ulDCBSize,&ulDCBSize);
  805.  
  806. if (ulRC)
  807.   {
  808.   ulCommError = COMM_ERROR_DCBINFOFAILED;
  809.   ulDosError  = ulRC;
  810.   ulCommMode  = COMM_MODE_GETDCBINFO;
  811.   return COMM_ERROR_DCBINFOFAILED;
  812.   }
  813.  
  814. return COMM_ERROR_NOERROR;
  815. }
  816.  
  817. /*------------------------------------------------------------------------*
  818.  *  SetDCBInfo
  819.  *
  820.  *  This method sets the DCB information for the comm port.
  821.  *------------------------------------------------------------------------*/
  822.  
  823. ULONG CommPort::SetDCBInfo(VOID)
  824. {
  825. ULONG
  826.   ulRC,
  827.   ulDCBSize;
  828.  
  829. ulDCBSize=sizeof(DCBINFO);
  830. ulRC=(unsigned long)DosDevIOCtl(hCommPort,IOCTL_ASYNC,ASYNC_SETDCBINFO,
  831.   &DCBInfo,ulDCBSize,&ulDCBSize,NULL,0L,NULL);
  832.  
  833. if (ulRC)
  834.   {
  835.   ulCommError = COMM_ERROR_DCBINFOFAILED;
  836.   ulDosError  = ulRC;
  837.   ulCommMode  = COMM_MODE_SETDCBINFO;
  838.   return COMM_ERROR_DCBINFOFAILED;
  839.   }
  840.  
  841. return COMM_ERROR_NOERROR;
  842. }
  843.  
  844. /*------------------------------------------------------------------------*
  845.  *  TimerValue
  846.  *
  847.  *  This routine returns a timer value in hundredths of seconds.  This
  848.  *  routine does not return a value which can be used for the current time,
  849.  *  but it does return a value useful for use as a timer.  If the value
  850.  *  returned is less than a previous value, you should add 8,640,000 which
  851.  *  is equivalent to one day in hundredths of seconds.
  852.  *------------------------------------------------------------------------*/
  853.  
  854. static ULONG TimerValue()
  855. {
  856. DATETIME
  857.   CurrentTime;
  858.  
  859. DosGetDateTime(&CurrentTime);
  860.  
  861. return 360000L*(unsigned long)CurrentTime.hours+
  862.          6000L*(unsigned long)CurrentTime.minutes+
  863.           100L*(unsigned long)CurrentTime.seconds+
  864.                (unsigned long)CurrentTime.hundredths;
  865. }
  866.  
  867. /*------------------------------------------------------------------------*
  868.  *  TimerDifference
  869.  *
  870.  *  This routine uses a base value obtained from TimerValue and calls 
  871.  *  TimerValue itself to return the difference in hundreths of seconds.
  872.  *------------------------------------------------------------------------*/
  873.  
  874. static ULONG TimerDifference(ULONG ulBaseTimerValue)
  875. {
  876. ULONG
  877.   ulCurrentTime;
  878.  
  879. ulCurrentTime=TimerValue();
  880. if (ulCurrentTime < ulBaseTimerValue)
  881.   ulCurrentTime += 8640000L;
  882.  
  883. return ulCurrentTime-ulBaseTimerValue;
  884. }                              
  885.  
  886.  
  887.  
  888.