Reading data from a GPS port, or any other data from a port, is not exactly a simple matter.
You need to ensure that there is some data waiting and that the COM port is clear of any previous errors before trying to read. Then, if the read is successful then you need to ensure that the data is properly terminated and comprises a complete NMEA sentence. Sometimes you may gat the beginning of the next NMEA sentence, or even several back to back in one read, so you have to deal with that.
Let's leave all that for another day, and focus on the read itself.
The 4th parameter of ReadFile should be a pointer to a DWORD which will store the number of bytes actually read. You should be using this, to make sure you got some real data. You should also be checking the return value for errors.
Here is how I do it, after checking that there is actually some data waiting to be read.
/**
Read data from port
@param[in] buffer pointer to location to store data
@param[in] limit maximum number of bytes to read
@return 0 if error
*/
int cSerial::ReadData( void *buffer, int limit )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
BOOL bReadStatus;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat;
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 );
return( (int) dwBytesRead );
}
return( 0 );
}
return( (int) dwBytesRead );
}
It seems all very complicated, however everything in the above code is proved necessary. Without it, your app may run for a while, but at some time it will either hang or give you garbles. You can leave some of these checks out, but then you will have to spend many hours trying to debug what went wrong with your app - like I did when developing this code.