www.pudn.com > SendMsgOCX.rar > WSerialComm.cpp
// WSerialComm.cpp: implementation of the CWSerialComm class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "WSerialComm.h" #include#ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// #define RXQUEUE 128 // < READ_BUFF_SIZE #define TXQUEUE 128 static UINT CommWatchProc( LPVOID lpData ) { CWSerialComm *pCommPort = ( CWSerialComm*) lpData ; DWORD dwEvtMask ; OVERLAPPED os ; BOOL bWaitResult; memset( &os, 0, sizeof( OVERLAPPED ) ) ; os.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ; if (os.hEvent == NULL) return ( FALSE ) ; if (!SetCommMask( pCommPort ->m_hComDev, EV_RXCHAR )) return ( FALSE ) ; while ( pCommPort->IsOpen() ) { dwEvtMask = 0 ; bWaitResult = WaitCommEvent( pCommPort ->m_hComDev, &dwEvtMask, &os ); if(!bWaitResult && GetLastError() == ERROR_IO_PENDING) { DWORD dwLength; bWaitResult = GetOverlappedResult(pCommPort ->m_hComDev, &os, &dwLength, TRUE); } if (!bWaitResult) { COMSTAT comStatus; DWORD dwErrorFlags; ClearCommError( pCommPort ->m_hComDev, &dwErrorFlags, &comStatus ) ; pCommPort->OnCommPortError(dwErrorFlags,TRUE); } else if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) while ( pCommPort->ReadCommBlock() > 0 ) ; } CloseHandle( os.hEvent ) ; pCommPort->m_dwThreadID = 0 ; pCommPort->m_hCommWatchThread = NULL ; return( TRUE ) ; } CWSerialComm::CWSerialComm() { if( !InitMembers() ) throw GetLastError(); } CWSerialComm::~CWSerialComm() { if( IsOpen() ) CloseCom(); CloseHandle( m_osRead.hEvent ) ; CloseHandle( m_osWrite.hEvent ) ; } BOOL CWSerialComm::IsOpen() { return m_bOpened; } void CWSerialComm::SetCommConfig() { COMMCONFIG cfg; DWORD dwSize; ::GetCommConfig(m_hComDev, &cfg, &dwSize); cfg.dcb.BaudRate = CBR_9600; cfg.dcb.ByteSize = 8; cfg.dcb.StopBits = ONESTOPBIT; cfg.dcb.fParity = FALSE; cfg.dcb.Parity = NOPARITY; ::SetCommConfig(m_hComDev, &cfg, sizeof(COMMCONFIG)); } BOOL CWSerialComm::InitMembers() { // common data members m_hComDev = 0 ; m_bOpened = FALSE ; //thread m_dwThreadID = 0; m_hCommWatchThread = NULL ; memset( (void*)&m_osWrite, 0, sizeof(m_osWrite) ); memset( (void*)&m_osRead , 0, sizeof(m_osRead ) ); m_osRead.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset req FALSE, // initial event reset NULL ) ; // no name if( NULL == m_osRead.hEvent ) return FALSE; m_osWrite.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset req FALSE, // initial event reset NULL ) ; // no name if ( NULL == m_osWrite.hEvent ) return FALSE; return TRUE; //no error } //end InitMembers void CWSerialComm::GetCommName( LPSTR lpszComName, int portNo) { sprintf(lpszComName, "COM%d", portNo); } BOOL CWSerialComm::OpenCom( int portNo ) { if( IsOpen() ) return TRUE; char szCommName[32]; GetCommName(szCommName, portNo); // open COMM device if ((m_hComDev = CreateFile( szCommName, GENERIC_READ | GENERIC_WRITE, 0, // exclusive access NULL, // no security attrs OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // overlapped I/O NULL )) == (HANDLE) -1 ) return ( FALSE ) ; else { SetCommConfig(); SetCommMask( m_hComDev, EV_RXCHAR ) ; SetupComm( m_hComDev, RXQUEUE, TXQUEUE ) ; PurgeComm( m_hComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ; } m_bOpened = TRUE ; // Create a thread HANDLE hCommWatchThread ; DWORD dwThreadID ; if (NULL == ( hCommWatchThread = CreateThread( (LPSECURITY_ATTRIBUTES) NULL, 0, (LPTHREAD_START_ROUTINE)CommWatchProc, (LPVOID) this, 0, &dwThreadID ))) { m_bOpened = FALSE ; CloseHandle( m_hComDev ) ; } else { m_dwThreadID = dwThreadID ; m_hCommWatchThread = hCommWatchThread ; // assert DTR EscapeCommFunction( m_hComDev, SETDTR ) ; } return ( m_bOpened ) ; } BOOL CWSerialComm::CloseCom( ) { // set connected flag to FALSE m_bOpened = FALSE ; // block until thread has been halted SetCommMask( m_hComDev, 0 ) ; // drop DTR EscapeCommFunction( m_hComDev, CLRDTR ) ; // purge any outstanding reads/writes and close device handle PurgeComm( m_hComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ; CloseHandle( m_hComDev ) ; m_hComDev = 0; return ( TRUE ) ; } DWORD CWSerialComm:: ReadCommBlock( ) { BOOL fReadStat ; DWORD dwErrorFlags; DWORD dwToRead, dwRead; COMSTAT comStatus; // only try to read number of bytes in queue ClearCommError( m_hComDev, &dwErrorFlags, &comStatus ) ; dwToRead = min(READ_BUFF_SIZE,comStatus.cbInQue); dwRead = 0; if (dwToRead > 0) { fReadStat = ReadFile( m_hComDev, m_pReadBuff, dwToRead, &dwRead, &m_osRead ) ; if (!fReadStat && GetLastError() == ERROR_IO_PENDING) fReadStat = GetOverlappedResult( m_hComDev, &m_osRead, &dwRead, TRUE); if(!fReadStat || dwRead != dwToRead) { dwRead = 0 ; ClearCommError( m_hComDev, &dwErrorFlags, &comStatus ) ; OnCommPortError( dwErrorFlags ); //report the error } } if( dwRead > 0 ) OnDataRead( m_pReadBuff, dwRead ); return dwRead; } // BOOL CWSerialComm::WriteDataBlock(const BYTE* lpByte , DWORD dwBytesToWrite) { BOOL fWriteStat ; DWORD dwBytesWritten ; DWORD dwErrorFlags; COMSTAT comStatus; ASSERT( IsOpen() ); fWriteStat = WriteFile( m_hComDev, lpByte, dwBytesToWrite, &dwBytesWritten, &m_osWrite ) ; if (!fWriteStat && GetLastError() == ERROR_IO_PENDING) fWriteStat = GetOverlappedResult( m_hComDev, &m_osWrite, &dwBytesWritten, TRUE ); if( !fWriteStat || dwBytesWritten != dwBytesToWrite ) { ClearCommError( m_hComDev, &dwErrorFlags, &comStatus ) ; OnCommPortError( dwErrorFlags, FALSE ); } return fWriteStat; } // end of WriteDataBlock() void CWSerialComm::OnDataRead( const LPBYTE lpData, DWORD dwLength ) { } BOOL CWSerialComm::OnCommPortError( DWORD dwError, BOOL bReading ) { TRACE3( "%s, CommError:%d, SystemError:%d\n", ( bReading ? "Reading" : "Writting" ), dwError, GetLastError() ); return TRUE; }