diff -r 000000000000 -r 3553901f7fa8 fax/faxclientandserver/FAXSVR/CFAX20.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fax/faxclientandserver/FAXSVR/CFAX20.CPP Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,520 @@ +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "FAXSERV.H" +#include "fax_reversebytes.h" +#include "FAXMODEM.H" +#include "FAXMDRV.H" + +#include "FAXLOG.H" + +const TInt KClass20HangupStatusTimer=20; // < Time used to wait for final +FHS: report. Was 5s, but typical GSM delays range between 4s and 10s. + +// this module has two parts +// first receive routines rx +// second transmit routines tx + +/********************************************************************/ + +CFaxModemDriver* CFaxClass20::NewLC(TFaxServerSessionSettings * aFaxServerSessionSettings, RFax::TProgress & aProgress) + { + CFaxModemDriver* self = new(ELeave) CFaxClass20; + CleanupStack::PushL(self); + self->ConstructL(aFaxServerSessionSettings, aProgress); + return self; + } + +CFaxModemDriver* CFaxClass20::NewL(TFaxServerSessionSettings * aFaxServerSessionSettings, RFax::TProgress & aProgress) + { + CFaxModemDriver* self = NewLC(aFaxServerSessionSettings, aProgress); + CleanupStack::Pop(); + return self; + } +/********************************************************************/ + +TInt CFaxClass20::RxConnectL() + { + __FLOG_FAXSRV( _L8("CFaxClass20::RxConnectL entering")); + + CheckCadenceExportL (_L8 ("AT+FNR=1,1,1,0\r")); + if ((iModem->GetMatchL (_L8 ("OK"), 5)) == 0) + return (KFaxErrModemNotWorking); + + CheckCadenceExportL(_L8("AT+FCC=?\r")); + if (!(iModem->ImportL (iResults, 35))) + return (KFaxErrModemNotWorking); + + iModem->iOurMessage.Format (_L8 ("%S"), &iResults); + iModem->ProgressUpdateL (); + ParseResults (iResults); + + iModem->GetMatchL (_L8 ("OK"), 2); + + if (iFaxServerSessionSettings->iRxResolution == EFaxNormal) + iModem->iProgress.iResolution = EFaxNormal; + else + iModem->iProgress.iResolution = EFaxFine; + + if (iFaxServerSessionSettings->iRxCompression == EModifiedRead) + iModem->iProgress.iCompression = EModifiedRead; + else + iModem->iProgress.iCompression = EModifiedHuffman; + + iActualFaxSpeed = iModem->iProgress.iSpeed; + if (iActualFaxSpeed > iFaxServerSessionSettings->iMaxSpeed) + iActualFaxSpeed = iFaxServerSessionSettings->iMaxSpeed; + + if (iFaxServerSessionSettings->iPreferredECM == 0) + iModem->iProgress.iECM = 0; + + iResults.Copy(_L8("AT+FCC=0,0,0,2,0,0,0,0\r")); + + iResults[7] = (TUint8) (iResults[7] + iModem->iProgress.iResolution); + iResults[9] = (TUint8) (((iActualFaxSpeed / 2400) - 1) + '0'); + iResults[15] = (TUint8) (iResults[15] + iModem->iProgress.iCompression); + iResults[17] = (TUint8) (iModem->iProgress.iECM + '0'); + CheckCadenceExportL(iResults); + if ((iModem->GetMatchL(_L8("OK"), 3)) == 0) + { + return (KFaxErrModemNotWorking); + } + CheckCadenceExportL(_L8 ("AT+FAA=0\r")); + if ((iModem->GetMatchL(_L8("OK"), 5)) == 0) + { + return (KFaxErrNoReceiveMode); + } + + TBuf8 narrowBuf; + narrowBuf.Copy(iFaxServerSessionSettings->iFaxId); // convert from unicode to narrow + + //-- By Dmitry Lyokhin. concerns PIA-58ELQK defect. + if( narrowBuf.Length() < 1 ) + { + narrowBuf.Append(' '); + } + + if (iFaxServerSessionSettings->iMode & KFaxPoll) + { + iModem->ExportL(_L8 ("AT+FSP=1\r")); + if ((iModem->GetMatchL(_L8("OK"), 5)) == 0) + { + return (KFaxPollingUnsupported); + } + iModem->ExportL(_L8("AT+FPI=\"")); + iModem->ExportL(narrowBuf); + iModem->ExportL(_L8 ("\"\r")); + if ((iModem->GetMatchL(_L8("OK"), 3)) == 0) + { + return (KFaxPollingUnsupported); + } + } + else + { + CheckCadenceExportL(_L8("AT+FCR=1\r")); + if ((iModem->GetMatchL(_L8("OK"), 5)) == 0) + { + return (KFaxErrNoReceiveMode); + } + CheckCadenceExportL(_L8("AT+FLI=\"")); + iModem->ExportL(narrowBuf); + iModem->ExportL(_L8("\"\r")); + if ((iModem->GetMatchL(_L8("OK"), 3)) == 0) + { + return (KFaxErrModemNotWorking); + } + } + + if (iFaxServerSessionSettings->iMode & KFaxWaitForRing) + { +// while ((iModem->GetMatchL(_L8("RING"), 3)) == 0); +// iTimeOfLastRing.UniversalTime(); + } + else + { + if ((iFaxServerSessionSettings->iMode & KFaxOffHook) == 0) + { + DialFaxOnDemandL(); + } + } + + if ((iFaxServerSessionSettings->iMode & KFaxPoll) == 0) + { + CheckCadenceExportL(_L8("ATA\r")); + } + + iModem->iProgress.iPhase = ECallEstablishment; + + TInt pollDocsAvailable = 0; + + for (;;) + { + if(!(iModem->ImportL(iResults, 35))) + { + return KFaxErrCannotAnswer; + } + + iModem->iOurMessage.Format(_L8("%S"), &iResults); + iModem->ProgressUpdateL(); + + if ((iResults.FindF(_L8("NO DIALTONE"))) >= 0 || + iResults.FindF(_L8("NO DIAL TONE")) >= 0) + return (KFaxErrNoDialTone); + if ((iResults.FindF(_L8("BUSY"))) >= 0) + return (KFaxErrBusy); + if ((iResults.FindF(_L8("NO ANSWER"))) >= 0) + return (KFaxErrNoAnswer); + if ((iResults.FindF(_L8("NO CARRIER"))) >= 0) + return (KFaxErrNoCarrier); + if ((iResults.FindF(_L8("OK"))) >= 0) + break; + if ((iResults.FindF(_L8("FHS"))) >= 0) + return (KFaxErrPrematureHangup); + if ((iResults.FindF(_L8("FCO"))) >= 0) + iModem->iProgress.iPhase = ESessionNegotiation; + else if ((iResults.FindF(_L8("FPO"))) >= 0) + pollDocsAvailable = 1; + else if ((iResults.FindF(_L8("FTI"))) >= 0) + ExtractAnswerback(iResults); + else if ((iResults.FindF(_L8("FCS"))) >= 0) + ParseResults(iResults); + } + + if ((iFaxServerSessionSettings->iMode & KFaxPoll) && (pollDocsAvailable == 0)) + return (KFaxNothingToPoll); + + iModem->iOurMessage.Format(_L8 ("about to receive fax")); + iModem->ProgressUpdateL(); + return RxPrePageL(); + } + +/********************************************************************/ +TInt CFaxClass20::RxPrePageL() + { + __FLOG_FAXSRV( _L8("CFaxClass20::RxPrePageL entering")); + + iModem->ExportL(_L8 ("AT+FDR\r")); + for (;;) + { + if (!(iModem->ImportL (iResults, 35))) + return (KFaxErrCannotConnect); + + iModem->iOurMessage.Format (_L8 ("%S"), &iResults); + iModem->ProgressUpdateL (); + + if ((iResults.FindF (_L8 ("ERROR"))) >= 0) + return (KFaxErrNoReceiveMode); + if ((iResults.FindF (_L8 ("FHS"))) >= 0) + return (KFaxErrPrematureHangup); + if ((iResults.FindF (_L8 ("CONNECT"))) >= 0) + break; + if ((iResults.FindF (_L8 ("FCS"))) >= 0) + ParseResults (iResults); + } + + iModem->TxcharL (Kdc2); + return (RxStartPageL ()); +} +/********************************************************************/ +TInt CFaxClass20::RxPostPageL () +{ + __FLOG_FAXSRV( _L8("CFaxClass20::RxPostPageL entering")); + + iModem->iProgress.iPhase = EPostPageStatus; + iModem->ProgressUpdateL (); + for (;;) + { + if (iModem->iProgress.iECM == 0) + { + if (!(iModem->ImportL (iResults, 20))) + return (KFaxErrModemResponse); + } + else + { + // coverity[check_return] + iModem->ImportL (iResults, 0x7fff); // no timeout if ECM enabled + } + + iModem->iOurMessage.Format (_L8 ("%S"), &iResults); + iModem->ProgressUpdateL (); + + if ((iResults.FindF (_L8 ("OK"))) >= 0) + return (KFaxErrPrematureOK); + if ((iResults.FindF (_L8 ("FHS"))) >= 0) + return (KFaxErrPrematureHangup); + if ((iResults.FindF (_L8 ("FET"))) >= 0) + break; + } + if (iModem->GetMatchL (_L8 ("OK"), 5) == 0) + return (KFaxErrNoFinalOK); + + if ((iResults.FindF (_L8 ("0"))) >= 0) + { + iModem->iOurMessage.Format (_L8 ("page %u successfully received"), iModem->iProgress.iPage); + iModem->ProgressUpdateL (); + return (RxPrePageL ()); + } + if ((iResults.FindF (_L8 ("1"))) >= 0) + { + iModem->iOurMessage.Format (_L8 ("page %u successfully received : end of document"), iModem->iProgress.iPage); + iModem->ProgressUpdateL (); + iModem->iOurMessage.Format (_L8 ("Next fax awaited")); + iModem->ProgressUpdateL (); + return (RxPrePageL ()); + } + if ((iResults.FindF (_L8 ("2"))) >= 0) + { + iModem->iOurMessage.Format (_L8 ("Final page %u successfully received"), iModem->iProgress.iPage); + iModem->ProgressUpdateL (); + iModem->iProgress.iPhase = EDisconnection; + iModem->ExportL (_L8 ("AT+FDR\r")); + if (iModem->GetMatchL (_L8 ("FHS"), KClass20HangupStatusTimer) == 0) + return (KFaxErrNoHangup); + if (iModem->GetMatchL (_L8 ("OK"), 5) == 0) + return (KFaxErrNoFinalOK); + return (KErrNone); + } + return (KFaxErrUnknownPageCode); +} +/********************************************************************/ + +TInt CFaxClass20::TxConnectL () +{ + __FLOG_FAXSRV( _L8("CFaxClass20::TxConnectL entering")); + + iModem->ExportL (_L8 ("AT+FNR=1,1,1,0\r")); + if ((iModem->GetMatchL (_L8 ("OK"), 5)) == 0) + return (KFaxErrModemNotWorking); + TBuf8 narrowBuf; + narrowBuf.Copy(iFaxServerSessionSettings->iFaxId); // convert from unicode to narrow + + //-- By Dmitry Lyokhin. concerns PIA-58ELQK defect. + if( narrowBuf.Length() < 1 ) narrowBuf.Append(' '); + + + iModem->ExportL (_L8 ("AT+FLI=\"")); + iModem->ExportL (narrowBuf); + iModem->ExportL (_L8 ("\"\r")); + if ((iModem->GetMatchL (_L8 ("OK"), 3)) == 0) + return (KFaxErrModemNotWorking); + + iModem->ExportL (_L8 ("AT+FCC=?\r")); + if (!(iModem->ImportL (iResults, 35))) + return (KFaxErrModemNotWorking); + + iModem->iOurMessage.Format (_L8 ("%S"), &iResults); + iModem->ProgressUpdateL (); + ParseResults (iResults); + + iModem->GetMatchL (_L8 ("OK"), 2); + + iActualFaxSpeed = iModem->iProgress.iSpeed; + if (iActualFaxSpeed > iFaxServerSessionSettings->iMaxSpeed) + iActualFaxSpeed = iFaxServerSessionSettings->iMaxSpeed; + + if (iFaxServerSessionSettings->iPreferredECM == 0) + iModem->iProgress.iECM = 0; + + iResults.Copy (_L8 ("AT+FCC=0,0,0,2,0,0,0,0\r")); + + iResults[7] = (TUint8) (iResults[7] + iFaxServerSessionSettings->iTxResolution); + iResults[9] = (TUint8) (((iActualFaxSpeed / 2400) - 1) + '0'); + + + // added to support 2Dfaxing using class 2.0 + if (iModem->iProgress.iCompression) + iResults[15] = (TUint8) (iResults[15] + iFaxServerSessionSettings->iTxCompression); + else + iResults[15] = (TUint8) (iResults[15] + EModifiedHuffman); + + //iResults[15] = (TUint8) (iResults[15] + iFaxServerSessionSettings->iTxCompression); + + + iResults[17] = (TUint8) (iModem->iProgress.iECM + '0'); + iModem->ExportL (iResults); + if ((iModem->GetMatchL (_L8 ("OK"), 3)) == 0) + return (KFaxErrModemNotWorking); + + iModem->ExportL (_L8 ("ATD")); + if ((iFaxServerSessionSettings->iMode & KFaxOffHook) == 0) + iModem->ExportL (iFaxServerSessionSettings->iPhoneNumber); + iModem->TxcharL (Kreturn); + + iModem->iProgress.iPhase = ECallEstablishment; + for (;;) + { + if (!(iModem->ImportL (iResults, KDialTimeout))) + return (KFaxErrNoDial); + + iModem->iOurMessage.Format (_L8 ("%S"), &iResults); + iModem->ProgressUpdateL (); + + if ((iResults.FindF (_L8 ("NO DIALTONE"))) >= 0 || + iResults.FindF (_L8 ("NO DIAL TONE")) >= 0) + return (KFaxErrNoDialTone); + if ((iResults.FindF (_L8 ("BUSY"))) >= 0) + return (KFaxErrBusy); + if ((iResults.FindF (_L8 ("NO ANSWER"))) >= 0) + return (KFaxErrNoAnswer); + if ((iResults.FindF (_L8 ("NO CARRIER"))) >= 0) + return (KFaxErrNoCarrier); + if ((iResults.FindF (_L8 ("FHS"))) >= 0) + return (KFaxErrNoNegotiate); + if ((iResults.FindF (_L8 ("OK"))) >= 0) + break; + if ((iResults.FindF (_L8 ("FCO"))) >= 0) + iModem->iProgress.iPhase = ESessionNegotiation; + else if ((iResults.FindF (_L8 ("FCI"))) >= 0) + ExtractAnswerback (iResults); + } + return (TxPrePageL ()); +} +/********************************************************************/ +TInt CFaxClass20::TxPrePageL () +{ + __FLOG_FAXSRV(_L8("CFaxClass20::TxPrePageL entering")); + + iModem->ExportL (_L8 ("AT+FDT\r")); + for (;;) + { + if (!(iModem->ImportL (iResults, 30))) + return (KFaxErrNoNegotiate); + + iModem->iOurMessage.Format (_L8 ("%S"), &iResults); + iModem->ProgressUpdateL (); + + if ((iResults.FindF (_L8 ("FHS"))) >= 0) + return (KFaxErrNoNegotiate); + if ((iResults.FindF (_L8 ("CONNECT"))) >= 0) + break; + if ((iResults.FindF (_L8 ("FCS"))) >= 0) + ParseResults (iResults); + } + + for (;;) + { + TInt XonTimeoutSec = CLK_TCK * 3; + + if ((iModem->RxcharWaitL(XonTimeoutSec)) == 0) + { + break; + } + + if (iModem->iReadone[0] == Kxon) + { + break; + } + } + return (TxStartPageL()); +} +/********************************************************************/ + +// + // TxPostPageL should return either with + // + // a) an error code and iPhase set to RFax::EPostPageStatus, in which case the send returns with the error + // b) KErrNone and iPhase set to RFax::EDataTransfer, in which case we send the next page + // c) KErrNone and iPhase set to RFax::EDisconnection, in which case the send returns with KErrNone + // + +TInt CFaxClass20::TxPostPageL () +{ + if (iModem->iProgress.iCompression == EModifiedRead) + { + iModem->iTransmitBuffer.Append (0x00); + iModem->iTransmitBuffer.Append (0x60); + iModem->iTransmitBuffer.Append (0x00); + iModem->iTransmitBuffer.Append (0x0C); + iModem->iTransmitBuffer.Append (0x80); + iModem->iTransmitBuffer.Append (0x01); + iModem->iTransmitBuffer.Append (0x30); + iModem->iTransmitBuffer.Append (0x00); + iModem->iTransmitBuffer.Append (0x06); + iModem->iTransmitBuffer.Append (0xC0); + } + else + { + for (TInt x = 3; x; x--) + { + iModem->iTransmitBuffer.Append (0x0); + iModem->iTransmitBuffer.Append (0x08); + iModem->iTransmitBuffer.Append (0x80); + } + } + + iModem->iTransmitBuffer.Append (Kdle); + iModem->iOurMessage.Format (_L8 ("RTC transmitted after %d lines"), iModem->iProgress.iLines); + iModem->ProgressUpdateL (); + if (iFaxServerSessionSettings->iTxPages == iModem->iProgress.iPage) + { + iModem->iTransmitBuffer.Append (0x2e); + iModem->iOurMessage.Format (_L8 ("End of document transmitted ")); + } + else + { + iModem->iTransmitBuffer.Append (0x2c); + iModem->iOurMessage.Format (_L8 ("End of page %u transmitted "), iModem->iProgress.iPage); + } + __FLOG_FAXSRV( iModem->iOurMessage); + + iModem->CommitTransmitBufferL (); + + iModem->iProgress.iPhase = EPostPageStatus; + iModem->ProgressUpdateL (); + while (iModem->Txstat () != 0) + ; + iModem->Xonoff (); + + // we've just ended phase C data, so we need to wait for the modem to respond with OK or ERROR + + for (;;) + { + if (iModem->iProgress.iECM == 0) + { + if (!(iModem->ImportL (iResults, (32 * 1024) / (iModem->iProgress.iSpeed / 10)))) + return (KFaxErrCannotEndData); + } + else + { + // coverity[check_return] + iModem->ImportL (iResults, 0x7fff); // no timeout if ECM enabled, but NO CARRIER possible from some mobile phones + if ((iResults.FindF (_L8 ("NO CARRIER"))) >= 0) + return (KFaxErrCannotEndData); + } + + iModem->iOurMessage.Format (_L8 ("%S"), &iResults); + iModem->ProgressUpdateL (); + + if ((iResults.FindF (_L8 ("ERROR"))) >= 0) + break; + if ((iResults.FindF (_L8 ("OK"))) >= 0) + break; + } + if (((iResults.FindF (_L8 ("ERROR"))) >= 0) && (iRepeatPage == 0)) + { + iModem->iProgress.iPhase = ESessionNegotiation; + iRepeatPage++; + iModem->iProgress.iPage--; + return (TxPrePageL ()); + } + if (iFaxServerSessionSettings->iTxPages != iModem->iProgress.iPage) + { + iRepeatPage = 0; + return (TxPrePageL ()); + } + iModem->iProgress.iPhase = EDisconnection; + return (KErrNone); +} +/********************************************************************/ +