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

📄 classtwo.cpp

📁 fax engine 传真引擎 relay fax 的开源项目 商业软件使用 高质量 高可靠
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
* 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 CClassTwo is contain the protocol specifics of EIA
// fax modem class 2
//
////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ClassTwo.h"


#define CLASSTWO_CONNECT		"+FCON"
#define CLASSTWO_CONNECT_SIZE	5
#define CLASSTWO_TSI			"+FTSI"
#define CLASSTWO_TSI_SIZE		5
#define CLASSTWO_DCS			"+FDCS"
#define CLASSTWO_DCS_SIZE		5
#define CLASSTWO_NSS		"	+FNSS"
#define CLASSTWO_NSS_SIZE		5
#define CLASSTWO_HNGUP			"+FHNG"
#define CLASSTWO_HNGUP_SIZE		5
#define CLASSTWO_CSI			"+FCSI"
#define CLASSTWO_CSI_SIZE		5
#define CLASSTWO_DIS			"+FDIS"
#define CLASSTWO_DIS_SIZE		5
#define CLASSTWO_NSF			"+FNSF"
#define CLASSTWO_NSF_SIZE		5
#define CLASSTWO_PTS			"+FPTS"
#define CLASSTWO_PTS_SIZE		5
#define CLASSTWO_ET				"+FET"
#define CLASSTWO_ET_SIZE		4

#define CLASSTWO_DR			"AT+FDR"
#define CLASSTWO_DR_SIZE	6
#define CLASSTWO_DT			"AT+FDT"
#define CLASSTWO_DT_SIZE	6	
#define CLASSTWO_FK			"AT+FK"
#define CLASSTWO_FK_SIZE	5

#define CLASSTWO_SETID		"AT+FLID=\"%s\""
#define CLASSTWO_SETRECV	"AT+FCR=%d"
#define CLASSTWO_SETBOR		"AT+FBOR=0"
#define CLASSTWO_SETPARAMS	"AT+FDIS=%d,%d,%d,%d,%d,%d,0,%d"
#define CLASSTWO_SENDET		"AT+FET=%d"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CClassTwo::CClassTwo()
{
	m_sEIAClass = "2";
	m_nScanTime = 0;
}

CClassTwo::~CClassTwo()
{

}

void CClassTwo::OnConnect(void)
{
	SetState( STATE_INIT );

	m_bGotOK = false;

	SendCommand( COMMAND_INIT );

	m_nLoopCtr = 0; 
}


bool CClassTwo::OnDisconnect(void)
{
	switch( m_nState )
	{
	case STATE_INIT:
		SignalEvent( EVENT_ERROR );
		return true;

	case STATE_PHASE_A:
	case STATE_PHASE_B:
	case STATE_PHASE_C:
 	case STATE_PHASE_D:
    case STATE_PHASE_E:
		Abort( true );
		return false;
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
// OnWrite
//////////////////////////////////////////////////////////////////////
void CClassTwo::OnWrite(void)
{
	m_dwActivityTimer = GetTickCount();

	if( m_nState == STATE_PHASE_C && !m_bReceiving  && m_bGotDCS )
	{
		m_nPageBytes += m_BytesWritten;

		int nPercent = 100 * m_nPageBytes / m_FaxFile.GetPageBytes();

		if( nPercent > 100 )
			nPercent = 100;

		SignalEvent( EVENT_PAGE_DATA, nPercent );
	}
}


//////////////////////////////////////////////////////////////////////
// OnReadLine
//////////////////////////////////////////////////////////////////////
void CClassTwo::OnReadLine(void)
{
	//char szMsg[256];
	//wsprintf( szMsg, "CClassTwo::OnReadLine: %s %d\n", m_szLineBuff, m_nLineBuffPtr );
	//OutputDebugString( szMsg );

	switch( m_nState )
	{
	case STATE_IDLE:
		PhaseIdle();
		break;

	case STATE_INIT:
		PhaseInit();
		break;

	case STATE_PHASE_A:
		PhaseA();
		break;

	case STATE_PHASE_B:
		PhaseB();
		break;

	case STATE_PHASE_C:
		PhaseC();
		break;

	case STATE_PHASE_D:
		PhaseD();
		break;

	case STATE_PHASE_E:
		PhaseE();
		break;

	case STATE_RINGING:
		PhaseRinging();
		break;

	case STATE_DISCONNECT:
		PhaseDisconnect();
		break;
	}

}


//////////////////////////////////////////////////////////////////////
// PhaseInit
//////////////////////////////////////////////////////////////////////
void CClassTwo::PhaseInit(void)
{
	if( stricmp( m_szLineBuff, m_LastCommandString.c_str() ) == 0 )
	{
		// Echo - ignore
		return;
	}

	if( IsRing() )
	{
		// RING
		m_nRingCount++;
		return;
	}

	switch( m_nLastCommand )
	{
	case COMMAND_INIT:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			m_bGotOK = true;
		}
		else 
		{
			if( ++m_nLoopCtr >= 3 )
			{
				ErrorUnexpectedResponse();
				KillTimer( TIMER_COMMAND );
				OnDisconnectMsg();
			}
		}
		break;

	case COMMAND_SETUP_STRING:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SendCommand( COMMAND_DISABLE_ECHO );
		}
		else
		{
			ErrorUnexpectedResponse();
			KillTimer( TIMER_COMMAND );
			OnDisconnectMsg();		
		}
		break;

	case COMMAND_DISABLE_ECHO:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SendCommand( COMMAND_SET_SPKR_VOL );
		}
		else
		{
			ErrorUnexpectedResponse();
			KillTimer( TIMER_COMMAND );
			OnDisconnectMsg();		
		}
		break;

	case COMMAND_SET_SPKR_VOL:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SendCommand( COMMAND_SET_SPKR_MODE );
		}
		else
		{
			ErrorUnexpectedResponse();
			KillTimer( TIMER_COMMAND );
			OnDisconnectMsg();		
		}
		break;

	case COMMAND_SET_SPKR_MODE:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SendCommand( COMMAND_SET_FCLASS_2 );
		}
		else
		{
			ErrorUnexpectedResponse();
			KillTimer( TIMER_COMMAND );
			OnDisconnectMsg();		
		}
		break;

	case COMMAND_SET_FCLASS_2:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SendCommand( COMMAND_QUERY_CLASS2_CAP );
		}
		else
		{
			ErrorUnexpectedResponse();
			KillTimer( TIMER_COMMAND );
			OnDisconnectMsg();		
		}
		break;

	case COMMAND_QUERY_CLASS2_CAP:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SendCommand( COMMAND_QUERY_SEND_SPEEDS );
		}
		else if( stricmp( m_szLineBuff, "ERROR" ) == 0 )
		{
			ErrorUnexpectedResponse();
			KillTimer( TIMER_COMMAND );
			OnDisconnectMsg();		
		}
		else
		{
			ProcCapabilities( m_szLineBuff );

			VerifyOptions();
		}
		break;

	case COMMAND_QUERY_SEND_SPEEDS:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SendCommand( COMMAND_QUERY_RECEIVE_SPEEDS );
		}
		else
		{
			ProcSupportedSpeeds( m_szLineBuff, true );
		}
		break;

	case COMMAND_QUERY_RECEIVE_SPEEDS:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SetLocalID();
		}
		else
		{
			ProcSupportedSpeeds( m_szLineBuff, false );
		}
		break;

	case COMMAND_SET_LOCAL_ID:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SetRecv();
		}
		else
		{
			ErrorUnexpectedResponse();
			KillTimer( TIMER_COMMAND );
			OnDisconnectMsg();		
		}
		break;

	case COMMAND_SET_RECV:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SetBitOrder();
		}
		else
		{
			ErrorUnexpectedResponse();
			KillTimer( TIMER_COMMAND );
			OnDisconnectMsg();		
		}
		break;

	case COMMAND_SET_BIT_ORDER:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{	
			m_nScanTime = 0;
			SetFaxParams( false );
		}
		else
		{
			ErrorUnexpectedResponse();
			KillTimer( TIMER_COMMAND );
			OnDisconnectMsg();		
		}
		break;

	case COMMAND_SET_FAX_PARAMS:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SetState( STATE_IDLE );
			KillTimer( TIMER_COMMAND );
		}
		else
		{
			ErrorUnexpectedResponse();
			SignalEventString( EVENT_INFO, (char*)LoadString(GEN_REDUCE_COMPRESSION_BAUD_RATE_OR_DISABLE_ECM).c_str() );
			KillTimer( TIMER_COMMAND );
			OnDisconnectMsg();		
		}
		break;
	}

}


//////////////////////////////////////////////////////////////////////
// PhaseIdle
//////////////////////////////////////////////////////////////////////
void CClassTwo::PhaseIdle(void)
{
	if( IsRing() )
	{
		m_nRingCount = 1;
		SetState( STATE_RINGING );

		SignalEvent( EVENT_RING, m_nRingCount );
	}
}

//////////////////////////////////////////////////////////////////////
// Phase Ringing
//////////////////////////////////////////////////////////////////////
void CClassTwo::PhaseRinging(void)
{
	if( IsRing() )
	{
		m_nRingCount++;

		SignalEvent( EVENT_RING, m_nRingCount );

		/*
		if( OkToAnswer() )
		{
			m_bReceiving = true;
			m_bSuccessful = false;
			SendCommand( COMMAND_ANSWER );
			SetState( STATE_PHASE_B, STATE_RECEIVING );
		}
		*/
	}
	else if( strnicmp( m_szLineBuff, CLASSTWO_CONNECT, CLASSTWO_CONNECT_SIZE ) == 0 )
	{
		EnableSoftFlowControl( false );
		m_FaxFile.SetSendEncoding( m_nSendEncoding );
		m_bReceiving = true;
		m_bSuccessful = false;
		SignalEvent( EVENT_START_RECV );
		SetState( STATE_PHASE_B, STATE_RECEIVING );
	}
	else
	{
		SignalEvent( EVENT_CALLERID );
	}
}


//////////////////////////////////////////////////////////////////////
// Phase A - call setup
//////////////////////////////////////////////////////////////////////
void CClassTwo::PhaseA(void)
{
	switch( m_nPhaseState )
	{
	case STATE_SET_PARAMS:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			SetLocalID();
			m_nPhaseState = STATE_SET_CSID;
		}
		else
		{
			// Error setting fax params
			m_sLastError.assign( (char*)LoadString(GEN_ERROR_SETTING_FAX_PARAMETERS).c_str() );
			//SignalEvent( EVENT_ERROR );
			Terminate();
			PhaseDisconnect();
		}
		break;
	
	case STATE_SET_CSID:
		if( stricmp( m_szLineBuff, "OK" ) == 0 )
		{
			if( m_bReceiving )
			{
				SendCommand( COMMAND_ANSWER );
				SetState( STATE_PHASE_B, STATE_RECEIVING );
			}
			else
			{
				SendCommand( COMMAND_DIAL );
				m_nPhaseState = STATE_DIALING;
			}
		}
		else
		{
			// Error setting ID
			m_sLastError.assign( (char*)LoadString(GEN_ERROR_SETTING_ID).c_str() );
			//SignalEvent( EVENT_ERROR );
			Terminate();
			PhaseDisconnect();
		}
		break;

	case STATE_DIALING:
		if( strnicmp( m_szLineBuff, CLASSTWO_CONNECT, CLASSTWO_CONNECT_SIZE ) == 0 )
		{
			m_nLoopCtr = 0;
			SetState( STATE_PHASE_B, STATE_SENDING );	
			m_bGotDIS = false;
			SignalEvent( EVENT_START_SEND );
		}
		else if( strnicmp( m_szLineBuff, CLASSTWO_HNGUP, CLASSTWO_HNGUP_SIZE ) == 0 )
		{
			OnFHNG();
		}
		else
		{
			ErrorConnectResponse();
			Terminate();
			PhaseDisconnect();
		}
		break;

	}
}


//////////////////////////////////////////////////////////////////////
// Phase B - negotiation and training
//////////////////////////////////////////////////////////////////////
void CClassTwo::PhaseB(void)
{
	switch( m_nPhaseState )
	{
	case STATE_RECEIVING:
		if( strnicmp( m_szLineBuff, "OK", 2 ) == 0 )
		{
			m_bGotEOP = false;
			m_bGotMPS = false;
			m_bGotEOM = false;

			// On to phase C
			DoWrite( CLASSTWO_DR, CLASSTWO_DR_SIZE, true );
			SetState( STATE_PHASE_C );
			m_FaxFile.WriteFileHeader();
			SignalEvent( EVENT_START_TRAINING );
		} 
		else if( strnicmp( m_szLineBuff, CLASSTWO_CONNECT, CLASSTWO_CONNECT_SIZE ) == 0 )
		{
			SignalEvent( EVENT_START_RECV );
		}
		else if( strnicmp( m_szLineBuff, CLASSTWO_TSI, CLASSTWO_TSI_SIZE ) == 0 )
		{
			OnCSI();
		}
		else if( strnicmp( m_szLineBuff, CLASSTWO_DCS, CLASSTWO_DCS_SIZE ) == 0 )
		{
			OnDCS();
		}
		else if( strnicmp( m_szLineBuff, CLASSTWO_NSS, CLASSTWO_NSS_SIZE ) == 0 )
		{
			OnNSS();
		}
		else if( strnicmp( m_szLineBuff, CLASSTWO_HNGUP, CLASSTWO_HNGUP_SIZE ) == 0 )
		{
			OnFHNG();
		}
		break;

	case STATE_SENDING:
		if( strnicmp( m_szLineBuff, "OK", 2 ) == 0 )
		{
			// Check DIS and re-set parameters if necessar
			if( m_bGotDIS && m_bResendFaxParams )
			{
				SetFaxParams( true );
				m_nPhaseState = STATE_RESET_PARAMS;
			}
			else
			{
				// On to Phase C
				DoWrite( CLASSTWO_DT, CLASSTWO_DT_SIZE, true );
				SetState( STATE_PHASE_C );
				m_bGotDCS = false;
				SignalEvent( EVENT_START_TRAINING );
				m_bLastPageGood = false;
			}
		} 
		else if( strnicmp( m_szLineBuff, CLASSTWO_CSI, CLASSTWO_CSI_SIZE ) == 0 )
		{
			OnCSI();
		}
		else if( strnicmp( m_szLineBuff, CLASSTWO_DIS, CLASSTWO_DIS_SIZE ) == 0 )
		{
			OnDIS();
		}
		else if( strnicmp( m_szLineBuff, CLASSTWO_NSF, CLASSTWO_NSF_SIZE ) == 0 )
		{
			OnNSF();
		}
		else if( strnicmp( m_szLineBuff, CLASSTWO_HNGUP, CLASSTWO_HNGUP_SIZE ) == 0 )
		{
			OnFHNG();
		}
		break;

	case STATE_RESET_PARAMS:
		if( strnicmp( m_szLineBuff, "OK", 2 ) == 0 )
		{

⌨️ 快捷键说明

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