home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
comos2.zip
/
COMM32.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-21
|
30KB
|
1,184 lines
/**************************************************************************
*
* 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);
}