--- /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<RCall::KFaxIdUserNameMaxSize> 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<RCall::KFaxIdUserNameMaxSize> 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 <dle><eop>"));
+ }
+ else
+ {
+ iModem->iTransmitBuffer.Append (0x2c);
+ iModem->iOurMessage.Format (_L8 ("End of page %u transmitted <dle><mps>"), 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);
+}
+/********************************************************************/
+