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;
}