📄 commport.cpp
字号:
// CommPort.cpp: implementation of the CCommPort class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CommPort.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCommPort::CCommPort()
{
m_hCommFile = INVALID_HANDLE_VALUE;
m_strDeviceName = "";
m_pOverlappedRead = NULL;
}
CCommPort::~CCommPort()
{
if (m_hCommFile != INVALID_HANDLE_VALUE)
{
Close();
}
if (m_pOverlappedRead != NULL)
{
// OutputDebugString("free overlapped read buffer\n");
free(m_pOverlappedRead);
}
}
BOOL CCommPort::Open(HWND hWnd, int iBaudRate, CString strDeviceName, UINT uMsg, HANDLE hCommFile)
{
m_hCommFile = hCommFile;
if (m_hCommFile == INVALID_HANDLE_VALUE)
{
m_hCommFile = CreateFile(strDeviceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED|FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING, NULL);
if (m_hCommFile == INVALID_HANDLE_VALUE)
{
goto Error;
}
}
else
{
if (GetFileType(m_hCommFile) != FILE_TYPE_CHAR) // Is this a valid comm handle?
{
m_hCommFile = INVALID_HANDLE_VALUE;
goto Error;
}
}
m_strDeviceName = strDeviceName;
if (Prepare(hWnd, iBaudRate, uMsg) == FALSE)
{
goto Error;
}
if (!SetState())
{
goto Error;
}
m_hReadThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReadThreadFunc, this, 0, &m_dwReadThreadId);
if (m_hReadThread == NULL)
{
OutputDebugString("CreateThread() failed in CCommPort::Open()\n");
goto Error;
}
SetThreadPriority(m_hReadThread, THREAD_PRIORITY_HIGHEST);
m_hWriteThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WriteThreadFunc, this, 0, &m_dwWriteThreadId);
if (m_hWriteThread == NULL)
{
OutputDebugString("CreateThread() failed in CCommPort::Open()\n");
goto Error;
}
SetThreadPriority(m_hWriteThread, THREAD_PRIORITY_ABOVE_NORMAL);
return TRUE;
Error:
Close();
return FALSE;
}
void CCommPort::Close()
{
if (m_hCommFile != INVALID_HANDLE_VALUE)
{
TRACE("Ready to close RS232\r\n");
if (m_hReadThread != NULL)
{
// Signal the event to close the worker threads.
SetEvent(m_hQuitEvent);
PurgeComm(m_hCommFile, PURGE_RXABORT|PURGE_RXCLEAR);
if (WaitForSingleObject(m_hReadThread, 3000) == WAIT_TIMEOUT)
{
OutputDebugString("Force to close CommPort read thread\n");
TerminateThread(m_hReadThread, 0);
CloseHandle(m_hReadThread);
}
m_hReadThread = NULL;
}
if (m_hWriteThread != NULL)
{
// Signal the event to close the worker threads.
SetEvent(m_hQuitEvent);
PurgeComm(m_hCommFile, PURGE_TXABORT|PURGE_TXCLEAR);
if (WaitForSingleObject(m_hWriteThread, 3000) == WAIT_TIMEOUT)
{
OutputDebugString("Force to close CommPort write thread\n");
TerminateThread(m_hWriteThread, 0);
CloseHandle(m_hWriteThread);
}
m_hWriteThread = NULL;
}
Unprepare();
if (m_strDeviceName != "")
{ // So this handle is OPENED by us in Open()
TRACE("Close Com file\r\n");
CloseHandle(m_hCommFile);
}
m_hCommFile = INVALID_HANDLE_VALUE;
m_strDeviceName = "";
}
}
BOOL CCommPort::Write(char * pData, int iLength)
{
if (m_hCommFile == INVALID_HANDLE_VALUE) return FALSE;
// if (m_hOutputEvent == NULL) return FALSE;
CSingleLock sLock(&m_critical);
Data * p = (Data *)malloc(sizeof(Data));
if (p == NULL)
{
OutputDebugString("malloc failed in CCommPort::Write\n");
return FALSE;
}
p->pData = (char *)malloc(COMMPORT_DATA_SIZE);
if (p->pData == NULL)
{
free(p);
OutputDebugString("malloc failed in CCommPort::Write\n");
return FALSE;
}
memcpy(p->pData, pData, iLength);
p->iLength = iLength;
sLock.Lock();
m_sendQueue.AddTail(p);
sLock.Unlock();
SetEvent(m_hOutputEvent);
return TRUE;
}
BOOL CCommPort::Put(char ch)
{
if (m_hCommFile == INVALID_HANDLE_VALUE) return FALSE;
// if (m_hOutputEvent == NULL) return FALSE;
CSingleLock sLock(&m_critical);
Data * p = (Data *)malloc(sizeof(Data));
if (p == NULL)
{
OutputDebugString("malloc failed in CCommPort::Write\n");
return FALSE;
}
p->pData = (char *)malloc(1);
if (p->pData == NULL)
{
free(p);
OutputDebugString("malloc failed in CCommPort::Write\n");
return FALSE;
}
p->pData[0] = ch;
p->iLength = 1;
sLock.Lock();
m_sendQueue.AddTail(p);
sLock.Unlock();
SetEvent(m_hOutputEvent);
return TRUE;
}
BOOL CCommPort::Busy()
{
return (m_sendQueue.GetCount() > COMMPORT_QUEUE_SIZE);
}
int CCommPort::GetBaudRate()
{
return m_iBaudRate;
}
BOOL CCommPort::Prepare(HWND hWnd, int iBaudRate, UINT uMsg)
{
m_hReadThread = m_hWriteThread = m_hQuitEvent = m_hOutputEvent = NULL;
m_hWnd = hWnd;
m_uMsg = uMsg;
m_iBaudRate = iBaudRate;
if (!PrepareOverlapped(&m_overlappedRead) || !PrepareOverlapped(&m_overlappedWrite) || !PrepareOverlapped(&m_overlappedCommEvent))
{
goto Error;
}
m_hOutputEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hQuitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!m_hOutputEvent || !m_hQuitEvent)
{
OutputDebugString("CreateEvent() failed in CCommPort::prepare()\n");
goto Error;
}
return TRUE;
Error:
Unprepare();
return FALSE;
}
void CCommPort::Unprepare()
{
if (m_hQuitEvent != NULL)
{
CloseHandle(m_hQuitEvent);
m_hQuitEvent = NULL;
}
if (m_hOutputEvent != NULL)
{
CloseHandle(m_hOutputEvent);
m_hOutputEvent = NULL;
}
UnprepareOverlapped(&m_overlappedWrite);
UnprepareOverlapped(&m_overlappedRead);
UnprepareOverlapped(&m_overlappedCommEvent);
while (!m_sendQueue.IsEmpty())
{
Data * p = m_sendQueue.RemoveHead();
free(p->pData);
free(p);
}
}
BOOL CCommPort::PrepareOverlapped(OVERLAPPED * p)
{
p->Internal = 0;
p->InternalHigh = 0;
p->Offset = 0;
p->OffsetHigh = 0;
p->hEvent = NULL;
p->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (p->hEvent == NULL)
{
OutputDebugString("Unable to CreateEvent in CCommPort::PrepareOverlapped\n");
return FALSE;
}
return TRUE;
}
void CCommPort::UnprepareOverlapped(OVERLAPPED * p)
{
if (p->hEvent != NULL)
{
CloseHandle(p->hEvent);
p->hEvent = NULL;
}
}
DWORD WINAPI CCommPort::ReadThreadFunc(LPVOID pParam)
{
DWORD dwWaitStatus; // holds return value of the wait
CCommPort * p = (CCommPort *)pParam;
HANDLE eventArray[3]; // The array of events which the read thread is currently waiting on.
eventArray[0] = p->m_hQuitEvent;
eventArray[1] = p->m_overlappedCommEvent.hEvent;
eventArray[2] = p->m_overlappedRead.hEvent;
if (!p->SetupCommEvent() || !p->SetupReadEvent()) // Start waiting for comm events (Errors) and read events
{
goto EndThread;
}
OutputDebugString("CommPort read thread starting\n");
// This is the main loop. Loop until we break out.
while (TRUE)
{
// Wait for an event
dwWaitStatus = WaitForMultipleObjects(3, eventArray, FALSE, INFINITE);
switch (dwWaitStatus)
{
case WAIT_FAILED: // A fatal error
OutputDebugString("WaitForMultipleObjects() failed in CommPort read thread\n");
PostMessage(p->m_hWnd, WM_COMMPORT_ERROR, 0, 0);
break;
case WAIT_OBJECT_0: // Quit time;
break;
case WAIT_OBJECT_0+1: // Overlapped Comm Event;
if (p->HandleCommEvent(TRUE))
{
if (p->SetupCommEvent())
{
continue;
}
}
PostMessage(p->m_hWnd, WM_COMMPORT_ERROR, 0, 0);
break;
case WAIT_OBJECT_0+2: // Overlapped Read;
if (p->HandleReadEvent())
{
if (p->SetupReadEvent())
{
continue;
}
}
PostMessage(p->m_hWnd, WM_COMMPORT_ERROR, 0, 0);
break;
default:
OutputDebugString("Unknown error: WaitForMultipleObjects() in CommPort read thread\n");
PostMessage(p->m_hWnd, WM_COMMPORT_ERROR, 0, 0);
break;
} // switch (dwWaitStatus)
// Break out of the while loop.
break;
} // while (1)
// Thats the end. Now clean up.
EndThread:
OutputDebugString("CommPort read thread shutting down\n");
CloseHandle(p->m_hReadThread);
return 0;
}
DWORD WINAPI CCommPort::WriteThreadFunc(LPVOID pParam)
{
DWORD dwWaitStatus; // holds return value of the wait
CCommPort * p = (CCommPort *)pParam;
HANDLE eventArray[2]; // The array of events which the write thread is currently waiting on.
eventArray[0] = p->m_hQuitEvent;
eventArray[1] = p->m_hOutputEvent;
// eventArray[2] = p->m_overlappedWrite.hEvent;
OutputDebugString("CommPort write thread starting\n");
// This is the main loop. Loop until we break out.
while (TRUE)
{
// Wait for an event
dwWaitStatus = WaitForMultipleObjects(2, eventArray, FALSE, INFINITE);
switch (dwWaitStatus)
{
case WAIT_FAILED: // A fatal error
OutputDebugString("WaitForMultipleObjects() failed in CommPort write thread\n");
PostMessage(p->m_hWnd, WM_COMMPORT_ERROR, 0, 0);
break;
case WAIT_OBJECT_0: // Quit time;
break;
case WAIT_OBJECT_0+1: // The hOutputEvent has been signaled.
if (p->HandleWriteEvent())
{
continue;
}
PostMessage(p->m_hWnd, WM_COMMPORT_ERROR, 0, 0);
break;
default:
OutputDebugString("Unknown error: WaitForMultipleObjects() in CommPort write thread\n");
PostMessage(p->m_hWnd, WM_COMMPORT_ERROR, 0, 0);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -