?? commport.cpp
字號(hào):
/*****************************************************************************
* RelayFax Open Source Project
* Copyright 1996-2004 Alt-N Technologies, Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the RelayFax Open
* Source License. A copy of this license is available in file LICENSE
* in the top-level directory of the distribution.
*
* RelayFax is a registered trademark of Alt-N Technologies, Ltd.
*
* Individual files and/or contributed packages may be copyright by
* other parties and subject to additional restrictions.
*****************************************************************************/
////////////////////////////////////////////////////////////////////////////////
//
// The purpose of CCommPort is to encapsulate all the Win32 communication API
//
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CommPort.h"
CLS1SPEEDS cls1Speeds[MAX_CLS1SPEEDS] =
{
0x00, 24, 24, 2400, 0, // 2400, v.27 ter
0x04, 48, 48, 4800, 1, // 4800, v.27
0x0c, 72, 72, 7200, 2, // 7200, v.29
0x08, 96, 96, 9600, 3, // 9600, v.29
0x06, 121, 121, 12000, 4, // 12000, V.33
0x02, 145, 145, 14400, 5, // 14400, V.33
0x0d, 73, 74, 7200, 2, // 7200, v.17
0x09, 97, 98, 9600, 3, // 9600, v.17
0x05, 121, 122, 12000, 4, // 12000, v.17
0x01, 145, 146, 14400, 5, // 14400, v.17
};
WORD Cls1ScanTimes_normal[8] = {20,40,10,5,10,20,40,0};
WORD Cls1ScanTimes_fine[8] = {20,40,10,5,5,10,20,0};
WORD Cls2ScanTimes_normal[8] = { 0, 5, 10, 10, 20, 20, 40, 40 };
WORD Cls2ScanTimes_fine[8] = { 0, 5, 5, 10, 10, 20, 20, 40 };
WORD Cls2FaxParamBitRates[6] = { 2400, 4800, 7200, 9600, 12000, 14400 };
char CCommPort::s_HexDigits[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCommPort::CCommPort()
{
m_hPort = NULL;
m_bDSRFlowControl = true;
m_bCTSFlowControl = true;
m_bSoftFlowControl = true;
m_BaudRate = CBR_19200;
m_ByteSize = 8;
m_Parity = NOPARITY;
m_StopBits = ONESTOPBIT;
ZeroMemory( &m_ReadOverlapped, sizeof(m_ReadOverlapped) );
ZeroMemory( &m_WriteOverlapped, sizeof(m_WriteOverlapped) );
ZeroMemory( &m_CommEventOverlapped, sizeof(m_CommEventOverlapped) );
m_ReadOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_WriteOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_CommEventOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
InitLineParser();
m_bWriteInProgress = false;
memset( &m_dcb, 0, sizeof(m_dcb) );
m_dcb.DCBlength = sizeof(m_dcb);
m_bDebugLog = false;
m_pLogFile = NULL;
}
CCommPort::~CCommPort()
{
CloseHandle( m_ReadOverlapped.hEvent );
CloseHandle( m_WriteOverlapped.hEvent );
CloseHandle( m_CommEventOverlapped.hEvent );
}
//////////////////////////////////////////////////////////////////////
// ConnectPort
//////////////////////////////////////////////////////////////////////
bool CCommPort::ConnectPort( string& sErr )
{
char szComDevice[16];
wsprintf( szComDevice, "\\\\.\\%s", m_sPort.c_str() );
m_hPort = CreateFile( szComDevice, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
// see if this works before committing
if( m_hPort == NULL || m_hPort == INVALID_HANDLE_VALUE )
{
if( GetLastError() == ERROR_ACCESS_DENIED )
{
// wait a second and try again
Sleep( 1000 );
m_hPort = CreateFile( szComDevice, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
}
}
if( m_hPort != NULL && m_hPort != INVALID_HANDLE_VALUE )
{
PurgeComm( m_hPort, PURGE_RXCLEAR | PURGE_TXCLEAR );
if( !GetCommState( m_hPort, &m_dcb ) )
{
sErr.assign( "Error in GetCommState" );
CloseHandle( m_hPort );
return false;
}
if( !SetupComm( m_hPort, 20000, 20000 ) )
{
sErr.assign( "Error in SetupComm" );
CloseHandle( m_hPort );
return false;
}
m_dcb.BaudRate = m_BaudRate;
m_dcb.ByteSize= m_ByteSize;
m_dcb.fBinary = TRUE;
m_dcb.Parity = m_Parity;
m_dcb.StopBits = m_StopBits;
m_dcb.fOutxCtsFlow = (m_bCTSFlowControl) ? TRUE : FALSE;
m_dcb.fOutxDsrFlow = (m_bDSRFlowControl) ? TRUE : FALSE;
m_dcb.fOutX = (m_bSoftFlowControl) ? 1 : 0;
m_dcb.fInX = 0; // we shouldn't need flow control for receiving data
// since we are using 20k buffers
m_dcb.XonChar = XON;
m_dcb.XoffChar = XOFF;
// One of these two was causing a problem with Multitech ISI5634/8 multi-port modem card
// m_dcb.fTXContinueOnXoff = TRUE;
m_dcb.fRtsControl = RTS_CONTROL_ENABLE;
m_dcb.fDtrControl = DTR_CONTROL_ENABLE;
m_dcb.fAbortOnError = FALSE; // Make sure this is reset otherwise any
//line errors will cause io to terminate
m_dcb.fErrorChar = FALSE;
m_dcb.fParity = FALSE;
// m_dcb.fDsrSensitivity = TRUE;
m_dcb.fNull = FALSE;
if ( !SetCommState( m_hPort, &m_dcb) )
{
sErr.assign( "Error in SetCommState" );
CloseHandle( m_hPort );
return false;
}
COMMTIMEOUTS cto;
//cto.ReadIntervalTimeout = 10;
//cto.ReadIntervalTimeout = (m_BaudRate / 10)
cto.ReadIntervalTimeout = 2;
cto.ReadTotalTimeoutMultiplier = 0;
cto.ReadTotalTimeoutConstant = 0;
cto.WriteTotalTimeoutMultiplier = 5;
cto.WriteTotalTimeoutConstant = 5000;
if( !SetCommTimeouts( m_hPort, &cto ) )
{
sErr.assign( "Error in SetCommTimeouts" );
CloseHandle( m_hPort );
return false;
}
COMSTAT cs = {0};
DWORD dwErrs = 0;
if( !ClearCommError( m_hPort, &dwErrs, &cs ) )
{
sErr.assign( "Error in ClearCommError" );
CloseHandle( m_hPort );
return false;
}
//DWORD dwMask = EV_CTS | EV_ERR | EV_DSR | EV_RLSD | EV_BREAK | EV_RING;
DWORD dwMask = EV_ERR;
if (!SetCommMask(m_hPort, dwMask))
{
sErr.assign( "Error in SetCommMask!" );
CloseHandle( m_hPort );
return false;
}
OpenDebugLog();
DoWaitCommEventLoop();
DoReadLoop();
OnConnect(); //-- moved to OnWaitTimeout to let the read buffer flush
return true;
}
else
{
// could not open port
char szError[256];
szError[0] = '\0';
GetLastErrorText( szError, 255 );
sErr.assign( szError );
}
return false;
}
//////////////////////////////////////////////////////////////////////
// DisconnectPort
//////////////////////////////////////////////////////////////////////
void CCommPort::DisconnectPort( void )
{
PurgeComm( m_hPort, PURGE_RXABORT | PURGE_RXCLEAR |
PURGE_TXABORT | PURGE_TXCLEAR );
CloseHandle( m_hPort );
m_hPort = NULL;
CloseDebugLog();
}
//////////////////////////////////////////////////////////////////////
// DoRead
//////////////////////////////////////////////////////////////////////
bool CCommPort::DoRead( void )
{
BOOL bRet;
m_BytesRead = 0;
bRet = ReadFile( m_hPort, m_szReadBuff, READBUF_SIZE, &m_BytesRead, &m_ReadOverlapped );
if( bRet )
{
return true;
}
else
{
DWORD dwLastError = GetLastError();
// LastError was ERROR_IO_PENDING, as expected.
if (dwLastError != ERROR_IO_PENDING)
{
OutputDebugString("Unexpected error.\n");
}
// Its possible for this error to occur if the
// service provider has closed the port. Time to end.
if (dwLastError == ERROR_INVALID_HANDLE)
{
OutputDebugString( "Likely that the Service Provider has closed the port.\n");
}
return false;
}
}
void CCommPort::FillWriteQueue( char* szChars, unsigned long nBytes, bool bCrLf )
{
bool bAddedCrLf = false;
while( nBytes > 0 )
{
int nbuflen = MAX_WRITE;
if( nbuflen > nBytes )
{
nbuflen = nBytes;
}
CWriteBuffer *buf = new CWriteBuffer;
memcpy( buf->Buffer, szChars, nbuflen );
buf->Bytes = nbuflen;
if( bCrLf && (nbuflen < MAX_WRITE) )
{
// must be last one
buf->Buffer[buf->Bytes++] = '\r';
bAddedCrLf = true;
}
m_WriteQueue.push_back( buf );
szChars += nbuflen;
nBytes -= nbuflen;
}
if( bCrLf && !bAddedCrLf)
{
CWriteBuffer *buf = new CWriteBuffer;
buf->Buffer[0] = '\r';
buf->Bytes = 1;
m_WriteQueue.push_back( buf );
}
}
bool CCommPort::WritePacket( char* szChars, unsigned long nBytes )
{
m_WriteOverlapped.Offset = 0;
m_WriteOverlapped.OffsetHigh = 0;
if( WriteFile( m_hPort, szChars, nBytes,
&m_BytesWritten, &m_WriteOverlapped ) )
{
//char szMsg[80];
//wsprintf( szMsg, "Wrote %d bytes 2\n", m_BytesWritten );
//OutputDebugString( szMsg );
ResetEvent( m_WriteOverlapped.hEvent );
OnWrite();
if( m_bDebugLog )
{
WriteDebugLog( false );
}
}
else
{
//char szMsg[80];
//wsprintf( szMsg, "Queued up %d bytes\n", nBytes );
//OutputDebugString( szMsg );
m_bWriteInProgress = true;
DWORD dwLastError = GetLastError();
// LastError was ERROR_IO_PENDING, as expected.
if (dwLastError != ERROR_IO_PENDING)
{
OutputDebugString("Unexpected error.\n");
}
// Its possible for this error to occur if the
// service provider has closed the port. Time to end.
if (dwLastError == ERROR_INVALID_HANDLE)
{
OutputDebugString( "Likely that the Service Provider has closed the port.\n");
}
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////
// DoWrite
//////////////////////////////////////////////////////////////////////
bool CCommPort::DoWrite( char* szChars, unsigned long nBytes, bool bCrLf )
{
if( m_bWriteInProgress )
{
FillWriteQueue( szChars, nBytes, bCrLf );
}
else
{
if( nBytes > MAX_WRITE )
{
FillWriteQueue( szChars, nBytes, bCrLf );
DoWriteLoop();
}
else
{
memcpy( m_szWriteBuff, szChars, nBytes );
if( bCrLf )
{
m_szWriteBuff[nBytes++] = '\r';
//m_szWriteBuff[nBytes++] = '\n';
}
if( WritePacket( m_szWriteBuff, nBytes ) )
{
//char szMsg[80];
//wsprintf( szMsg, "Sent %d bytes 3\n", nBytes );
//OutputDebugString( szMsg );
}
}
}
return true;
}
//////////////////////////////////////////////////////////////////////
// DoRead
//////////////////////////////////////////////////////////////////////
bool CCommPort::DoWaitCommEvent( void )
{
BOOL bRet;
m_BytesRead = 0;
bRet = WaitCommEvent( m_hPort, &m_CommEvent, &m_CommEventOverlapped );
if( bRet )
{
return true;
}
else
{
DWORD dwLastError = GetLastError();
// LastError was ERROR_IO_PENDING, as expected.
if (dwLastError != ERROR_IO_PENDING)
{
OutputDebugString("Unexpected error.\n");
}
// Its possible for this error to occur if the
// service provider has closed the port. Time to end.
if (dwLastError == ERROR_INVALID_HANDLE)
{
OutputDebugString( "Likely that the Service Provider has closed the port.\n");
}
return false;
}
}
// DoReadLoop
//////////////////////////////////////////////////////////////////////
void CCommPort::DoReadLoop( void )
{
int i;
for( i = 0; i < 100; i++ )
{
if( m_hPort == NULL )
break;
if( DoRead() )
{
m_szReadBuff[m_BytesRead] = '\0';
if( m_bDebugLog )
{
WriteDebugLog( true );
}
OnRead();
}
else
{
break;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -