0
votes

I am trying to read data written to a serial port created with com0com. The current configuration has two serial ports, namely COM8 and COM9 connected to each other.

When I open those two serial ports using PuTTY and write something in one terminal, it immediately appear in other terminal. However, when I try to do it programmatically, it's different story.

I can do writes without a problem, but read fails for some reasons. I use CSerial library by Tom Archer and Rick Leinecker.

The function for reading data is like below.

int CSerial::ReadData( void *buffer, int limit )
{
    if( !m_bOpened || m_hIDComDev == NULL ) 
        return( 0 );

    BOOL bReadStatus;
    DWORD dwBytesRead, dwErrorFlags;
    COMSTAT ComStat;

    SetCommMask (m_hIDComDev, 0);
    SetCommMask (m_hIDComDev, EV_RXCHAR);
    ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
    if( !ComStat.cbInQue ) return( 0 );

    dwBytesRead = (DWORD) ComStat.cbInQue;
    if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;

    bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
    if( !bReadStatus ){
        if (GetLastError() == ERROR_IO_PENDING ){
            WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
            cout<< "Read data" << endl;
            return( (int) dwBytesRead );
        }
        return( 0 );
    }
    return( (int) dwBytesRead );
}

I cannot read data from the serial port as program exits at this line:

if( !ComStat.cbInQue )
    return( 0 );

This is really strange as the serial buffer has data, yet cbInQue which tells whether data available for read operation or not is set to zero.

Is there a workaround for this scenario? Or is there any setting that should be changed in com0com?

FYI, I'm using Code::Blocks IDE with MinGW compiler on Windows 7 64 bit.

1
Don't you have the same issue as here? - Lol4t0
ClearCommError() etc. return a result - you are not checking them. Also, (debugging 101), what happens if you comment out that check - does the ReadFile() call do anything interesting? ? - Martin James
@Martin James Commenting out that cbInQue check does not do anything. I'll check ClearCommError result. - tharumax
@Lol4t0 I'll check. It seems similar. - tharumax

1 Answers

0
votes

Since cbInQue() is returning zero, it means there is no data yet available. You need to put your program to sleep until some data becomes available.

Something like this:

/**

  Check for data waiting to be read

  @return  the number of bytes waiting to be read

*/
int cSerial::ReadDataWaiting( void )
{

    if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );

    DWORD dwErrorFlags;
    COMSTAT ComStat;

    ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );

    return( (int) ComStat.cbInQue );

}
/**

  Blocking wait for an amount of data to be ready

  @param[in] len number of bytes required
  @param[in] msec number of milliseconds to wait

  @return 1 if data ready, 0 if timeout

  */
int cSerial::WaitForData( int len, int msec )
{
    int timeout = 0;
    while( ReadDataWaiting() < len )
    {
        if( timeout++ > msec ) {
            return 0;
        }
        Sleep(1);
    }
    return 1;
}