⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modem.cpp

📁 fax engine 传真引擎 relay fax 的开源项目 商业软件使用 高质量 高可靠
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
* 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 CModem build the message loop of an independent thread
// into CCommPort and handle communication with other threads.
//
////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Modem.h"


char* CModem::s_CommonCmds[COMMAND_COUNT] =
{
	"",						// COMMAND_NONE, 
	"ATZ",					// COMMAND_INIT, 
	"AT&F&C1&D2S7=55S0=0",	// COMMAND_SETUP_STRING
	"ATE0",					// COMMAND_DISABLE_ECHO, 
	"ATL%d",				// COMMAND_SET_SPKR_VOL, 
	"ATM%d",				// COMMAND_SET_SPKR_MODE, 
	"AT+FCLASS=1",			// COMMAND_SET_FCLASS_1
	"AT+FCLASS=1.0",		// COMMAND_SET_FCLASS_1_0
	"AT+FCLASS=2",			// COMMAND_SET_FCLASS_2
	"AT+FCLASS=2.0",		// COMMAND_SET_FCLASS_2_0
	"AT+FCLASS=2.1",		// COMMAND_SET_FCLASS_2_1
	"AT+FTM=?",				// COMMAND_QUERY_SEND_SPEEDS,
	"AT+FRM=?",				// COMMAND_QUERY_RECEIVE_SPEEDS,
	"",						// COMMAND_SET_LOCAL_ID,
	"",						// COMMAND_SET_RECV
	"",						// COMMAND_SET_BIT_ORDER
	"AT+FLO=%d",			// COMMAND_SET_FLOW_CONTROL
	"",						// COMMAND_SET_HDLC_REPORTING
	"",						// COMMAND_SET_FAX_PARAMS
	"ATDT%s",				// COMMAND_DIAL
	"ATH0",					// COMMAND_HANGUP
	"ATA",					// COMMAND_ANSWER
	"AT+FCLASS=?",			// COMMAND_QUERY_FCLASS
	"ATI0",					// COMMAND_QUERY_PRODUCT_CODE
	"ATI3",					// COMMAND_QUERY_MANUFACTURER
	"AT+FDCC=?",			// COMMAND_QUERY_CLASS2_CAP
	"AT+FMFR?",				// COMMAND_QUERY_CLASS2_MANUFACT
	"AT+FMDL?",				// COMMAND_QUERY_CLASS2_MODEL
	"AT+FCC=?",				// COMMAND_QUERY_CLASS2_0_CAP
	"AT+FMI?",				// COMMAND_QUERY_CLASS2_0_MANUFACT
	"AT+FMM?",				// COMMAND_QUERY_CLASS2_0_MODEL
};


//MODEM_EVENT_HANDLER_FUNC CModem::s_ModemEventHandlerFunc = NULL;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CModem::CModem()
{
	m_bConnected = false;
	m_sInitString.assign( s_CommonCmds[COMMAND_SETUP_STRING] );
	m_nSpkrVol = 0;
	m_nSpkrMode = 0;
	m_nState = STATE_NONE;
	m_nLastCommand = COMMAND_NONE;
	m_nRingCount = 0;
	m_nAnswerOnRing = 2;
	m_bReceiving = false;
	m_nWaitTimeout = 1000;
	m_bEnableReceive = true;
	InitHDLC();
	m_bHDLCMode = false;
	m_bGotOK = false;
	m_bECMSupported = true;
	m_nSendEncoding = FAXAPI_ENC_CCITT_T6;
	ZeroMemory( m_ParamMatrix, sizeof(m_ParamMatrix) );
	m_nSendBaud = FAXAPI_BAUD_14400;
	m_nRecvBaud = FAXAPI_BAUD_14400;
	m_nMaxSendBaud = FAXAPI_BAUD_33600;
	m_nMaxRecvBaud = FAXAPI_BAUD_33600;
	m_bPulseDialing = false;
	m_FaxThreadID = 0;
	m_nMaxPageRetries = 0; // no limit
	m_nMaxPageRetriesPageNo = -1;
	m_bTerminated = false;
	m_bLastPageGood = false;
}

CModem::~CModem()
{
}

//////////////////////////////////////////////////////////////////////
// Initialize - start the modem thread
//////////////////////////////////////////////////////////////////////
void CModem::Initialize( HANDLE hStop, DWORD faxThreadID )
{
	m_FaxThreadID = faxThreadID;
	AddEvent( hStop );
	AddEvent( m_ReadOverlapped.hEvent );
	AddEvent( m_WriteOverlapped.hEvent );
	AddEvent( m_CommEventOverlapped.hEvent );

	StartThread();
}


//////////////////////////////////////////////////////////////////////
// SetPort
//////////////////////////////////////////////////////////////////////
void CModem::SetPort( char* szPort )
{
	m_sPort = szPort;
}

//////////////////////////////////////////////////////////////////////
// Disconnect - send a message to initiate the disconnect
//////////////////////////////////////////////////////////////////////
void CModem::Disconnect(void)
{
	PostMsg( WM_MODEM_DISCONNECT, 0, 0 );
}

//////////////////////////////////////////////////////////////////////
// Disconnect - send a message to initiate the disconnect
//////////////////////////////////////////////////////////////////////
void CModem::RecvFax( char* szFaxFile )
{
	InternalModemMsg* pMsg = new InternalModemMsg;

	strcpy( pMsg->szFile, szFaxFile );
//	m_FaxFile.SetFileName( szFaxFile );

	PostMsg( WM_MODEM_RECVFAX, (WPARAM)pMsg, 0 );
}

//////////////////////////////////////////////////////////////////////
// SetInitString
//////////////////////////////////////////////////////////////////////
void CModem::SetInitString( LPCSTR szString )
{
	m_sInitString.assign( szString );
}


//////////////////////////////////////////////////////////////////////
// SetInitString
//////////////////////////////////////////////////////////////////////
void CModem::ChangeCSID( LPCSTR szString )
{
	InternalModemMsg* pMsg = new InternalModemMsg;

	strcpy( pMsg->szNumber, szString );

	PostMsg( WM_MODEM_SETID, (WPARAM)pMsg, 0 );
}

//////////////////////////////////////////////////////////////////////
// SetInitString
//////////////////////////////////////////////////////////////////////
void CModem::SetCSID( LPCSTR szString )
{
	char szID[21];
	int nLen = 0;

	while( *szString && nLen < 20 )
	{
		if( *szString > 31 && *szString < 127 && *szString != 34 )
		{
			szID[nLen++] = toupper(*szString);
		}
		szString++;
	}
	szID[nLen] = 0;

	m_sLocalCSID.assign( szID );
}

//////////////////////////////////////////////////////////////////////
// Connect - send a message to initiate the disconnect
//////////////////////////////////////////////////////////////////////
void CModem::SetSpkrParams( int nSpkrVol, int nSpkrMode )
{
	m_nSpkrVol = nSpkrVol;
	m_nSpkrMode = nSpkrMode;
}


bool CModem::SendFax( char* szNumberToDial, char* szFaxFile )
{
	InternalModemMsg* pMsg = new InternalModemMsg;

	strcpy( pMsg->szNumber, szNumberToDial );
	strcpy( pMsg->szFile, szFaxFile );

//	m_sNumberToDial.assign( szNumberToDial );
//	m_FaxFile.SetFileName( szFaxFile );

	PostMsg( WM_MODEM_SENDFAX, (WPARAM)pMsg, 0 );

	return true;
}



//////////////////////////////////////////////////////////////////////
// OnStartup
//////////////////////////////////////////////////////////////////////
bool CModem::OnStartup( void )
{
	m_sThreadName.assign( "Modem Thread" );

	if( CThread::OnStartup() )
	{
		InitWindow();

		PostMsg( WM_MODEM_CONNECT, 0, 0 );

		return true;
	}

	return false;
}


//////////////////////////////////////////////////////////////////////
// OnShutdown - called before thread exits
//////////////////////////////////////////////////////////////////////
void CModem::OnShutdown( void )
{
	CThread::OnShutdown();

	ShutdownWindow();

	if( m_bConnected )
	{
		DisconnectPort();
		m_nState = STATE_NONE;
		m_bConnected = false;
	}
}


//////////////////////////////////////////////////////////////////////
// Handle message - return true if WM_QUIT received
//////////////////////////////////////////////////////////////////////
bool CModem::OnMsg( MSG* pMsg )
{
	if( CThread::OnMsg( pMsg ) )
		return true;

	m_dwActivityTimer = GetTickCount();

	switch( pMsg->message )
	{
	case WM_MODEM_CONNECT:
		OnConnectMsg();
		break;

	case WM_MODEM_DISCONNECT:
		OnDisconnectMsg();
		break;

	case WM_MODEM_SENDFAX:
		OnSendFaxMsg( pMsg );
		break;

	case WM_MODEM_RECVFAX:
		OnRecvFaxMsg( pMsg );
		break;

	case WM_MODEM_ABORTFAX:
		OnAbortFaxMsg();
		break;

	case WM_MODEM_CLEARRINGCNT:
		m_nRingCount = 0;
		m_nState = STATE_IDLE;
		break;

	case WM_MODEM_SETID:
		{
			InternalModemMsg* pModemMsg = (InternalModemMsg*) pMsg->wParam;

			if( pModemMsg)
			{
				SetCSID( pModemMsg->szNumber );
			}
			delete pModemMsg;
		}
		break;
	}

	return false;
}


//////////////////////////////////////////////////////////////////////
// Handle event - return true if cancel event set
//////////////////////////////////////////////////////////////////////
bool CModem::OnEvent( int nIndex )
{

	switch( nIndex )
	{
	case 0:
		// Cancel event
		OnDisconnectMsg();
		return true;

	case 1:
		// Read event
		ReadEventSignalled();
		return false;

	case 2:
		// Write event
		WriteEventSignalled();
		return false;

	case 3:
		// WaitComm event
		WaitCommEventSignalled();
		return false;

	case 4:
		// Disconnect Event
		return true;
	}

	return false;
}



//////////////////////////////////////////////////////////////////////
// OnConnectMsg
//////////////////////////////////////////////////////////////////////
void CModem::OnConnectMsg(void)
{
	if( !m_bConnected )
	{
		m_nRingCount = 0;
		m_bConnected = ConnectPort( m_sLastError );

		if( !m_bConnected )
		{
			SignalEvent( EVENT_ERROR );
			m_nState = STATE_NONE;
			SignalEvent( EVENT_DISCONNECT );
			ExitAndDelete();
		}
	}
}

//////////////////////////////////////////////////////////////////////
// OnDisconnectMsg
//////////////////////////////////////////////////////////////////////
void CModem::OnDisconnectMsg(void)
{
	if( m_bConnected )
	{
		if( OnDisconnect() )
		{
			DisconnectPort();
			m_nState = STATE_NONE;
			SignalEvent( EVENT_DISCONNECT );
			m_bConnected = false;
			ExitAndDelete();
		}
	}
}


//////////////////////////////////////////////////////////////////////
// OnSendFaxMsg
//////////////////////////////////////////////////////////////////////
void CModem::OnSendFaxMsg( MSG* pMsg )
{
	InternalModemMsg* pModemMsg = (InternalModemMsg*) pMsg->wParam;

	if( pModemMsg == NULL)
		return;

	m_sNumberToDial.assign( pModemMsg->szNumber );
	m_FaxFile.SetFileName( pModemMsg->szFile );	

	delete pModemMsg;

	m_nMaxPageRetriesPageNo = -1;
}

void CModem::OnRecvFaxMsg( MSG* pMsg )
{
	InternalModemMsg* pModemMsg = (InternalModemMsg*) pMsg->wParam;

	if( pModemMsg == NULL)
		return;

	m_FaxFile.SetFileName( pModemMsg->szFile );	

	delete pModemMsg;
}


void CModem::OnAbortFaxMsg(void)
{

}

//////////////////////////////////////////////////////////////////////
// SendCommand
//////////////////////////////////////////////////////////////////////
void CModem::SendCommand( int nCommand, char* szCmdString )
{
	char szWorkBuffer[256];
	char* szCmd = NULL;


	if( szCmdString )
	{
		szCmd = szCmdString;
	}
	else if( nCommand == COMMAND_SETUP_STRING )
	{
		szCmd = (char*)m_sInitString.c_str();
	}
	else 
	{
		switch( nCommand )
		{
		case COMMAND_SET_SPKR_VOL:
			wsprintf( szWorkBuffer, s_CommonCmds[nCommand], m_nSpkrVol );
			szCmd = szWorkBuffer;
			break;

		case COMMAND_SET_SPKR_MODE:
			wsprintf( szWorkBuffer, s_CommonCmds[nCommand], m_nSpkrMode );
			szCmd = szWorkBuffer;
			break;

		case COMMAND_DIAL:
			if( m_bPulseDialing )
			{
				wsprintf( szWorkBuffer, "ATDP%s", m_sNumberToDial.c_str() );
			}
			else
			{
				wsprintf( szWorkBuffer, "ATDT%s", m_sNumberToDial.c_str() );
			}
			szCmd = szWorkBuffer;
			break;

		case COMMAND_SET_FLOW_CONTROL:
			wsprintf( szWorkBuffer, s_CommonCmds[nCommand], m_bCTSFlowControl ? 2 : 1 );
			szCmd = szWorkBuffer;
			break;

		default:
			if( nCommand >= 0 && nCommand < COMMAND_COUNT )
			{
				szCmd = s_CommonCmds[nCommand];
			}
			break;
		}
	}
	
	if( szCmd )
	{
		m_nLastCommand = nCommand;
		m_LastCommandString.assign( szCmd );

		m_bGotOK = false;
		KillTimer( TIMER_COMMAND );
		if( (nCommand != COMMAND_DIAL) && (nCommand != COMMAND_ANSWER) )
		{
			SetTimer( TIMER_COMMAND, 2000 );
		}

//		m_nLastCommandTickCount = GetTickCount();

		DoWrite( szCmd, strlen(szCmd), true );

		//wsprintf( szWorkBuffer, "Sent Command: %s\n", m_LastCommandString.c_str() );
		//OutputDebugString( szWorkBuffer );
	}
}

//////////////////////////////////////////////////////////////////////
// SignalEvent
//////////////////////////////////////////////////////////////////////
void CModem::SignalEvent( int nEvent, char info )
{
	FaxApiModemMsg* pMsg = new FaxApiModemMsg;

	memset( pMsg, 0, sizeof(FaxApiModemMsg) );

	pMsg->m_cbSize = sizeof(FaxApiModemMsg);

	switch( nEvent )
	{
	case EVENT_ERROR:
		strncpy( pMsg->sz, m_sLastError.c_str(), FAXAPI_MODEMMSG_INFOLEN );
		pMsg->sz[FAXAPI_MODEMMSG_INFOLEN-1] = '\0';
		break;

	case EVENT_RECV_DIS:
	case EVENT_SENT_DIS:
		memcpy( &pMsg->p, &m_DISParams.p, sizeof(FaxApiParameters) );
		break;

	case EVENT_RECV_DCS:
	case EVENT_SENT_DCS:
		memcpy( &pMsg->p, &m_DCSParams.p, sizeof(FaxApiParameters) );
		break;

	case EVENT_GOT_REMOTEID:
		strcpy( pMsg->sz, m_sRemoteCSID.c_str() );
		trimws( pMsg->sz );
		break;

	case EVENT_START_PAGE:
		pMsg->t.nPages = GetPageCount();
		break;

	case EVENT_TERMINATE:
		strncpy( pMsg->sz, m_sLastError.c_str(), FAXAPI_MODEMMSG_INFOLEN );
		pMsg->sz[FAXAPI_MODEMMSG_INFOLEN-1] = '\0';
		pMsg->t.nPages = GetPageCount();
		pMsg->t.nSuccessful = (m_bSuccessful && GetPageCount() > 0 ) ? 1 : 0;
		break;

	case EVENT_CALLERID:
		strncpy( pMsg->sz, m_szLineBuff, FAXAPI_MODEMMSG_INFOLEN );
		pMsg->szID[FAXAPI_MODEMMSG_INFOLEN-1] = '\0';
		break;

	default:
		pMsg->sz[0] = info;
		break;
	}

	SendModemMessage( nEvent, pMsg );
}


void CModem::SignalEventString( int nEvent, LPCSTR szMsg )
{
	FaxApiModemMsg* pMsg = new FaxApiModemMsg;

	memset( pMsg, 0, sizeof(FaxApiModemMsg) );

	pMsg->m_cbSize = sizeof(FaxApiModemMsg);

	strncpy( pMsg->sz, szMsg, FAXAPI_MODEMMSG_INFOLEN );
	pMsg->sz[FAXAPI_MODEMMSG_INFOLEN-1] = '\0';

	SendModemMessage( nEvent, pMsg );
}

void CModem::SendModemMessage( int nEvent, FaxApiModemMsg* pMsg )
{
	strcpy( pMsg->szID, m_sPort.c_str() );
	PostThreadMessage( m_FaxThreadID, WM_MODEM_MESSAGE, (WPARAM)pMsg, nEvent );
}

//////////////////////////////////////////////////////////////////////
// ErrorUnexpectedResponse
//////////////////////////////////////////////////////////////////////
void CModem::ErrorUnexpectedResponse( void )
{
	char szMsg[512];
	wsprintf( szMsg, (char*)LoadString(GEN_RECEIVED_IN_RESPONSE_TO).c_str(), m_szLineBuff, m_LastCommandString.c_str() );
	m_sLastError.assign( szMsg );
	SignalEvent( EVENT_ERROR );
}

//////////////////////////////////////////////////////////////////////
// ErrorConnectResponse
//////////////////////////////////////////////////////////////////////
void CModem::ErrorConnectResponse( void )
{
	// For now, use the return string as the error description
	m_sLastError.assign( m_szLineBuff );
	SignalEvent( EVENT_ERROR );
}


void CModem::ProcSupportedSpeeds( LPSTR lpSpeeds, bool bSend )
{
	LPSTR lpTok;
	int val;

	char szDefSpeeds[64];

	if( stricmp( m_szLineBuff, "ERROR" ) == 0 )
	{
		strcpy( szDefSpeeds, "3,24,48,72,73,74,96,97,98,121,122,145,146" );
		lpSpeeds = szDefSpeeds;
	}


	bool* bSupported = (bSend) ? &m_bSendSupported[0] : &m_bRecvSupported[0];

	ZeroMemory( bSupported, sizeof(bool) * MAX_CLS1SPEEDS );

	lpTok = strtok( lpSpeeds, ",");

	while( lpTok ) {
		val = atoi( lpTok );
		
		switch( val ) {
			case 24:
				bSupported[0] = 1;
				break;

			case 48:
				bSupported[1] = 1;
				break;
		
			case 72:
				bSupported[2] = 1;
				break;

			case 73:
				bSupported[6] = 1;
				break;
						
			case 96:
				bSupported[3] = 1;
				break;

			case 97:
				bSupported[7] = 1;
				break;

			case 121:
				bSupported[8] = 1;
				bSupported[4] = 1;
				break;

			case 145:
				bSupported[9] = 1;
				bSupported[5] = 1;
				break;
		}

		lpTok = strtok( NULL, "," );
	}


	if( bSend )
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -