Files
LM-Middleware/HSI_HexagonMI_EF3/SevenOcean/CMMIO_SERIAL.CPP
T
2022-12-01 16:03:30 +08:00

1591 lines
42 KiB
C++
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "../stdafx.h"
#include <process.h>
#include "CMMIO_SERIAL.H "
#include <string>
using namespace std;
//////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
#define LONG_TIMEOUT 5000
#define MAXBLOCK 4096
/*
/////////////////////////////////////////////////////////////////////////////
// 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
static_cast<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 = 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、CreateEvent 创建事件。
//函数原型如下所示,一共四个参数:
//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<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, 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))
{
TRACE(_T("CmmIO> Port OPEN %s, m_Baud\n", m_Port, m_Baud), Ok);
//printf("m_Baud: %d\n", m_Baud);
// 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
// 设置你关心的事件, 当此事件发生时, 将得到事件通知, 通过SetCommMask函数设置, SetCommMask函数两个参数, 第一个为串口句柄, 第二个为事件, 可通过位或的方式指定多个事件,如下:
// BOOL WINAPI SetCommMask(
// __in HANDLE hFile,
// __in DWORD dwEvtMask);
//示例代码:
// SetCommMask(m_hCom, EV_RXCHAR);
// EV_RXCHAR事件指当输入缓冲区内有数据时, 通过WaitCommEvent函数可获得通知, 其他事件同理, 其他事件还有EV_BREAK / EV_CTS / EV_RING等,
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<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(5);
// 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, nullptr);
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);
}
/////////////////////////////////////////////////////////////////////////////
//单纯读取单包串口数据,拼包功能在上层实现
int CPSerial::ReadBlock(BYTE* abIn, int MaxLength)
{
BOOL JudgeRead;
COMSTAT ComStat;
DWORD dwErrorFlags, dwLength;
ClearCommError(m_PortHandle, &dwErrorFlags, &ComStat);
if (dwErrorFlags > 0)
{
//PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR
//分别表示:
//立即中断写操作并清空输出缓冲区 | 清空输出缓冲区 | 立即中断读操作并清空输入缓冲区 | 清空输入缓冲区
PurgeComm(m_PortHandle, PURGE_RXABORT | PURGE_RXCLEAR);
return 0;
}
dwLength = (static_cast<DWORD>(MaxLength) < ComStat.cbInQue ? MaxLength : ComStat.cbInQue);
//memset(abIn, 0, MaxLength);
//如果有字符即读入, 这种策略下无法解决读入的字符不是完整的一帧的问题
if (dwLength)
{
//BOOL ReadFile(
// HANDLE hFile, //文件的句柄
// LPVOID lpBuffer, //用于保存读入数据的一个缓冲区
// DWORD nNumberOfBytesToRead, //要读入的字节数
// LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针
// LPOVERLAPPED lpOverlapped
// //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。
// //该结构定义了一次异步读取操作。否则,应将这个参数设为NULL
//);
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;
//等待一次异步操作超时的情况下,GetOverlappedResult返回FALSE,同时GetLastError返回ERROR_IO_INCOMPLETE
/* if (WaitForSingleObject(m_osRead.hEvent, 1000) == WAIT_TIMEOUT)
{
dwLength = 0;
} */
}
//异常情况
else
{
dwLength = 0;
}
}
}
return dwLength;
}
int CPSerial::Receive(void* buf, int maxlen, bool sync)
{
//HANDLE hCom = *(HANDLE*)m_PortHandle;
if (sync)
{
//同步方式
DWORD wCount = maxlen; //成功读取的数据字节数
BOOL bReadStat = ReadFile(m_PortHandle, //串口句柄
buf, //数据首地址
wCount, //要读取的数据最大字节数
&wCount, //DWORD*,用来接收返回成功读取的数据字节数
NULL); //NULL为同步发送,OVERLAPPED*为异步发送
if (!bReadStat)
{
return 0;
}
return wCount;
}
else
{
//异步方式
DWORD wCount = maxlen; //成功读取的数据字节数
DWORD dwErrorFlags; //错误标志
COMSTAT comStat; //通讯状态
OVERLAPPED m_osRead; //异步输入输出结构体
//创建一个用于OVERLAPPED的事件处理,不会真正用到,但系统要求这么做
memset(&m_osRead, 0, sizeof(m_osRead));
//m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, L"ReadEvent");
ClearCommError(m_PortHandle, &dwErrorFlags, &comStat); //清除通讯错误,获得设备当前状态
if (!comStat.cbInQue)return 0; //如果输入缓冲区字节数为0,则返回false
BOOL bReadStat = ReadFile(m_PortHandle, //串口句柄
buf, //数据首地址
wCount, //要读取的数据最大字节数
&wCount, //DWORD*,用来接收返回成功读取的数据字节数
&m_osRead); //NULL为同步发送,OVERLAPPED*为异步发送
if (!bReadStat)
{
if (GetLastError() == ERROR_IO_PENDING) //如果串口正在读取中
{
//GetOverlappedResult函数的最后一个参数设为TRUE
//函数会一直等待,直到读操作完成或由于错误而返回
GetOverlappedResult(m_PortHandle, &m_osRead, &wCount, TRUE);
/* memcpy(m_RecvData, buf, wCount);
m_iRecvBytes = wCount;
m_iRecvState = true;*/
}
else
{
ClearCommError(m_PortHandle, &dwErrorFlags, &comStat); //清除通讯错误
CloseHandle(m_osRead.hEvent); //关闭并释放hEvent的内存
return 0;
}
}
return wCount;
}
}
/*
// C prototype : void HexToStr(char *pszDest, byte *pbSrc, int nLen)
// parameter(s): [OUT] pszDest - 存放目标字符串
// [IN] pbSrc - 输入16进制数的起始地址
// [IN] nLen - 16进制数的字节数
// return value:
// remarks : 将16进制数转化为字符串
*/
void CPSerial::hex2str(char* pszDest, byte* pbSrc, int nLen)
{
char ddl, ddh;
for (int i = 0; i < nLen; i++)
{
ddh = 48 + pbSrc[i] / 16;
ddl = 48 + pbSrc[i] % 16;
if (ddh > 57) ddh = ddh + 7;
if (ddl > 57) ddl = ddl + 7;
pszDest[i * 2] = ddh;
pszDest[i * 2 + 1] = ddl;
}
pszDest[nLen * 2] = '\0';
}
/////////////////////////////////////////////////////////////////////////////
// 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;
int temp_Packlen = 0; //临时存放包长度
do
{
Sleep(3);
BYTE abIn[MAXBLOCK];
int len;
//len = ReadBlock(abIn, MAXBLOCK); //读取一包串口数据
len = Receive(abIn, MAXBLOCK, 0);//方式2
if ((len > 0) && (len < MAX_RECIEVE_BUFFER_SIZE))
{
//memset(m_RecvData, 0, m_iRecvBytes);
if (m_bDebug)
{
auto pszDest = new char[len * 2 + 1];
hex2str(pszDest, abIn, len);
printf("kaishi len=%d, m_iExpectBytes=%d, %s\n", len, m_iExpectBytes, pszDest); //打印单包数据,每次可以从这里得到单包数据
}
// 第一层判断,当前接收正好为期望返回
if (len == m_iExpectBytes)
{
memcpy(m_RecvData, abIn, len);
m_iRecvBytes = len;
m_iRecvState = true;
printf("=====");
temp_Packlen = 0;
}
// 第二层判断,当前接收为期望返回的一部分
else if (len < m_iExpectBytes)
{
memcpy(m_RecvData + temp_Packlen, abIn, len);
temp_Packlen += len;
//打印拼包后的数据
auto pszDest = new char[m_iRecvBytes * 2 + 1];
hex2str(pszDest, m_RecvData, m_iRecvBytes);
printf("pinbao = %d %s\n", m_iRecvBytes, pszDest);
// 第三层判断,当前接收为期望返回的最后一部分
if (temp_Packlen == m_iExpectBytes)
{
m_iRecvBytes = temp_Packlen;
m_iRecvState = true;
printf("pinbao========");
}
}
// 第四层判断,当前接收为期望返回的超出部分,以实际接收为准
else if (len > m_iExpectBytes)
{
memcpy(m_RecvData, abIn, len);
m_iRecvBytes = len;
m_iRecvState = true;
printf(">>>>>>>>>>>>========");
temp_Packlen = 0;
}
}
// 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());
}
#if 0
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());
}
#endif
/////////////////////////////////////////////////////////////////////////////
// OnReceive() : Default OnReceive()
// V114
void CPSerial::OnReceive()
{
// Dummy OnReceieve if not used
char s[MAX_RECIEVE_BUFFER_SIZE] = {0};
s[1] = '\0';
CurrentPointer = 0;
int num = 0;
if (m_HandShake == CS_HANDSHAKE_FOR_TRESASTR_E)
{
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
{
num = ReadPort(s, m_iRecvCount);
printf("----Data received:: %d----\r\n", num);
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;
for (int i = 0; i < num; i++)
{
printf(" %02X ", m_RecvData[i]);
}
}
}
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(5);
// 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<BYTE>(Bits); // data size, xmit, and rcv
SerialDCB.StopBits = static_cast<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, Program Port 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);
}
//字节数据转换为16进制字符串
CString CPSerial::HexToStr(const char* pData, int nLen)
{
CString str;
CString strTemp;
for (int i = 0; i < nLen; i++)
{
strTemp.Format(_T(" %02X "), pData[i]);
str += strTemp;
}
return str;
}
//unsigned char CPSerial::HexCharToByte(char ch)
//{
// if ((ch >= '0') && (ch <= '9'))
// return ch - '0';
// if ((ch >= 'A') && (ch <= 'F'))
// return ch - 'A' + 10;
// if ((ch >= 'a') && (ch <= 'f'))
// return ch - 'a' + 10;
// return 0;
//}
/////////////////////////////////////////////////////////////////////////////
// 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