Hello,

VS 2003.NET
WinXP SP2

I've got a C console application that sends and receives data through my
PC's COM port 1. When I use just ReadFile and WriteFile everything works
fine. However, I need to be able to check if there is really any data
available before I read it, so it seemed that PeekNamedPipe would be the
appropriate approach. However it always indicates that there are many
characters available. I know it's probably something simple. Here's how
what I think are the important parts of the code look. Nothing is actually
coming into the COM port and all my program does is check it:

HANDLE InitSerialPort(const char *comPort, int baudRate);

HANDLE hComm;

int main(void)
{
char inCh;
DWORD dwRead;
DWORD dwBytesRead;
DWORD dwTotalBytesAvail;
DWORD dwBytesLeftThisMessage;

InitSerialPort("COM1", CBR_115200);

for (;;)
PeekNamedPipe(hComm, &inCh, (DWORD)1, &dwBytesRead,
&dwTotalBytesAvail, &dwBytesLeftThisMessage);

return 0;
}


HANDLE InitSerialPort(const char *comPort, int baudRate)
{
COMMTIMEOUTS comTimeOut;
DCB dcb = {0};

// Open the com port
hComm = CreateFile(comPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hComm == INVALID_HANDLE_VALUE)
{
DWORD errorCode = GetLastError();
printf("SYSTEM ERROR code 0x%x opening PC %s\r\n", errorCode, comPort);
exit(EXIT_FAILURE);
}

comTimeOut.ReadIntervalTimeout = MAXDWORD;
comTimeOut.ReadTotalTimeoutMultiplier = 0;
comTimeOut.ReadTotalTimeoutConstant = 0;
comTimeOut.WriteTotalTimeoutMultiplier = 0;
comTimeOut.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &comTimeOut);

dcb.DCBlength = sizeof(dcb);
GetCommState(hComm, &dcb);
dcb.BaudRate = (DWORD)baudRate;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.fParity = 0;
dcb.Parity = NOPARITY;
dcb.fBinary = 1;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
SetCommState(hComm, &dcb);

return hComm;
}

Thanks,
Ray
Post by Ray Mitchell
I've got a C console application that sends and receives data through
my PC's COM port 1. When I use just ReadFile and WriteFile
everything works fine. However, I need to be able to check if there
is really any data available before I read it
See SetCommTimeouts. You can configure it so ReadFile returns
immediately even if no bytes are available.
Post by Ray Mitchell
so it seemed that
PeekNamedPipe would be the appropriate approach.
You don't have a handle to a named pipe, so what makes you think
PeekNamedPipe is going to work?
Post by Ray Mitchell
However it always
indicates that there are many characters available.
Check the return value. It simply fails, and you take garbage that is
still stored in dwTotalBytesAvail to mean something.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Post by Igor Tandetnik
Post by Ray Mitchell
I've got a C console application that sends and receives data through
my PC's COM port 1. When I use just ReadFile and WriteFile
everything works fine. However, I need to be able to check if there
is really any data available before I read it
See SetCommTimeouts. You can configure it so ReadFile returns
immediately even if no bytes are available.
Post by Ray Mitchell
so it seemed that
PeekNamedPipe would be the appropriate approach.
You don't have a handle to a named pipe, so what makes you think
PeekNamedPipe is going to work?
Post by Ray Mitchell
However it always
indicates that there are many characters available.
Check the return value. It simply fails, and you take garbage that is
still stored in dwTotalBytesAvail to mean something.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Okay, maybe I should rephrase my question. I would like to be able to know
when a new character is available for reading, but I don't want there to be
any chance that it will actually be removed from the input buffer until I
actually want to read it. What is the correct way to accomplish this? In a
C console program I would merely do a kbhit to see if a keyboard character
had been struck, then do a getch if I really wanted to read that character
and remove it from input. How do I do the same thing with a serial port? At
present I have implemented an internal "pushback" scheme similar to ungetc,
but I had hoped I could actually detect character availability without
removing the character and resorting to this level of complexity.

Thanks
Post by Ray Mitchell
Okay, maybe I should rephrase my question. I would like to be able
to know when a new character is available for reading, but I don't
want there to be any chance that it will actually be removed from the
input buffer until I actually want to read it.
What do you mean, removed? If you don't read it, where do you think it's
going to disappear to? I'm not sure I understand your question.

See WaitCommEvent, or use ReadFile in overlapped mode. For an exhaustive
treatment of serial I/O, see MTTTY sample:

http://msdn.microsoft.com/library/en-us/dnfiles/html/msdn_serial.asp
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Post by Igor Tandetnik
Post by Ray Mitchell
Okay, maybe I should rephrase my question. I would like to be able
to know when a new character is available for reading, but I don't
want there to be any chance that it will actually be removed from the
input buffer until I actually want to read it.
What do you mean, removed? If you don't read it, where do you think it's
going to disappear to? I'm not sure I understand your question.
See WaitCommEvent, or use ReadFile in overlapped mode. For an exhaustive
http://msdn.microsoft.com/library/en-us/dnfiles/html/msdn_serial.asp
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Hi Igor,

I guess this is so simple it's difficult. I don't want to use overlaps,
threads, or events - just a simple non-blocking polled algorithm. I would
simply like to know if a character is available for reading in the receive
buffer associated with a COMM port without having to actually read that
character or rely on an event. I'm sure that at a low level the OS (or maybe
the hardware) maintains an interrupt-driven FIFO to buffer the input. This
FIFO is probably implemented with an array and two pointers, where one
pointer points to the oldest unread character and the other points to where
the next character will be placed. If these pointers are equal, the buffer
is empty. If not, the number of characters in the buffer can be determined
by simply subtracting these pointers (allowing for array wrap). At least,
when I design hardware and low-level UART routines that's the way I do it.
It then becomes trivial to merely poll these two pointers (or a "FIFO EMPTY"
flag associated with them) to find out the status of the read buffer. Then,
if desired, one or more characters can be read from the FIFO. Maybe there
are so many layers of abstraction in the Windows environment that this level
of simplicity is not possible - I don't know, but it sure seems like a simple
concept to me.

Thanks for your help,
Ray Mitchell
Post by Ray Mitchell
I guess this is so simple it's difficult. I don't want to use overlaps,
threads, or events - just a simple non-blocking polled algorithm. I would
simply like to know if a character is available for reading in the receive
buffer associated with a COMM port without having to actually read that
character or rely on an event.
ClearCommError returns the number of bytes in the receive buffer.
--
Scott McPhillips [VC++ MVP]
Post by Scott McPhillips [MVP]
Post by Ray Mitchell
I guess this is so simple it's difficult. I don't want to use overlaps,
threads, or events - just a simple non-blocking polled algorithm. I would
simply like to know if a character is available for reading in the receive
buffer associated with a COMM port without having to actually read that
character or rely on an event.
ClearCommError returns the number of bytes in the receive buffer.
--
Scott McPhillips [VC++ MVP]
Thanks Scott. That was just the type of simple information I was after!