⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commport.cpp

📁 cell phone source code
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -