/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
// RealSerialComm.cpp: implementation of the CRealSerialComm class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RealSerialComm.h"
//#include "pn_const.h"
//#include "OSTConstants.h"
#include "Connection.h"
#ifdef _DEBUG
//static char sLogMsg[3000];
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
#define LogErrorText(err) { if (err > 0) GetErrorText(err); }
#define LogErrorText2(err) { if (err > 0) GetErrorText2(err); }
#else
#define LogErrorText(err) {}
#define LogErrorText2(err) {}
#endif
#ifdef _DEBUG
#define DUMPCOMSTAT(x) DumpComStat(x)
#define DUMPCOMSTATP(x) DumpComStatP(x)
#else
#define DUMPCOMSTAT(x)
#define DUMPCOMSTATP(x)
#endif
CRealSerialComm::CRealSerialComm()
{
#ifdef _DEBUG
if (gDoLogging)
{
FILE* f = fopen("c:\\tcf\\rscommlog.txt", "at");
fprintf(f, "CRealSerialComm::CRealSerialComm() (default constructor)\n");
fclose(f);
}
#endif
m_hSerial = INVALID_HANDLE_VALUE;
m_serialPortName[0] = 0;
m_pBuffer = NULL;
m_ProcDebugLog = NULL;
}
CRealSerialComm::CRealSerialComm(ConnectData* connectSettings, DWORD connectionId, CBaseProtocol* protocol)
{
#ifdef _DEBUG
if (gDoLogging)
{
FILE* f = fopen("c:\\tcf\\rscommlog.txt", "at");
fprintf(f, "connectSettings=%x connectionId=%d, protocol=%x\n", connectSettings, connectionId, protocol);
fclose(f);
}
#endif
m_hSerial = INVALID_HANDLE_VALUE;
m_serialPortName[0] = 0;
m_pBuffer = NULL;
m_connId = connectionId;
m_Protocol = protocol;
m_ConnectSettings = new ConnectData();
memcpy(m_ConnectSettings, connectSettings, sizeof(ConnectData));
#if (defined(LOG_COMM) || defined(LOG_PROCCOMM)) && defined(_DEBUG)
if (gDoLogging)
{
m_CommDebugLog = new TCDebugLog("TCF_Comm", connectionId, 2000L);
m_ProcDebugLog = new TCDebugLog("TCF_CommP", connectionId, 2000L);
}
#endif
}
CRealSerialComm::~CRealSerialComm()
{
#ifdef _DEBUG
if (gDoLogging)
{
FILE* f = fopen("c:\\tcf\\rscommlog.txt", "at");
fprintf(f, "CRealSerialComm::~CRealSerialComm()\n");
fclose(f);
}
#endif
if (m_hSerial != INVALID_HANDLE_VALUE)
::CloseHandle(m_hSerial);
if (m_pBuffer)
delete[] m_pBuffer;
}
long CRealSerialComm::OpenPort()
{
COMMLOGOPEN();
COMMLOGS("CRealSerialComm::OpenPort\n");
long err = TCAPI_ERR_NONE;
char* comPort = m_ConnectSettings->realSerialSettings.comPort;
DWORD baudRate = m_ConnectSettings->realSerialSettings.baudRate;
DWORD dataBits = m_ConnectSettings->realSerialSettings.dataBits;
eParity parity = m_ConnectSettings->realSerialSettings.parity;
eStopBits stopBits = m_ConnectSettings->realSerialSettings.stopBits;
eFlowControl flow = m_ConnectSettings->realSerialSettings.flowControl;
COMMLOGA2("CRealSerialComm::OpenPort comPort=%s baudRate=%d\n", comPort, baudRate);
COMMLOGA2("CRealSerialComm::OpenPort dataBits=%d parity=%d\n", dataBits, parity);
COMMLOGA2("CRealSerialComm::OpenPort stopBits=%d flow=%d\n", stopBits, flow);
// fill in DCB
m_dcb.DCBlength = sizeof(DCB);
m_dcb.BaudRate = baudRate;
m_dcb.ByteSize = dataBits;
// parity
switch(parity)
{
default:
case eParityNone:
m_dcb.fParity = FALSE;
m_dcb.Parity = NOPARITY;
break;
case eParityEven:
m_dcb.fParity = TRUE;
m_dcb.Parity = EVENPARITY;
break;
case eParityOdd:
m_dcb.fParity = TRUE;
m_dcb.Parity = ODDPARITY;
break;
}
// stop bits
switch(stopBits)
{
default:
case eStopBits1:
m_dcb.StopBits = ONESTOPBIT;
break;
case eStopBits15:
m_dcb.StopBits = ONE5STOPBITS;
break;
case eStopBits2:
m_dcb.StopBits = TWOSTOPBITS;
break;
}
// flow control
switch(flow)
{
default:
case eFlowControlNone:
m_dcb.fRtsControl = RTS_CONTROL_DISABLE;
m_dcb.fOutxCtsFlow = FALSE;
m_dcb.fInX = m_dcb.fOutX = FALSE;
break;
case eFlowControlHW:
m_dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
m_dcb.fOutxCtsFlow = TRUE;
m_dcb.fInX = m_dcb.fOutX = FALSE;
break;
case eFlowControlSW:
m_dcb.fRtsControl = RTS_CONTROL_DISABLE;
m_dcb.fOutxCtsFlow = FALSE;
m_dcb.fInX = m_dcb.fOutX = TRUE;
m_dcb.XonChar = '\021'; // Ctrl-Q;
m_dcb.XoffChar = '\023'; // Ctrl-S;
m_dcb.XonLim = 100;
m_dcb.XoffLim = 100;
break;
}
// other things in DCB
m_dcb.fDtrControl = DTR_CONTROL_ENABLE;
m_dcb.fDsrSensitivity = FALSE;
m_dcb.fBinary = TRUE;
m_dcb.fNull = FALSE;
m_dcb.fAbortOnError = TRUE; // reads & writes will terminate with errors if one occurs
// translate serial port
char p[20]; char* pp = p;
strncpy(p, comPort, 20);
int len = (int)strlen(p);
for (int i = 0; i < len; i++)
{
p[i] = toupper(p[i]);
}
if (strncmp(p, "COM", 3) == 0)
{
pp+=3;
}
int val = atoi((const char*)pp);
if (val == INT_MIN || val == INT_MAX)
{
err = TCAPI_ERR_INVALID_MEDIA_DATA;
}
else
{
// must translate for CreatFile
_snprintf(m_serialPortName, MAX_COMPORT_SIZE, "\\\\.\\COM%d", val);
}
if (err == TCAPI_ERR_NONE)
{
m_hSerial = CreateFile(m_serialPortName,
GENERIC_READ|GENERIC_WRITE, // dwDesiredAccess = read & write
0, // dwSharedMode = 0 ==> device not shared
NULL, // lpSecurityAttributes = NULL ==> not inheritable
OPEN_EXISTING, // dwCreationDisposition ==> required for devices
0, // dwFlagsAndAttributes ==> no special flags or attributes (not overlapped)
NULL ); // hTemplateFile = NULL ==> required for devices
if (m_hSerial != INVALID_HANDLE_VALUE)
{
// TODO: this is really not needed as we're not doing overlapped IO
// and we're not creating an event nor waiting on that event
if (!SetCommMask(m_hSerial, EV_RXCHAR))
{
::CloseHandle(m_hSerial);
m_hSerial = INVALID_HANDLE_VALUE;
m_lastCommError = GetLastError();
err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
}
else
{
// no error from SetCommMask
if (!SetupComm(m_hSerial,MAX_MESSAGE_LENGTH,MAX_SERIAL_MESSAGE_BUFFER_LENGTH))
{
CloseHandle(m_hSerial);
m_hSerial = INVALID_HANDLE_VALUE;
m_lastCommError = GetLastError();
err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
}
else
{
// no error from SetupComm
// Get rid of any junk that might be sitting there.
PurgeComm( m_hSerial, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR );
// Using these settings, the ReadFile command will return immediately
// rather than waiting for a timeout.
COMMTIMEOUTS lclCommTimeOuts;
lclCommTimeOuts.ReadIntervalTimeout = MAXDWORD; // we don't care about time between chars
lclCommTimeOuts.ReadTotalTimeoutMultiplier = 100;
lclCommTimeOuts.ReadTotalTimeoutConstant = 0;
lclCommTimeOuts.WriteTotalTimeoutMultiplier = 100;
lclCommTimeOuts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts( m_hSerial, &lclCommTimeOuts ))
{
CloseHandle(m_hSerial);
m_hSerial = INVALID_HANDLE_VALUE;
m_lastCommError = GetLastError();
err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
}
else
{
// no error from SetCommTimeouts
err = SetDCB();
if (err != TCAPI_ERR_NONE)
{
CloseHandle(m_hSerial);
m_hSerial = INVALID_HANDLE_VALUE;
}
else
{
// no error from SetDCB
err = TCAPI_ERR_NONE;
m_numberBytes = 0;
m_lastCommError = 0;
m_isConnected = true;
m_pBuffer = new BYTE[MAX_SERIAL_MESSAGE_BUFFER_LENGTH];
}
}
}
}
}
else
{
// error from CreateFile
// couldn't open serial port
m_lastCommError = GetLastError();
err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
}
}
COMMLOGA2("CRealSerialComm::OpenPort err=%d osError=%d\n", err, m_lastCommError);
LogErrorText(m_lastCommError);
// if (m_lastCommError > 0)
// LogErrorText(m_lastCommError);
COMMLOGCLOSE();
return err;
}
long CRealSerialComm::SetDCB()
{
// assumes serial port is open
long err = TCAPI_ERR_NONE;
if (m_hSerial == INVALID_HANDLE_VALUE)
return err;
// setup DCB
DCB lcldcb;
lcldcb.DCBlength = sizeof(DCB);
if (!GetCommState( m_hSerial, &lcldcb ))
{
m_lastCommError = GetLastError();
err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
}
// LogDCB(pInfo);
// copy only the ones that Connect() set initially
lcldcb.BaudRate = m_dcb.BaudRate;
lcldcb.ByteSize = m_dcb.ByteSize;
lcldcb.Parity = m_dcb.Parity;
lcldcb.StopBits = m_dcb.StopBits;
lcldcb.fRtsControl = m_dcb.fRtsControl;
lcldcb.fOutxCtsFlow = m_dcb.fOutxCtsFlow;
lcldcb.fDtrControl = m_dcb.fDtrControl;
lcldcb.fDsrSensitivity = m_dcb.fDsrSensitivity;
lcldcb.fInX = m_dcb.fInX;
lcldcb.fOutX = m_dcb.fOutX;
lcldcb.XonChar = m_dcb.XonChar;
lcldcb.XoffChar = m_dcb.XoffChar;
lcldcb.XonLim = m_dcb.XonLim;
lcldcb.XoffLim = m_dcb.XoffLim;
lcldcb.fBinary = m_dcb.fBinary;
lcldcb.fParity = m_dcb.fParity;
lcldcb.fNull = m_dcb.fNull;
lcldcb.fAbortOnError = m_dcb.fAbortOnError;
// DCB has been changed
// If setting the port went well then we are connected properly!
if (!SetCommState( m_hSerial, &lcldcb))
{
m_lastCommError = GetLastError();
err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
}
return err;
}
long CRealSerialComm::ClosePort()
{
COMMLOGOPEN();
COMMLOGS("CRealSerialComm::ClosePort\n");
long err = TCAPI_ERR_NONE;
if (!IsConnected())
{
err = TCAPI_ERR_MEDIA_NOT_OPEN;
}
else if (m_hSerial != INVALID_HANDLE_VALUE)
{
// disable event notification
SetCommMask( m_hSerial, 0 );
// drop DTR
EscapeCommFunction( m_hSerial, CLRDTR );
// purge any outstanding reads/writes and close device handle
PurgeComm( m_hSerial,
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
CloseHandle( m_hSerial );
m_hSerial = INVALID_HANDLE_VALUE;
if (m_pBuffer)
{
delete[] m_pBuffer;
m_pBuffer = NULL;
}
m_isConnected = false;
}
COMMLOGCLOSE();
return err;
}
void CRealSerialComm::DeleteMsg(DWORD inMsgLength)
{
if (!IsConnected())
return;
// inMsgLength includes header
// delete from beginning of buffer
if (inMsgLength == 0)
return;
if (m_numberBytes > 0 && m_numberBytes >= inMsgLength)
{
size_t moveLen = m_numberBytes - inMsgLength;
if (moveLen > 0)
memcpy(&m_pBuffer[0], &m_pBuffer[inMsgLength], moveLen);
m_numberBytes -= inMsgLength;
}
}
long CRealSerialComm::SendDataToPort(DWORD inSize, const void *inData)
{
long err = TCAPI_ERR_NONE;
DWORD lclNumBytes=0;
COMMLOGOPEN();
COMMLOGS("CRealSerialComm::SendDataToPort\n");
COMMLOGCLOSE();
if (!IsConnected())
{
COMMLOGOPEN();
COMMLOGS("CRealSerialComm::SendDataToPort notConnected\n");
COMMLOGCLOSE();
return TCAPI_ERR_MEDIA_NOT_OPEN;
}
if (WriteFile(m_hSerial, inData, inSize, &lclNumBytes, NULL))
{
// we were successful, but did we send all data? (i.e., a timeout occurred)
// we are not doing overlapped I/O so if not all data went, then we timed out
// and there was some kind of error
if (lclNumBytes != inSize)
{
COMMLOGOPEN();
COMMLOGA3("CRealSerialComm::SendDataToPort WriteFile not all bytes sent: lclNumBytes=%d inSize=%d err=%d\n", lclNumBytes, inSize, GetLastError());
COMMLOGCLOSE();
COMSTAT lclComStat;
DWORD lclErrorFlags = 0;
if (!ClearCommError(m_hSerial, &lclErrorFlags, &lclComStat))
{
// clear comm error returned error (this doesn't normally happen if the handle is valid and port is still open)
m_lastCommError = GetLastError();
err = TCAPI_ERR_COMM_ERROR;
COMMLOGOPEN();
COMMLOGA1("CRealSerialComm::SendDataToPort ClearCommError failed=%d\n", m_lastCommError);
COMMLOGCLOSE();
}
else
{
// clear comm error returned OK
// check error flags
if (lclErrorFlags)
{
// there really was an error
m_lastCommError = lclErrorFlags;
err = TCAPI_ERR_COMM_ERROR;
COMMLOGOPEN();
COMMLOGA1("CRealSerialComm::SendDataToPort ClearCommError succeeded lclErrorFlags=%d\n", m_lastCommError);
COMMLOGCLOSE();
}
else
{
// No OS error returned, but WriteFile failed to write out all bytes
// therefore, since we are not doing overlapped I/O, this is an error.
err = TCAPI_ERR_COMM_ERROR;
COMMLOGOPEN();
COMMLOGS("CRealSerialComm::SendDataToPort ClearCommError succeeded lclErrorFlags=0\n");
COMMLOGCLOSE();
// DUMPCOMSTAT(&lclComStat);
}
}
}
else
{
// we sent all the data we requested
err = TCAPI_ERR_NONE;
#ifdef _DEBUG
COMMLOGOPEN();
COMMLOGS("CRealSerialComm::SendDataToPort WriteFile successful\n");
BYTE* ptr = (BYTE*)inData;
long numBytes = (inSize > 80) ? 80 : inSize;
char msg[200];
sprintf(msg, "CRealSerialComm::SendDataToPort = ");
for (int i = 0; i < numBytes; i++)
{
sprintf(msg, "%s %02.2x", msg, ptr[i]);
}
sprintf(msg, "%s\n", msg);
COMMLOGS(msg);
COMMLOGCLOSE();
#endif
}
}
else
{
// write failed
m_lastCommError = GetLastError();
err = TCAPI_ERR_COMM_ERROR;
COMMLOGOPEN();
COMMLOGA1("CRealSerialComm::SendDataToPort WriteFile failed = %d\n", m_lastCommError);
COMMLOGCLOSE();
}
return err;
}
long CRealSerialComm::PollPort(DWORD &outSize)
{
long err = TCAPI_ERR_NONE;
outSize = 0;
COMSTAT lclComStat;
DWORD lclErrorFlags=0;
if (!IsConnected())
return TCAPI_ERR_MEDIA_NOT_OPEN;
// Sleep(1);
if (!ClearCommError( m_hSerial, &lclErrorFlags, &lclComStat ))
{
m_lastCommError = GetLastError();
err = TCAPI_ERR_COMM_ERROR;
PROCLOGOPEN();
PROCLOGA1("CRealSerialComm::PollPort ClearCommError failed=%d\n", m_lastCommError);
// if (m_lastCommError > 0)
LogErrorText2(m_lastCommError);
PROCLOGCLOSE();
}
else
{
// ClearCommError succeeded
if (lclErrorFlags)
{
m_lastCommError = lclErrorFlags;
err = TCAPI_ERR_COMM_ERROR;
PROCLOGOPEN();
PROCLOGA1("CRealSerialComm::PollPort ClearCommError succeeded but lclErrorFlags=%d\n", m_lastCommError);
PROCLOGCLOSE();
}
else
{
// DUMPCOMSTATP(&lclComStat);
// PROCLOGOPEN();
// PROCLOGA1("CRealSerialComm::PollPort ClearCommError succeeded cbInQue=%d\n", lclComStat.cbInQue);
// PROCLOGCLOSE();
m_lastCommError = 0;
}
outSize = lclComStat.cbInQue;
}
return err;
}
#ifdef _DEBUG
void CRealSerialComm::DumpComStat(COMSTAT* stat)
{
COMMLOGOPEN();
COMMLOGA3(" comstat fCtsHold =%d fDsrHold =%d fRlsdHold=%d\n", stat->fCtsHold, stat->fDsrHold, stat->fRlsdHold);
COMMLOGA3(" comstat fXoffHold=%d fXoffSent=%d fEof =%d\n", stat->fXoffHold, stat->fXoffSent, stat->fEof);
COMMLOGA3(" comstat fTxim =%d cbInQue =%d cbOutQue =%d\n", stat->fTxim, stat->cbInQue, stat->cbOutQue);
COMMLOGCLOSE();
}
void CRealSerialComm::DumpComStatP(COMSTAT* stat)
{
PROCLOGOPEN();
PROCLOGA3(" comstat fCtsHold =%d fDsrHold =%d fRlsdHold=%d\n", stat->fCtsHold, stat->fDsrHold, stat->fRlsdHold);
PROCLOGA3(" comstat fXoffHold=%d fXoffSent=%d fEof =%d\n", stat->fXoffHold, stat->fXoffSent, stat->fEof);
PROCLOGA3(" comstat fTxim =%d cbInQue =%d cbOutQue =%d\n", stat->fTxim, stat->cbInQue, stat->cbOutQue);
PROCLOGCLOSE();
}
#endif
long CRealSerialComm::ReadPort(DWORD inSize, void *outData, DWORD &outSize)
{
long err = TCAPI_ERR_NONE;
outSize = 0;
COMSTAT lclComStat;
DWORD lclErrorFlags=0;
DWORD lclLength;
if (!IsConnected())
return TCAPI_ERR_MEDIA_NOT_OPEN;
// clear out any errors in the channel and get the length of the buffer
if (!ClearCommError( m_hSerial, &lclErrorFlags, &lclComStat ))
{
// ClearCommError failed
m_lastCommError = GetLastError();
err = TCAPI_ERR_COMM_ERROR;
PROCLOGOPEN();
PROCLOGA1("CRealSerialComm::ReadPort ClearCommError failed=%d\n", m_lastCommError);
PROCLOGCLOSE();
}
else
{
if (lclErrorFlags)
{
m_lastCommError = lclErrorFlags;
err = TCAPI_ERR_COMM_ERROR;
PROCLOGOPEN();
PROCLOGA1("CRealSerialComm::ReadPort ClearCommError succeeded but lclErrorFlags=%d\n", m_lastCommError);
PROCLOGCLOSE();
}
else
{
m_lastCommError = 0;
lclLength = min( inSize, lclComStat.cbInQue );
if (lclLength > 0)
{
// Read lclLength number of bytes into outData.
if (!ReadFile(m_hSerial,outData,lclLength,&outSize,NULL))
{
m_lastCommError = GetLastError();
err = TCAPI_ERR_COMM_ERROR;
PROCLOGOPEN();
PROCLOGA1("CRealSerialComm::ReadPort ReadFile failed = %d\n", m_lastCommError);
PROCLOGCLOSE();
}
else
{
// ReadFile returned successful, check to see all our bytes came in
// If a timeout happened - we may not get all the data
if (lclLength != outSize)
{
lclErrorFlags = 0;
if (!ClearCommError( m_hSerial, &lclErrorFlags, &lclComStat ))
{
// ClearCommError failed
m_lastCommError = GetLastError();
err = TCAPI_ERR_COMM_ERROR;
PROCLOGOPEN();
PROCLOGA1("CRealSerialComm::ReadPort ClearCommError failed=%d\n", m_lastCommError);
PROCLOGCLOSE();
}
else
{
// ClearCommError succeeded
if (lclErrorFlags)
{
// there really was an error
m_lastCommError = lclErrorFlags;
err = TCAPI_ERR_COMM_ERROR;
PROCLOGOPEN();
PROCLOGA1("CRealSerialComm::ReadPort ReadFile succeeded-not all data read lclErrorFlags=%d\n", m_lastCommError);
PROCLOGCLOSE();
}
else
{
// Since we are not doing overlapped I/O
// and our timeout values say to timeout, we should read all the bytes
// that the last Poll told us, if not this is an error
err = TCAPI_ERR_COMM_ERROR;
PROCLOGOPEN();
PROCLOGS("CRealSerialComm::ReadPort ReadFile succeeded-not all data read lclErrorFlags=0\n");
PROCLOGCLOSE();
}
}
}
else
{
// all data read
m_lastCommError = 0;
PROCLOGOPEN();
PROCLOGS("CRealSerialComm::ReadPort ReadFile successful\n");
PROCLOGCLOSE();
}
}
}
}
}
return err;
}
long CRealSerialComm::ProcessBuffer(CConnection* pConn, CRegistry* pRegistry, long& numberProcessed)
{
PROCLOGOPEN();
PROCLOGS("CRealSerialComm::ProcessBuffer\n");
PROCLOGCLOSE();
long err = TCAPI_ERR_NONE;
long routingErr = TCAPI_ERR_NONE;
if (!IsConnected())
return TCAPI_ERR_MEDIA_NOT_OPEN;
if (!m_Protocol)
return TCAPI_ERR_UNKNOWN_MEDIA_TYPE;
DWORD protocolHeaderLength = m_Protocol->GetHeaderLength();
// fill buffer
if (m_numberBytes < MAX_SERIAL_MESSAGE_BUFFER_LENGTH)
{
DWORD outLen = 0;
err = PollPort(outLen);
if (err == TCAPI_ERR_NONE && outLen > 0)
{
if (outLen > (MAX_SERIAL_MESSAGE_BUFFER_LENGTH - m_numberBytes))
outLen = MAX_SERIAL_MESSAGE_BUFFER_LENGTH - m_numberBytes;
BYTE *ptr = &m_pBuffer[m_numberBytes];
err = ReadPort(outLen, ptr, outLen);
if (err == TCAPI_ERR_NONE && outLen > 0)
{
m_numberBytes += outLen;
}
}
}
// now process buffer but only for complete messages
if (err == TCAPI_ERR_NONE)
{
if (m_numberBytes >= protocolHeaderLength)
{
BYTE* ptr = m_pBuffer;
long bytesRemaining = m_numberBytes;
long usedLen = 0;
bool done = false;
long numberSkipped=0;
while (!done)
{
DWORD fullMessageLength = bytesRemaining;
DWORD rawLength = 0;
BYTE* fullMessage = ptr;
BYTE* rawMessage = ptr;
BYTE msgId = 0;
int result = m_Protocol->DecodeMessage(fullMessage, fullMessageLength, msgId, rawMessage, rawLength);
if (result == DECODE_NOT_ENOUGH_BYTES_TO_SEARCH)
{
done = true;
}
else if (result == DECODE_MESSAGE_NOT_FOUND)
{
numberSkipped++;
usedLen += fullMessageLength;
bytesRemaining -= fullMessageLength;
ptr += fullMessageLength;
if (bytesRemaining < protocolHeaderLength)
done = true;
}
else if (result == DECODE_MESSAGE_FOUND)
{
err = PreProcessMessage(msgId, fullMessageLength, fullMessage);
if (err != TCAPI_ERR_NONE)
{
PROCLOGOPEN();
PROCLOGA1("CTcpComm::ProcessBuffer Notify err = %x\n", err);
PROCLOGCLOSE();
// notify all clients right now
pConn->NotifyClientsCommError(err, false, 0);
err = TCAPI_ERR_NONE;
}
#ifdef _DEBUG
int reallen = fullMessageLength;
if (reallen > 80) reallen = 80;
char msg[6];
msg[0] = '\0';
sLogMsg[0] = '\0';
if (reallen > 0)
{
sLogMsg[0] = '\0';
for (int i = 0; i < reallen; i++)
{
if (isalnum(ptr[i]))
{
sprintf(msg, "%c", ptr[i]);
}
else
{
sprintf(msg, "%02.2x ", ptr[i]);
}
strcat(sLogMsg, msg);
}
}
#endif
PROCLOGOPEN();
PROCLOGA5("CRealSerialComm::ProcessBuffer - RouteMesssage pRegistry = %x id=%x len=%d len=%d msg=%s\n", pRegistry, msgId, fullMessageLength, rawLength, sLogMsg);
PROCLOGCLOSE();
err = pRegistry->RouteMessage(msgId, fullMessage, fullMessageLength, rawMessage, rawLength);
if (err != TCAPI_ERR_NONE) routingErr = err; // saved for future
numberProcessed++;
usedLen += fullMessageLength;
bytesRemaining -= fullMessageLength;
ptr += fullMessageLength;
if (bytesRemaining < protocolHeaderLength)
done = true;
}
}
DeleteMsg(usedLen);
}
}
// PROCLOGOPEN();
// PROCLOGA1("CRealSerialComm::ProcessBuffer err = %d\n", err);
// PROCLOGCLOSE();
if (routingErr == TCAPI_ERR_NONE)
return err;
else
return routingErr;
}
bool CRealSerialComm::IsConnectionEqual(ConnectData* pConn)
{
bool equal = false;
// forms accepted:
// "comNN", "NN"
char* ptr1 = m_ConnectSettings->realSerialSettings.comPort;
char* ptr2 = pConn->realSerialSettings.comPort;
bool digit1found = false;
while(!digit1found && *ptr1 != NULL)
{
if (*ptr1 >= '0' && *ptr1 <= '9')
{
digit1found = true;
break;
}
ptr1++;
}
bool digit2found = false;
while(!digit2found && *ptr2 != NULL)
{
if (*ptr2 >= '0' && *ptr2 <= '9')
{
digit2found = true;
break;
}
ptr2++;
}
if (digit1found && digit2found)
{
if (strcmp(ptr1, ptr2) == 0)
equal = true;
}
return equal;
}
#ifdef _DEBUG
DWORD CRealSerialComm::GetErrorText(DWORD inError)
{
LPVOID lpMsgBuf;
if (inError == 0) return inError;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
inError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
COMMLOGA1(" -- GetErrorText=%s", lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
return inError;
}
DWORD CRealSerialComm::GetErrorText2(DWORD inError)
{
LPVOID lpMsgBuf;
if (inError == 0) return inError;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
inError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
PROCLOGA1(" -- GetErrorText=%s", lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
return inError;
}
void CRealSerialComm::DumpBuffer(BYTE* ptr, long length)
{
char msg[256] = {0};
if (length > 50) length = 50;
for (int i = 0; i < length; i++)
{
sprintf(msg, "%s%02.2X ", msg, ptr[i]);
}
sprintf(msg, "%s\n", msg);
PROCLOGS(msg);
}
#endif