diff -r 630d2f34d719 -r 07a122eea281 fax/faxclientandserver/FAXSVR/CFAXMODM.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fax/faxclientandserver/FAXSVR/CFAXMODM.CPP Wed Sep 01 12:40:21 2010 +0100 @@ -0,0 +1,985 @@ +// 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: +// CFaxModem class implementation +// +// + +/** + @file +*/ + + +#include "FAXSERV.H" +#include +#include "FAXMODEM.H" + +#include "FAXLOG.H" + +// we embed this so that the session log tells us the version used + +#define FaxTransVersionString "FAX SERVER SESSION LOG (Release 033)" + +/********************************************************************/ + +CFaxModem::CFaxModem (RFax::TProgress & aProgress) +:iProgress (aProgress) + { + } +/********************************************************************/ + +CFaxModem *CFaxModem::NewLC (TFaxServerSessionSettings * aFaxServerSessionSettings, RFax::TProgress & aProgress) + { + CFaxModem *self = new (ELeave) CFaxModem (aProgress); + CleanupStack::PushL (self); + self->ConstructL (aFaxServerSessionSettings); + return self; + } +/********************************************************************/ + +CFaxModem *CFaxModem::NewL (TFaxServerSessionSettings * aFaxServerSessionSettings, RFax::TProgress & aProgress) + { + CFaxModem *self = NewLC (aFaxServerSessionSettings, aProgress); + CleanupStack::Pop (); + return self; + } +/********************************************************************/ + +void CFaxModem::ConstructL (TFaxServerSessionSettings * aFaxServerSessionSettings) + { + TInt r; +// TBufC < 24 > logname (_L ("C:\\SYSTEM\\FAXLOG.TXT")); +// RFsBase closefile; + + __FLOG_FAXSRV( _L8("CFaxModem::ConstructL entering")); + + iVerbose = 1; + +// we start off with our timer functions + + iStartTime.UniversalTime(); + +// work out the granularity of the clock + + TTimeIntervalMicroSeconds32 ourGranularity; + if (UserHal::TickPeriod (ourGranularity) == KErrNotSupported) + User::Leave (KErrNotSupported); + iGranularity = ourGranularity.Int (); + +// calibrate a 2 ms timing loop - see notes at start of cfaxTransfer::ExportL +// this is only used for class 1 when iTimingLoopDelay is true + + iCalls = 0; + TInt t; + t = clock () + iGranularity; + while (t > clock ()) + ; // wait for the clock to tick once + t = clock () + iGranularity; // reset target + while (t > clock ()) // wait for it to tick again + iCalls++; // this time counting calls to clock + iCalls *= (CLK_TCK / iGranularity); // work out calls per second + iCalls /= 500; // and work out calls per 2 ms + if (iCalls == 0) + iCalls++; + +#if defined (__WINS__) +#define PDD_NAME _L("ECDRV") +#define LDD_NAME _L("ECOMM") +#else +#define PDD_NAME _L("EUART1") +#define LDD_NAME _L("ECOMM") +#endif + + r = iFileSession.Connect (); // we may need the RFs link for PDD/LDD loading as well as the log + if (r) + User::Leave (KFaxFileSessionError); + iFileSessionOpen = ETrue; + + if (iVerbose) + { + + +//This is a log file that would normally only be created in debug builds, however due to the time critical nature of fax it is always generated +//to avoid timing differences between debug and release builds. +//With the introduction of platform security it not advisable to have a log file in a public directory so will now be created in the private dir +//of the fax server. + + //create log in private path of server + TFileName logfile; + TDriveUnit driveUnit(EDriveC); + TDriveName drive=driveUnit.Name(); + logfile.Insert(0, drive); + //append private path + TPath privatePath; + iFileSession.PrivatePath(privatePath); + logfile.Append(privatePath); + //append subdir & file name + logfile.Append(_L("fax\\FAXLOG.TXT")); + + //generate dir + TInt kerr(iFileSession.MkDirAll(logfile)); //the directory may not exist, So create one. + if(kerr != KErrAlreadyExists) + { + User::LeaveIfError(kerr); + } + r = iFile.Replace(iFileSession, logfile, EFileWrite | EFileShareAny); + if (r) + { + User::Leave (KFaxLogCreateError); + } + iFileOpen = ETrue; + + } +/* + r = User::LoadPhysicalDevice (PDD_NAME); + if ((r != KErrNone) && (r != KErrAlreadyExists)) + User::Leave (KFaxPDDError); + + r = User::LoadLogicalDevice (LDD_NAME); + if ((r != KErrNone) && (r != KErrAlreadyExists)) + User::Leave (KFaxLDDError); +*/ + + RCommServ s; + r = s.Connect (); + if (r) + User::Leave (KFaxCommsServerError); + + + r = s.LoadCommModule (aFaxServerSessionSettings->iPortDriverName); + if (r) + User::Leave (KFaxCommsPortError); + + r = iCommSession.Open (s, aFaxServerSessionSettings->iCommPortName, ECommShared); + if (r) + User::Leave (KFaxCannotOpenPort); + + iPortOpen = ETrue; + + iCommSession.Config (iRS232Settings); + + iRS232Settings ().iRate = EBps19200; + + iRS232Settings ().iHandshake = 0; + + iRS232Settings ().iTerminator[0] = Ketx; + iRS232Settings ().iTerminator[1] = Kxon; + iRS232Settings ().iTerminator[2] = Klinefeed; + iRS232Settings ().iTerminatorCount = 3; + + r = iCommSession.SetConfig (iRS232Settings); + if (r) + User::Leave (KFaxConfigError); + + iCommSession.SetSignals (KSignalDTR, 0); + iCommSession.SetSignals (KSignalRTS, 0); + + iCommSession.SetReceiveBufferLength (KBufSize); + iCommSession.ResetBuffers(); + + iTransmitBuffer.Zero (); + iSendone.Zero (); + SendL (iSendone); // activate port - switch on DTR/RTS + iSendone.SetMax (); // we send single characters via iSendone[0] + + TBuf8 < 20 > thisclass; + thisclass.SetMax (); + + iOurMessage.Format (_L8 (FaxTransVersionString)); + ProgressUpdateL (); + iOurMessage.Format (_L8 ("The clock ticks at %d Hz"), CLK_TCK / iGranularity); + ProgressUpdateL (); + iOurMessage.Format (_L8 ("Calibration of 2 ms timer at %u calls"), iCalls); + ProgressUpdateL (); + + Speed (EBps19200); + iOurMessage.Format (_L8 ("Initialising at 19200 bps ....")); + ProgressUpdateL (); + + +// added by JerryC from faxtrans cfaxmodm.cpp + + + Silence (CLK_TCK); + TxcharL (Kreturn); + Silence (); +// Silence (); +// Silence (); + // GetMatchL(_L8("OK"),3); + + +// while (iCommSession.QueryReceiveBuffer()!=0) GetMatch (_L8 ("OK"), 1); +// ExportL (_L8 ("AT+FCLASS=?\r")); +// GetMatchL (_L8 ("OK"), 3); + +// GetMatchL (_L8 ("OK"), 3); + + + //r = CLK_TCK; + //while (RxcharWaitL (r)); + +// the addition ends here + +// TxcharL (Kreturn); + + iModemSet = ETrue; + iTimingLoopDelay = EFalse; + + //-- Switch modem into command mode and clear its buffer. + SetModemCommandModeL(); + + if ((aFaxServerSessionSettings->iFaxClass) == (TFaxClass) EClassAuto) + { + ExportL (_L8 ("AT+FCLASS=?\r")); + if(0 == ImportL (thisclass, 2)) + { + User::Leave (KFaxErrWrongModemType); + } + + iOurMessage.Format (_L8 ("%S"), &thisclass); + ProgressUpdateL (); + if ((thisclass.FindF (_L8 ("ERROR"))) >= 0) + User::Leave (KFaxErrWrongModemType); + GetMatchL (_L8 ("OK"), 1); + + if ((thisclass.FindF (_L8 ("2.0"))) >= 0) + { + aFaxServerSessionSettings->iFaxClass = EClass2point0; + } + else if ((thisclass.FindF (_L8 ("2.1"))) >= 0) + { + aFaxServerSessionSettings->iFaxClass = EClass2point0; + } + else if ((thisclass.FindF (_L8 ("2"))) >= 0) + { + aFaxServerSessionSettings->iFaxClass = EClass2; + } + else if ((thisclass.FindF (_L8 ("1"))) >= 0) + { + aFaxServerSessionSettings->iFaxClass = EClass1; + } + else if ((thisclass.FindF (_L8 ("1.0"))) >= 0) + { + aFaxServerSessionSettings->iFaxClass = EClass1; + } + else + User::Leave (KFaxErrWrongModemType); + + User::Leave (KFaxOnlyJustAutoDetected); + } + + thisclass.Copy (_L8 ("AT+FCLASS=")); + if (aFaxServerSessionSettings->iFaxClass == EClass2point0) + { + thisclass.Append (_L8 ("2.0\r")); + } + else if (aFaxServerSessionSettings->iFaxClass == EClass2) + { + thisclass.Append (_L8 ("2\r")); + } + else if (aFaxServerSessionSettings->iFaxClass == EClass1) + { + thisclass.Append (_L8 ("1\r")); + iTimingLoopDelay = ETrue; + } + else + User::Leave (KFaxErrWrongModemType); + + Silence (); + ExportL (thisclass); + if ((GetMatchL (_L8 ("OK"), 1)) == 0) + User::Leave (KFaxErrWrongModemType); + + //Speed (EBps19200); + + if (aFaxServerSessionSettings->iFaxInitString.Length ()) + { + ExportL (aFaxServerSessionSettings->iFaxInitString); + ExportL (_L8 ("\r")); + //GetMatchL (_L8 ("OK"), 3); + } + else + { + ExportL (_L8 ("AT\r")); + } + if ((GetMatchL (_L8 ("OK"), 3)) == 0) + User::Leave (KFaxBadInitialization); + + __FLOG_FAXSRV( _L8("CFaxModem::ConstructL exiting")); + + } + +/********************************************************************/ + +CFaxModem::~CFaxModem () + { +// iOurMessage.Format (_L8 ("Entering CFaxModem Destructor")); +// ProgressUpdateL (); + + __FLOG_FAXSRV( _L8("CFaxModem::~CFaxModem")); + + iCancel = 2; + + if (iModemSet) + { + Xonoff (); + Dropdtr (); + + TRAPD(ret, SetModemCommandModeL()); //-- Switch modem into command mode and clear its buffer. + TRAP (ret, HangupProcedureL()); //-- Issue hung up commands + + Silence (); + } + + if (iPortOpen) + { + iCommSession.ResetBuffers (); + iCommSession.Close (); + } + + if (iFileOpen) + { + iFile.Close (); + } + + if (iFileSessionOpen) + iFileSession.Close (); + } + +/** +* Hang up. Senda 'ATH' command to the modem and sets Echo off, fax class = 0 +* +* @note This function can leave +*/ +void CFaxModem::HangupProcedureL() + { + ExportL (_L8 ("ATH\r")); + GetMatchL (_L8 ("OK"), 2); + ExportL (_L8 ("ATE0+FCLASS=0\r")); // Defect fix PBN-4ZLLX7, NM 23/07/01 + GetMatchL (_L8 ("OK"), 2); + ExportL (_L8 ("\r")); + } + + +/** +* Switch modem into command mode and clear its buffer. +* LYN-585JMR defect fix. By Dmitry Lyokhin. 11.03.02 +* +* @note This function can leave +*/ +void CFaxModem::SetModemCommandModeL(void) +{ + const TInt K_uS_ComWait=500000; //-- used in cleaning up buffer. 0.5 sec timeout. + + ExportL (_L8("+++")); //-- switch the modem to command mode + + //-- clear modem's buffer by reading data + while(iCommSession.QueryReceiveBuffer() > 0) + { + iCommSession.Read (iRecstat, K_uS_ComWait ,iReceiveBuffer); // read data from the serial port + User::WaitForRequest (iRecstat); + } + + Silence(); +} + +/********************************************************************/ +/* +TBool CFaxModem::CheckModemL (TFaxSettings * aFaxSettings) + { + TInt len = aFaxSettings->iDialStoreData.iModemInitString.Length (); + for (TInt attempt = 0; attempt < 3; attempt++) + { + ExportL (_L8 ("ATH\r")); + GetMatchL (_L8 ("OK"), 1); + if (len) + { + ExportL (aFaxSettings->iDialStoreData.iModemInitString); + ExportL (_L8 ("\r")); + GetMatchL (_L8 ("OK"), 1); + } + iOurMessage.Format (_L8 ("ATE0X0Q0V1M%uL%uS0=0S8=%u\r"), + (TUint) aFaxSettings->iDialStoreData.iSpeaker, + (TUint) aFaxSettings->iDialStoreData.iSpeakerVolume, + aFaxSettings->iDialStoreData.iPauseTime); + ExportL (iOurMessage); + if (GetMatchL (_L8 ("OK"), 1) != 0) + { + Silence (); // allow s-l-o-w modems to catch up with us + return (ETrue); + } + } + return (EFalse); + }*/ +/********************************************************************/ + + +/** +* +* @return number of microseconds elapsed since calling CFaxModem::ConstructL(). +* +*/ +TInt CFaxModem::clock () + { + TTime now; + now.UniversalTime (); + TInt64 runningTime = now.MicroSecondsFrom (iStartTime).Int64 (); + return I64LOW(runningTime); + } + +/********************************************************************/ + +/** +* Searches for a given substring in modem's answer. +* also calls ProgressUpdate(). +* +* @param aMatstring - sample string. +* @param aMattime - timeout in seconds. +* +* @see ImportL function +* +* @return 0 - given string (see param aMatstring) is found in modem answer. +* 1 - sample not found or answer timeout. +* +* @leave This function can leave +*/ +TInt CFaxModem::GetMatchL (const TDesC8 & aMatstring, TInt aMattime) + + { + TBuf8 < 64 > modemstring; + TBuf8 < 64 > copymodemstring; + modemstring.SetMax (); + + while (ImportL (modemstring, aMattime)) + { + copymodemstring.Copy (modemstring); + iOurMessage.Format (_L8 ("%S"), ©modemstring); + ProgressUpdateL (); + + if ((modemstring.FindF (aMatstring)) >= 0) + return (1); + + + } + ProgressUpdateL (); + return (0); + } + + +/********************************************************************/ +/** +* Gets textual answer from the modem. +* Calls SubImportL() and ProgressUpdateL(). +* +* @param aLine - ref. to the string descriptor that will accept data from modem if any. + will contain string in upper case without terminating 0x0d, 0x0a. +* @param aTimeout - Timeout in seconds. +* +* @see SubImport function +* +* @return 0 - if timeout occured or wrong input descriptor. Otherwise - +* number of characters in string descriptor. +* +* @note This function can leave +*/ +TInt CFaxModem::ImportL (TDes8 & aLine, TInt aTimeout) +{ + const TInt SubTimeout = 3; //-- modem response 3 seconds timeout + TInt linestate = 0; + TInt CurrTimeout; + + while( aTimeout > 0 ) + { + if (aTimeout <= SubTimeout) CurrTimeout = aTimeout; + else CurrTimeout = SubTimeout; + + linestate = SubImportL (aLine, CurrTimeout); + + if (linestate) + {//-- a response from modem received + __FLOG_FAXSRV2(_L8("mdm imp[%d]: %S"), aTimeout, &aLine); + + //-- look for '+CREG' or '+CGREG' answers from modem. + //-- if found, ignore them and continue waiting. + //-- these unwanted answers represent network registration status (unsolicited result code) + //-- and interfere with fax modem responses. For more information see mm.tsy and gprs.tsy + if ((aLine.FindF(_L8("REG"))) >= 0) + { + aLine.FillZ(); + aLine.Zero (); + } + else break; + + }//if (linestate) + + aTimeout -= SubTimeout; + + ProgressUpdateL (); + }// while + + if (!linestate) + { + __FLOG_FAXSRV2(_L8("mdm imp[%d]: %S"), aTimeout, &aLine); + } + + return (linestate); +} + + +/********************************************************************/ + +/** +* Gets textual answer from the modem. +* +* @param aLine - ref. to the string descriptor that will accept data from modem if any. +* will contain string in upper case without terminating 0x0d, 0x0a +* @param aTimeout - Timeout in seconds. +* +* @see RxcharWait function, iReadone +* +* @return 0 - if timeout occured or wrong input descriptor. Otherwise - +* number of characters in string descriptor +* +* @note This function can leave +*/ +TInt CFaxModem::SubImportL (TDes8 & aLine, TInt aTimeout) + + { + TInt i; + TInt8 k; + TInt t; + + if (aLine.MaxLength () == 0) + return (0); + aLine.FillZ (); + aLine.Zero (); + + t = aTimeout * CLK_TCK; + + do + { + if ((RxcharWaitL (t)) == 0) + return (0); + k = iReadone[0]; + } + + + while (k < 32); + + for (i = 0; i < aLine.MaxLength (); i++) + { + aLine.Append (k); + aLine.UpperCase (); + t = aTimeout * CLK_TCK; + if ((RxcharWaitL (t)) == 0) + return (0); + k = iReadone[0]; + if (k < 32) + break; + } + + if (k == 0x0d) + for (;;) + { + t = CLK_TCK; + if ((RxcharWaitL (t)) == 0) + break; + if (iReadone[0] == 0x0a) + break; + } + + return (i); + } +/********************************************************************/ + +/** +Sends a textual string to the modem with delay. + +@param aLine - const. ref. to the string descriptor to be sent to modem. + +@see SendL function + +@return number of symbols sent to modem. + +@note This function can leave +*/ +TInt CFaxModem::ExportL(const TDesC8& aLine) + { + __FLOG_FAXSRV1(_L8("mdm exp: %S"), &aLine); + + TInt i = 0; + + // we need to guarantee a delay here before sending characters + // lots of modems ignore commands that come in too quickly + // we need to wait for at least twice the clock granularity to ensure + // a decent wait interval as the clock may be just about to tick + + // example : + + // Silence ((iGranularity * 2) + 2); + + // BUT ... + + // on Protea, the clock ticks at 64 beats per second + // that's every 15 ms or to be precise every 15625 microseconds + // iGranularity actually does return this value of 15625 + // our maximum wait will be 30 ms (with a minumum of 15 ms) + // there's also a maximum 35 ms overhead on any timer call or active + // object or whatever - so we could have a delay here of up to 65 ms + + // with the time the modem takes to respond, this leads to too much + // unreliability as we have a strict 75 ms +/- 20% T.30 requirement + // for class 1 modems. (For class 2 and 2.0 modems this isn't a + // problem so we happily delay for iGranularity*2). + + // this applies also to WINS on the PC ticks 10 times per second + // this gives us a maximum delay of 200 ms, which is rather long + // so we resort to a timing loop we calibrate on first entry + + for (;;) + { + i = Rxstat (); + if (iTimingLoopDelay != EFalse) + { + for (TInt x = 0; x < iCalls; x++) + clock (); + } + else + { + Silence ((iGranularity * 2) + 2); + } + if (i == Rxstat ()) + break; + } + + if (aLine.Length()) + { +#ifdef _DEBUG + TRAPD(modemUnplugged, SendL(aLine)); + __FLOG_FAXSRV1(_L8("CFaxModem::ExportL SendL leave error code: %d"), modemUnplugged); +#else + TRAP_IGNORE(SendL(aLine)); +#endif + + iOurMessage.Format(_L8("%S"), &aLine); + i = iOurMessage.Length(); + if ((i != 0) && (iOurMessage[i - 1] == 0x0d)) + { + iOurMessage.Delete(i - 1, 1); + } + ProgressUpdateL(); + } + return i; + } +/********************************************************************/ + +void CFaxModem::Dropdtr () + { + + __FLOG_FAXSRV( _L8("CFaxModem::Dropdtr")); + + LowerDTR (); + Silence (CLK_TCK); + RaiseDTR (); + Silence (CLK_TCK); + } +/********************************************************************/ + + +/** +* Wait approximately 75 ms +*/ +void CFaxModem::Silence () + { + Silence (CLK_TCK / 13); // wait approx 75 milliseconds + } + +/********************************************************************/ + +/** +* Wait given number of microseconds +*/ +void CFaxModem::Silence (TInt ticks) const + { + User::After (ticks); // wait however long + } +/********************************************************************/ + +void CFaxModem::Speed (TBps aSpeed) + { + iRS232Settings ().iRate = aSpeed; + iCommSession.SetConfig (iRS232Settings); + } +/********************************************************************/ + +/** +* Turns on obeying XON, XOFF characters and CTS signal +*/ +void CFaxModem::Xonon () + { + iRS232Settings ().iHandshake = (KConfigObeyXoff | KConfigObeyCTS | KConfigWriteBufferedComplete); + iCommSession.SetConfig (iRS232Settings); + } +/********************************************************************/ + +/** +Turns off handshaking +*/ +void CFaxModem::Xonoff() + { + iSendone.Zero(); // sending a null descriptor +#ifdef _DEBUG + TRAPD(modemUnplugged, SendL(iSendone)); // waits till all pending transmits have gone + __FLOG_FAXSRV1(_L8("CFaxModem::Xonoff SendL leave error code: %d"), modemUnplugged); +#else + TRAP_IGNORE(SendL(iSendone)); // waits till all pending transmits have gone +#endif + + iSendone.SetMax(); // we send single characters via iSendone[0] + + iRS232Settings().iHandshake = 0; + iCommSession.SetConfig(iRS232Settings); + } +/********************************************************************/ + +void CFaxModem::LowerDTR() + { + iCommSession.SetSignals (0, KSignalDTR); // SetSignals(SetMask,ClearMask) ; + } +/********************************************************************/ + +void CFaxModem::RaiseDTR() + { + iCommSession.SetSignals (KSignalDTR, 0); // SetSignals(SetMask,ClearMask) ; + } +/********************************************************************/ + +/** +* @return 0 - if there are no data waiting in driver's input buffer and receiver's buffer to be read. +* otherwise - number of bytes to be read. +*/ +TInt CFaxModem::Rxstat (void) + { + if (iReceiveBuffer.Length () != 0) + return (1); + else + return (iCommSession.QueryReceiveBuffer ()); + } +/********************************************************************/ + +/** +* Does nothing. Just returns 0. +*/ +TInt CFaxModem::Txstat() + { + return 0; + } +/********************************************************************/ + +/** +* Sends 1 byte to modem. +* +* @param aChar -Byte to be sent. +* +* @note This function can leave. +* +* @see SendL() function +* +* @return none. +*/ +void CFaxModem::TxcharL (TUint8 aChar) + { + iSendone[0] = aChar; + SendL (iSendone); + } +/********************************************************************/ + + +// this routine amended July 1998 to offer infinite timeouts when sending data in fax ECM + +void CFaxModem::SendL(const TDesC8 & astring) + { + TTimeIntervalMicroSeconds32 timeout = CLK_TCK * 10; + if ((iProgress.iECM) && (iProgress.iPhase == EDataTransfer)) + { + iCommSession.Write(iTranstat, timeout, astring); + User::WaitForRequest(iTranstat); + if (iTranstat == KErrTimedOut) + { + TInt ticks = 1; + while (Rxstat() != 0) + { + RxcharWaitL(ticks); + if (iReadone[0] == Kcan) + User::Leave(KFaxErrModemDisconnect); + } + } + else if (iTranstat != KErrNone) + iCommSession.ResetBuffers(KCommResetTx); + } + else + { + iCommSession.Write(iTranstat, timeout, astring); + User::WaitForRequest(iTranstat); + if (iTranstat != KErrNone) + { + iCommSession.ResetBuffers(KCommResetTx); + if (iTranstat == KErrTimedOut) + User::Leave(KFaxTransmitterStalled); + } + } + } +/********************************************************************/ + +/** +* Transmits iTransmitBuffer by calling SendL. After sending sets buffer's +* length to zero. +* +* @note This function can leave. +* +* @see SendL() function +*/ +void CFaxModem::CommitTransmitBufferL () + { + SendL (iTransmitBuffer); + iTransmitBuffer.Zero (); + } +/********************************************************************/ + + +/** +* Reads 1 byte from serial port (or iReceiveBuffer) and puts it to iReadone buffer. +* +* @param atimeout - timeout in microseconds. +* +* @return 0 - timeout, +* 1 - byte read and put into iReadone +* +* @note This function can leave. See comments in CFAXMODM.CPP +* +*/ + +// this is our basic get char function with timeout + +// Note that this function *can* leave, despite not being named as an L +// function. This is because the leave is as a result of a user request +// to end the entire fax thread and could occur at any time. This +// function (to read a character) is used at some point by virtually +// every part of the fax system and consequently, were the normal +// convention to be followed, every function would have to be an L +// function - this destroys the whole point of having a separate +// nomenclature. Therefore, I declare that the possibility of a leave +// as a result of the user cancel request is henceforth regarded as an +// exception to the rule than a function which leaves must be called an +// L function. The new rule is that any fax session must be run inside +// a trap harness - not simply because the modem and port need tidying up. + +// Note to the note : The check for user cancel request has been moved to +// ProgressUpdate(). However, this function can still leave if the +// rx buffer overruns, in which case we use the standard iCancel flag to +// check if it is safe to leave and do so. The original note still applies +// but to be honest, I'm less happy about it now. + +TInt CFaxModem::RxcharWaitL (TInt & atimeout) + { + iReadone.Zero (); + if (atimeout == 0) + return (0); + if (iReceiveBuffer.Length () == 0) //iReceiveBuffer == Receive descriptor + { + for (;;) + { + TInt timeBegin = clock (); + iCommSession.Read (iRecstat, atimeout, iReceiveBuffer, KBufSize); // read data from the serial port + User::WaitForRequest (iRecstat); + if ((iRecstat == KErrCommsOverrun) && (iCancel == 0)) // check for overrun and user cancel request + { + iCancel = 2; + iCommSession.ResetBuffers (KCommResetRx); //Reset serial port buffers + User::Leave (KErrCommsOverrun); + } + + if ((iReceiveBuffer.Length () == 0) && (iRecstat == KErrTimedOut)) + { + if (iCommSession.QueryReceiveBuffer () != 0 ) + { + iCommSession.ReadOneOrMore (iRecstat, iReceiveBuffer); + User::WaitForRequest (iRecstat); + } + } + atimeout -= (clock () - timeBegin); //decrement timeout + + if (iReceiveBuffer.Length () != 0) + break; + if (atimeout > 0) + continue; + atimeout = 0; + return (0); + } + if (atimeout < 1) + atimeout = 1; + } + iReadone.Append (iReceiveBuffer[0]); + iReceiveBuffer.Delete (0, 1); + return (1); + } +/********************************************************************/ + +void CFaxModem::ProgressUpdateL () + { +// Commented out by AMC 13/3/00. Pending complete deletion. Not completely removed as removal of function from +// Base has not yet propagated down Device Drivers. Until the device drivers support it there's a chance it +// will have to be re-introduced. + +// UserHal::ResetAutoSwitchOffTimer (); // required to stop powerdown + if (iCancel == 1) + { + iCancel++; + User::Leave (KFaxCancelRequested); + } + + TTime now; + now.UniversalTime (); + + iProgress.iLastUpdateTime = now; + + if (iVerbose) + { + if (iOurMessage.Length ()) + { +#ifdef _DEBUG + // + // Write the log message also to the main log file... + // + TBuf8<256> temp; + + temp.Copy(iOurMessage); + __FLOG_FAXSRV1(_L8("ProgressUpdateL: %S"), &temp); +#endif + + TDateTime dateTime; + TBuf8 < 16 > datestamp; + dateTime = now.DateTime (); + datestamp.Format (_L8 ("%02d.%02d:%02d:%06d "), dateTime.Hour (), dateTime.Minute (), dateTime.Second (), dateTime.MicroSecond ()); + iOurMessage.Insert (0, datestamp); + iOurMessage.Append (13); + iOurMessage.Append (10); + + if (iFileOpen) + iFile.Write (iOurMessage); + + iOurMessage.Zero (); + } + } + } +/*********************************************************************/