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