home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- *
- * COMM32.C
- *
- * This file contains the 32-bit routines which provide the basic
- * serial support
- *
- * This file was compiled with the IBM C Set/2 compiler using the
- * following flags:
- *
- * To produce a multi-thread version of the library
- * /W3 /Ss /Gm /Gd- /Ge /O /Re /C /Kbcepr
- *
- * To produce a single-thread version of the library
- * /W3 /Ss /Gm- /Gd- /Ge /O /Re /C /Kbcepr
- *_________________________________________________________________________
- *
- * Copyright (c) 1992 by ASH Software, Inc.
- *
- * Update History
- *
- * 11/28/1992 - Module created
- *
- **************************************************************************/
-
- #define INCL_COMMOS2_32BIT
- #include "COMM.H"
-
- /*------------------------------------------------------------------------*
- * CommStartSystem
- *
- * This routine initializes the comm library. This routine must be
- * called before other routines in the comm library and must specify the
- * maximum number of ports to be handled by the library.
- *------------------------------------------------------------------------*/
-
- ULONG CommStartSystem(int iCommPorts)
- {
- ULONG
- ulRC;
-
- int
- iLoop;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- if (iCommPorts <= 0)
- return COMM_ERROR_INVALIDMAXPORTS; // Invalid number of ports
-
- iLoop=TRUE;
-
- ulRC=DosCreateMutexSem(NULL,&hCommSem,0L,TRUE);
- if (ulRC)
- return COMM_ERROR_SEMAPHOREFAILED;
-
- if (iMaxNumberCommPorts > 0)
- iLoop=FALSE;
- else
- iMaxNumberCommPorts = iCommPorts;
-
- if (!iLoop)
- {
- DosReleaseMutexSem(hCommSem);
- return COMM_ERROR_ALREADYINITIALIZED; // System already initialized
- }
-
- pCommOS2Struct=malloc(iCommPorts*sizeof(COMMOS2_STRUCT));
- if (pCommOS2Struct == NULL)
- {
- DosReleaseMutexSem(hCommSem);
- return COMM_ERROR_SYSINITFAILED;
- }
-
- //
- // Initialize the COMM structure
- //
-
- for (iLoop=0; iLoop<iCommPorts; iLoop++)
- {
- pCommStruct = &pCommOS2Struct[iLoop];
- pCommStruct->ulCommErrorCode = COMM_ERROR_NOERROR;
- pCommStruct->ulDosErrorCode = NO_ERROR;
- pCommStruct->hCommPortFile = 0;
- pCommStruct->ulCommMode = COMM_MODE_NOTSTARTED;
- pCommStruct->fPortOpen = FALSE;
- pCommStruct->fPortOpened = FALSE;
- }
-
- DosReleaseMutexSem(hCommSem);
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommStopSystem
- *
- * This system frees the resources used when initializing the comm
- * library. This should be called when the comm library is no longer
- * needed or during program termination.
- *------------------------------------------------------------------------*/
-
- ULONG CommStopSystem(void)
- {
- ULONG
- ulDCBSize;
-
- int
- iLoop;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- if (pCommOS2Struct != NULL)
- {
- for (iLoop=0; iLoop<iMaxNumberCommPorts; iLoop++)
- CommClose(iLoop);
-
- free(pCommOS2Struct);
- }
- iMaxNumberCommPorts = 0;
- DosCloseMutexSem(hCommSem);
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommGetLastError
- *
- * This routine returns information concerning the last error for the
- * requested comm port.
- *------------------------------------------------------------------------*/
-
- ULONG CommGetLastError(HCOMMPORT hCommPort,ULONG *ulCommError,
- ULONG *ulDosError,ULONG *ulCommMode)
- {
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=CommGetStruct(hCommPort);
-
- if (pCommStruct == NULL)
- return COMM_ERROR_PORTNOTFOUND; // Unable to locate comm port
-
- (*ulCommError) = pCommStruct->ulCommErrorCode;
- (*ulDosError) = pCommStruct->ulDosErrorCode;
- (*ulCommMode) = pCommStruct->ulCommMode;
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommOpen
- *
- * This routine invokes DosOpen to open the specified serial comm port.
- * The error return is the same as for DosOpen.
- *------------------------------------------------------------------------*/
-
- ULONG CommOpen(int iCommPort,PHCOMMPORT phCommPort)
- {
- int
- iLoop,
- fKeepLooping;
-
- ULONG
- ulParmLength,
- ulAction,
- ulRC;
-
- char
- cPortName[21];
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- LINECONTROL
- COMParams;
-
- //
- // Find an empty location in the static structure.
- // Use a Mutex semaphore to serialize access.
- //
-
- ulRC=DosRequestMutexSem(hCommSem,COMMOS2_RESOURCE_SEM_WAIT);
- if (ulRC)
- return COMM_ERROR_SEMAPHOREFAILED;
-
- fKeepLooping=TRUE;
- iLoop=0;
- pCommStruct=NULL;
- while(fKeepLooping)
- {
- if (pCommOS2Struct[iLoop].fPortOpened)
- {
- iLoop++;
- if (iLoop == iMaxNumberCommPorts)
- fKeepLooping=FALSE;
- }
- else
- {
- pCommStruct=&pCommOS2Struct[iLoop];
- fKeepLooping=FALSE;
- pCommStruct->fPortOpened=TRUE;
- *phCommPort=iLoop;
- }
- }
- DosReleaseMutexSem(hCommSem);
-
- if (pCommStruct == NULL)
- return COMM_ERROR_MAXPORTSEXCEEDED; // Max number of comm ports exceeded
-
- sprintf(cPortName,"COM%d",iCommPort);
- ulRC=(ULONG)DosOpen(cPortName,&(pCommStruct->hCommPortFile),&ulAction,0L,
- FILE_NORMAL,FILE_OPEN,
- OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
- NULL);
-
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_OPENFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->hCommPortFile = -1;
- pCommStruct->ulCommMode = COMM_MODE_OPEN;
- return COMM_ERROR_OPENFAILED;
- }
- else
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_NOERROR;
- pCommStruct->ulDosErrorCode = NO_ERROR;
- pCommStruct->ulCommMode = COMM_MODE_OPEN;
- pCommStruct->fPortOpen = TRUE;
- }
-
- //
- // Initialize read and write semaphores
- //
-
- ulRC=DosCreateMutexSem(NULL,&(pCommStruct->hCommWriteSem),0L,FALSE);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_SEMAPHOREFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_OPEN;
- return COMM_ERROR_SEMAPHOREFAILED;
- }
- ulRC=DosCreateMutexSem(NULL,&(pCommStruct->hCommReadSem),0L,FALSE);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_SEMAPHOREFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_OPEN;
- return COMM_ERROR_SEMAPHOREFAILED;
- }
-
- //
- // Initialize the DCB structure
- //
-
- ulRC=CommGetDCBInfo(*phCommPort);
- if (ulRC)
- return COMM_ERROR_DCBINFOFAILED;
- pCommStruct->DCBOriginal=pCommStruct->DCBInfo;
-
- //
- // Initialize other parameters
- //
-
- ulParmLength=sizeof(LINECONTROL);
- ulRC=DosDevIOCtl(pCommStruct->hCommPortFile,
- IOCTL_ASYNC,ASYNC_GETLINECTRL,
- NULL,0L,NULL,
- &COMParams,ulParmLength,&ulParmLength);
- pCommStruct->usDataBits = COMParams.bDataBits;
- pCommStruct->usParity = COMParams.bParity;
- pCommStruct->usStopBits = COMParams.bStopBits;
- pCommStruct->usTxBreak = COMParams.fTransBreak;
- if (ulRC)
- return COMM_ERROR_BAUDFAILED;
-
- ulParmLength=sizeof(short);
- ulRC=DosDevIOCtl(pCommStruct->hCommPortFile,
- IOCTL_ASYNC,ASYNC_GETBAUDRATE,
- NULL,0L,NULL,
- &(pCommStruct->usBaudRate),ulParmLength,&ulParmLength);
- if (ulRC)
- return COMM_ERROR_BAUDFAILED;
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommInit
- *
- * This routine initializes a serial comm port by calling the
- * DosDevIOCtl routine with the proper parameters.
- *------------------------------------------------------------------------*/
-
- ULONG CommInit(HCOMMPORT hCommPort,USHORT usBaudRate,
- USHORT usParity,USHORT usDataBits,
- USHORT usStopBits,USHORT usTxBreak)
- {
- USHORT
- usErrorCode;
-
- ULONG
- ulParmLength,
- ulDataLength,
- ulRC;
-
- LINECONTROL
- COMParams;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- //
- // Set the baud rate
- //
-
- pCommStruct=CommGetStruct(hCommPort);
- ulParmLength=sizeof(short);
- ulRC=DosDevIOCtl(pCommStruct->hCommPortFile,
- IOCTL_ASYNC,ASYNC_SETBAUDRATE,
- &usBaudRate,ulParmLength,&ulParmLength,
- NULL,0L,NULL);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_BAUDFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_SETBAUD;
- return COMM_ERROR_BAUDFAILED;
- }
-
- //
- // Set the number of bits, parity, stop bits, and Transmit break
- //
-
- COMParams.bDataBits =(UCHAR)usDataBits; // Set data bits
- COMParams.bParity =(UCHAR)usParity; // Set parity
- COMParams.bStopBits =(UCHAR)usStopBits; // Set stop bits
- COMParams.fTransBreak=(UCHAR)usTxBreak; // Set Transmit break
- ulParmLength=sizeof(LINECONTROL);
-
- ulRC=DosDevIOCtl(pCommStruct->hCommPortFile,
- IOCTL_ASYNC,ASYNC_SETLINECTRL,
- &COMParams,ulParmLength,&ulParmLength,
- NULL,0L,NULL);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_LINECNTRLFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_SETLINECNTRL;
- return COMM_ERROR_LINECNTRLFAILED;
- }
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommClear
- *
- * This routine clears both the transmit and receive buffers for the
- * com port
- *------------------------------------------------------------------------*/
-
- ULONG CommClear(HCOMMPORT hCommPort)
- {
- ULONG
- ulRC;
-
- ulRC=CommClearTxBuffer(hCommPort);
- if (!ulRC)
- ulRC=CommClearRxBuffer(hCommPort);
-
- return ulRC;
- }
-
- /*------------------------------------------------------------------------*
- * CommClearTxBuffer
- *
- * This routine clears the transmit buffer for the com port
- *------------------------------------------------------------------------*/
-
- ULONG CommClearTxBuffer(HCOMMPORT hCommPort)
- {
- UCHAR
- ucZero;
-
- ULONG
- ulRC,
- ulParmLength;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- ucZero=0;
- ulParmLength=sizeof(UCHAR);
- pCommStruct=CommGetStruct(hCommPort);
-
- ulRC=DosDevIOCtl(pCommStruct->hCommPortFile,
- IOCTL_GENERAL,DEV_FLUSHOUTPUT,
- &ucZero,ulParmLength,&ulParmLength,
- NULL,0L,NULL);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_CLEARBUFFERFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_CLEARTXBUFFER;
- return COMM_ERROR_CLEARBUFFERFAILED;
- }
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommClearRxBuffer
- *
- * This routine clears receive buffer for the com port
- *------------------------------------------------------------------------*/
-
- ULONG CommClearRxBuffer(HCOMMPORT hCommPort)
- {
- UCHAR
- ucZero;
-
- ULONG
- ulRC,
- ulParmLength;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- ucZero=0;
- ulParmLength=sizeof(UCHAR);
- pCommStruct=CommGetStruct(hCommPort);
-
- ulRC=DosDevIOCtl(pCommStruct->hCommPortFile,
- IOCTL_GENERAL,DEV_FLUSHINPUT,
- &ucZero,ulParmLength,&ulParmLength,
- NULL,0L,NULL);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_CLEARBUFFERFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_CLEARRXBUFFER;
- return COMM_ERROR_CLEARBUFFERFAILED;
- }
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommClose
- *
- * This routine invokes DosClose to close a serial comm port.
- *------------------------------------------------------------------------*/
-
- ULONG CommClose(HCOMMPORT hCommPort)
- {
- ULONG
- ulDCBSize;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=CommGetStruct(hCommPort);
-
- if (pCommStruct == NULL)
- return COMM_ERROR_PORTNOTFOUND; // Unable to locate comm port
-
- if (pCommStruct->fPortOpen)
- {
-
- //
- // Restore port to original condition
- //
-
- ulDCBSize=sizeof(DCBINFO);
- DosDevIOCtl(pCommStruct->hCommPortFile,
- IOCTL_ASYNC,ASYNC_SETDCBINFO,
- &(pCommStruct->DCBOriginal),ulDCBSize,&ulDCBSize,
- NULL,0L,NULL);
- CommInit(hCommPort,pCommStruct->usBaudRate,
- pCommStruct->usParity,pCommStruct->usDataBits,
- pCommStruct->usStopBits,pCommStruct->usTxBreak);
- DosClose(pCommStruct->hCommPortFile);
- }
- DosCloseMutexSem(pCommStruct->hCommReadSem);
- DosCloseMutexSem(pCommStruct->hCommWriteSem);
-
- pCommStruct->ulCommErrorCode = COMM_ERROR_NOERROR;
- pCommStruct->ulDosErrorCode = NO_ERROR;
- pCommStruct->ulCommMode = COMM_MODE_NOTSTARTED;
- pCommStruct->fPortOpen = FALSE;
- pCommStruct->fPortOpened = FALSE;
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommWrite
- *
- * This routine invokes DosWrite to write the data to the serial comm
- * port.
- *------------------------------------------------------------------------*/
-
- ULONG CommWrite(HCOMMPORT hCommPort,UCHAR *pucDataArea,
- USHORT usDataAreaSize,ULONG *pulWritten)
- {
- ULONG
- ulRC;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=CommGetStruct(hCommPort);
- ulRC=DosRequestMutexSem(pCommStruct->hCommWriteSem,COMMOS2_RESOURCE_SEM_WAIT);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_SEMAPHOREFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_WRITE;
- return COMM_ERROR_SEMAPHOREFAILED;
- }
-
- ulRC=(ULONG)DosWrite(pCommStruct->hCommPortFile,pucDataArea,
- (ULONG)usDataAreaSize,pulWritten);
-
- DosReleaseMutexSem(pCommStruct->hCommWriteSem);
-
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_WRITEFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_WRITE;
- return COMM_ERROR_WRITEFAILED;
- }
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommRead
- *
- * This routine invokes DosRead to read the data from the serial comm
- * port. This routine reads whatever data is currently available from
- * the port buffer. It does not wait for information to arrive.
- *------------------------------------------------------------------------*/
-
- ULONG CommRead(HCOMMPORT hCommPort,UCHAR *pucDataArea,
- USHORT usDataAreaSize,ULONG *pulRead)
- {
- ULONG
- ulRC;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=CommGetStruct(hCommPort);
- ulRC=DosRequestMutexSem(pCommStruct->hCommReadSem,COMMOS2_RESOURCE_SEM_WAIT);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_SEMAPHOREFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_READ;
- return COMM_ERROR_SEMAPHOREFAILED;
- }
-
- ulRC=(ULONG)DosRead(pCommStruct->hCommPortFile,pucDataArea,
- (ULONG)usDataAreaSize,pulRead);
-
- DosReleaseMutexSem(pCommStruct->hCommReadSem);
-
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_READFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_READ;
- return COMM_ERROR_WRITEFAILED;
- }
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommReadTimeOut
- *
- * This routine invokes DosRead and DosDevIOCtl to either read the
- * specified number of characters or to return once the timeout specified
- * has elapsed.
- *------------------------------------------------------------------------*/
-
- ULONG CommReadTimeOut(HCOMMPORT hCommPort,
- UCHAR *pucDataArea,USHORT usDataAreaSize,
- ULONG *pulRead,long lTimeOutmSec)
- {
- int
- fCheck,
- fKeepWaiting;
-
- ULONG
- ulStartTime,
- ulTimeOut,
- ulCharCount,
- ulSleepTime,
- ulReadRC,
- ulRC;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=CommGetStruct(hCommPort);
- ulRC=DosRequestMutexSem(pCommStruct->hCommReadSem,COMMOS2_RESOURCE_SEM_WAIT);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_SEMAPHOREFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_READTIMEOUT;
- return COMM_ERROR_SEMAPHOREFAILED;
- }
-
- ulStartTime=TimerValue();
- ulTimeOut=lTimeOutmSec/10L;
- ulSleepTime=1L;
- fKeepWaiting=TRUE;
- if (lTimeOutmSec == TIMEOUT_INDEFINITE)
- fCheck=FALSE;
- else
- fCheck=TRUE;
- ulReadRC=COMM_ERROR_NOERROR;
- do
- {
- ulRC=CommQueryQueue(hCommPort,COMM_QUERY_RXCOUNT,&ulCharCount);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_IOCTLFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_READTIMEOUT;
- DosReleaseMutexSem(pCommStruct->hCommReadSem);
- return COMM_ERROR_IOCTLFAILED;
- }
-
- if (ulCharCount >= usDataAreaSize)
- {
-
- //
- // The number of characters requested are available. Read the data
- // and return to the calling program.
- //
-
- fKeepWaiting=FALSE;
- ulReadRC=CommRead(hCommPort,pucDataArea,usDataAreaSize,pulRead);
- }
- else
- {
-
- //
- // The requested number of characters are not available at this
- // time. Test to see if the specified time has elapsed and return
- // to the calling program if it has.
- //
-
- if (fCheck && (TimerDifference(ulStartTime) > ulTimeOut))
- {
- fKeepWaiting=FALSE;
- (*pulRead)=0;
- pCommStruct->ulCommErrorCode = COMM_ERROR_TIMEOUTEXCEEDED;
- pCommStruct->ulDosErrorCode = NO_ERROR;
- pCommStruct->ulCommMode = COMM_MODE_READTIMEOUT;
- ulReadRC=COMM_ERROR_TIMEOUTEXCEEDED;
- }
- }
- if (fKeepWaiting)
- {
- DosSleep(ulSleepTime);
-
- //
- // If port is not responding, slowly increase sleep interval. Do
- // not exceed 256 (approximately 1/4 second).
- //
-
- if (ulSleepTime < 256L)
- ulSleepTime *= 2L;
- }
- } while (fKeepWaiting);
-
- DosReleaseMutexSem(pCommStruct->hCommReadSem);
- return ulReadRC;
- }
-
- /*------------------------------------------------------------------------*
- * CommReadUntilByte
- *
- * This routine invokes DosRead and DosDevIOCtl to either read either the
- * specified number of characters or to return once the character
- * specified has been read. The routine will also return if the timeout
- * specified has elapsed.
- *------------------------------------------------------------------------*/
-
- ULONG CommReadUntilByte(HCOMMPORT hCommPort,
- UCHAR *pucDataArea,USHORT usDataAreaSize,
- ULONG *pulRead,UCHAR ucWaitByte,long lTimeOutmSec)
- {
- USHORT
- usDataPosition;
-
- UCHAR
- ucNextChar;
-
- int
- fCheck,
- fKeepWaiting;
-
- ULONG
- ulStartTime,
- ulTimeOut,
- ulSleepTime,
- ulCharCount,
- ulReadRC,
- ulRC;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=CommGetStruct(hCommPort);
- ulRC=DosRequestMutexSem(pCommStruct->hCommReadSem,COMMOS2_RESOURCE_SEM_WAIT);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_SEMAPHOREFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_READUNTILBYTE;
- return COMM_ERROR_SEMAPHOREFAILED;
- }
-
- ulStartTime=TimerValue();
- ulTimeOut=lTimeOutmSec/10L;
- ulSleepTime=1L;
- fKeepWaiting=TRUE;
- if (lTimeOutmSec == TIMEOUT_INDEFINITE)
- fCheck=FALSE;
- else
- fCheck=TRUE;
- ulReadRC=COMM_ERROR_NOERROR;
- usDataPosition=0;
- (*pulRead)=0;
- do
- {
- ulRC=CommQueryQueue(hCommPort,COMM_QUERY_RXCOUNT,&ulCharCount);
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_IOCTLFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_READUNTILBYTE;
- DosReleaseMutexSem(pCommStruct->hCommReadSem);
- return COMM_ERROR_IOCTLFAILED;
- }
-
- if (ulCharCount > 0)
- {
-
- //
- // Some characters are available. Read them one by one checking
- // to see if the termination character is present or the maximum
- // number of characters have been read.
- //
-
- do
- {
- ulReadRC=CommRead(hCommPort,&ucNextChar,1,pulRead);
- if (ulReadRC)
- fKeepWaiting=FALSE;
- if (fKeepWaiting)
- {
- pucDataArea[usDataPosition]=ucNextChar;
- usDataPosition++;
- ulCharCount--;
- if (ucNextChar == ucWaitByte)
- fKeepWaiting=FALSE;
- if (usDataPosition >= usDataAreaSize)
- fKeepWaiting=FALSE;
- }
- } while (fKeepWaiting && (ulCharCount > 0));
- (*pulRead)=(ULONG)usDataPosition;
- }
- else
- {
-
- //
- // The requested number of characters are not available at this
- // time. Test to see if the specified time has elapsed and return
- // to the calling program if it has.
- //
-
- if (fCheck && (TimerDifference(ulStartTime) > ulTimeOut))
- {
- fKeepWaiting=FALSE;
- pCommStruct->ulCommErrorCode = COMM_ERROR_TIMEOUTEXCEEDED;
- pCommStruct->ulDosErrorCode = NO_ERROR;
- pCommStruct->ulCommMode = COMM_MODE_READUNTILBYTE;
- ulReadRC=COMM_ERROR_TIMEOUTEXCEEDED;
- }
- }
- if (fKeepWaiting)
- {
- DosSleep(ulSleepTime);
-
- //
- // If port is not responding, slowly increase sleep interval. Do
- // not exceed 256 (approximately 1/4 second).
- //
-
- if (ulSleepTime < 256L)
- ulSleepTime *= 2L;
- }
- } while (fKeepWaiting);
-
- DosReleaseMutexSem(pCommStruct->hCommReadSem);
- return ulReadRC;
- }
-
- /*------------------------------------------------------------------------*
- * TimerValue
- *
- * This routine returns a timer value in hundredths of seconds. This
- * routine does not return a value which can be used for the current time,
- * but it does return a value useful for use as a timer. If the value
- * returned is less than a previous value, you should add 8,640,000 which
- * is equivalent to one day in hundredths of seconds.
- *------------------------------------------------------------------------*/
-
- static ULONG TimerValue()
- {
- DATETIME
- CurrentTime;
-
- DosGetDateTime(&CurrentTime);
-
- return 360000L*(ULONG)CurrentTime.hours+
- 6000L*(ULONG)CurrentTime.minutes+
- 100L*(ULONG)CurrentTime.seconds+
- (ULONG)CurrentTime.hundredths;
- }
-
- /*------------------------------------------------------------------------*
- * TimerDifference
- *
- * This routine uses a base value obtained from TimerValue and calls
- * TimerValue itself to return the difference in hundreths of seconds.
- *------------------------------------------------------------------------*/
-
- static ULONG TimerDifference(ULONG ulBaseTimerValue)
- {
- ULONG
- ulCurrentTime;
-
- ulCurrentTime=TimerValue();
- if (ulCurrentTime < ulBaseTimerValue)
- ulCurrentTime += 8640000L;
-
- return ulCurrentTime-ulBaseTimerValue;
- }
-
- /*------------------------------------------------------------------------*
- * CommGetStruct
- *
- * This is an internal routine which returns the address of the error
- * structure for the requested comm port.
- *------------------------------------------------------------------------*/
-
- static PCOMMOS2_STRUCT CommGetStruct(HCOMMPORT hCommPort)
- {
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=NULL;
- if (pCommOS2Struct[hCommPort].fPortOpened)
- pCommStruct=&pCommOS2Struct[hCommPort];
-
- return pCommStruct;
- }
-
- /*------------------------------------------------------------------------*
- * CommQueryQueue
- *
- * This routine queries the values of count and size for both the
- * receive and transmit buffers.
- *------------------------------------------------------------------------*/
-
- static ULONG CommQueryQueue(HCOMMPORT hCommPort,short sMode,ULONG *ulValue)
- {
- RXQUEUE
- RxQueue;
-
- ULONG
- ulRC,
- ulRxQueue,
- ulFunction;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- switch (sMode)
- {
- case COMM_QUERY_RXCOUNT: // Query Rx character count
- case COMM_QUERY_RXBUFFER: // Query Rx buffer size
- ulFunction=ASYNC_GETINQUECOUNT;
- break;
-
- case COMM_QUERY_TXCOUNT: // Query Tx character count
- case COMM_QUERY_TXBUFFER: // Query Tx buffer size
- ulFunction=ASYNC_GETOUTQUECOUNT;
- break;
- }
-
- pCommStruct=CommGetStruct(hCommPort);
- ulRxQueue=sizeof(RXQUEUE);
- (*ulValue)=0;
- ulRC=DosDevIOCtl(pCommStruct->hCommPortFile,
- IOCTL_ASYNC,ulFunction,
- NULL,0L,NULL,
- &RxQueue,ulRxQueue,&ulRxQueue);
-
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_IOCTLFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- return COMM_ERROR_IOCTLFAILED;
- }
-
- switch (sMode)
- {
- case COMM_QUERY_RXCOUNT: // Return Rx buffer count
- case COMM_QUERY_TXCOUNT: // Return Tx buffer count
- (*ulValue)=RxQueue.cch;
- break;
-
- case COMM_QUERY_RXBUFFER: // Return Rx buffer size
- case COMM_QUERY_TXBUFFER: // Return Tx buffer size
- (*ulValue)=RxQueue.cb;
- break;
- }
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommQueryRxCount
- *
- * This routine returns the number of characters in the receiver buffer.
- *------------------------------------------------------------------------*/
-
- ULONG CommQueryRxCount(HCOMMPORT hCommPort,ULONG *ulCount)
- {
- ULONG
- ulRC;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- ulRC=CommQueryQueue(hCommPort,COMM_QUERY_RXCOUNT,ulCount);
- if (ulRC)
- {
- pCommStruct=CommGetStruct(hCommPort);
- pCommStruct->ulCommMode = COMM_MODE_QUERYRXCOUNT;
- }
-
- return ulRC;
- }
-
- /*------------------------------------------------------------------------*
- * CommQueryRxBufSize
- *
- * This routine returns the size of the receiver buffer.
- *------------------------------------------------------------------------*/
-
- ULONG CommQueryRxBufSize(HCOMMPORT hCommPort,ULONG *ulSize)
- {
- ULONG
- ulRC;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- ulRC=CommQueryQueue(hCommPort,COMM_QUERY_RXBUFFER,ulSize);
- if (ulRC)
- {
- pCommStruct=CommGetStruct(hCommPort);
- pCommStruct->ulCommMode = COMM_MODE_QUERYRXBUFSIZE;
- }
-
- return ulRC;
- }
-
- /*------------------------------------------------------------------------*
- * CommQueryTxCount
- *
- * This routine returns the number of characters in the transmit buffer.
- *------------------------------------------------------------------------*/
-
- ULONG CommQueryTxCount(HCOMMPORT hCommPort,ULONG *ulCount)
- {
- ULONG
- ulRC;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- ulRC=CommQueryQueue(hCommPort,COMM_QUERY_TXCOUNT,ulCount);
- if (ulRC)
- {
- pCommStruct=CommGetStruct(hCommPort);
- pCommStruct->ulCommMode = COMM_MODE_QUERYTXCOUNT;
- }
-
- return ulRC;
- }
-
- /*------------------------------------------------------------------------*
- * CommQueryTxBufSize
- *
- * This routine returns the size of the transmit buffer.
- *------------------------------------------------------------------------*/
-
- ULONG CommQueryTxBufSize(HCOMMPORT hCommPort,ULONG *ulSize)
- {
- ULONG
- ulRC;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- ulRC=CommQueryQueue(hCommPort,COMM_QUERY_TXBUFFER,ulSize);
- if (ulRC)
- {
- pCommStruct=CommGetStruct(hCommPort);
- pCommStruct->ulCommMode = COMM_MODE_QUERYTXBUFSIZE;
- }
-
- return ulRC;
- }
-
- /*------------------------------------------------------------------------*
- * CommGetDCBInfo
- *
- * This routine gets the DCB information for the comm port.
- *------------------------------------------------------------------------*/
-
- ULONG CommGetDCBInfo(HCOMMPORT hCommPort)
- {
- ULONG
- ulRC,
- ulDCBSize;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=CommGetStruct(hCommPort);
- ulDCBSize=sizeof(DCBINFO);
- ulRC=DosDevIOCtl(pCommStruct->hCommPortFile,
- IOCTL_ASYNC,ASYNC_GETDCBINFO,
- NULL,0L,NULL,
- &(pCommStruct->DCBInfo),ulDCBSize,&ulDCBSize);
-
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_DCBINFOFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_GETDCBINFO;
- return COMM_ERROR_DCBINFOFAILED;
- }
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommSetDCBInfo
- *
- * This routine sets the DCB information for the comm port.
- *------------------------------------------------------------------------*/
-
- ULONG CommSetDCBInfo(HCOMMPORT hCommPort)
- {
- ULONG
- ulRC,
- ulDCBSize;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=CommGetStruct(hCommPort);
- ulDCBSize=sizeof(DCBINFO);
- ulRC=DosDevIOCtl(pCommStruct->hCommPortFile,
- IOCTL_ASYNC,ASYNC_SETDCBINFO,
- &(pCommStruct->DCBInfo),ulDCBSize,&ulDCBSize,
- NULL,0L,NULL);
-
- if (ulRC)
- {
- pCommStruct->ulCommErrorCode = COMM_ERROR_DCBINFOFAILED;
- pCommStruct->ulDosErrorCode = ulRC;
- pCommStruct->ulCommMode = COMM_MODE_SETDCBINFO;
- return COMM_ERROR_DCBINFOFAILED;
- }
-
- return COMM_ERROR_NOERROR;
- }
-
- /*------------------------------------------------------------------------*
- * CommSetReadTimeOut
- *
- * This routine sets the read timeout for the comm port.
- *------------------------------------------------------------------------*/
-
- ULONG CommSetReadTimeOut(HCOMMPORT hCommPort,ULONG ulTimeMsec)
- {
- USHORT
- usTimeOut;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=CommGetStruct(hCommPort);
-
- if (ulTimeMsec == TIMEOUT_INDEFINITE) // Make wait as large as possible!
- ulTimeMsec=64000;
-
- if (ulTimeMsec > 64000)
- ulTimeMsec=64000;
- usTimeOut=(USHORT)ulTimeMsec/10;
- pCommStruct->DCBInfo.usReadTimeout = usTimeOut;
-
- //
- // Clear MODE_NOWAIT_READ_TIMEOUT bits and then
- // set MODE_WAIT_READ_TIMEOUT bits
- //
-
- pCommStruct->DCBInfo.fbTimeout &= (~(BYTE)(MODE_NOWAIT_READ_TIMEOUT));
- pCommStruct->DCBInfo.fbTimeout |= MODE_WAIT_READ_TIMEOUT;
-
- return CommSetDCBInfo(hCommPort);
- }
-
- /*------------------------------------------------------------------------*
- * CommSetWriteTimeOut
- *
- * This routine sets the write timeout for the comm port.
- *------------------------------------------------------------------------*/
-
- ULONG CommSetWriteTimeOut(HCOMMPORT hCommPort,ULONG ulTimeMsec)
- {
- USHORT
- usTimeOut;
-
- PCOMMOS2_STRUCT
- pCommStruct;
-
- pCommStruct=CommGetStruct(hCommPort);
- if (ulTimeMsec == TIMEOUT_INDEFINITE)
- {
- pCommStruct->DCBInfo.usWriteTimeout = 0;
-
- //
- // Set MODE_NO_WRITE_TIMEOUT bit
- //
-
- pCommStruct->DCBInfo.fbTimeout |= MODE_NO_WRITE_TIMEOUT;
- }
- else
- {
- if (ulTimeMsec > 64000)
- ulTimeMsec=64000;
- usTimeOut=(USHORT)ulTimeMsec/10;
- pCommStruct->DCBInfo.usWriteTimeout = usTimeOut;
-
- //
- // Clear MODE_NO_WRITE_TIMEOUT bit
- //
-
- pCommStruct->DCBInfo.fbTimeout &= (~(BYTE)(MODE_NO_WRITE_TIMEOUT));
- }
- return CommSetDCBInfo(hCommPort);
- }
-
-
-