Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bad communication when using Remote Desktop serial port

15 views
Skip to first unread message

Sander Verhagen

unread,
Sep 21, 2005, 7:09:21 AM9/21/05
to
Hi,


I have an application (MFC dialog based, multi-threaded) that services a
device on a serial port. This application works absolutely flawless when the
serial port is on the "same" computer.

Using Remote Desktop Connection of Windows I can log into computer B from
computer A while using computer A's serial ports as if it were computer B's
serial ports ("Serial ports" check box in "Local Resources" of my Remote
Desktop Connection). Thus: device on A, application on B.

When I use Remote Desktop as described the performance of the serial
communication with my application is awful. Bytes go missing, bytes are made
up that have never been sent.

I have another application; a simple command-line tool, that performs
similar functions, and that performs just fine. The only real difference is
that this little tool does not use overlaying, in contrast to my actual
application, which does use that, basically so that I can use
MsgWaitForMultipleObjects.

Anyone this seen before? Experiences? I'll post some code, below, from the
actual application. Perhaps you'll be able to help me with this!

Thanks in advance! Regards,


Sander Verhagen
[ Verh...@nonono.Sander.com ]

------------------------------------------------------------

int CSerialCCR::Run()
{
// Set up overlapped I/O so that we
// can monitor both the port as well
// as window messages at the same time
memset(&m_overlapped,0,sizeof(m_overlapped));
m_overlapped.hEvent = CreateEvent(0,true,0,0);

// Some vars to be used later
BYTE cHeader;
unsigned long nRead;
DWORD dwEvtMask = 0;
MSG msg;
DWORD waitresult;

// Clear an existing COM event
SetCommMask(m_hCommFile, 0 );

while( true )
{
// Clear the corresponding overlapped event
ResetEvent( m_overlapped.hEvent );
nRead = 0;

// Cancel previous read operations
CancelIo( m_hCommFile );

// Tell the COM port that we are waiting for a data to read
ReadFile( m_hCommFile, &cHeader, 1, &nRead, &m_overlapped );

// Wait until monitoring senses either:
// - the COM event that we are waiting for (EV_RXCHAR)
// - a WM_QUIT message
// - some application specific window messages that we have defined
// - timeout
// (in this order of priority)
waitresult = MsgWaitForMultipleObjects(
1,
&m_overlapped.hEvent,
FALSE,
CalculateSleep(), // calculates how long to sleep (2~20s)
QS_POSTMESSAGE|QS_SENDMESSAGE );

// Now we go and check to see what ended the wait state

// See if it was a quit message that ended the wait
if( PeekMessage(
&msg,
NULL,
WM_QUIT,
WM_QUIT,
PM_REMOVE ) )
{
// Quit
// This is a 'normal' program termination,
// thus not one resulting from errors or such
return ExitInstance();
}

// See if actually something was read
else if( GetOverlappedResult(m_hCommFile, &m_overlapped, &nRead,
false )
{
// Handle communications
// Etcetera
}

------------------------------------------------------------

bool Connect()
{
CString comname;

// MUST BE this string to work above COM9!!!
comname.Format( TEXT("\\\\.\\COM%d"), m_com );
// Open COM port
m_hCommFile = CreateFile(
comname,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL );

if(m_hCommFile == INVALID_HANDLE_VALUE)
{
// Display error implied
return false;
}
else if(!SetupComm(m_hCommFile, 256, 256))
{
// Display error implied
CloseHandle( m_hCommFile );
m_hCommFile = INVALID_HANDLE_VALUE;
return false;
}
else
{
DCB DCBvar = {0};
DCBvar.DCBlength = sizeof(DCB);
DCBvar.BaudRate = m_baudrate;
DCBvar.fBinary = TRUE;
DCBvar.fDtrControl = DTR_CONTROL_DISABLE;
DCBvar.fRtsControl = RTS_CONTROL_DISABLE;
DCBvar.fAbortOnError = TRUE;
DCBvar.ByteSize = 8;
DCBvar.Parity = NOPARITY;
DCBvar.StopBits = ONESTOPBIT;

if(!SetCommState(m_hCommFile, &DCBvar))
{
// Display error implied
CloseHandle( m_hCommFile );
return false;
}
else
{
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;

// CBR_9600 is approximately 1byte/ms
// For our purposes, allow double the
// expected time per character
CommTimeOuts.WriteTotalTimeoutMultiplier = 2*CBR_9600/CBR_9600;
// 2 bytetimes !!
CommTimeOuts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(m_hCommFile, &CommTimeOuts);

PurgeComm(m_hCommFile, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR);

// Getting here means connected successfully

return true;
}
}
}

------------------------------------------------------------
Receive example:

ResetEvent( m_overlapped.hEvent );
if( ReadFile( m_hCommFile, buf, cLength+1, &nRead, &m_overlapped )==FALSE )
{
WaitForSingleObject(m_overlapped.hEvent,200);
GetOverlappedResult( m_hCommFile, &m_overlapped, &nRead2, false );
nRead += nRead2;
}


------------------------------------------------------------
Send example:

ResetEvent( m_overlapped.hEvent );
if( WriteFile( m_hCommFile, buf, data.GetFullLength()+3, &nWritten,
&m_overlapped )==FALSE )
{
WaitForSingleObject(m_overlapped.hEvent,200);
GetOverlappedResult( m_hCommFile, &m_overlapped, &nWritten2, true );
ResetEvent( m_overlapped.hEvent );

nWritten += nWritten2;

if( nWritten!=(unsigned)data.GetFullLength()+3 )
{
// Display write timeout error implied
return false;
}
}
else
{
// Display write error implied
return false;
}

------------------------------------------------------------


0 new messages