📄 communication.cpp
字号:
m_hPortHandle = INVALID_HANDLE_VALUE;
CloseHandle(hPort);
}
return bStatus;
}
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
BOOL CCommunication::SetOutput(LPCSTR lpszText)
{
#ifdef BUILD_USB_CONFIG
if (m_eComm == ccUSB)
{
return m_pUsb->SendData((BYTE*)lpszText, strlen(lpszText));
}
else
#endif
{
return SetOutput((BYTE*)lpszText, strlen(lpszText));
}
}
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
BOOL CCommunication::SetOutput(BYTE *pData, int nSize)
{
#ifdef BUILD_USB_CONFIG
if (m_eComm == ccUSB)
{
m_pUsb->SendData(pData, nSize);
}
else
#endif
{
CByteArray byteArray;
byteArray.SetSize(nSize);
BYTE *pDest = byteArray.GetData();
CopyMemory((void*)pDest, (void*)pData, nSize);
int nWriteDataSize = 0;
{
CMakeSafe ms(&m_MakeSafeWriterArray); // make access to que thread-safe
m_WriterByteArray.Append(byteArray);
nWriteDataSize = m_WriterByteArray.GetSize();
}
::ResetEvent(m_hWriteBufferEmptyEvent); // buffer contains data
// notify writer thread that new data is in que
::SetEvent(m_hWriteDataEvent);
if (nWriteDataSize > HEAP_WRITEBUFFER_LIMIT)
{
WaitForWriteToComplete();
}
}
return TRUE;
}
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
BOOL CCommunication::WaitForWriteToComplete()
{
HANDLE hArray[2];
hArray[0] = m_hWriteBufferEmptyEvent;
hArray[1] = m_hKillEvent;
DWORD dwRes = WaitForMultipleObjects(2, hArray, FALSE,
WRITE_CHECK_TIMEOUT);
BOOL bStatus = TRUE;
switch (dwRes)
{
case WAIT_OBJECT_0:
break;
// thread exit event
case WAIT_OBJECT_0 + 1:
default:
bStatus = FALSE;
}
return bStatus;
}
//----------------------------------------------------------------------------
// Public method
//----------------------------------------------------------------------------
void CCommunication::GetInput(CByteArray& ref_byteArray)
{
DWORD dwSize = 0;
{
CMakeSafe ms(&m_MakeSafeReaderArray); // make access to que thread-safe
m_bPostedDataToReadMessage = FALSE;
dwSize = m_ReaderByteArray.GetSize();
if (dwSize)
{
ref_byteArray.Copy(m_ReaderByteArray);
m_ReaderByteArray.RemoveAll();
}
else
{
ref_byteArray.RemoveAll();
}
}
}
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
BOOL CCommunication::FlushBuffer()
{
CMakeSafe ms(&m_MakeSafeReaderArray); // make access to que thread-safe
m_ReaderByteArray.RemoveAll();
return TRUE;
}
//----------------------------------------------------------------------------
// Private method
//----------------------------------------------------------------------------
BOOL CCommunication::UpdateCommState(int nBaudRate)
{
if (INVALID_HANDLE_VALUE == m_hPortHandle)
{
return FALSE;
}
DCB dcb = {0};
dcb.DCBlength = sizeof(dcb);
// get current DCB settings
if (FALSE == GetCommState(m_hPortHandle, &dcb))
{
TRACE("GetCommState failed\n");
return FALSE;
}
//------------------------------------------------------------------------
// Set comm states here
//------------------------------------------------------------------------
dcb.fParity = FALSE;
dcb.Parity = NOPARITY;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.fOutxCtsFlow = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.BaudRate = nBaudRate;
if (FALSE == SetCommState(m_hPortHandle, &dcb))
{
TRACE("SetCommState failed\n");
return FALSE;
}
if (FALSE == SetCommTimeouts(m_hPortHandle, &TimeoutsDefault))
{
DWORD dwErr = GetLastError();
TRACE("<CCommunication::UpdateCommState> SetCommTimeouts failed: Handle=0x%08X, Err=0x%08X\n", m_hPortHandle, dwErr);
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------------
// Private method
//----------------------------------------------------------------------------
void CCommunication::CheckModemStatus()
{
if (INVALID_HANDLE_VALUE == m_hPortHandle)
{
return;
}
if (FALSE == GetCommModemStatus(m_hPortHandle, &m_dwModemStatus))
{
TRACE("GetCommModemStatus failed\n");
return;
}
}
//----------------------------------------------------------------------------
// Private method
//----------------------------------------------------------------------------
void CCommunication::CheckComStatus()
{
if (INVALID_HANDLE_VALUE == m_hPortHandle)
{
return;
}
// The ClearCommError function retrieves information about a communications
// error and reports the current status of a communications device. The
// function is called when a communications error occurs, and it clears
// the device's error flag to enable additional input and output (I/O)
// operations.
if (FALSE == ClearCommError(m_hPortHandle, &m_dwComError, &m_ComStatus))
{
TRACE("ClearCommError failed\n");
return;
}
}
//----------------------------------------------------------------------------
// Private method
//
// Return: TRUE= I/O is pending.
//----------------------------------------------------------------------------
BOOL CCommunication::AttemptToRead(char *pBuffer, DWORD dwBuffSize,
OVERLAPPED *posReader)
{
if (INVALID_HANDLE_VALUE == m_hPortHandle)
{
return FALSE;
}
DWORD dwRead = 0;
if (FALSE == ReadFile(m_hPortHandle, pBuffer,
dwBuffSize, &dwRead, posReader))
{
DWORD dwError = GetLastError();
if (ERROR_IO_PENDING != dwError) // read not delayed?
{
TRACE("ReadFile failed Err=%d\n", dwError);
// We must clear the device's error flag to enable additional I/O operations.
CheckComStatus();
}
else
{
return TRUE; // I/O is pending
}
}
else
{
// read completed immediately
if (MAX_READ_BUFFER != dwRead)
{
TRACE("Read timed-out immediately\n");
}
if (dwRead)
{
PutDataReadInQue(pBuffer, dwRead);
}
}
return FALSE; // I/O operation completed (I/O not pending).
}
//----------------------------------------------------------------------------
// Private method
//
// Return: TRUE= Status is pending.
//----------------------------------------------------------------------------
BOOL CCommunication::AttemptToGetCommEvent(OVERLAPPED *posStatus,
DWORD& refdwEvent)
{
if (INVALID_HANDLE_VALUE == m_hPortHandle)
{
return FALSE;
}
if (FALSE == WaitCommEvent(m_hPortHandle, &refdwEvent,
posStatus))
{
if (ERROR_IO_PENDING != GetLastError()) // Wait not delayed?
{
TRACE("WaitCommEvent failed\n");
// We must clear the device's error flag to enable additional I/O operations.
CheckComStatus();
}
else
{
return TRUE; // Status is pending
}
}
else
{
// WaitCommEvent returned immediately
ReportStatusEvent(refdwEvent);
}
return FALSE; // Status completed (not pending).
}
//----------------------------------------------------------------------------
// Private method
//----------------------------------------------------------------------------
void CCommunication::ReportStatusEvent(DWORD dwEvent)
{
#if defined(_MAX_DEBUG)
TRACE("Got status event 0x%08X\n", dwEvent);
#endif
}
//----------------------------------------------------------------------------
// Private method
//----------------------------------------------------------------------------
BOOL CCommunication::PostComMessage(UINT iMessage,
WPARAM wParam /* = 0 */,
LPARAM lParam /* = 0 */)
{
if (m_hParentWnd)
{
return PostMessage(m_hParentWnd, iMessage, wParam, lParam);
}
return ::PostThreadMessage(m_dwMainThreadId,
iMessage,
wParam,
lParam);
}
//----------------------------------------------------------------------------
// Private method
//----------------------------------------------------------------------------
BOOL CCommunication::PutDataReadInQue(char *pData, DWORD dwSize)
{
CByteArray byteArray;
byteArray.SetSize(dwSize);
BYTE *pBuffer = byteArray.GetData();
CopyMemory(pBuffer, pData, dwSize);
{
CMakeSafe ms(&m_MakeSafeReaderArray); // make access to que thread-safe
m_ReaderByteArray.Append(byteArray);
#ifdef _MAX_DEBUG
TRACE("Got %d bytes: ", dwSize);
for (int i = 0; i < (int)dwSize; i++)
{
TRACE("0x%02X ", pBuffer[i]);
}
CString cStr((LPCSTR)pBuffer, dwSize);
TRACE(" %s", cStr);
TRACE("\n");
#endif
if (FALSE == m_bPostedDataToReadMessage)
{
if (FALSE == PostComMessage(COM_PORT_MESSAGE, vbMSCommEvReceive))
{
TRACE("PostComMessage failed\n");
}
else
{
m_bPostedDataToReadMessage = TRUE;
}
}
}
return TRUE;
}
typedef enum
{
reKILL,
reREADER,
reSTATUS
} READEREVENTS;
#define NUMBER_OF_READER_EVENTS (3)
//----------------------------------------------------------------------------
// Static private thread procedure.
//----------------------------------------------------------------------------
DWORD WINAPI CCommunication::ReaderThreadProc(LPVOID pParam)
{
CCommunication *pThis = (CCommunication*)pParam;
OVERLAPPED osReader = {0}; // overlapped structure for read operations
OVERLAPPED osStatus = {0}; // overlapped structure for status operations
// Create two overlapped structures, one for read events and another for
// status events.
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == osReader.hEvent || NULL == osStatus.hEvent)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -