📄 ccomm.cpp
字号:
#include "stdafx.h"
#include <afxmt.h>
#include "CPacker.h"
#include <afxtempl.h>
#include "CChannel.h"
#include "CMultiplex.h"
#include "CDemultiplex.h"
#include "CByteBuffer.h"
#include "CComm.h"
CComm::CComm(CommCallBackFunc pCallBackFunc,
CMultiplex * pMultiplex,
CDemultiplex * pDemultiplex,
int nBaudRate,
int nInputBufferSize,
int nOutputBufferSize,
BOOL bDisplayError):m_InputBuffer(READ_BUFFER_SIZE)
{
m_pMultiplex=pMultiplex;
m_pDemultiplex=pDemultiplex;
m_hComm=NULL;
ZeroMemory(&m_WriteOS,sizeof(OVERLAPPED));
ZeroMemory(&m_ReadOS,sizeof(OVERLAPPED));;
m_nPort=0;
m_bConnected=FALSE;
m_bDisplayError=bDisplayError;
m_nBaudRate=nBaudRate;
m_nInputBufferSize=nInputBufferSize;
m_nOutputBufferSize=nOutputBufferSize;
m_dwThreadID=0;
m_hThread=NULL;
m_dwWriteThreadID=0;
m_hWriteThread=NULL;
m_dwReadThreadID=0;
m_hReadThread=NULL;
m_pCallBackFunc=pCallBackFunc;
m_lpUserInstance=NULL;
m_uBlockSize=m_nOutputBufferSize/2;
if(m_uBlockSize>4096)
m_uBlockSize=4096;
m_uMiniBlockSize=100;
if(m_uMiniBlockSize>m_uBlockSize/2)
m_uMiniBlockSize=0;
m_hQuitEvent=NULL;
m_hWriteEvent=NULL;
m_hCTSEvent=NULL;
m_hReadEvent=NULL;
}
BOOL CComm::OpenComm(int nPortNumber,LPVOID lpUserInstance)
{
if(m_bConnected)return FALSE;
m_lpUserInstance=lpUserInstance;
m_nPort=nPortNumber;
if(!CreateTTYInfo())return FALSE;
m_hQuitEvent=CreateEvent((LPSECURITY_ATTRIBUTES)NULL,TRUE,FALSE,NULL);
if(!m_hQuitEvent)return FALSE;
m_hWriteEvent=CreateEvent((LPSECURITY_ATTRIBUTES)NULL,FALSE,TRUE,NULL);
if(!m_hWriteEvent)
{
CloseHandle(m_hQuitEvent);
m_hQuitEvent=0;
return FALSE;
}
m_hReadEvent=CreateEvent((LPSECURITY_ATTRIBUTES)NULL,FALSE,FALSE,NULL);
if(!m_hReadEvent)
{
CloseHandle(m_hWriteEvent);
CloseHandle(m_hQuitEvent);
m_hWriteEvent=0;
m_hQuitEvent=0;
return FALSE;
}
m_hCTSEvent=CreateEvent((LPSECURITY_ATTRIBUTES)NULL,FALSE,FALSE,NULL);
if(!m_hCTSEvent)
{
CloseHandle(m_hWriteEvent);
CloseHandle(m_hQuitEvent);
CloseHandle(m_hReadEvent);
m_hWriteEvent=0;
m_hQuitEvent=0;
m_hReadEvent=0;
return FALSE;
}
if(!OpenConnection())
{
CloseHandle(m_hWriteEvent);
CloseHandle(m_hQuitEvent);
CloseHandle(m_hReadEvent);
CloseHandle(m_hCTSEvent);
m_hWriteEvent=0;
m_hQuitEvent=0;
m_hReadEvent=0;
m_hCTSEvent=0;
return FALSE;
}
return TRUE;
}
BOOL CComm::CreateTTYInfo()
{
m_WriteOS.Offset = 0 ;
m_WriteOS.OffsetHigh = 0 ;
m_ReadOS.Offset = 0 ;
m_ReadOS.OffsetHigh = 0 ;
// create I/O event used for overlapped reads / writes
m_ReadOS.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (m_ReadOS.hEvent == NULL)
return FALSE;
m_WriteOS.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (NULL == m_WriteOS.hEvent)
{
CloseHandle(m_ReadOS.hEvent ) ;
return FALSE;
}
return TRUE;
} // end of CreateTTYInfo()
DWORD FAR PASCAL ReadThreadProc(CComm* pCommObject)
{
CComm* pComm=(CComm*)pCommObject;
HANDLE phWaitObjects[2]={pComm->m_hQuitEvent,pComm->m_hReadEvent};
DWORD dwEvtMask=0;
int nRequireLength=256;
BYTE abIn[1024] ;
int nLength ;
while(1)
{
dwEvtMask=WaitForMultipleObjects(2,phWaitObjects,FALSE,INFINITE);
if(dwEvtMask==WAIT_OBJECT_0)
break;
if(dwEvtMask==WAIT_OBJECT_0+1)
{
/* do
{
if (nLength = (pComm->ReadCommBlock((LPSTR) abIn, MAXBLOCK )))
{
if(pComm->m_pCallBackFunc)
(*(pComm->m_pCallBackFunc))(abIn,nLength,pComm->m_lpUserInstance);
}
}
while ( nLength > 0 ) ;
*/
do
{
if (nLength=pComm->m_InputBuffer.DetachHeader(abIn,nRequireLength))
{
if(pComm->m_pCallBackFunc)
(*(pComm->m_pCallBackFunc))(abIn,nLength,pComm->m_lpUserInstance);
}
}
while ( nLength > 0 ) ;
continue;
}
if(dwEvtMask==WAIT_TIMEOUT)
continue;
}
pComm->m_hReadThread=0;
pComm->m_dwReadThreadID=0;
return 0;
}
DWORD FAR PASCAL WriteThreadProc(CComm* pCommObject)
{
DWORD dwEvtMask=0;
CComm* pComm=(CComm*)pCommObject;
BYTE pbyTransferBlock[4096];
int nStreamLength;
HANDLE phWaitObjects[3]={
pComm->m_hQuitEvent,
pComm->m_hWriteEvent,
pComm->m_hCTSEvent
};
while(1)
{
dwEvtMask=WaitForMultipleObjects(3,phWaitObjects,FALSE,25);
if(dwEvtMask==WAIT_OBJECT_0)
break;
if(dwEvtMask==WAIT_OBJECT_0+1)
{
while(1)
{
int nStreamLength=pComm->m_pMultiplex->DetachStream(pbyTransferBlock,256);
if(nStreamLength)
{
pComm->WriteCommBlock(pbyTransferBlock,nStreamLength);
break;
}
if(WAIT_OBJECT_0==WaitForSingleObject(pComm->m_hQuitEvent,50))
goto END;
}
}
if(dwEvtMask==WAIT_OBJECT_0+2)
{
static bFull;
bFull=!bFull;
}
if(dwEvtMask==WAIT_TIMEOUT)
{
nStreamLength=pComm->m_pMultiplex->DetachStream(pbyTransferBlock,128);
if(nStreamLength)
{
pComm->WriteCommBlock(pbyTransferBlock,nStreamLength);
}
}
}
END:
pComm->m_hWriteThread=NULL;
pComm->m_dwWriteThreadID=0;
return 0;
}
DWORD FAR PASCAL CommWatchProc(CComm* pCommObject)
{
DWORD dwEvtMask ;
CComm* pComm= (CComm*)pCommObject;
OVERLAPPED os ;
int nLength ;
BYTE abIn[ MAXBLOCK + 1] ;
memset( &os, 0, sizeof( OVERLAPPED ) ) ;
// create I/O event used for overlapped read
os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (os.hEvent == NULL)
{
MessageBox( NULL, "Failed to create event for thread!", "TTY Error!",
MB_ICONEXCLAMATION | MB_OK ) ;
return ( FALSE ) ;
}
if (!SetCommMask(pComm->m_hComm, EV_RXCHAR|EV_RLSD|EV_TXEMPTY|EV_CTS))
return ( FALSE ) ;
while (pComm->m_bConnected)
{
dwEvtMask = 0 ;
WaitCommEvent(pComm->m_hComm, &dwEvtMask, NULL );
if ((dwEvtMask & EV_RLSD) == EV_RLSD)
{
if(pComm->m_pCallBackFunc)
(*(pComm->m_pCallBackFunc))(NULL,0xffffffff,pComm->m_lpUserInstance);
}
if((dwEvtMask & EV_TXEMPTY) == EV_TXEMPTY)
{
SetEvent(pComm->m_hWriteEvent);
}
if((dwEvtMask & EV_CTS) == EV_CTS)
{
SetEvent(pComm->m_hCTSEvent);
}
if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
{/*
do
{
if (nLength = (pComm->ReadCommBlock((LPSTR) abIn, MAXBLOCK )))
{
if(pComm->m_pCallBackFunc)
(*(pComm->m_pCallBackFunc))(abIn,nLength,pComm->m_lpUserInstance);
}
}
while ( nLength > 0 ) ;
*/
do
{
if (nLength = (pComm->ReadCommBlock((LPSTR) abIn, MAXBLOCK )))
pComm->m_InputBuffer.AppendTail(abIn,nLength);
}
while ( nLength > 0 ) ;
SetEvent(pComm->m_hReadEvent);
}
}
// get rid of event handle
CloseHandle( os.hEvent ) ;
// clear information in structure (kind of a "we're done flag")
pComm->m_dwThreadID = 0 ;
pComm->m_hThread = NULL ;
return( TRUE ) ;
} // end of CommWatchProc()
int CComm::ReadCommBlock(LPSTR lpszBlock, int nMaxLength )
{
BOOL fReadStat ;
COMSTAT ComStat ;
DWORD dwErrorFlags;
DWORD dwLength;
DWORD dwError;
char szError[ 10 ] ;
// only try to read number of bytes in queue
ClearCommError(m_hComm, &dwErrorFlags, &ComStat ) ;
dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;
if (dwLength > 0)
{
fReadStat = ReadFile(m_hComm, lpszBlock,
dwLength, &dwLength, &m_ReadOS) ;
if (!fReadStat)
{
if (GetLastError() == ERROR_IO_PENDING)
{
OutputDebugString("\n\rIO Pending");
// We have to wait for read to complete.
// This function will timeout according to the
// CommTimeOuts.ReadTotalTimeoutConstant variable
// Every time it times out, check for port errors
while(!GetOverlappedResult(m_hComm,&m_ReadOS, &dwLength, TRUE))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
// normal result if not finished
continue;
else
{
// an error occurred, try to recover
wsprintf( szError, "<CE-%u>", dwError ) ;
MessageBox(NULL,szError,"Read Error",MB_OK);
ClearCommError(m_hComm, &dwErrorFlags, &ComStat ) ;
if ((dwErrorFlags > 0) &&m_bDisplayError)
{
wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
MessageBox(NULL,szError,"Read Error",MB_OK);
}
break;
}
}
}
else
{
// some other error occurred
dwLength = 0 ;
ClearCommError(m_hComm, &dwErrorFlags, &ComStat ) ;
if ((dwErrorFlags > 0) &&m_bDisplayError)
{
wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
MessageBox(NULL,szError,"Read Error",MB_OK);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -