Files
EF3-Interface/PcDmis/Base/Interfac/Msi/Hsi/SevenOcean/CMMIO_SERIAL.CPP
T
2013-12-13 08:53:55 +08:00

1255 lines
33 KiB
C++

#include "stdafx.h"
#include <process.h>
#include "CMMIO_SERIAL.H "
//////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
#define LONG_TIMEOUT 5000
/*
/////////////////////////////////////////////////////////////////////////////
// Code - Text for debug window
static char Codes[][6] =
{
"<NUL>","<SOH>","<STX>","<ETX>","<EOT>","<ENQ>","<ACK>","<BEL>",
"<BS>","<HT>","<LF>","<VT>","<FF>","<CR>","<SO>","<SI>","<DLE>",
"<DC1>","<DC2>","<DC3>","<DC4>","<NAK>","<SYN>","<ETB>","<CAN>",
"<EM>","<SUB>","<ESC>","<FS>","<GS>","<RS>","<VS>"
};
*/
/////////////////////////////////////////////////////////////////////////////
// CPSerial() : Constructor
/////////////////////////////////////////////////////////////////////////////
// CSerialTask() : Function to run ReceiveTask() method as a task
//
unsigned int WINAPI CSerialTask(LPVOID CSerialPtr)
{
TRACE( TEXT("Serial task has started \n") );
// Call the ControlTask function in the specified plugin
((CPSerial *)CSerialPtr)->ReceiveTask();
TRACE( TEXT("Serial task has completed \n") );
_endthreadex(0);
return(0);
}
CPSerial::CPSerial()
{
// Serial port is not open
m_PortHandle = INVALID_HANDLE_VALUE;
m_IsWrtingData=FALSE;
// Default port settings
m_Port = 1;
m_Baud = CBR_115200;
m_Parity ='N';
m_Bits = 8;
m_StopBits = 1;
m_HandShake =CS_HANDSHAKE_FOR_SO7;
m_RXTimeout = CS_DEFAULT_RX_TIMEOUT;
m_TXTimeout = CS_DEFAULT_TX_TIMEOUT;
m_iRecvState=FALSE;
m_iRecvBytes=0;
memset(m_RecvData,0,MAX_RECIEVE_BUFFER_SIZE);
// Everything else set to NULL
m_ThreadHandle = NULL;
//m_TXHead = NULL;
//m_TXTail = NULL;
//m_RXHead = NULL;
//m_RXTail =NULL;
memset( &m_ReceiveOLap, 0, sizeof( OVERLAPPED ));
memset( &m_TransmitOLap, 0, sizeof( OVERLAPPED ));
memset( &m_ReadOLap, 0, sizeof( OVERLAPPED ));
memset( &m_WriteOLap, 0, sizeof( OVERLAPPED ));
m_hWaitCMMResponse = CreateEvent( NULL, TRUE, FALSE, NULL );
m_hNewRx = CreateEvent( NULL, TRUE, FALSE, NULL ); // to trigger OnRx
//m_RXTempPtr = NULL;
m_DebugInPtr = 0;
m_DebugCount = 0;
m_Item = 0;
m_MaxTXRetries = 5;
/*
// CriticalSection for locking lists
InitializeCriticalSection( &m_QueueLock );
InitializeCriticalSection( &m_WriteLock );
InitializeCriticalSection( &m_ReadLock );
*/
// IsValidBuffer = FALSE;
CurrentPointer = 0;
m_hWaitCMMResponse = CreateEvent( NULL, TRUE, FALSE, NULL );
m_hNewRx = CreateEvent( NULL, TRUE, FALSE, NULL ); // to trigger OnRx
// pParent = NULL;
}
/////////////////////////////////////////////////////////////////////////////
// ~CPSerial() : Destructor - Close the port and free up the CriticalSection
CPSerial::~CPSerial()
{
if( IsOpen( ) )
{
TRACE(TEXT("Warning : closing serial port in destructor\n"));
Close();
}
while(GetNextReceived())
; // mp 3/3/99 prevents leaks
/*
DeleteCriticalSection( &m_QueueLock );
DeleteCriticalSection( &m_ReadLock );
DeleteCriticalSection( &m_WriteLock );
*/
// close the overlapped io event
CloseHandle( m_ReadOLap.hEvent );
CloseHandle( m_WriteOLap.hEvent );
//
CloseHandle( m_hWaitCMMResponse );
CloseHandle( m_hNewRx);
}
/////////////////////////////////////////////////////////////////////////////
// OpenPort() : Opens the serial port using the parameters set by default
// or a call to SetPort
DWORD CPSerial::Open()
{
CString PortName;
COMMTIMEOUTS CommTimeOut;
int Ok;
unsigned int ThreadID;
// Ensure the debug window is registered
// RegisterDebugWindow( );
// Close the port incase it is already open
Close( );
// Start of assuming the worst
Ok = FALSE;
// Format the file name and open it
// COM<number> opens ports from 1..9 for two-difit ports it's becessary to use \\\\.\\COM<num>
#if 0
PortName.Format( TEXT("\\\\.\\COM%d"), m_Port );
#else
PortName.Format( TEXT("COM%d"), m_Port );
#endif
m_PortHandle = CreateFile( PortName, GENERIC_WRITE | GENERIC_READ, 0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL );
if( IsOpen( ) )
{
// Setup the port according to the stored parameters
if( ProgramPort( m_Port, m_Baud, m_Parity, m_Bits, m_StopBits, m_HandShake ) )
{
// Setup the timeouts
CommTimeOut.ReadIntervalTimeout = 25;
CommTimeOut.ReadTotalTimeoutMultiplier = 1;
CommTimeOut.ReadTotalTimeoutConstant = 0;
CommTimeOut.WriteTotalTimeoutMultiplier = 0;
CommTimeOut.WriteTotalTimeoutConstant = m_TXTimeout;
if( SetCommTimeouts( m_PortHandle, &CommTimeOut ) )
{
// Setup the buffer sizes
if( SetupComm( m_PortHandle, 2048, 2048 ) )
{
// Setup the event masks for the monitoring task
if( SetCommMask( m_PortHandle, EV_RXCHAR | EV_TXEMPTY | EV_BREAK |
EV_CTS | EV_DSR | EV_ERR | EV_RLSD ) )
{
// Initialise the Overlapping structures and start the
// monitoring task
m_ReceiveOLap.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_TransmitOLap.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_ThreadHandle = (HANDLE)_beginthreadex( NULL, 0, CSerialTask, this,
0, &ThreadID );
//Sleep(1000);
Ok = TRUE;
}
}
}
// clear msg waiting
m_iNbMsgWaiting = 0;
}
// Things have gone wrong so close the port
if( Ok == FALSE )
{
TRACE(_T("CmmIO> Port OPEN issue -> CLOSED\n"),Ok);
Close( );
}
}
TRACE(_T("CmmIO> Port OPEN = %d \n"),Ok);
// Return the state
return( IsOpen( ) );
}
/////////////////////////////////////////////////////////////////////////////
// IsOpen() : returns true if the serial port is open
//
int CPSerial::IsOpen( )
{
return( m_PortHandle != INVALID_HANDLE_VALUE );
}
/////////////////////////////////////////////////////////////////////////////
// SetPort() : Store the serial settings. If the port is open then these
// settings are applied now
int CPSerial::SetPort(int Port,int Baud,char Parity,int Bits,int StopBits,int HandShake)
{
// Use the current settings if the value has the default of 0
m_Port = Port;
if(Baud == 0)
Baud = m_Baud;
if(Parity == 0)
Parity = m_Parity;
if(Bits == 0)
Bits = m_Bits;
if(StopBits == 0)
StopBits = m_StopBits;
if (HandShake==0)
HandShake=m_HandShake;
// If the values are ok then store them
if( ProgramPort( Port, Baud, Parity, Bits, StopBits, HandShake ) )
{
m_Port = Port;
m_Baud = Baud;
m_Parity = Parity;
m_Bits = Bits;
m_StopBits = StopBits;
m_HandShake = HandShake;
return(TRUE);
}
return(FALSE);
}
/////////////////////////////////////////////////////////////////////////////
// GetPortData() : return the current settings
//
void CPSerial::GetPortData(int *Port,int *Baud,char *Parity,int *Bits,int *StopBits,int *HandShake)
{
// return the requested settings
if( Port )
*Port = m_Port;
if( m_Baud )
*Baud = m_Baud;
if( Parity )
*Parity = m_Parity;
if( Bits )
*Bits = m_Bits;
if( StopBits )
*StopBits = m_StopBits;
if( HandShake )
*HandShake = m_HandShake;
}
/////////////////////////////////////////////////////////////////////////////
// ClosePort() : Close the port and shut down the monitoring thread
//
DWORD CPSerial::Close()
{
//struct SerialList *Free;
HANDLE Port;
// If the port is open then close it
if( IsOpen( ) )
{
Port = m_PortHandle;
m_PortHandle = INVALID_HANDLE_VALUE;
CloseHandle( Port );
if( WaitForSingleObject( m_ThreadHandle, (5 * LONG_TIMEOUT) ) != WAIT_OBJECT_0 )
TRACE( TEXT("ERR:Serial port thread failed to terminate\n") );
m_ThreadHandle = NULL;
CloseHandle( m_ReceiveOLap.hEvent );
CloseHandle( m_TransmitOLap.hEvent );
}
CMMIO::Close();
//ZH
/*
// Delete the contents of the temp rx pointer if any
delete[] m_RXTempPtr;
m_RXTempPtr = NULL;
// Clear down all internal lists
EnterCriticalSection( &m_QueueLock );
while( m_RXHead )
{
Free = m_RXHead;
m_RXHead = m_RXHead->Next;
delete[] Free->Buffer;
delete Free;
}
m_RXHead = NULL;
while( m_TXHead )
{
Free = m_TXHead;
m_TXHead = m_TXHead->Next;
delete[] Free->Buffer;
delete Free;
}
m_TXHead = NULL;
LeaveCriticalSection( &m_QueueLock );
*/
return(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// Send functions // [8/11/2004]
//
DWORD CPSerial::Send(LPCSTR buffer, int l, BOOL /*needsResponse=FALSE*/)
{
m_IsWrtingData=TRUE;
return ( WritePort ((const char*) buffer, (DWORD) l));
}
/*
DWORD CPSerial::Send(CString buffer)
{
char LocBuffer[MAX_OUTPUT_BUFFER_SIZE];
int length = buffer.GetLength ();
if (length >MAX_OUTPUT_BUFFER_SIZE)
{
length = MAX_OUTPUT_BUFFER_SIZE;
}
unsigned short* ptr = (unsigned short*)buffer.GetBuffer (MAX_OUTPUT_BUFFER_SIZE);
for (int i=0;i<length;i++)
{
LocBuffer[i] = (char)(ptr[i] & 0xff);
}
DWORD res = Send(LocBuffer,length);
return res;
}
*/
/////////////////////////////////////////////////////////////////////////////
// WritePort() : Writes the specifed bytes to the serial port
//
DWORD CPSerial::WritePort(const char *Buffer,DWORD Bytes)
{
DWORD BytesWritten, TotalWritten, Error;
BOOL WriteState;
int Retrys;
TotalWritten=0;
// Check that the port is open
if( IsOpen( ) )
{
// Enter a critical section incase this is been used from multiple threads
//EnterCriticalSection(&m_WriteLock);
// The following retry loop is required because a TRACE output from NT running
// in remote debug mode will kill any tranmission on any serial port !!!!!!!
// don`t you just love NT.
Retrys = 0;
do
{
Retrys++;
BytesWritten = 0;
// Write the data
WriteState = WriteFile( m_PortHandle, &Buffer[TotalWritten],
Bytes-TotalWritten, &BytesWritten,
&m_WriteOLap );
if( !WriteState )
{
Sleep(50);
// Ensure the write is going on in the background
if( GetLastError() == ERROR_IO_PENDING )
{
// And wait for it to finish
WaitForSingleObject( m_WriteOLap.hEvent, LONG_TIMEOUT ); // GER
GetOverlappedResult( m_PortHandle, &m_WriteOLap, &BytesWritten,
FALSE );
}
else
{
// Gone wrong so clear any erros
ClearCommError( m_PortHandle, &Error, NULL );
BytesWritten= 0 ;
}
}
TotalWritten += BytesWritten;
}
while( Retrys <= m_MaxTXRetries && TotalWritten < Bytes );
//ZH
/*
// Written some bytes so add then to the debug list
if( BytesWritten )
AddToDebug( Buffer, BytesWritten, 2 );
*/
// Remember to leave the critical section
//LeaveCriticalSection( &m_WriteLock );
}
return( TotalWritten );
}
/////////////////////////////////////////////////////////////////////////////
// ReceiveTask() : Internal function, this runs as a thread and provides the
// OnRecieve and OnTransmit events
void CPSerial::ReceiveTask( void )
{
//DWORD BytesWritten;
DWORD Events;
unsigned long State;
do
{
Events=0;
// Wait for a comm event
State=WaitCommEvent(m_PortHandle,&Events,&m_ReceiveOLap);
if(!State)
{
// Since we are using overlapping IO we may have to wait
// for the result
if(GetLastError() == ERROR_IO_PENDING)
GetOverlappedResult(m_PortHandle,&m_ReceiveOLap,&State,TRUE);
}
//m_iRecvState=FALSE;
// If we have a result then OK otherwise the event was probable
// the serial port being closed and we shall exit the loop
if( State && IsOpen( ) )
{
// Check the events and act accordingly
if( Events & EV_RXCHAR )
{
OnReceive( );
}
//ZH
/*
if( Events & EV_TXEMPTY )
{
if( m_TXHead )
{
GetOverlappedResult(m_PortHandle,&m_TransmitOLap,&BytesWritten,TRUE);
if( BytesWritten )
AddToDebug( m_TXHead->Buffer, BytesWritten, 2 );
OnTransmit( 0, BytesWritten );
SendBuffer(TRUE);
}
}
*/
if(Events & EV_BREAK)
TRACE(_T("Break detected\n"));
if(Events & EV_CTS)
TRACE(_T("CTS Changed State\n"));
if(Events & EV_DSR)
TRACE(_T("DSR Changed State\n"));
if(Events & EV_ERR)
TRACE(_T("Line error\n"));
if(Events & EV_RLSD)
TRACE(_T("EV_RLSD error\n"));
}
// Go round while the port is open
}
while( IsOpen( ) );
}
/////////////////////////////////////////////////////////////////////////////
// OnReceive() : Default OnReceive()
// V114
void CPSerial::OnReceive()
{
// Dummy OnReceieve if not used
char s[MAX_RECIEVE_BUFFER_SIZE]={0};
s[1]='\0';
CurrentPointer = 0;
if (m_HandShake==CS_HANDSHAKE_FOR_TRESASTR_E)
{
int num = ReadPort(s, MAX_RECIEVE_BUFFER_SIZE);
if ((num>0) && (num<MAX_RECIEVE_BUFFER_SIZE))
{
if(m_IsWrtingData)
{
memset(m_RecvData,0,MAX_RECIEVE_BUFFER_SIZE);
m_IsWrtingData=FALSE;
m_iRecvBytes=0;
}
TRACE1("----RECV%d----\r\n",num);
TRACE3("%02X %02X %02X ",s[0],s[1],s[2]);
TRACE3("%02X %02X %02X ",s[3],s[4],s[5]);
TRACE3("%02X %02X %02X\r\n",s[6],s[7],s[8]);
for(int i=0;i<num;i++)
{
m_RecvData[m_iRecvBytes++]=s[i];
}
m_iRecvState=TRUE;
}
}
else
{
int num = ReadPort(s, 252);
if ((num>0) && (num<MAX_RECIEVE_BUFFER_SIZE))
{
memset(m_RecvData,0,m_iRecvBytes);
memcpy(m_RecvData,s, num);
m_iRecvBytes=num;
m_iRecvState=TRUE;
}
}
//LineReceive(s, num);
}
/////////////////////////////////////////////////////////////////////////////
// ReadPort() : Read the specifed number of bytes.
//
DWORD CPSerial::ReadPort(char *Buffer,DWORD Bytes)
{
DWORD BytesRead,Error;
BOOL ReadState;
BytesRead = 0;
// Check the port is open
if( IsOpen( ) )
{
// Enter a critical section incase this is been used from multiple threads
// EnterCriticalSection(&m_ReadLock);
// Start the read
ReadState = ReadFile(m_PortHandle,Buffer,Bytes,&BytesRead,&m_ReadOLap);
if( !ReadState )
{
Sleep(50);
// the specifed number of bytes were not available so
// the read will continue in the background aslong as
// GetLastError() returns ERROR_IO_PENDING
if( GetLastError() == ERROR_IO_PENDING )
{
// Wait for the read to complete
WaitForSingleObject( m_ReadOLap.hEvent, LONG_TIMEOUT ); // GER
// get the result of the read
if( GetOverlappedResult( m_PortHandle, &m_ReadOLap, &BytesRead, FALSE ) == 0 )
Error = GetLastError();
}
else
{
// Gone wrong so clear any erros
ClearCommError( m_PortHandle, &Error, NULL );
BytesRead = 0 ;
}
}
//ZH
/*
// Read some bytes so add then to the debug list
if( BytesRead )
AddToDebug( Buffer, BytesRead, 1 );
*/
// LeaveCriticalSection( &m_ReadLock );
}
return(BytesRead);
}
/////////////////////////////////////////////////////////////////////////////
// ReadPort() : Read the specifed number of bytes into a CString class.
//
#if 0
DWORD CPSerial::ReadPort(CString &Buffer,DWORD Bytes)
{
DWORD BytesRead;
USES_CONVERSION;
BytesRead = ReadPort( T2A(Buffer.GetBuffer( Bytes + 1 )), Bytes );
Buffer.ReleaseBuffer( );
return(BytesRead);
}
#endif
/////////////////////////////////////////////////////////////////////////////
// ProgramPort() : Internal function to setup the serial port
//
int CPSerial::ProgramPort(int Port,int Baud,char Parity,int Bits,int StopBits,int HandShake)
{
CString Param,Params;
DCB SerialDCB;
int Ok;
// Build up the serial port settings
Params.Format( TEXT("com%d"), Port );
Param.Format( TEXT(" baud=%d"), Baud );
Params += Param;
Param.Format( TEXT(" parity=%c"), Parity );
Params += Param;
Param.Format( TEXT(" data=%d"), Bits );
Params += Param;
Param.Format( TEXT(" stop=%d"), StopBits );
Params += Param;
Ok = FALSE;
memset( (void *)&SerialDCB, 0, sizeof(SerialDCB) );
SerialDCB.DCBlength = sizeof(SerialDCB);
// Place them in the DCB structure, this also validates them if the
// serial port is not open
if( BuildCommDCB( Params, &SerialDCB ) )
{
// If the port is open
if( IsOpen( ) )
{
// Set the handshake bits
switch(HandShake)
{
case CS_HANDSHAKE_RTSCTS:
SerialDCB.fOutxCtsFlow = TRUE;
SerialDCB.fRtsControl = RTS_CONTROL_HANDSHAKE;
SerialDCB.fDtrControl = DTR_CONTROL_ENABLE;
break;
case CS_HANDSHAKE_RTSCTS_DTRDSR:
SerialDCB.fOutxCtsFlow = TRUE;
SerialDCB.fRtsControl = RTS_CONTROL_HANDSHAKE;
SerialDCB.fOutxDsrFlow = TRUE;
SerialDCB.fDtrControl = DTR_CONTROL_HANDSHAKE;
break;
case CS_HANDSHAKE_XONXOFF:
SerialDCB.fOutX = TRUE;
SerialDCB.fInX = TRUE;
SerialDCB.XonChar = 17;
SerialDCB.XoffChar = 19;
SerialDCB.fRtsControl = RTS_CONTROL_DISABLE;
SerialDCB.fDtrControl = DTR_CONTROL_DISABLE;
break;
case CS_HANDSHAKE_NONE:
SerialDCB.fRtsControl = RTS_CONTROL_ENABLE;
SerialDCB.fDtrControl = DTR_CONTROL_ENABLE;
break;
case CS_HANDSHAKE_FOR_SO7:
SerialDCB.fDsrSensitivity=FALSE;
SerialDCB.XonChar = 17;
SerialDCB.XoffChar = 19;
SerialDCB.fOutX=FALSE;
SerialDCB.fInX=FALSE;
SerialDCB.fErrorChar=FALSE;
SerialDCB.fRtsControl=RTS_CONTROL_ENABLE;
SerialDCB.fDtrControl = DTR_CONTROL_ENABLE;
SerialDCB.fOutxCtsFlow=FALSE;
SerialDCB.fOutxDsrFlow=FALSE;
SerialDCB.XonLim=2048;
SerialDCB.XoffLim=512;
case CS_HANDSHAKE_FOR_TRESASTR_E:
SerialDCB.EofChar = 26;
SerialDCB.XonChar = 17;
SerialDCB.XoffChar = 19;
SerialDCB.fOutX=TRUE;
SerialDCB.fInX=TRUE;
SerialDCB.fRtsControl=RTS_CONTROL_DISABLE;
SerialDCB.fDtrControl = DTR_CONTROL_ENABLE;
SerialDCB.fDsrSensitivity=FALSE;
SerialDCB.XonLim=256;
SerialDCB.XoffLim=256;
break;
default:
break;
}
// Finally apply the params to the port
if(SetCommState( m_PortHandle, &SerialDCB ) )
{
Ok = TRUE;
}
else
{
GetCommState(m_PortHandle, &SerialDCB);
SerialDCB.BaudRate = Baud; // set the baud rate
SerialDCB.ByteSize = (BYTE)Bits; // data size, xmit, and rcv
SerialDCB.StopBits = (BYTE)StopBits; // one stop bit
switch(Parity)
{
case 'O':
case 'o':
SerialDCB.Parity = ODDPARITY; // odd parity bit
break;
case 'E':
case 'e':
SerialDCB.Parity = EVENPARITY; // even parity bit
break;
default:
SerialDCB.Parity = NOPARITY; // no parity bit
break;
}
// Set the handshake bits
switch(HandShake)
{
case CS_HANDSHAKE_RTSCTS:
SerialDCB.fOutxCtsFlow = TRUE;
SerialDCB.fRtsControl = RTS_CONTROL_HANDSHAKE;
SerialDCB.fDtrControl = DTR_CONTROL_ENABLE;
break;
case CS_HANDSHAKE_XONXOFF:
SerialDCB.fOutX = TRUE;
SerialDCB.fInX = TRUE;
SerialDCB.XonChar = 17;
SerialDCB.XoffChar = 19;
SerialDCB.fRtsControl = RTS_CONTROL_DISABLE;
SerialDCB.fDtrControl = DTR_CONTROL_DISABLE;
break;
case CS_HANDSHAKE_NONE:
SerialDCB.fRtsControl = RTS_CONTROL_ENABLE;
SerialDCB.fDtrControl = DTR_CONTROL_ENABLE;
break;
case CS_HANDSHAKE_FOR_SO7:
SerialDCB.fDsrSensitivity=FALSE;
SerialDCB.XonChar = 17;
SerialDCB.XoffChar = 19;
SerialDCB.fOutX=FALSE;
SerialDCB.fInX=FALSE;
SerialDCB.fErrorChar=FALSE;
SerialDCB.fRtsControl=RTS_CONTROL_ENABLE;
SerialDCB.fDtrControl = DTR_CONTROL_ENABLE;
SerialDCB.fOutxCtsFlow=FALSE;
SerialDCB.fOutxDsrFlow=FALSE;
SerialDCB.XonLim=2048;
SerialDCB.XoffLim=512;
break;
case CS_HANDSHAKE_FOR_TRESASTR_E:
SerialDCB.EofChar = 26;
SerialDCB.XonChar = 17;
SerialDCB.XoffChar = 19;
SerialDCB.fOutX=TRUE;
SerialDCB.fInX=TRUE;
SerialDCB.fRtsControl=RTS_CONTROL_DISABLE;
SerialDCB.fDtrControl = DTR_CONTROL_ENABLE;
SerialDCB.fDsrSensitivity=FALSE;
SerialDCB.XonLim=256;
SerialDCB.XoffLim=256;
break;
default:
break;
}
// Finally apply the params to the port
if(SetCommState( m_PortHandle, &SerialDCB ) )
{
Ok = TRUE;
}
}
TRACE(_T("CmmIO> Port was OPEN, ProgramPort done \n"));
}
else
{
TRACE(_T("CmmIO> Port was not OPEN ProgramPort not done \n"));
Ok = TRUE;
}
}
return(Ok);
}
/////////////////////////////////////////////////////////////////////////////
// OnTransmit() : Default OnTransmit()
//
void CPSerial::OnTransmit(int /*Item*/, DWORD /*Error*/)
{
// Dummy OnTransmit if not used
}
/////////////////////////////////////////////////////////////////////////////
// SetTimeouts() : Sets the rx and tx timeouts
//
void CPSerial::SetTimeouts( int RXTimeout, int TXTimeout )
{
COMMTIMEOUTS CommTimeOut;
// Store the timeouts
m_RXTimeout = RXTimeout;
m_TXTimeout = TXTimeout;
// If the port is open then configure the port also
// Currently we only use the Fixed timeouts
if( IsOpen( ) )
{
CommTimeOut.ReadIntervalTimeout = 25;
CommTimeOut.ReadTotalTimeoutMultiplier = 1;
CommTimeOut.ReadTotalTimeoutConstant = 0;
CommTimeOut.WriteTotalTimeoutMultiplier = 0;
CommTimeOut.WriteTotalTimeoutConstant = m_TXTimeout;
SetCommTimeouts( m_PortHandle, &CommTimeOut );
}
}
/////////////////////////////////////////////////////////////////////////////
// AddToDebug() : Add the data to the debug output. State is 1 = rx 2 = tx
// 3 = user
void CPSerial::AddToDebug( const char * /*Ptr*/, DWORD /*BytesToCopy*/, int /*State*/ )
{
//ZH
#if 0
// We are messing with pointers so use the CriticalSection
EnterCriticalSection(&m_QueueLock);
// If ptr = NULL the change to string containing <NULL>
if( Ptr == NULL )
{
BytesToCopy = 0;
//Ptr = _T("<NULL>");
Ptr = "<NULL>";
}
// If zero length then use length of string instead
if( BytesToCopy == 0)
BytesToCopy = strlen( Ptr );
// If length of data is greater then the debug buffer then just
// use the end of the data
if(BytesToCopy > CS_DEBUG_SIZE)
{
Ptr += BytesToCopy - CS_DEBUG_SIZE;
BytesToCopy = CS_DEBUG_SIZE;
}
// If the data will wrap around then just copy the first block
if( ( m_DebugInPtr + BytesToCopy ) > CS_DEBUG_SIZE)
{
// Copy data to the end of the debug buffer
memcpy(m_DebugData + m_DebugInPtr, Ptr, CS_DEBUG_SIZE - m_DebugInPtr);
memset(m_DebugState + m_DebugInPtr, State, CS_DEBUG_SIZE - m_DebugInPtr);
m_DebugWnd.AddData( m_DebugData + m_DebugInPtr,
m_DebugState + m_DebugInPtr,
CS_DEBUG_SIZE - m_DebugInPtr );
// Move on by the amount copied
Ptr += CS_DEBUG_SIZE - m_DebugInPtr;
BytesToCopy -= CS_DEBUG_SIZE - m_DebugInPtr;
// Point at the begining of the buffer
m_DebugInPtr = 0;
}
// Copy the rest into the buffer
memcpy(m_DebugData + m_DebugInPtr, Ptr, BytesToCopy);
memset(m_DebugState + m_DebugInPtr, State, BytesToCopy);
m_DebugWnd.AddData( m_DebugData + m_DebugInPtr,
m_DebugState + m_DebugInPtr, BytesToCopy );
m_DebugInPtr += BytesToCopy;
m_DebugCount += BytesToCopy;
// Keep a count of howmany bytes are in the buffer
if( m_DebugCount > CS_DEBUG_SIZE )
m_DebugCount = CS_DEBUG_SIZE;
// All done so out of the CriticalSection
LeaveCriticalSection(&m_QueueLock);
#endif
}
/////////////////////////////////////////////////////////////////////////////
// FlushPort() : Removes all characters in the serial buffer
//
/*
int CPSerial::FlushPort(void)
{
int TXTimeout,RXTimeout;
char FlushBuffer[256];
DWORD BytesRead,BytesTotal;
struct SerialList *Free;
if( IsOpen( ) )
{
// We are messing with pointers so use the CriticalSection
EnterCriticalSection(&m_QueueLock);
// Make a copy of the timeouts and set back to the defaults
RXTimeout = m_RXTimeout;
TXTimeout = m_TXTimeout;
SetTimeouts( 10, 10 );
// Read all data from the port
BytesTotal=0;
while( ( BytesRead = ReadPort( FlushBuffer, 256 ) ) == 256 )
BytesTotal+=BytesRead;
BytesTotal+=BytesRead;
// Clear the Received list
while(m_RXHead)
{
Free=m_RXHead;
m_RXHead=m_RXHead->Next;
delete[] Free->Buffer;
delete Free;
}
// put the timeouts back
SetTimeouts( RXTimeout, TXTimeout );
m_iNbMsgWaiting = 0;
// All done so out of the CriticalSection
LeaveCriticalSection(&m_QueueLock);
}
return(BytesTotal);
}
*/
/////////////////////////////////////////////////////////////////////////////
// MaxPort() :
//
int CPSerial::MaxPort()
{
// return the max port, :-)
return(8);
}
/////////////////////////////////////////////////////////////////////////////
// Transmit() : Adds data into a list to be transmitted when possible.
// the function OnTransmit() will be called for each block of
// data sent.
//
int CPSerial::Transmit(const char * /*Buffer*/,DWORD /*Bytes*/)
{
/*
struct SerialList *Ptr;
int Start;
// Is the port open
if( IsOpen( ) )
{
TRACE(_T("CmmIo> Port OPEN ... transmitting %d bytes \n"),Bytes);
// Yes so CriticalSection again
EnterCriticalSection(&m_QueueLock);
// Create a new list entry structure for the block of data
Ptr = new struct SerialList;
Ptr->Buffer = new char[Bytes];
Ptr->Bytes = Bytes;
Ptr->Next = NULL;
Ptr->Item = m_Item++;
if(Ptr->Item == 0 )
Ptr->Item = m_Item++;
memcpy( Ptr->Buffer, Buffer, Bytes );
// Add it into the list
if( m_TXTail )
{
Start = FALSE;
m_TXTail->Next = Ptr;
}
else
{
Start = TRUE;
m_TXHead = Ptr;
}
m_TXTail = Ptr;
// If the list was empty then start sending the data, otherwise
// it will be sentout when the previous data has been sent
if(Start)
SendBuffer(FALSE);
// All done so out of the CriticalSection
LeaveCriticalSection(&m_QueueLock);
//return the ID for this block
return( Ptr->Item );
}
else{
TRACE(_T("CmmIo> Port NOT OPEN ... FAILED TO TRANSMIT %d bytes \n"),Bytes);
}
*/
return(0);
}
/////////////////////////////////////////////////////////////////////////////
// AddReceived() : Helper function, this adds a block of data to a list which
// read back by GetNextReceived()
//
/*
int CPSerial::AddReceived( const char *Buffer,DWORD Bytes)
{
DWORD index = 0; //primary buffer index
struct SerialList *Ptr;
static char Buffer2[1000]; // result buffer
static char* pBuffer2 = &Buffer2[0];
unsigned char c;
bool bArmed;
int count;
static int escape = 0;
static int tilde = 0;
static int tildeseqcount = 0;
bool bDone = false;
bool bEventRequest = false;
// ATLTRACE("AddReceived> pBuffer2 = %x\n",pBuffer2);
// ATLTRACE("Content %s\n",Buffer);
if (Bytes==0){
// TRACE("CMMIO> Exiting , no real input");
return TRUE;
}
do {
bArmed = false;
for (;index<Bytes;index++){
c=Buffer[index] & 0xff;
//ATLTRACE("== %02x% ==\n",c); //copy char one by one
if ((c!='\r') && (c!='\n') && bArmed){ // out of CR/LF sequence...
break;
}
else if((c=='\r') || (c=='\n') || (c < 32)){ // Don't work with unprintable characters line 0 -GER
if (index !=0) bArmed = true;// don't make an empty record if LF is first char !
// but still skip it
}
else {
*(pBuffer2++) = c ; //copy char one by one
//new
if (tilde){
if(++tildeseqcount == 2) bArmed = true;
}
if (escape ==1){
if(c!='z' && c!='O')bArmed = true; //not a CLP or PRB
else escape = 0; // reset if part of POS / POINT Msg
}
///n
}
if( c>0x80 ){
++ escape; // max will be 1
// ATLTRACE(" ESCAPE ___>> %d\n",escape);
}
if( c=='~' ){
++ tilde; // max = 1
// ATLTRACE(" TILDE ESC___>> %d\n",tilde);
}
}
if (index == Bytes) bDone=true;
// else TRACE("\nCMMIO> (Serial)Splitting received stream....\n");
// We are messing with pointers so use the CriticalSection
if (bArmed ){
EnterCriticalSection(&m_QueueLock);
//Allocate a new list and add it in
count = pBuffer2-(&Buffer2[0]);
Ptr = new struct SerialList;
Ptr->Buffer = new char[count + 1 ];
Ptr->Bytes = count;
Ptr->Next = NULL;
memcpy( Ptr->Buffer, Buffer2, count );
Ptr->Buffer[count] = 0;
memcpy(m_sLastMessage,Buffer2,count); //copy to last message
m_sLastMessage[count]=0;
if( m_RXTail )
m_RXTail->Next = Ptr;
else
m_RXHead = Ptr;
m_RXTail = Ptr;
// All done so out of the CriticalSection
++m_iNbMsgWaiting;
LeaveCriticalSection( &m_QueueLock );
pBuffer2=&Buffer2[0]; // reset out buffer
count = 0;
escape = 0;
//new
tilde = 0;
tildeseqcount = 0;
///n
bEventRequest = true;
}
} while (!bDone);
// ATLTRACE ("CMMIO> Done\n");
//ZH
#if 0
if(bEventRequest){
if (!(pParent->m_bNoFireEvent)) {
// ATLTRACE("CmmIO Serial> Setting Event m_hNewRx \n");
SetEvent(m_hNewRx);// tell the system to fire event if needed...
}
else {
// ATLTRACE("CmmIO Serial> Setting Event pParent->m_hCmmResponded \n");
// SetEvent(pParent->m_hCmmResponded);
}
}
#endif
// if(bEventRequest){
// if (pParent){
// SetEvent(pParent->m_hCmmResponded);
// }
// }
// else ATLTRACE("--- AddReceived> Leaving with part of msg in buffer, pBuffer2= %x\n",pBuffer2);
return(TRUE);
}
*/
/////////////////////////////////////////////////////////////////////////////
// GetNextReceived() : Helper function, receives messages placed in the queue
// by AddReceievd()
//
//ZH
/*
char *CPSerial::GetNextReceived(void)
{
struct SerialList *Free;
// If there is a previous block then delete it
delete[] m_RXTempPtr;
m_RXTempPtr = NULL;
// We are messing with pointers so use the CriticalSection
EnterCriticalSection(&m_QueueLock);
// If there any more to return
if( m_RXHead )
{
Free = m_RXHead;
m_RXHead = m_RXHead->Next;
// Point the temp pointer at the block
m_RXTempPtr = Free->Buffer;
// delete the list entry
delete Free;
--m_iNbMsgWaiting; // mp
}
if( m_RXHead == NULL )
m_RXTail = NULL;
// All done so out of the CriticalSection
LeaveCriticalSection( &m_QueueLock );
return( m_RXTempPtr );
}
*/
/////////////////////////////////////////////////////////////////////////////
// HexToInt() : Helper function, converts the specifed number of bytes from
// ascii hex
//
int CPSerial::HexToInt(char *Data, int Bytes)
{
int Byte;
int HexChar, Value;
Value = 0;
for( Byte = 0; Byte < Bytes; Byte++ )
{
Value <<= 4;
HexChar = *Data++ -= '0';
if( HexChar > 32 )
HexChar -= 39;
else if( HexChar > 9 )
HexChar -= 7;
Value += HexChar;
}
return( Value );
}
/////////////////////////////////////////////////////////////////////////////
// Private functions
//
/////////////////////////////////////////////////////////////////////////////
// RegisterDebugWindow() : Registers the window class for the debug window.
//
//ZH
/*
void CPSerial::RegisterDebugWindow()
{
// Register the CSerialRaw window for future use
WNDCLASS wndcls;
memset( &wndcls, 0, sizeof( WNDCLASS ) );
wndcls.lpfnWndProc = DefWindowProc;
wndcls.hInstance = AfxGetInstanceHandle( );
wndcls.hCursor = LoadCursor( NULL, IDC_ARROW );
wndcls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpszClassName = TEXT("CPSerial");
AfxRegisterClass( &wndcls );
}
*/
#if 0
/////////////////////////////////////////////////////////////////////////////
// SendBuffer() : Internal function, this writes the next block of data
// queued to the serial port.
void CPSerial::SendBuffer(int Next)
{
struct SerialList *Free;
// DWORD BytesWritten;
// We are messing with pointers so use the CriticalSection
EnterCriticalSection(&m_QueueLock);
// If we been told to go the next then do it
if(Next && m_TXHead)
{
Free=m_TXHead;
m_TXHead=m_TXHead->Next;
delete[] Free->Buffer;
delete Free;
}
// If there is still some data then send it
if(m_TXHead)
// WriteFile(m_PortHandle,m_TXHead->Buffer,m_TXHead->Bytes,&BytesWritten,&m_TransmitOLap);
WritePort(m_TXHead->Buffer,m_TXHead->Bytes);
else
m_TXTail=NULL;
// All done so out of the CriticalSection
LeaveCriticalSection(&m_QueueLock);
}
#endif