// 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 <e32hal.h>
#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 ();
}
}
}
/*********************************************************************/