?? modem.cpp
字號:
/*****************************************************************************
* 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 + -