www.pudn.com > RPort.rar > PortThread.cpp


// PortThread.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "RPort.h" 
#include "PortThread.h" 
#include "Nser.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CPortThread 
 
IMPLEMENT_DYNCREATE(CPortThread, CWinThread) 
 
CPortThread::CPortThread() 
{ 
	m_hFile = INVALID_HANDLE_VALUE; 
	m_hTimer = 0; 
	m_nIndex = 0; 
	m_pConnect = NULL; 
	m_nbufCount = m_nBufDesired = 0; 
	m_bCommandReceiving = m_bPreIsFF = FALSE; 
	m_nTimerCount = 0; 
} 
 
CPortThread::~CPortThread() 
{ 
} 
 
BOOL CPortThread::InitInstance() 
{ 
	TRACE(_T("CPortThread::InitInstance with port: %s\n"), (LPCTSTR)m_strPort); 
 
	BOOL bRet = TRUE; 
	CString	strHead; 
	strHead.Format(_T("\\\\.\\%s"), (LPCSTR)m_strPort); 
	HANDLE hFile = CreateFile((LPCTSTR)strHead, 
		GENERIC_READ | GENERIC_WRITE, 
		0, 
		NULL, 
		OPEN_EXISTING, 
		FILE_ATTRIBUTE_NORMAL, 
		NULL); 
	 
	if(hFile == INVALID_HANDLE_VALUE) 
	{ 
		DWORD dw = GetLastError(); 
		if(dw == ERROR_FILE_NOT_FOUND) 
		{ 
			g_csPortState.Lock(); 
			g_arrPortState[m_nIndex].bOpened = -2; 
			g_csPortState.Unlock(); 
			m_sServer.Close(); 
			bRet = FALSE; 
		} 
	} 
	else 
		CloseHandle(hFile); 
 
	if(bRet) 
	{ 
		m_sServer.m_pThread = this; 
		if(!m_sServer.Create(SERVERPORTBASE + 1 + m_nIndex) || !m_sServer.Listen()) 
		{ 
			g_csPortState.Lock(); 
			g_arrPortState[m_nIndex].bOpened = -1; 
			g_csPortState.Unlock(); 
			m_sServer.Close(); 
			bRet = FALSE; 
		} 
	} 
	 
	::PostMessage(m_hWnd, WM_USER, 0 , 0); 
 
	return bRet; 
} 
 
int CPortThread::ExitInstance() 
{ 
	TRACE(_T("CPortThread::ExitInstance with port: %s\n"), (LPCTSTR)m_strPort); 
	CWinThread::ExitInstance(); 
	return -1; 
} 
 
BEGIN_MESSAGE_MAP(CPortThread, CWinThread) 
	//{{AFX_MSG_MAP(CPortThread) 
		// NOTE - the ClassWizard will add and remove mapping macros here. 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CPortThread message handlers 
 
BOOL CPortThread::PreTranslateMessage(MSG* pMsg)  
{ 
	if(pMsg->message == WM_TIMER && pMsg->wParam == m_hTimer) 
	{ 
		BOOL bToBeClosed = FALSE; 
 
		ULONG nUnRead = 0; 
		if(m_pConnect->IOCtl(FIONREAD, &nUnRead)) 
		{ 
			if(nUnRead) 
			{ 
				int nRead; 
				BYTE *pRecData = new BYTE[nUnRead]; 
				if((nRead = m_pConnect->Receive(pRecData, nUnRead)) != SOCKET_ERROR) 
				{ 
					TRACE("Data: "); 
					for(int nIndex = 0;nIndex < nRead; nIndex ++) 
					{ 
						TRACE("%02X ", pRecData[nIndex]); 
						BOOL bCommandOk = FALSE; 
						BOOL bSendCurChar = TRUE; 
						if(m_bCommandReceiving) 
						{ 
							bSendCurChar = FALSE; 
							m_Buffer[m_nbufCount] = pRecData[nIndex]; 
							m_nbufCount ++; 
							if(m_nbufCount == m_nBufDesired) 
							{ 
								bCommandOk = TRUE; 
								m_bCommandReceiving = FALSE; 
							} 
						} 
						else switch(pRecData[nIndex]) 
						{ 
						case	0xff: 
							if(!m_bPreIsFF) 
								bSendCurChar = FALSE; 
							break; 
						case	0x01: 
							if(m_bPreIsFF) 
							{ 
								bSendCurChar = FALSE; 
								m_bCommandReceiving = TRUE; 
								m_nBufDesired = 9; 
								m_nbufCount = 1; 
								m_Buffer[0] = pRecData[nIndex]; 
							} 
							break; 
						case	0xef: 
							if(m_bPreIsFF) 
							{ 
								bSendCurChar = FALSE; 
								m_bCommandReceiving = TRUE; 
								m_nBufDesired = 17; 
								m_nbufCount = 1; 
								m_Buffer[0] = pRecData[nIndex]; 
							} 
							break; 
						case	0x02: 
							if(m_bPreIsFF) 
							{ 
								bSendCurChar = FALSE; 
								m_bCommandReceiving = TRUE; 
								m_nBufDesired = 2; 
								m_nbufCount = 1; 
								m_Buffer[0] = pRecData[nIndex]; 
							} 
							break; 
						case	0x04: 
							if(m_bPreIsFF) 
							{ 
								bSendCurChar = FALSE; 
								bToBeClosed = TRUE; 
								m_nBufDesired = 1; 
								m_Buffer[0] = pRecData[nIndex]; 
							} 
							break; 
						case	0x05: 
							if(m_bPreIsFF) 
							{ 
								bSendCurChar = FALSE; 
								m_bCommandReceiving = TRUE; 
								m_nBufDesired = 5; 
								m_nbufCount = 1; 
								m_Buffer[0] = pRecData[nIndex]; 
							} 
							break; 
						case	0xf1: 
							if(m_bPreIsFF) 
							{ 
								bSendCurChar = FALSE; 
								bCommandOk = TRUE; 
								m_nBufDesired = 1; 
								m_Buffer[0] = pRecData[nIndex]; 
							} 
							break; 
						} 
 
						if(pRecData[nIndex] == 0xff) 
							m_bPreIsFF = TRUE; 
						else 
							m_bPreIsFF = FALSE; 
						 
						if(bSendCurChar) 
						{ 
							ULONG nWrite; 
							WriteFile(m_hFile, &pRecData[nIndex], 1, &nWrite, NULL); 
						} 
 
						if(bCommandOk) 
							CommandProc(); 
					} 
					TRACE("\n"); 
				} 
				delete[] pRecData; 
			} 
		} 
		if(bToBeClosed) 
			ClosePort(); 
		else 
		{ 
			DWORD dwError; 
			COMSTAT ComStat; 
			ClearCommError(m_hFile, &dwError, &ComStat); 
 
			m_nTimerCount ++; 
			if(m_nTimerCount == 1000 / INTERNALTIMER || 
				(dwError & (CE_RXPARITY | CE_FRAME | CE_OVERRUN | CE_BREAK))) 
			{ 
				ReportState(dwError); 
				m_nTimerCount = 0; 
			} 
			 
			if(ComStat.cbInQue) 
			{ 
				BYTE *pRecData = new BYTE[ComStat.cbInQue]; 
				DWORD dwRead = ComStat.cbInQue; 
				if(ReadFile(m_hFile, pRecData, dwRead, &dwRead, NULL)) 
				{ 
					for(DWORD i = 0; i < dwRead ; i++) 
					{ 
						if(pRecData[i] == 0xff) 
							m_pConnect->Send(pRecData + i, 1); 
						m_pConnect->Send(pRecData + i, 1); 
					} 
				} 
				delete[] pRecData; 
			} 
		} 
		return TRUE; 
	} 
	return CWinThread::PreTranslateMessage(pMsg); 
} 
 
static BYTE InitAckData[] = {0xff,0xf0, 
0x9a,0x0e,0x48,0x65,0xbd,0x48,0x34,0x03, 
0x22,0x08,0x49,0x62,0x3b,0xe3,0x4b,0x69}; 
 
void CPortThread::CommandProc() 
{ 
	BYTE c = 0xff; 
	switch(m_Buffer[0]) 
	{ 
	case	0xef: 
//		m_pConnect->Send(&c, 1); 
//		c = 0xf0; 
//		m_pConnect->Send(&c, 1); 
//		m_pConnect->Send(m_Buffer + 1, 16); 
//		m_pConnect->Send(InitAckData + 2, 16); 
		m_pConnect->Send(InitAckData, 18); 
		TRACE("Command : 0xef\n"); 
		break; 
	case	0x01: 
		g_csPortState.Lock(); 
 
		DCB dcb; 
		dcb.DCBlength = sizeof( DCB ); 
		GetCommState( m_hFile, &dcb ); 
		 
		if(m_Buffer[1] & MASK_BAUD) 
		{ 
			dcb.BaudRate = *(DWORD *)(m_Buffer + 5); 
			g_arrPortState[m_nIndex].nBaud = dcb.BaudRate; 
		} 
 
		if(m_Buffer[1] & MASK_MODE) 
		{ 
			if((m_Buffer[2] & 3) == CS5) 
			{ 
				dcb.ByteSize = 5; 
				g_arrPortState[m_nIndex].strData = _T("5"); 
			} 
			if((m_Buffer[2] & 3) == CS6) 
			{ 
				dcb.ByteSize = 6; 
				g_arrPortState[m_nIndex].strData = _T("6"); 
			} 
			if((m_Buffer[2] & 3) == CS7) 
			{ 
				dcb.ByteSize = 7; 
				g_arrPortState[m_nIndex].strData = _T("7"); 
			} 
			if((m_Buffer[2] & 3) == CS8) 
			{ 
				dcb.ByteSize = 8; 
				g_arrPortState[m_nIndex].strData = _T("8"); 
			} 
 
			if((m_Buffer[2] & 4) == STOP1) 
			{ 
				dcb.StopBits = ONESTOPBIT; 
				g_arrPortState[m_nIndex].strStop = _T("1"); 
			} 
			else 
			{ 
				if((m_Buffer[2] & 3) == CS5) 
				{ 
					dcb.StopBits = ONE5STOPBITS; 
					g_arrPortState[m_nIndex].strStop = _T("1.5"); 
				} 
				else 
				{ 
					dcb.StopBits = TWOSTOPBITS; 
					g_arrPortState[m_nIndex].strStop = _T("2"); 
				} 
			} 
 
			if((m_Buffer[2] & 0x38) == PAR_NONE) 
			{ 
				dcb.Parity = NOPARITY; 
				g_arrPortState[m_nIndex].strParity = _T("N"); 
			} 
			if((m_Buffer[2] & 0x38) == PAR_ODD) 
			{ 
				dcb.Parity = ODDPARITY; 
				g_arrPortState[m_nIndex].strParity = _T("O"); 
			} 
			if((m_Buffer[2] & 0x38) == PAR_EVEN) 
			{ 
				dcb.Parity = EVENPARITY; 
				g_arrPortState[m_nIndex].strParity = _T("E"); 
			} 
			if((m_Buffer[2] & 0x38) == PAR_MARK) 
			{ 
				dcb.Parity = MARKPARITY; 
				g_arrPortState[m_nIndex].strParity = _T("M"); 
			} 
			if((m_Buffer[2] & 0x38) == PAR_SPACE) 
			{ 
				dcb.Parity = SPACEPARITY; 
				g_arrPortState[m_nIndex].strParity = _T("S"); 
			} 
		} 
		 
		SetCommState(m_hFile, &dcb); 
		 
		if(m_Buffer[1] & MASK_CTRL) 
		{ 
			if(m_Buffer[4] & C_DTR) 
			{ 
				EscapeCommFunction(m_hFile, SETDTR); 
				g_arrPortState[m_nIndex].strDtr = _T("DTR:ON"); 
			} 
			else 
			{ 
				EscapeCommFunction(m_hFile, CLRDTR); 
				g_arrPortState[m_nIndex].strDtr = _T("DTR:OFF"); 
			} 
 
			if(m_Buffer[4] & C_RTS) 
			{ 
				EscapeCommFunction(m_hFile, SETRTS); 
				g_arrPortState[m_nIndex].strRts = _T("RTS:ON"); 
			} 
			else 
			{ 
				EscapeCommFunction(m_hFile, CLRRTS); 
				g_arrPortState[m_nIndex].strRts = _T("RTS:OFF"); 
			} 
		} 
 
		if(m_Buffer[1] & MASK_FLOW)	//not supported 
		{ 
		} 
 
		if(m_Buffer[1] & MASK_BRK)	//not supported 
		{ 
		} 
 
		g_csPortState.Unlock(); 
		TRACE("Command : 0x01\n"); 
		break; 
	case	0x02: 
	case	0x04: 
		//close later when this return 
	case	0x05: 
	case	0xf1: 
	default: 
		break; 
	} 
} 
 
void CPortThread::ReportState(DWORD dwError) 
{ 
	BYTE buff[4]; 
	buff[0] = 0xff; 
	buff[1] = 0x03; 
	buff[2] = buff[3] = 0; 
 
	DWORD	dwState; 
	if(GetCommModemStatus(m_hFile, &dwState)) 
	{ 
		if(dwState & MS_CTS_ON) 
			buff[2] |= M_CTS; 
		if(dwState & MS_DSR_ON) 
			buff[2] |= M_DSR; 
		if(dwState & MS_RING_ON) 
			buff[2] |= M_RI; 
		if(dwState & MS_RLSD_ON) 
			buff[2] |= M_CD; 
	} 
 
	if(dwError & CE_RXPARITY) 
		buff[3] |= ERR_PARITY; 
	if(dwError & CE_FRAME) 
		buff[3] |= ERR_FRAME; 
	if(dwError & CE_OVERRUN) 
		buff[3] |= ERR_OVERRUN; 
	if(dwError & CE_BREAK) 
		buff[3] |= ERR_BRK; 
 
	m_pConnect->Send(buff, 4); 
} 
 
void CPortThread::ClosePort() 
{ 
	TRACE(_T("CPortThread::ClosePort(%s)\n"), (LPCTSTR)m_strPort); 
 
	g_csPortState.Lock(); 
	g_arrPortState[m_nIndex].bOpened = 0; 
	g_csPortState.Unlock(); 
 
	KillTimer(NULL, m_hTimer); 
	m_hTimer = 0; 
 
	delete m_pConnect; 
	m_pConnect = NULL; 
 
	PurgeComm(m_hFile, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); 
	CloseHandle(m_hFile); 
	m_hFile = INVALID_HANDLE_VALUE; 
 
	::PostMessage(m_hWnd, WM_USER, 0 , 0); 
} 
 
BOOL CPortThread::OpenPort() 
{ 
	TRACE(_T("CPortThread::OpenPort(%s)\n"), (LPCSTR)m_strPort); 
 
	CConnectSocket *p = new CConnectSocket; 
	p->m_pThread = this; 
 
	BOOL bOk = FALSE; 
	if(m_sServer.Accept(*p)) 
	{ 
		if(!m_pConnect) 
		{ 
			m_pConnect = p; 
			bOk = TRUE; 
		} 
	} 
	if(!bOk) 
	{ 
		delete p; 
		return	FALSE; 
	} 
 
	CString	strHead; 
	strHead.Format(_T("\\\\.\\%s"), (LPCSTR)m_strPort); 
	m_hFile = CreateFile((LPCTSTR)strHead, 
				GENERIC_READ | GENERIC_WRITE, 
				0, 
				NULL, 
				OPEN_EXISTING, 
				FILE_ATTRIBUTE_NORMAL, 
				NULL); 
 
	BOOL bRet = TRUE; 
 
	g_csPortState.Lock(); 
 
	m_pConnect->GetPeerName( 
		g_arrPortState[m_nIndex].strClientIp, g_arrPortState[m_nIndex].nClientPort); 
 
	if(m_hFile == INVALID_HANDLE_VALUE) 
	{ 
		g_arrPortState[m_nIndex].bOpened = -3; 
		delete p; 
		m_pConnect = NULL; 
		bRet = FALSE; 
	} 
	else 
	{ 
		m_hTimer = SetTimer(NULL, NULL, INTERNALTIMER, NULL); 
		m_nTimerCount = 0; 
		m_bCommandReceiving = m_bPreIsFF = FALSE; 
		 
		DCB dcb; 
		dcb.DCBlength = sizeof( DCB ); 
		GetCommState( m_hFile, &dcb ); 
		g_arrPortState[m_nIndex].nBaud = dcb.BaudRate = 9600; 
		 
		dcb.Parity = NOPARITY; 
		g_arrPortState[m_nIndex].strParity = _T("N"); 
		 
		dcb.ByteSize = 8; 
		g_arrPortState[m_nIndex].strData = _T("8"); 
		 
		dcb.StopBits = ONESTOPBIT; 
		g_arrPortState[m_nIndex].strStop = _T("1"); 
 
		SetCommState(m_hFile, &dcb); 
		 
		g_arrPortState[m_nIndex].bOpened = 1; 
	} 
	g_csPortState.Unlock(); 
 
	::PostMessage(m_hWnd, WM_USER, 0 , 0); 
	 
	return	bRet; 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CServerSocket 
 
CServerSocket::CServerSocket() 
{ 
	m_pThread = NULL; 
} 
 
CServerSocket::~CServerSocket() 
{ 
} 
 
 
// Do not edit the following lines, which are needed by ClassWizard. 
#if 0 
BEGIN_MESSAGE_MAP(CServerSocket, CSocket) 
	//{{AFX_MSG_MAP(CServerSocket) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
#endif	// 0 
 
///////////////////////////////////////////////////////////////////////////// 
// CServerSocket member functions 
void CServerSocket::OnAccept(int nErrorCode)  
{ 
	m_pThread->OpenPort(); 
 
	CSocket::OnAccept(nErrorCode); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CConnectSocket 
 
CConnectSocket::CConnectSocket() 
{ 
	m_pThread = NULL; 
} 
 
CConnectSocket::~CConnectSocket() 
{ 
} 
 
 
// Do not edit the following lines, which are needed by ClassWizard. 
#if 0 
BEGIN_MESSAGE_MAP(CConnectSocket, CSocket) 
	//{{AFX_MSG_MAP(CConnectSocket) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
#endif	// 0 
 
///////////////////////////////////////////////////////////////////////////// 
// CConnectSocket member functions 
void CConnectSocket::OnClose(int nErrorCode)  
{ 
	ASSERT(this == m_pThread->m_pConnect); 
	m_pThread->ClosePort(); 
	 
	CSocket::OnClose(nErrorCode); 
} 
 
CString RPortState::GetInfo() 
{ 
	CString	strRet; 
 
	switch(bOpened) 
	{ 
	case	1: 
		strRet.Format(_T("Connected\r\nHost:%s\r\nTCP Port:%d\r\nPort Parameter:%d %s,%s,%s\r\n%s\r\n%s"),  
			(LPCTSTR)strClientIp, nClientPort, 
			nBaud,(LPCTSTR)strParity,(LPCTSTR)strData,(LPCTSTR)strStop,(LPCTSTR)strDtr,(LPCTSTR)strRts); 
		break; 
 
	case	0: 
		strRet.Format(_T("Not Connected")); 
	break; 
 
	case	-1: 
		strRet.Format(_T("Can not create TCP(%d)"), nPort + SERVERPORTBASE); 
	break; 
 
	case	-2: 
		strRet.Format(_T("Device not found")); 
	break; 
 
	case	-3: 
		strRet.Format(_T("Open port failed")); 
	break; 
	} 
 
	return strRet; 
}