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

📄 commport.cpp

📁 cell phone source code
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		} // switch (dwWaitStatus)
		// Break out of the while loop.
		break;
	} // while (1)

	// Thats the end.  Now clean up.
//EndThread:
	OutputDebugString("CommPort write thread shutting down\n");
	CloseHandle(p->m_hWriteThread);
	return 0;
}

BOOL CCommPort::SetState()
{
	COMMPROP commprop;
	COMMTIMEOUTS commtimeouts;
	DCB dcb;

	if (!PurgeComm(m_hCommFile, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR))
	{
		OutputDebugString("Purge Comm fail\n");
		return FALSE;
	}

	if (!GetCommProperties(m_hCommFile, &commprop))
	{
		OutputDebugString("Get Comm Properties fail\n");
		return FALSE;
	}

	if (!SetupComm(m_hCommFile, COMMPORT_DATA_SIZE, COMMPORT_DATA_SIZE))	
	{
		OutputDebugString("Setup Comm fail\n");
		return FALSE;
	}

	commtimeouts.ReadIntervalTimeout         = 0;
	commtimeouts.ReadTotalTimeoutMultiplier  = 0;
	commtimeouts.ReadTotalTimeoutConstant    = 1;
	commtimeouts.WriteTotalTimeoutMultiplier = 0;
	commtimeouts.WriteTotalTimeoutConstant   = 1;
	if (!SetCommTimeouts(m_hCommFile, &commtimeouts))
	{
		OutputDebugString("Set Comm Timeout fail\n");
		return FALSE;
	}

	if (!GetCommState(m_hCommFile, &dcb))
	{
		OutputDebugString("Get Comm State fail\n");
		return FALSE;
	}
	dcb.fAbortOnError	= FALSE;
	dcb.BaudRate		= m_iBaudRate;
	dcb.fBinary			= TRUE;
	dcb.StopBits		= ONESTOPBIT;
	dcb.Parity			= NOPARITY;
	dcb.fParity			= FALSE;
	dcb.fNull			= FALSE;
	dcb.fOutxCtsFlow	= FALSE;
	dcb.fOutxDsrFlow	= FALSE;
	dcb.fDtrControl		= DTR_CONTROL_DISABLE;
	dcb.fDsrSensitivity	= FALSE;
	dcb.fTXContinueOnXoff = FALSE;
	dcb.fOutX			= FALSE;
	dcb.fInX			= FALSE;
	dcb.fErrorChar		= FALSE;
	dcb.fRtsControl		= RTS_CONTROL_DISABLE;
	if (!SetCommState(m_hCommFile, &dcb))
	{
		OutputDebugString("Set Comm State fail\n");
		return FALSE;
	}

	if (!SetCommMask(m_hCommFile, EV_ERR))	// Set the comm mask so we receive error signals.
	{
		OutputDebugString("Unable to SetCommMask: EV_ERR\n");
		return FALSE;
	}

	return TRUE;
}

BOOL CCommPort::SetupReadEvent()
{
	DWORD dwLastError, dwRead;
	char * pData;

	while (TRUE)
	{
		// Make sure the CloseEvent hasn't been signaled yet. Check is needed because this function is potentially recursive.
		if (WAIT_TIMEOUT != WaitForSingleObject(m_hQuitEvent, 0))
		{
			return FALSE;
		}
  
		// Start the overlapped ReadFile.
		pData = (char *)malloc(COMMPORT_DATA_SIZE);
		if (pData == NULL)	return FALSE;
		if (ReadFile(m_hCommFile, pData, COMMPORT_DATA_SIZE, &dwRead, &m_overlappedRead))
		{	// This would only happen if there was data waiting to be read.
			OutputDebugString("Data waiting for ReadFile.\n");
			// Handle the data.
			if (dwRead > 0)
			{
				CString temp;
				temp.Format("Read %d bytes\n", dwRead);
				OutputDebugString(temp);
				PostMessage(m_hWnd, m_uMsg, (WPARAM)dwRead, (LPARAM)pData);
			}
			else
			{
				free(pData);
			}
		}
		else
			break;
	}

	// ReadFile failed.  Expected because of overlapped I/O.
	dwLastError = GetLastError();
	if (dwLastError == ERROR_IO_PENDING)    // LastError was ERROR_IO_PENDING, as expected.
	{
		if (m_pOverlappedRead != NULL)
			free(m_pOverlappedRead);
		m_pOverlappedRead = pData;
		return TRUE;
	}
	else if (dwLastError == ERROR_INVALID_HANDLE)
	{	// Its possible for this error to occur if the service provider has closed the port.  Time to end.
		OutputDebugString("ERROR_INVALID_HANDLE: Likely that the Service Provider has closed the port.\n");
	}

	// Unexpected error. No idea what could cause this to happen.
	OutputDebugString("Unexpected ReadFile error in CommPort read thread.\n");
	free(pData);
	return FALSE;
}

BOOL CCommPort::HandleReadEvent()
{
	DWORD dwLastError, dwRead;

	if (GetOverlappedResult(m_hCommFile, &m_overlappedRead, &dwRead, FALSE))
	{
		if (dwRead > 0)
		{
			PostMessage(m_hWnd, m_uMsg, (WPARAM)dwRead, (LPARAM)m_pOverlappedRead);
		}
		else
		{
			free(m_pOverlappedRead);
		}
		m_pOverlappedRead = NULL;
		return TRUE;
	}
	free(m_pOverlappedRead);
	m_pOverlappedRead = NULL;

	// Error in GetOverlappedResult; handle it.
	dwLastError = GetLastError();
	if (dwLastError == ERROR_INVALID_HANDLE)
	{	// Its possible for this error to occur if the service provider has closed the port.  Time to end.
		OutputDebugString("ERROR_INVALID_HANDLE: Likely that the Service Provider has closed the port.\n");
	}
	OutputDebugString("Unexpected GetOverlappedResult Read Error in CommPort read thread.\n");
	return FALSE;
}

BOOL CCommPort::SetupCommEvent()
{
	DWORD dwLastError;

	while (TRUE)
	{
		// Make sure the CloseEvent hasn't been signaled yet. Check is needed because this function is potentially recursive.
		if (WAIT_TIMEOUT != WaitForSingleObject(m_hQuitEvent, 0))
		{
			return FALSE;
		}
		
		// Start waiting for Comm Errors.
		if (WaitCommEvent(m_hCommFile, &m_dwEventMask, &m_overlappedCommEvent))
		{
			// This could happen if there was an error waiting on the comm port.  Lets try and handle it.
			OutputDebugString("Event (Error) waiting before WaitCommEvent.\n");
			if (!HandleCommEvent(FALSE))
			{
				return FALSE;
			}
			// What could cause infinite recursion at this point?
			continue;
		}
		break;
	}

	// We expect ERROR_IO_PENDING returned from WaitCommEvent because we are waiting with an overlapped structure.
	dwLastError = GetLastError();
	if (dwLastError == ERROR_IO_PENDING)
	{	// LastError was ERROR_IO_PENDING, as expected.
		OutputDebugString("Waiting for a CommEvent (Error) to occur.\n");
		return TRUE;
	}
	else if (dwLastError == ERROR_INVALID_HANDLE)
	{	// Its possible for this error to occur if the service provider has closed the port.  Time to end.
		OutputDebugString("ERROR_INVALID_HANDLE: Likely that the Service Provider has closed the port.\n");
		return FALSE;
	}
	// Unexpected error. No idea what could cause this to happen.
	OutputDebugString("Unexpected WaitCommEvent error in CommPort read thread.\n");
	return FALSE;
}

BOOL CCommPort::HandleCommEvent(BOOL bRetrieveEvent)
{
	DWORD dwDummy, dwErrors, dwLastError;
	CString strError = "Comm Event: ";

	// If this fails, it could be because the file was closed (and I/O is finished) or because the overlapped I/O
	// is still in progress. In either case (or any others) its a bug and return FALSE.
	if (bRetrieveEvent)
	{
		if (!GetOverlappedResult(m_hCommFile, &m_overlappedCommEvent, &dwDummy, FALSE))
		{
			dwLastError = GetLastError();
			if (dwLastError == ERROR_INVALID_HANDLE)
			{	// Its possible for this error to occur if the service provider has closed the port.  Time to end.
				OutputDebugString("ERROR_INVALID_HANDLE: Likely that the Service Provider has closed the port.\n");
				return FALSE;
			}
			OutputDebugString("Unexpected GetOverlappedResult for WaitCommEvent in CommPort IO threaed.\n");
			return FALSE;
		}
	}

	// Was the event an error?
	if (m_dwEventMask & EV_ERR)
	{
		// Which error was it?
		if (!ClearCommError(m_hCommFile, &dwErrors, NULL))
		{
			dwLastError = GetLastError();
			if (dwLastError == ERROR_INVALID_HANDLE)
			{	// Its possible for this error to occur if the service provider has closed the port.  Time to end.
				OutputDebugString("ERROR_INVALID_HANDLE: Likely that the Service Provider has closed the port.\n");
				return FALSE;
			}
			OutputDebugString("ClearCommError in CommPort read thread.\n");
			return FALSE;
		}

		// Its possible that multiple errors occured and were handled in the last ClearCommError.  Because all errors
		// were signaled individually, but cleared all at once, pending comm events can yield EV_ERR while dwErrors equals 0.  Ignore this event.
		if (dwErrors == 0)
		{
			strError += "NULL Error, ";
		}
		if (dwErrors & CE_FRAME)
		{
			strError += "CE_FRAME, ";
		}
		if (dwErrors & CE_OVERRUN)
		{
			strError += "CE_OVERRUN, ";
		}
		if (dwErrors & CE_RXPARITY)
		{
			strError += "CE_RXPARITY, ";
		}
		if (dwErrors & ~ (CE_FRAME | CE_OVERRUN | CE_RXPARITY))
        {
			strError += "EV_ERR Unknown EvtMask";
        }
		strError += "\n";
		OutputDebugString(strError);
		return TRUE;
	}

	// Should not have gotten here.  Only interested in ERR conditions.
	OutputDebugString("Unexpected comm event in CommPort read thread.\n");
	return FALSE;
}

BOOL CCommPort::HandleWriteEvent()
{
	DWORD dwHandleSignaled, dwLastError, dwNumberWritten = 0, dwStartWriting = 0;
	int iLength; // Start at the beginning.
	char * pData;
	HANDLE eventArray[2];	// The array of events which the write operation is currently waiting on.
	CSingleLock sLock(&m_critical);
	Data * p = NULL;

	sLock.Lock();
	if (!m_sendQueue.IsEmpty())
	{
		p = m_sendQueue.RemoveHead();
	}
	sLock.Unlock();

	if (p == NULL)
		return TRUE;

	iLength = p->iLength;
	pData = p->pData;

	eventArray[0] = m_hQuitEvent;
	eventArray[1] = m_overlappedWrite.hEvent;

	// Keep looping until all bytes have been written.
	do
	{
		// Start the overlapped I/O.
		if (!WriteFile(m_hCommFile, &pData[dwStartWriting], iLength, &dwNumberWritten, &m_overlappedWrite))
		{
			// WriteFile failed.  Expected; lets handle it.
			dwLastError = GetLastError();
			if (dwLastError == ERROR_INVALID_HANDLE)
			{	// Its possible for this error to occur if the service provider has closed the port.  Time to end.
				OutputDebugString("ERROR_INVALID_HANDLE: Likely that the Service Provider has closed the port.\n");
				goto Error;
			}
			if (dwLastError != ERROR_IO_PENDING)
			{	// Unexpected error.  No idea what.
				OutputDebugString("Error to writing to CommFile in CommPort write thread.\n");
				goto Error;
			}

			// This is the expected ERROR_IO_PENDING case.
			// Wait for either overlapped I/O completion, or for the CloseEvent to get signaled.
			dwHandleSignaled = WaitForMultipleObjects(2, eventArray, FALSE, INFINITE);
			switch (dwHandleSignaled)
			{
			case WAIT_OBJECT_0:     // CloseEvent signaled! Time to exit.
				goto Error;

			case WAIT_OBJECT_0 + 1: // Wait finished.  Time to get the results of the WriteFile
				break;

			case WAIT_FAILED: // Wait failed.  Shouldn't happen.
				OutputDebugString("Write WAIT_FAILED in CommPort write thread.\n");
				goto Error;

			default: // This case should never occur.
				OutputDebugString("Unexpected Wait return value in CommPort write thread.\n");
				goto Error;
			}

			if (!GetOverlappedResult(m_hCommFile, &m_overlappedWrite, &dwNumberWritten, TRUE))
			{
				dwLastError = GetLastError();
				if (dwLastError == ERROR_INVALID_HANDLE)
				{	// Its possible for this error to occur if the  service provider has closed the port.
					OutputDebugString("ERROR_INVALID_HANDLE: Likely that the Service Provider has closed the port.\n");
					goto Error;
				}
				// No idea what could cause another error.
				OutputDebugString("Error writing to CommFile while waiting in CommPort write thread.\n");
				goto Error;
			}
		}

		// Some data was written.  Make sure it all got written.
		iLength -= dwNumberWritten;
		dwStartWriting += dwNumberWritten;
	} while(iLength > 0);  // Write the whole thing!

	free(pData);
	free(p);

	sLock.Lock();
	if (!m_sendQueue.IsEmpty())
	{
		SetEvent(m_hOutputEvent);
	}
	sLock.Unlock();

	return TRUE;

Error:
	free(pData);
	free(p);
	return FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -