cjameston
cjameston

Reputation: 309

Wait on serial receive event and console input event in Windows API

I'm an intermediate C++ programmer, but I'm new to using Windows' API functions.

I'm trying to create a console program that will sit/sleep until either

  1. The user inputs something in the console and presses enter
  2. Serial data is received on a serial port that's already been opened

Searching around, it sounds like the way to do this in Windows is with Events, (which sound like they're the same basic idea as interrupts?)

I found documentation on the WaitCommEvent, and I've read about reading console input buffer events. I'm guessing the function to use is WaitForMultipleObjects, but what handles specifically do I send it so it will wait for both a serial RX event or a console standard input event?

UPDATE: Thanks for the response!

Currently I've just been using std::cin/cout to read from and write to the console. I looked over the Console API you mentioned and saw the GetStdHandle function which will give the CONIN$ handle you mentioned. Can I just send that CONIN$handle to the wait function instead of using CreateFile and manually using ReadFile/the Console API like you suggested?

For the Serial, I know how to open my serial handle as OVERLAPPED instead of as NONOVERLAPPED, but I'm not sure what you mean by

it is not usually too difficult to modify synchronous I/O code to use an asynchronous handle

Something like this?

uint32 read(HANDLE serialHandle, uint8* pBuffer, int32 bufferLenght)
{
  DWORD dwBytesRead;

  if (!ReadFile(SerialHandle, pBuffer, bufferLength, &dwBytesRead, NULL))
  { /*ERROR*/ }
  else
  {
    // Wait on some flag or variable until read is complete 
    // to make this call synchronous/NONOVERLAPPED ?
    return static_cast<uint32>(dwBytesRead);
  }    
}

What/where would that flag be to wait on until the read is complete?

Upvotes: 2

Views: 1141

Answers (1)

Harry Johnston
Harry Johnston

Reputation: 36308

From Low-Level Console Input Functions on MSDN:

A thread of an application's process can perform a wait operation to wait for input to be available in an input buffer. To initiate a wait operation, specify a handle to the input buffer in a call to any of the wait functions.

So you need to use a console handle, which you can obtain by calling CreateFile on CONIN$. You will also need to use the same handle, either with ReadFile or the console API, to read the console input; using runtime library functions is likely to mess you up due to buffering.

For the serial port, I believe you will need to use asynchronous I/O. The WaitCommEvent function (when provided with an asynchronous mode handle) accepts an OVERLAPPED structure containing a handle to a manual-reset event object. You would then use the same event handle in the call to WaitForMultipleObjects.

Unfortunately this is an all-or-nothing, so you have to open the COM handle in asynchronous mode and use asynchronous I/O exclusively. (Luckily, it is not usually too difficult to modify synchronous I/O code to use an asynchronous handle, although if there are a lot of I/O calls you might want to write a wrapper function to do the repetitive work of building the OVERLAPPED structure and waiting for the operation to complete.)

Upvotes: 4

Related Questions