home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
comos2.zip
/
COMM16.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-21
|
30KB
|
1,158 lines
/**************************************************************************
*
* COMM16.C
*
* This file contains the 16-bit routines which provide the basic
* serial support.
*
* This file was compiled with the MicroSoft C6.00AX compiler using the
* following flags:
*
* To produce a multi-thread version of the library
* /MT /W3 /Alfu /Gt64 /G2s /FPi87 /c
*
* To produce a single-thread version of the library
* /W3 /Alfu /Gt64 /G2s /FPi87 /c
*_________________________________________________________________________
*
* Copyright (c) 1992 by ASH Software, Inc.
*
* Update History
*
* 11/28/1992 - Module created
*
**************************************************************************/
#define INCL_COMMOS2_16BIT
#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;
hCommSem.cb = sizeof(DOSFSRSEM);
hCommSem.pid = 0;
hCommSem.tid = 0;
hCommSem.cUsage = 0;
hCommSem.client = 0;
hCommSem.sem = 0;
ulRC=(ULONG)DosFSRamSemRequest(&hCommSem,COMMOS2_RESOURCE_SEM_WAIT);
if (ulRC)
return COMM_ERROR_SEMAPHOREFAILED;
if (iMaxNumberCommPorts > 0)
iLoop=FALSE;
else
iMaxNumberCommPorts = iCommPorts;
if (!iLoop)
{
DosFSRamSemClear(&hCommSem);
return COMM_ERROR_ALREADYINITIALIZED; // System already initialized
}
pCommOS2Struct=malloc(iCommPorts*sizeof(COMMOS2_STRUCT));
if (pCommOS2Struct == NULL)
{
DosFSRamSemClear(&hCommSem);
return COMM_ERROR_SYSINITFAILED; // Unable to allocate resources
}
//
// 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;
pCommStruct->hCommWriteSem.cb = sizeof(DOSFSRSEM);
pCommStruct->hCommWriteSem.pid = 0;
pCommStruct->hCommWriteSem.tid = 0;
pCommStruct->hCommWriteSem.cUsage = 0;
pCommStruct->hCommWriteSem.client = 0;
pCommStruct->hCommWriteSem.sem = 0;
pCommStruct->hCommReadSem.cb = sizeof(DOSFSRSEM);
pCommStruct->hCommReadSem.pid = 0;
pCommStruct->hCommReadSem.tid = 0;
pCommStruct->hCommReadSem.cUsage = 0;
pCommStruct->hCommReadSem.client = 0;
pCommStruct->hCommReadSem.sem = 0;
}
DosFSRamSemClear(&hCommSem);
return COMM_ERROR_NOERROR;
}
/*------------------------------------------------------------------------*
* CommStopSystem
*
* This system frees the resources used when initializing the comm
* library and closes any open ports. This should be called when the
* comm library is no longer needed or during program termination.
*------------------------------------------------------------------------*/
ULONG CommStopSystem(void)
{
int
iLoop;
if (pCommOS2Struct != NULL)
{
for (iLoop=0; iLoop<iMaxNumberCommPorts; iLoop++)
CommClose(iLoop);
free(pCommOS2Struct);
}
iMaxNumberCommPorts = 0;
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;
USHORT
usAction;
ULONG
ulRC;
char
cPortName[21];
PCOMMOS2_STRUCT
pCommStruct;
LINECONTROL
COMParams;
//
// Find an empty location in the static structure.
// Use a Fast Safe Ram semaphore to serialize access.
//
ulRC=(ULONG)DosFSRamSemRequest(&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;
}
}
DosFSRamSemClear(&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),&usAction,0L,
FILE_NORMAL,FILE_OPEN,
OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
0L);
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 the DCB structure
//
ulRC=CommGetDCBInfo(*phCommPort);
if (ulRC)
return COMM_ERROR_DCBINFOFAILED;
pCommStruct->DCBOriginal=pCommStruct->DCBInfo;
//
// Initialize other parameters
//
ulRC=(ULONG)DosDevIOCtl(&COMParams,NULL,
ASYNC_GETLINECTRL,IOCTL_ASYNC,pCommStruct->hCommPortFile);
pCommStruct->usDataBits = COMParams.bDataBits;
pCommStruct->usParity = COMParams.bParity;
pCommStruct->usStopBits = COMParams.bStopBits;
pCommStruct->usTxBreak = COMParams.fTransBreak;
if (ulRC)
return COMM_ERROR_BAUDFAILED;
ulRC=(ULONG)DosDevIOCtl(&(pCommStruct->usBaudRate),NULL,
ASYNC_GETBAUDRATE,IOCTL_ASYNC,pCommStruct->hCommPortFile);
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)
{
ULONG
ulParmLength,
ulRC;
LINECONTROL
COMParams;
PCOMMOS2_STRUCT
pCommStruct;
//
// Set the baud rate
//
pCommStruct=CommGetStruct(hCommPort);
ulRC=(ULONG)DosDevIOCtl(NULL,&usBaudRate,
ASYNC_SETBAUDRATE,IOCTL_ASYNC,pCommStruct->hCommPortFile);
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=(ULONG)DosDevIOCtl(NULL,&COMParams,
ASYNC_SETLINECTRL,IOCTL_ASYNC,pCommStruct->hCommPortFile);
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;
PCOMMOS2_STRUCT
pCommStruct;
ucZero=0;
pCommStruct=CommGetStruct(hCommPort);
ulRC=(ULONG)DosDevIOCtl(NULL,&ucZero,
DEV_FLUSHOUTPUT,IOCTL_GENERAL,pCommStruct->hCommPortFile);
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;
PCOMMOS2_STRUCT
pCommStruct;
ucZero=0;
pCommStruct=CommGetStruct(hCommPort);
ulRC=(ULONG)DosDevIOCtl(NULL,&ucZero,
DEV_FLUSHINPUT,IOCTL_GENERAL,pCommStruct->hCommPortFile);
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)
{
ulDCBSize=sizeof(DCBINFO);
DosDevIOCtl(NULL,&(pCommStruct->DCBOriginal),ASYNC_SETDCBINFO,
IOCTL_ASYNC,pCommStruct->hCommPortFile);
CommInit(hCommPort,pCommStruct->usBaudRate,
pCommStruct->usParity,pCommStruct->usDataBits,
pCommStruct->usStopBits,pCommStruct->usTxBreak);
DosClose(pCommStruct->hCommPortFile);
}
pCommStruct->ulCommErrorCode = COMM_ERROR_NOERROR;
pCommStruct->ulDosErrorCode = NO_ERROR;
pCommStruct->hCommPortFile = 0;
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)
{
USHORT
usWritten;
ULONG
ulRC;
PCOMMOS2_STRUCT
pCommStruct;
pCommStruct=CommGetStruct(hCommPort);
ulRC=(ULONG)DosFSRamSemRequest(&(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,
usDataAreaSize,&usWritten);
(*pulWritten)=(ULONG)usWritten;
DosFSRamSemClear(&(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)
{
USHORT
usRead;
ULONG
ulRC;
PCOMMOS2_STRUCT
pCommStruct;
pCommStruct=CommGetStruct(hCommPort);
ulRC=(ULONG)DosFSRamSemRequest(&(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,
usDataAreaSize,&usRead);
(*pulRead)=(ULONG)usRead;
DosFSRamSemClear(&(pCommStruct->hCommReadSem));
if (ulRC)
{
pCommStruct->ulCommErrorCode = COMM_ERROR_READFAILED;
pCommStruct->ulDosErrorCode = ulRC;
pCommStruct->ulCommMode = COMM_MODE_READ;
return COMM_ERROR_READFAILED;
}
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,
ulSleepTime,
ulCharCount,
ulReadRC,
ulRC;
PCOMMOS2_STRUCT
pCommStruct;
pCommStruct=CommGetStruct(hCommPort);
ulRC=(ULONG)DosFSRamSemRequest(&(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;
DosFSRamSemClear(&(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);
DosFSRamSemClear(&(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,
ulRead,
ulReadRC,
ulCharCount,
ulRC;
PCOMMOS2_STRUCT
pCommStruct;
pCommStruct=CommGetStruct(hCommPort);
ulRC=(ULONG)DosFSRamSemRequest(&(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;
DosFSRamSemClear(&(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,&ulRead);
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);
DosFSRamSemClear(&(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)
{
USHORT
usFunction;
RXQUEUE
RxQueue;
ULONG
ulRC,
ulRxQueue;
PCOMMOS2_STRUCT
pCommStruct;
switch (sMode)
{
case COMM_QUERY_RXCOUNT: // Query Rx character count
case COMM_QUERY_RXBUFFER: // Query Rx buffer size
usFunction=ASYNC_GETINQUECOUNT;
break;
case COMM_QUERY_TXCOUNT: // Query Tx character count
case COMM_QUERY_TXBUFFER: // Query Tx buffer size
usFunction=ASYNC_GETOUTQUECOUNT;
break;
}
pCommStruct=CommGetStruct(hCommPort);
ulRxQueue=sizeof(RXQUEUE);
(*ulValue)=0;
ulRC=(ULONG)DosDevIOCtl(&RxQueue,NULL,
usFunction,IOCTL_ASYNC,pCommStruct->hCommPortFile);
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=(ULONG)DosDevIOCtl(&(pCommStruct->DCBInfo),NULL,
ASYNC_GETDCBINFO,IOCTL_ASYNC,pCommStruct->hCommPortFile);
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=(ULONG)DosDevIOCtl(NULL,&(pCommStruct->DCBInfo),
ASYNC_SETDCBINFO,IOCTL_ASYNC,pCommStruct->hCommPortFile);
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);
}