#include "../stdafx.h" #include #include "CMMIO_SERIAL.H " ////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// #define LONG_TIMEOUT 5000 #define MAXBLOCK 4096 /* ///////////////////////////////////////////////////////////////////////////// // Code - Text for debug window static char Codes[][6] = { "","","","","","","","", "","","","","","","","","", "","","","","","","","", "","","","","","","" }; */ ///////////////////////////////////////////////////////////////////////////// // 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 static_cast(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 = nullptr; //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)); //事件最常用在多线程同步互斥机制。 //1、HANDLE CreateEvent( // // LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES结构指针,可为NULL // BOOL bManualReset, // 手动/自动 // // TRUE:表示手动,在WaitForSingleObject后必须手动调用ResetEvent清除信号 // // FALSE:表示自动,在WaitForSingleObject后,系统自动清除事件信号 // BOOL bInitialState, //初始状态,FALSE为无信号,TRUE为有信号 // LPCTSTR lpName //事件的名称 //); // //2、SetEvent:设置为激活触发状态。 // //3、ResetEvent:设置为未激活触发状态。 // //4、WaitForSingleObject:检测信号,如果未激活,代码就会处于挂起状态,不再往下执行。 // //———————————————— //版权声明:本文为CSDN博主「AI浩」的原创文章,遵循CC 4.0 BY - SA版权协议,转载请附上原文出处链接及本声明。 //原文链接:https ://blog.csdn.net/hhhhhhhhhhwwwwwwwwww/article/details/108380956 m_hWaitCMMResponse = CreateEvent(nullptr, TRUE, FALSE, nullptr); m_hNewRx = CreateEvent(nullptr, TRUE, FALSE, nullptr); // to trigger OnRx m_ReadOLap.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); //m_RXTempPtr = NULL; m_DebugInPtr = 0; m_DebugCount = 0; m_Item = 0; m_MaxTXRetries = 5; m_iRecvCount = 252; /* // CriticalSection for locking lists InitializeCriticalSection( &m_QueueLock ); InitializeCriticalSection( &m_WriteLock ); InitializeCriticalSection( &m_ReadLock ); */ // IsValidBuffer = FALSE; CurrentPointer = 0; m_hWaitCMMResponse = CreateEvent(nullptr, TRUE, FALSE, nullptr); m_hNewRx = CreateEvent(nullptr, TRUE, FALSE, nullptr); // 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 opens ports from 1..9 for two-difit ports it's becessary to use \\\\.\\COM #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, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, nullptr); 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 = 1; CommTimeOut.WriteTotalTimeoutMultiplier = 1; 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)) { // Initialize the Overlapping structures and start the // monitoring task m_ReceiveOLap.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); m_TransmitOLap.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); m_ThreadHandle = (HANDLE)_beginthreadex(nullptr, 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; } DWORD CPSerial::SendWriteFile(const char* Buffer, DWORD Bytes) { DWORD BytesWritten; BOOL WriteState; WriteState = WriteFile(m_PortHandle, &Buffer[0], Bytes, &BytesWritten, &m_WriteOLap); return WriteState; } ///////////////////////////////////////////////////////////////////////////// // 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 = nullptr; 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(buffer, static_cast(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 0) { PurgeComm(m_PortHandle, PURGE_RXABORT | PURGE_RXCLEAR); return 0; } dwLength = (static_cast(MaxLength) < ComStat.cbInQue ? MaxLength : ComStat.cbInQue); memset(abIn, 0, MaxLength); //如果有字符即读入 if (dwLength) { JudgeRead = ReadFile(m_PortHandle, abIn, dwLength, &dwLength, &m_ReceiveOLap); //读出字符至abIn处 if (!JudgeRead) { //如果重叠操作未完成,等待直到操作完成 if (GetLastError() == ERROR_IO_PENDING) { // WaitForSingleObject(m_osRead.hEvent,INFINITE); GetOverlappedResult(m_PortHandle, &m_ReceiveOLap, &dwLength, TRUE); m_ReceiveOLap.Offset = 0; // m_osRead.Offset=(m_osRead.Offset+dwLength)%MAXBLOCK; } else dwLength = 0; } } return dwLength; } ///////////////////////////////////////////////////////////////////////////// // 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 { Sleep(2); BYTE abIn[MAXBLOCK]; int len; len = ReadBlock(abIn, MAXBLOCK); if ((len > 0) && (len < MAX_RECIEVE_BUFFER_SIZE)) { //memset(m_RecvData, 0, m_iRecvBytes); memcpy(m_RecvData, abIn, len); m_iRecvBytes = len; m_iRecvState = TRUE; } // 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, m_iRecvCount); 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(3); // 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, nullptr); 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(&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; 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; } else { GetCommState(m_PortHandle, &SerialDCB); SerialDCB.BaudRate = Baud; // set the baud rate SerialDCB.ByteSize = static_cast(Bits); // data size, xmit, and rcv SerialDCB.StopBits = static_cast(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 if( Ptr == NULL ) { BytesToCopy = 0; //Ptr = _T(""); Ptr = ""; } // 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 (;index0x80 ){ ++ 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