fax/faxclientandserver/FAXCLI/FAXCLI.CPP
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:41:59 +0200
changeset 0 3553901f7fa8
permissions -rw-r--r--
Revision: 201005 Kit: 201005

// 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 "CFAX32.H"
#include "dial.h"	                      // we no longer depend on DialStor, so must depend directly on Dial

#include "FAXLOG.H"
#include "faxsettings.h"

 #include <commsdattypesv1_1.h>
 #include <commsdatutils.h>
 #include <commsdat_partner.h>

 using namespace CommsDat;

TInt FaxClientThread (TAny * session);  // function declaration needed here
//TInt FaxConverterThread (TAny *);
//RSemaphore jerry;
/********************************************************************/


/********************************************************************/

CFaxTransfer::CFaxTransfer()
	: CBase()
	{}

EXPORT_C CFaxTransfer *CFaxTransfer::NewLC (const TFaxSettings & aFaxSettings)
/** Constructs a CFaxTransfer object, which offers the publicly exported 
Symbian OS Fax Client API. 
As is usual in Symbian OS, the only difference between this function and 
NewL() is that this variant pushes the object to the cleanup stack.

@param aFaxSettings  A reference to a TFaxSettings object which contains 
persistent information applicable to all fax sessions. 
@return  Pointer to the newly created object. 
@leave KErrNoMemory There is insufficient memory to perform the operation. 
@capability None
*/
   {
   CFaxTransfer *self = new (ELeave) CFaxTransfer;
   CleanupStack::PushL (self);
   self->ConstructL (aFaxSettings);
   return self;
   }

EXPORT_C CFaxTransfer *CFaxTransfer::NewL (const TFaxSettings & aFaxSettings)
/** Constructs a CFaxTransfer object, which offers the publicly exported 
Symbian OS Fax Client API.

@param aFaxSettings A reference to a TFaxSettings object, which
contains persistent information applicable to all fax sessions. 
@return A pointer to the newly created object. 
@leave KErrNoMemory There is insufficient memory to perform the operation. 
@capability None
*/
   {
   CFaxTransfer *self = NewLC (aFaxSettings);
   CleanupStack::Pop ();
   return self;
   }
/********************************************************************/

void CFaxTransfer::ConstructL (const TFaxSettings & aFaxSettings)
   {
   // we now copy the TFaxSettings passed to us - we then
   // validate the contents and fill in the DialStor bits.
   // if we don't know the modem class we find it our here
   iFaxSettings = aFaxSettings;
   CFaxSettings *currentsettings;
   currentsettings = CFaxSettings::NewL ();     // bug fix thanks to MartinA
   CleanupStack::PushL (currentsettings);       // currentsettings saved
   currentsettings->ValidateAndSetClassL (&iFaxSettings);       // since this could leave
   CleanupStack::PopAndDestroy ();      // currentsettings deleted

	//   if (((TFaxClass) iFaxSettings.iFaxClass != EClass1) &&
	//     ((TFaxClass) iFaxSettings.iFaxClass != EClass2) &&
	//       ((TFaxClass) iFaxSettings.iFaxClass != EClass2point0))
	//      User::Leave (KFaxCannotAutodetect);

   iFaxSessionSettings.iFaxClass = (TFaxClass) iFaxSettings.iFaxClass;
   iFaxSessionSettings.iFaxId.Copy (iFaxSettings.iFaxId);
   iFaxSessionSettings.iMaxSpeed = iFaxSettings.iMaxSpeed;
   iFaxSessionSettings.iMinSpeed = iFaxSettings.iMinSpeed;
   iFaxSessionSettings.iRxResolution = iFaxSettings.iPreferredResolution;
   iFaxSessionSettings.iRxCompression = iFaxSettings.iPreferredCompression;
   iFaxSessionSettings.iPreferredECM = iFaxSettings.iPreferredECM;
   iFaxSessionSettings.iFaxOnDemandDelay = iFaxSettings.iFaxOnDemandDelay;

   iSource = CFaxTransferSource::NewL ();
   }
/********************************************************************/

CFaxTransfer::~CFaxTransfer ()
/** Destructor

Frees all resources owned by the object, prior to its destruction. */
   {
   delete iSource;
   }
/********************************************************************/

// this function updates the TFaxTransferProgress structure for the
// caller. It should be prior to inspection.

EXPORT_C TInt CFaxTransfer::Progress ()
/** Causes ETel to update the fax progress information in RFax::TProgress.

It should be called prior to displaying the fax progress information.

@return KErrNone if successful, otherwise another of the system-wide error 
codes. 
@capability None
*/
{
	if (iFaxStarted)
		{
		iFaxClientProgress=EProgressRxTx;
		return (iFax.GetProgress (iProgress));
		}
	if (iConverting)
		{
		iFaxClientProgress=EProgressConverting;
		//aProgress=EProgressPreparing;
		return (KErrNone);
		}

	//aProgress=EProgressInitialising;
	return (KErrNone);
}
/********************************************************************/

// this function tells faxtrans what phone number to dial
// obviously only useful in a dialling mode !
// the phone number is translated for the modem and service
// and location required using dialstor facilities if they are
// available - if not, the number is used in its raw state
//
// if use of a raw phonenumber is required then the inline function
// SetPhoneNumber should be called instead.

EXPORT_C void CFaxTransfer::SetPhoneNumberL (TDesC8 & aNumber)
/** Resolves a local telephone number into an international number by 
taking account of the current location and country.
The alternative SetPhoneNumber() should be used if the phone number 
must be used in its raw state. One of these functions must be called 
before CFaxTransfer::Start() when a fax is to be sent. 
This function may leave with KErrNoMemory if there is insufficient 
memory to perform the operation. The leave code is one of the system 
error codes: see system-wide error codes. 
The current location and country information is obtained from the 
location table in the communications database.
The resolved number is then set as the actual phone number to dial.

@param aNumber  Descriptor containing the phone number to be resolved. 
@capability WriteUserData
*/
	{
	SetPhoneNumber (aNumber);
	TBuf < KMaxDialString > rawPhoneNumber;
	rawPhoneNumber.Copy (aNumber);

#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
	CMDBSession* db = CMDBSession::NewL(KCDVersion1_2);
#else
	CMDBSession* db = CMDBSession::NewL(KCDVersion1_1);
#endif
	CleanupStack::PushL(db);
		
	// Read the currently selected connection preference and find preferred IAP
	TInt prefRank  = 1;
	
	CCDConnectionPrefsRecord *connectionPrefs =
		static_cast<CCDConnectionPrefsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord));
	CleanupStack::PushL(connectionPrefs);
	connectionPrefs->iRanking = prefRank;
	connectionPrefs->iDirection = ECommDbConnectionDirectionOutgoing;
	TBool error = connectionPrefs->FindL(*db);	
	
	// The following code is a temporary solution until an issue has been resolved in CommsDat
	// start
	CCDIAPRecord* tempPIapRecord =
		static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
	tempPIapRecord->SetRecordId(connectionPrefs->iDefaultIAP);
	connectionPrefs->iDefaultIAP.iLinkedRecord = tempPIapRecord;
	
	CCDIAPRecord* pIapRecord = (CCDIAPRecord*)connectionPrefs->iDefaultIAP.iLinkedRecord;
	pIapRecord->SetRecordId(connectionPrefs->iDefaultIAP);
	pIapRecord->LoadL(*db);
	
	CCDBearerRecordBase* tempBearerRecord =
		static_cast<CCDBearerRecordBase*>(CCDRecordBase::RecordFactoryL(KCDTIdModemBearerRecord));
	tempBearerRecord->SetRecordId(pIapRecord->iBearer);
	pIapRecord->iBearer.iLinkedRecord = tempBearerRecord;

	CCDBearerRecordBase* pBearerRecord = (CCDBearerRecordBase*) pIapRecord->iBearer.iLinkedRecord;
	pBearerRecord->SetRecordId(pIapRecord->iBearer);
	pBearerRecord->LoadL(*db);
	// end
	
	TUint32 iapId = pBearerRecord->iRecordTag;
	
	CCDIAPRecord *iapRecord =
		static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
	CleanupStack::PushL(iapRecord);
	iapRecord->SetRecordId(iapId);
	iapRecord->LoadL(*db);

	// more temporary code
	// start	
	CCDBearerRecordBase* tempLocationRecord =
		static_cast<CCDBearerRecordBase*>(CCDRecordBase::RecordFactoryL(KCDTIdLocationRecord));
	tempLocationRecord->SetRecordId(iapRecord->iLocation);
	iapRecord->iLocation.iLinkedRecord = tempLocationRecord;
	
	CCDLocationRecord* pLocationRecord = (CCDLocationRecord*)iapRecord->iLocation.iLinkedRecord;
	pLocationRecord->SetRecordId(iapRecord->iLocation);
	pLocationRecord->LoadL(*db);
	// end
	
	//CommsDat Migration: Would this be the correct way to check whether or not a linked record exists:
	if (pLocationRecord == NULL)	
		{
		iPhoneNumber.Copy(rawPhoneNumber);
		}
	else
		{
		TBuf<32> serviceType;
		serviceType.Copy(iapRecord->iServiceType);

		if (!serviceType.Compare(TBuf<32>(DIAL_OUT_ISP)))	// Chargecard only valid for dial out ISP
			{
			// Get service type id
			TUint32 serviceId = iapRecord->iService;
			
			CCDDialOutISPRecord *ispRecord =
				static_cast<CCDDialOutISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialOutISPRecord));
			CleanupStack::PushL(ispRecord);
			ispRecord->SetRecordId(serviceId);
			ispRecord->LoadL(*db);
			TUint32 locationId = 0;
			TUint32 chargecardId = 0;
			TRAPD(err,CommsDatUtils::CCommsDatUtils::ResolvePhoneNumberL(rawPhoneNumber, iPhoneNumber, TParseMode(EForDialing), locationId, chargecardId));
			// if resolving the phone number fails, use the raw phone number
			if (err)
				{
				iPhoneNumber.Copy(rawPhoneNumber);
				}
			
			CleanupStack::PopAndDestroy(ispRecord);
			}
		else
			{
			iPhoneNumber.Copy(rawPhoneNumber);
			}
		}
	CleanupStack::PopAndDestroy(3); // db, connectionPrefs, iapRecord
	}
/********************************************************************/

// in order to cancel a fax session we set a cancel flag in the lowest
// level (CFaxModem) - if this has not yet been fully created then we set
// a flag in the next level up (CFaxModemDriver) instead, which is always
// going to be there as it is created via CFaxTransfer::ConstructL
//
// because of the way that the CFaxModem monitors its request flag
// we need to avoid multiple cancel requests, so only the first call to
// Cancel has any effect on it

EXPORT_C void CFaxTransfer::Cancel ()
/** Tells the fax engine to cancel the fax session at the first convenient 
opportunity.

The caller should wait for cancellation to complete, which will usually be 
signalled by the fax thread's TRequestStatus completing with a KFaxCancelRequested 
error code. After the fax thread completes, Stop() should be called in the 
normal way.

The function can be called at any time after the call to Start(). 
@capability None
*/
   {
   if ((iClientCancel == KRequestPending) || (iClientCancel == KErrNone))
      {
      TRequestStatus *cancelClient = &iClientCancel;
      iDriverThread.RequestComplete (cancelClient, KErrCancel);
      }
   }
/********************************************************************/

EXPORT_C TInt CFaxTransfer::Start (TRequestStatus & aThreadStat)
/**
Start fax sending or receiving session by launching a separate high priority thread.
A call to Start must be paired with a call to Stop as this is an EPOC32 requirement.

@param     aThreadStat  thread logon request status
@return    thread creation code
@capability NetworkServices
@capability ReadUserData
@capability WriteUserData
*/
   {
    // the heap and stack sizes set here (4K each) are pure guesswork
    // CFaxModemDriver has allocated heap space in the parent thread
    // for any objects it needs to create after this stage
    // stack sizes increased by 512K to allow etel to connect

   TInt state = KErrNone;
   TInt heapSize = 0x14000;
   TInt stackSize = 0x14000;

	__FLOG_FAXCLI(_L8(" "));
	__FLOG_FAXCLI(_L8("-------------------------- new log --------------------------"));
	__FLOG_FAXCLI(_L8("CFaxTransfer::Start, starting FaxClientThread"));
	__FLOG_FAXCLI(_L8(" "));

   state = iDriverThread.Create ((_L ("FaxClientThread")), FaxClientThread, stackSize, heapSize, heapSize, this, EOwnerThread);
   if (state)
      {
      state = KFaxThreadError;
      }
   else
      {
      aThreadStat = KRequestPending;
      if (iClientCancel != KErrCancel)
         iClientCancel = KRequestPending;
      iDriverThread.Logon (aThreadStat);
      iDriverThread.SetPriority (EPriorityRealTime);
      iDriverThread.Resume ();
      }
   return (state);
   }
/*********************************************************************/

EXPORT_C void CFaxTransfer::Stop ()
/** Kills the fax thread once it has completed. 

Fax threads do not kill themselves, so every successful call to CFaxTransfer::Start() 
must be paired with a call to CFaxTransfer::Stop(). 
@capability NetworkServices
@capability ReadUserData
@capability WriteUserData
*/
   {
   iDriverThread.Close ();
   }
/*********************************************************************/

// this is a utility function which is the entry to our thread
// it isn't part of any class, but we pass the address
// of our CFaxTransfer in so that we can check the
// session parameter and get back to the required function
//
// All possible leaves should be trapped as the return
// from this function is the TRequestStatus which the
// caller to CFaxTransfer::Start is waiting for.

TInt FaxClientThread (TAny * session)
   {


   // start of unecessary bureaucracy - error checking left out
/*#define CSY_NAME _L("ECUART")
#define LDD_NAME _L("ECOMM")
#if defined (__WINS__)
#define PDD_NAME _L("ECDRV")
#else
#define PDD_NAME _L("EUART1")
#endif*/

/*
   User::LoadPhysicalDevice (PDD_NAME);
   User::LoadLogicalDevice (LDD_NAME);*/
// jerry.CreateGlobal(_L("FaxCliSem"),0,EOwnerProcess);
   
   RCommServ server;
   // coverity[check_return]
   server.Connect ();
// end of unecessary bureaucracy

   TInt state;
   CTrapCleanup *cleanup = CTrapCleanup::New ();
// CFaxTransfer *faxsession = (CFaxTransfer *) session;
   CFaxTransfer *faxsession =reinterpret_cast<CFaxTransfer *>(session);
	__FLOG_FAXCLI(_L8("FaxClientThread entering..."));

   state = faxsession->iTelServer.Connect ();
   if (state == KErrNone)
   {
   TBuf<KCommsDbSvrMaxFieldLength> tsyName;
   TRAP(state,faxsession->GetPhoneModuleNameL(tsyName));
   if (state==KErrNone)
	{
      state = faxsession->iTelServer.LoadPhoneModule (tsyName);
      if (state == KErrNone)
         {
		 RTelServer::TPhoneInfo phoneInfo;
		 state = faxsession->GetPhoneInfoForTsy(tsyName,phoneInfo);
		 if (state == KErrNone)
			{
			
			__FLOG_FAXCLI(_L8("FaxClientThread iPhone.Open"));
			state = faxsession->iPhone.Open (faxsession->iTelServer, phoneInfo.iName);
            if (state == KErrNone)
				{
				
				__FLOG_FAXCLI(_L8("FaxClientThread iLine.Open"));
				state = faxsession->iLine.Open (faxsession->iPhone, _L ("Fax"));
				if (state == KErrNone)
					{
					//
					// If the call name has been provided, then open the
					// existing call, otherwise open a new call.
					//
					if (faxsession->iCallName.Length() == 0)
						{
						__FLOG_FAXCLI(_L8("FaxClientThread iCall.OpenNewCall"));
						state = faxsession->iCall.OpenNewCall (faxsession->iLine);
						}
					else
						{
						__FLOG_FAXCLI(_L8("FaxClientThread iCall.OpenExistingCall"));
						state = faxsession->iCall.OpenExistingCall(faxsession->iLine, faxsession->iCallName);
						}

					if (state == KErrNone)
						{
						faxsession->iSource->iPage = 0;
						if (faxsession->iMode & KFaxReceive)
							{
							faxsession->iFaxSessionSettings.iMode = RCall::EReceive;
							TRAP (state, faxsession->FaxReceiveL ());
							
							__FLOG_FAXCLI1(_L8("FaxClientThread FaxReceiveL exited state=%d"),state);
							
							faxsession->iSource->CloseFaxInStore ();
							}		
			            else
					        {
							faxsession->iFaxSessionSettings.iMode = RCall::ETransmit;
							TRAP (state, faxsession->FaxTransmitL ());
							faxsession->iSource->iInstream.Close ();
							}

	                    // we tidy up by deleting any objects created
						// (it does no harm if their pointers are already NULL)
						// and we close any streams (which also does no harm
						// if they have already been closed)

						faxsession->iFaxStarted = EFalse;
						faxsession->iFax.Close ();
						faxsession->iSource->CloseFaxStore ();
						delete faxsession->iSource->iWriteFaxFile;
						faxsession->iSource->iWriteFaxFile = NULL;
		                delete faxsession->iSource->iReadFaxFile;
						faxsession->iSource->iReadFaxFile = NULL;
						
						faxsession->iSource->iOutstream.Close ();
						faxsession->iSource->iInstream.Close ();
						
						RCall::TStatus callStatus;
						faxsession->iCall.GetStatus(callStatus);
						
						__FLOG_FAXCLI1(_L8("FaxClientThread callStatus=%d"),callStatus);

						if (callStatus!=RCall::EStatusIdle)
							faxsession->iCall.HangUp ();
						
						__FLOG_FAXCLI(_L8("FaxClientThread iCall.Close"));
						faxsession->iCall.Close ();
						}
					
					__FLOG_FAXCLI(_L8("FaxClientThread iLine.Close"));
					faxsession->iLine.Close ();
					}
				
				__FLOG_FAXCLI(_L8("FaxClientThread iPhone.Close"));
				faxsession->iPhone.Close ();
				}
			}
		faxsession->iTelServer.UnloadPhoneModule (tsyName);
		}
		}
    faxsession->iTelServer.Close ();
    }

   delete cleanup;

// intercept the etel wrong modem type error
   if (state == KErrEtelWrongModemType) state = KFaxErrWrongModemType;

   return (state);
   }

/*********************************************************************/

void CFaxTransfer::GetPhoneModuleNameL(TDes& aModuleName) const
	{
	// AnnW, 9/8/99 - This all assumes that we are taking the modem settings from the 
	// dial out IAP, which is fince for now, but may not be in the future?  This may also 
	// need modifying for Linda?
	
	CMDBSession* db = CMDBSession::NewL(KCDVersion1_1);
	CleanupStack::PushL(db);
	
	// Read the currently selected connection preference and find preferred IAP
	TInt prefRank  = 1;
	
	CCDConnectionPrefsRecord *connectionPrefs = 
		static_cast<CCDConnectionPrefsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord));
	CleanupStack::PushL(connectionPrefs);
	connectionPrefs->iRanking = prefRank;
	connectionPrefs->iDirection = ECommDbConnectionDirectionOutgoing;
	connectionPrefs->FindL(*db);
	
	// The following code is a temporary solution until an issue has been resolved in CommsDat
	// start
	CCDIAPRecord* tempPIapRecord =
		static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
	tempPIapRecord->SetRecordId(connectionPrefs->iDefaultIAP);
	connectionPrefs->iDefaultIAP.iLinkedRecord = tempPIapRecord;
	
	CCDIAPRecord* pIapRecord = (CCDIAPRecord*)connectionPrefs->iDefaultIAP.iLinkedRecord;
	pIapRecord->SetRecordId(connectionPrefs->iDefaultIAP);
	pIapRecord->LoadL(*db);
	
	CCDBearerRecordBase* tempBearerRecord =
		static_cast<CCDBearerRecordBase*>(CCDRecordBase::RecordFactoryL(KCDTIdModemBearerRecord));
	tempBearerRecord->SetRecordId(pIapRecord->iBearer);
	pIapRecord->iBearer.iLinkedRecord = tempBearerRecord;

	CCDBearerRecordBase* pBearerRecord = (CCDBearerRecordBase*) pIapRecord->iBearer.iLinkedRecord;
	pBearerRecord->SetRecordId(pIapRecord->iBearer);
	pBearerRecord->LoadL(*db);
	// end
	
	TUint32 iapId = pBearerRecord->iRecordTag;
	
	CMDBField<TUint32>* bearerField = new(ELeave) CMDBField<TUint32>(KCDTIdIAPBearer);
	CleanupStack::PushL(bearerField);
	bearerField->SetRecordId(iapId);
	bearerField->LoadL(*db);
	TUint32 modemId = *bearerField;
	CleanupStack::PopAndDestroy(bearerField);

	CMDBField<TDesC>* tsyField = new(ELeave) CMDBField<TDesC>(KCDTIdTsyName);
	CleanupStack::PushL(tsyField);
	tsyField->SetRecordId(modemId);
	tsyField->SetMaxLengthL(KMaxTextLength);
	tsyField->LoadL(*db);
	aModuleName = *tsyField;
	CleanupStack::PopAndDestroy(tsyField);
	
	CleanupStack::PopAndDestroy(2); // db, connectionPrefs
	}

void CFaxTransfer::CancelFaxServerSession ()
   {
   if (iMode & KFaxWaitForRing)
      iCall.AnswerIncomingCallCancel ();
   else
      {
      if (iMode & KFaxOffHook)
         iCall.ConnectCancel ();
      else
         iCall.DialCancel ();
      }
   }
/*********************************************************************/
// receiving a fax is easy because it is passive
// just open the file for receiving and off we go

void CFaxTransfer::FaxReceiveL ()
   {

	__FLOG_FAXCLI(_L8("CFaxTransfer::FaxReceiveL entering"));

   if (iMode & KFaxPoll)
      iFaxSessionSettings.iFaxRetrieveType = RCall::EFaxPoll;
   else
      iFaxSessionSettings.iFaxRetrieveType = RCall::EFaxOnDemand;

   iSource->OpenFaxInL (iReceiveFileName);

   SetFaxSettingsL();

   if (iMode & KFaxWaitForRing)
      {//-- answering incoming call if fax is waiting for a call
	  iCall.AnswerIncomingCall (iTransferStatus);	
      if (iClientCancel != KRequestPending)
         {//-- cancel request, leave
         iCall.AnswerIncomingCallCancel ();
		 User::WaitForRequest(iTransferStatus);
         User::Leave (KFaxCancelRequested);
         }
      }
   else	//if (iMode & KFaxWaitForRing) 
      {//-- if fax is not waiting for a call, dial
      if (iMode & KFaxOffHook)
         iCall.Connect (iTransferStatus);
      else
         {
         if (iPhoneNumber.Length() == 0)
            User::Leave (KErrCouldNotConnect);
         iCall.Dial (iTransferStatus, iPhoneNumber);
         }
      }

   TRequestStatus reqStatus;
   RCall::TStatus callStatus;
   iCall.NotifyStatusChange (reqStatus, callStatus);

   for (;;)
      {
      User::WaitForAnyRequest ();
      if (reqStatus != KRequestPending)
         {
         //-- Call status changed
         if (reqStatus.Int () != KErrNone)
            {
            CancelFaxServerSession ();
            User::Leave (reqStatus.Int ());
            }
         if (iMode & KFaxWaitForRing)
            {//-- Fax is waiting for a ring
			if (callStatus == RCall::EStatusRinging)
				{//-- Call status is 'Ringing', continue waiting 
				iCall.NotifyStatusChange(reqStatus, callStatus);
				reqStatus = KRequestPending;
				continue;
				}
			else 
			 //-- due to PIA-586KGE fix (changes in CATAnswerFax::Start()) 'Connecting' may be not noticed here
			 //-- so EStatusConnected state is ok
			 if (callStatus != RCall::EStatusAnswering && callStatus != RCall::EStatusConnected )
					{
					iCall.AnswerIncomingCallCancel ();
					User::Leave (KFaxEtelServerError);
					} //if (callStatus != RCall::EStatusAnswering)
            } //if (iMode & KFaxWaitForRing)
         else
            {//-- Fax is not waiting for a ring 
            if (iMode & KFaxOffHook)
               {
               if (callStatus != RCall::EStatusConnecting)
                  {
                  iCall.ConnectCancel ();
                  User::Leave (KFaxEtelServerError);
                  }
               }
            else if (callStatus != RCall::EStatusDialling)
               {
               iCall.DialCancel ();
               User::Leave (KFaxEtelServerError);
               }
            }
         TInt ret = iFax.Open (iCall);
         if (ret != KErrNone)
            {
            CancelFaxServerSession ();
            User::Leave (ret);
            }
         iFaxStarted = ETrue;
         reqStatus = KRequestPending;
         }//if (reqStatus != KRequestPending)
      else if (iClientCancel != KRequestPending)
         {//-- Fax cancel request
         if (iFaxStarted == EFalse)
            iCall.NotifyStatusChangeCancel ();
         CancelFaxServerSession ();
         User::Leave (KFaxCancelRequested);
         }
      else if (iTransferStatus != KRequestPending)
         {//--iCall.AnswerIncomingCall status changed
         if (iFaxStarted == EFalse)
            iCall.NotifyStatusChangeCancel ();
         User::LeaveIfError (iTransferStatus.Int ());
         break;
         }
      else
         {
         if (iFaxStarted == EFalse)
            iCall.NotifyStatusChangeCancel ();
         CancelFaxServerSession ();
         User::Leave (KErrCompletion);  // stray event handle
         }
      }

   //-- Data transfer phase
   User::LeaveIfError (iFax.GetProgress (iProgress));
   while (iProgress.iPhase == EDataTransfer)
      {
      iSource->iResolu = iProgress.iResolution;
      iSource->iCompression = iProgress.iCompression;
      for (;;)
         {
         iFax.Read (iTransferStatus, iDataBuf);
         User::WaitForRequest (iTransferStatus, iClientCancel);
         if (iClientCancel != KRequestPending)
            {
            iFax.TerminateFaxSession ();
            User::Leave (KFaxCancelRequested);
            }
         User::LeaveIfError (iTransferStatus.Int ());

         // the server has buffered up lines to minimize interaction
         // iDataBuf starts with a TInt containing the number of lines
         // Each line follows, preceded with a TInt containing its length
         // which must be copied as it might not be aligned on a 4-byte
         // boundary - a line of zero length indicates we have reached
         // the end of the page

         TUint8 *nextLine = CONST_CAST (TUint8 *, iDataBuf.Ptr ());
         TInt lengthOfLine=0;
         TInt numberOfLines;

         Mem::Copy (&numberOfLines, nextLine, sizeof (TInt));
         nextLine += sizeof (TInt);

         while (numberOfLines--)
            {
            Mem::Copy (&lengthOfLine, nextLine, sizeof (TInt));
            if (lengthOfLine == 0)
               break;
            nextLine += sizeof (TInt);
            TPtrC8 currentLine (nextLine, lengthOfLine);
            iSource->WriteFaxDataL (currentLine);
            nextLine += lengthOfLine;
            }
         if (lengthOfLine == 0)
            break;
         }
      iSource->WritePageParmsL (iProgress.iAnswerback);
      iFax.WaitForEndOfPage (iTransferStatus);
      User::WaitForRequest (iTransferStatus, iClientCancel);
      if (iClientCancel != KRequestPending)
         {
         iFax.TerminateFaxSession ();
         User::Leave (KFaxCancelRequested);
         }
      User::LeaveIfError (iTransferStatus.Int ());
      User::LeaveIfError (iFax.GetProgress (iProgress));
	  	  
      }
//	iSource->CloseFaxInStore ();
    if (iProgress.iCompression==EModifiedRead)
		 Convert1dL ();
   }
/*********************************************************************/

// sending a fax is rather more complex
//
// we need a valid phone number (we don't do polling)
//
// we need a valid list of pages to send
//
// we need to set the resolution we require to that of the
// fax we want to send (use the last page)
//

void CFaxTransfer::FaxTransmitL ()
   {
   
   
   __FLOG_FAXCLI(_L8("CFaxTransfer::FaxTransmitL entering"));

   TBool ConversionStatus=FALSE;
   //TInt err=0;
   if (iSource->iOurPreferredCompression==Prefer2D)
		{	
		TRAPD (retcode,Convert2dL());
		if (retcode==KErrNone)
			ConversionStatus=TRUE;
		else
			{
			ConversionStatus=FALSE;
			iSource->iOurPreferredCompression=Prefer1D;		// if anything goes wrong during conversion
			}												// try the 1D version.
		}
   if ((iSource->iFaxPages == 0) || (iSource->iFaxListEntries == 0))
      User::Leave (KErrNotFound);
   iSource->iSavedFaxListEntries = iSource->iFaxListEntries;
   iSource->iOurFaxEntry.iPageCount = 0; 
   iSource->iInstream.Open (*iSource->iSources);
   iSource->GetNextPageReadyL ();

   if (iSource->iOurPreferredCompression==Prefer1D)
	   iFaxSessionSettings.iTxPages=iSource->iFaxPages;

   // we pass in to the server the resolution of the last added source page

   iFaxSessionSettings.iTxResolution = (TFaxResolution) iSource->iResolu;
   if ((iSource->iOurPreferredCompression==Prefer2D) && ConversionStatus==TRUE)
		iFaxSessionSettings.iTxCompression = (TFaxCompression) EModifiedRead;	
   else
	   iFaxSessionSettings.iTxCompression = (TFaxCompression) iSource->iCompression;

   SetFaxSettingsL();	// pass the settings to the Fax Server
   SetSharedFileHandlesL();

   if (iMode & KFaxOffHook)
      iCall.Connect (iTransferStatus);
   else
      {
      if (iPhoneNumber.Length() == 0)
         User::Leave (KErrCouldNotConnect);
      iCall.Dial (iTransferStatus, iPhoneNumber);
      }

   TRequestStatus reqStatus;
   RCall::TStatus callStatus;
   iCall.NotifyStatusChange (reqStatus, callStatus);

   for (;;)
      {
      User::WaitForAnyRequest ();
      if (reqStatus != KRequestPending)
         {
         if (reqStatus.Int () != KErrNone)
														// initialisation and comm port errors
            {
            CancelFaxServerSession ();
            User::Leave (reqStatus.Int ());
            }
         if (iMode & KFaxOffHook)
            {
            if (callStatus != RCall::EStatusConnecting)
               {
               iCall.ConnectCancel ();
               User::Leave (KFaxEtelServerError);
               }
            }
         else if (callStatus != RCall::EStatusDialling)
            {
            iCall.DialCancel ();
            User::Leave (KFaxEtelServerError);
            }
         TInt ret = iFax.Open (iCall);
         if (ret != KErrNone)
            {
            CancelFaxServerSession ();
            User::Leave (ret);
            }
         iFaxStarted = ETrue;
         reqStatus = KRequestPending;   // to prevent first scenario being
										// chosen each time any request comes in
         }
      else if (iClientCancel != KRequestPending)
         {
         if (iFaxStarted == EFalse)
            iCall.NotifyStatusChangeCancel ();
         CancelFaxServerSession ();
         User::Leave (KFaxCancelRequested);
         }
      else if (iTransferStatus != KRequestPending)
         {
         if (iFaxStarted == EFalse)
            iCall.NotifyStatusChangeCancel ();
         User::LeaveIfError (iTransferStatus.Int ());
         break;
         }
      else
         {
         if (iFaxStarted == EFalse)
            iCall.NotifyStatusChangeCancel ();
         CancelFaxServerSession ();
         User::Leave (KErrCompletion);  // stray event handle
         }
      }

   for (;;)
      {
      User::LeaveIfError (iFax.GetProgress (iProgress));
      TInt thispage = iProgress.iPage;
      TInt thisline = 1;
      ASSERT (iSource->iLines);

		if ((iProgress.iCompression) && (iSource->iSavedFaxListEntries>=1))
			{
			while (iSource->iCompression == EModifiedHuffman)		// loop until we 
			iSource->GetNextPageReadyL ();							// find the 2D document
			}
	  
      //we buffer up lines to minimize client-server interaction
      //iDataBuf starts with a TInt containing the number of lines
      //Each line follows, preceded with a TInt containing its length
      //which must be copied as it might not be aligned on a 4-byte boundary

      TUint8 *startData;
      TUint8 *lineData;
      TInt numberOfLines;
      const TUint8 *maxData;

      TUint8 *currentLineData;
      TInt currentLineLength;

      for (;;)
         {
         lineData = startData = CONST_CAST (TUint8 *, iDataBuf.Ptr ());
         maxData = startData + iDataBuf.MaxLength () - KMaxT4Des - sizeof (TInt);

         iDataBuf.SetMax ();
         numberOfLines = 0;
         lineData += sizeof (TInt);
         for (;;)
            {
            if (thisline > iSource->iLines)
               break;
            thisline++;
            numberOfLines++;
            currentLineData = lineData + sizeof (TInt);
            *currentLineData = 0x0;
            TPtr8 currentLine (currentLineData + 1, 0, KMaxT4Des - 1);
            iSource->ReadFaxData (currentLine);
            currentLineLength = currentLine.Length () + 1;
            Mem::Copy (lineData, &currentLineLength, sizeof (TInt));
            lineData += sizeof (TInt);
            lineData += currentLineLength;
            if (lineData > maxData)
               break;
            }
         Mem::Copy (startData, &numberOfLines, sizeof (TInt));
         iDataBuf.SetLength (lineData - startData);
         iFax.Write (iTransferStatus, iDataBuf);
         User::WaitForRequest (iTransferStatus, iClientCancel);
         if (iClientCancel != KRequestPending)
            {
            iFax.TerminateFaxSession ();
            User::Leave (KFaxCancelRequested);
            }
         User::LeaveIfError (iTransferStatus.Int ());
         if (thisline > iSource->iLines)
            break;
         }
      iDataBuf.Zero ();
      iFax.WaitForEndOfPage (iTransferStatus);
      User::WaitForRequest (iTransferStatus, iClientCancel);
      if (iClientCancel != KRequestPending)
         {
         iFax.TerminateFaxSession ();
         User::Leave (KFaxCancelRequested);
         }
      User::LeaveIfError (iTransferStatus.Int ());
      User::LeaveIfError (iFax.GetProgress (iProgress));
      if (iProgress.iPhase != EDataTransfer)
         break;
      if (thispage == iProgress.iPage)
         iSource->PreviousPageFindL ();
      else
         iSource->GetNextPageReadyL ();
      }
   if ((iProgress.iCompression==EModifiedHuffman) && (iSource->iOurPreferredCompression==Prefer2D))
   {
	   for (TInt i=0; i<(iSource->iFaxPages/2);i++)
	   iSource->GetNextPageReadyL ();						
   }
}

void CFaxTransfer::SetFaxSettingsL()
	{
   TInt error;
   RPhone::TStatus phoneStatus;
   
   error=iPhone.GetStatus(phoneStatus);
	if (error == KErrNone)
		{
		if ((phoneStatus.iModemDetected == RPhone::EDetectedNotPresent) || (phoneStatus.iModemDetected == RPhone::EDetectedUnknown))
			{
			TRequestStatus initialiseStatus;
			iPhone.Initialise(initialiseStatus);
			User::WaitForAnyRequest();
			if (iClientCancel != KRequestPending)
				{
				iPhone.InitialiseCancel();					// issue initialiseCancel command
				User::WaitForRequest(initialiseStatus);		// wait for it to complete
				User::Leave(KFaxCancelRequested);			// leave with  KFaxCancelRequested
				}	
			User::LeaveIfError(initialiseStatus.Int());
			}
		}   
   TInt ret=KErrNone;	// so communication with modem has begun...
   TInt count=0;		// we have a loop where we try three times to set fax settings in the
						// unlikely event that the initialisation sequence has just started
						// so the phoneStatus gives ModemDetected Present, but the supported fax
						// classes have not yet been ascertained.
   do 
	{
	ret=iCall.SetFaxSettings (iFaxSessionSettings);	// retry until init sequence has found out what
													// the fax classes supported are.
	if (ret==KErrEtelUnknownModemCapability)
		User::After(500000);
	}
   while (ret==KErrEtelUnknownModemCapability && iClientCancel==KRequestPending && count++<3);
   if (iClientCancel!=KRequestPending)
	   ret=KFaxCancelRequested;
   User::LeaveIfError(ret);
   }
void CFaxTransfer::SetSharedFileHandlesL()
	{
	//Open a file server session and a file handle on the private header file to be shared.
	RFs sharedFs;
	RFile sharedHeaderFile;
	
	User::LeaveIfError(sharedFs.Connect());
	CleanupClosePushL(sharedFs);
	//allow it to be shared
	User::LeaveIfError(sharedFs.ShareProtected());
	
	//get path 
	TFileName headerFullPath;
	CFaxHeaderLines::GeneratePathForHeaderFileL(headerFullPath);
	
	//Open the file in read-only mode
	User::LeaveIfError(sharedHeaderFile.Open(sharedFs, headerFullPath, EFileRead));
	CleanupClosePushL(sharedHeaderFile);
	
	User::LeaveIfError(iCall.AdoptFaxSharedHeaderFile(sharedHeaderFile));
	CleanupStack::PopAndDestroy();//sharedHeaderFile
	CleanupStack::PopAndDestroy();//sharedFs
	}
	
TInt CFaxTransfer::GetPhoneInfoForTsy(const TDes& aTsyName, RTelServer::TPhoneInfo& aPhoneInfo) const
//
//	Finds the index of the phone which belongs to TSY named "aTsyName", and retrieves its info.
//
	{
	 TInt count=0;
	 iTelServer.EnumeratePhones(count);
	 TName matchTsyName;
	 TInt ret = iTelServer.GetTsyName(0,matchTsyName);
	 if (ret == KErrNone)
		{
		 TInt i=0;
		 if (count>1)
			{
			while (matchTsyName.CompareF(aTsyName)!=KErrNone && i++<count && ret==KErrNone)
				ret = iTelServer.GetTsyName(i,matchTsyName);
			}
		 ASSERT(matchTsyName.CompareF(aTsyName)==KErrNone);
		 iTelServer.GetPhoneInfo(i,aPhoneInfo);
		}
	 return ret;
	}

/********************************************************************/

EXPORT_C void CFaxTransfer::AddSourceL (const TFileName & aFaxPageStore, TFaxPreferredCompression aPreferredCompression)
/** Specifies which pages of a fax store file should be sent. 
It can be called more than once to add multiple pages from different files. Typically, 
this function is called twice for each transmission: once to queue the cover sheet, 
and a second time to queue the remainder of the fax.
The overloaded variants are supplied primarily to help error recovery in cases when 
a fax transmission is either incomplete or when specific pages need to be resent. 
When transmitting a fax, at least one variant of this function must be called before 
CFaxTransfer::Start().

@param aFaxPageStore  Name of the fax store file from which to take pages.
@param  aPreferredCompression Preferred compression.
@capability WriteUserData
*/
   {
   iSource->AddSourceL (aFaxPageStore, 1,aPreferredCompression);
   }

EXPORT_C void CFaxTransfer::AddSourceL (const TFileName & aFaxPageStore, TInt aStartPage,TFaxPreferredCompression aPreferredCompression)
/** Specifies which pages of a fax store file should be sent. 
It can be called more than once to add multiple pages from different files. 
Typically, this function is called twice for each transmission: once to queue 
the cover sheet, and a second time to queue the remainder of the fax.
The overloaded variants are supplied primarily to help error recovery in cases 
when a fax transmission is either incomplete or when specific pages need to be 
resent. When transmitting a fax, at least one variant of this function must be 
called before CFaxTransfer::Start().

@param aFaxPageStore  Name of the fax store file from which to take pages. 
@param aStartPage  Page in file to start from. If omitted, the file is sent 
from the start. 
@param  aPreferredCompression Preferred compression.
@capability WriteUserData
*/
   {
   iSource->AddSourceL (aFaxPageStore, aStartPage, aPreferredCompression);
   }

EXPORT_C void CFaxTransfer::AddSourceL (const TFileName & aFaxPageStore, TInt aStartPage, TInt aEndPage, TFaxPreferredCompression aPreferredCompression)
/**Specifies which pages of a fax store file should be sent. 
It can be called more than once to add multiple pages from different files. 
Typically, this function is called twice for each transmission: once to queue 
the cover sheet, and a second time to queue the remainder of the fax.
The overloaded variants are supplied primarily to help error recovery in cases 
when a fax transmission is either incomplete or when specific pages need to be 
resent. When transmitting a fax, at least one variant of this function must be 
called before CFaxTransfer::Start().

@param aFaxPageStore  Name of the fax store file from which to take pages. 
@param aStartPage  Page in file to start from. If omitted, the file is sent from the start. 
@param aEndPage  Page in file to stop sending. If omitted, transmission continues to the end. 
@param  aPreferredCompression Preferred compression.
@capability WriteUserData
*/
   {
   iSource->AddSourceL (aFaxPageStore, aStartPage, aEndPage, aPreferredCompression);
   }

//EXPORT_C void CFaxTransfer::AddSourceL (const TFileName & aFaxPageStore, const TFileName & aFaxPageStore2)
//	{
//	iSource->AddSourceL(aFaxPageStore, aFaxPageStore2);
//	}

EXPORT_C void CFaxTransfer::RemoveAllSources ()
/** Clears the complete list of pages previously selected for faxing using one 
of the variants of AddSourceL(). 

Removal of individual items from the list of pages to be fax is not possible. 

This function must be used between successive fax transmissions if previously 
sent pages aren't to be sent again. 
@capability WriteUserData
*/
   {
   iSource->RemoveAllSources ();
   }

/********************************************************************/
void CFaxTransfer::Convert2dL ()
	{	
	TInt err=0;
	TInt k=0;
	TBuf<64> filename;
	CWriteFaxFile*  writeFaxFile;
	CReadFaxFile*   readFaxFile;
	TRawScanLine	decodedScanLine;
	//TFaxBufSenderId sd;
	TFaxBufSenderId senderId;


	writeFaxFile = CWriteFaxFile::NewL();
	CleanupStack::PushL(writeFaxFile);
	readFaxFile  = CReadFaxFile::NewL();
	CleanupStack::PushL(readFaxFile);
	iConverting=TRUE;
	
	TRAP (err,readFaxFile->OpenL(iSource->iOurFaxEntry.iFaxPageStore));
	if (err!=KErrNone)
		{
		iConverting=FALSE;
		User::Leave(err);
		}

 	readFaxFile->iReadFaxPages->SetPageL(0);
	TFaxPageInfo info = readFaxFile->iReadFaxPages->CurrentPageInfo();
	if (info.iCompression != EModifiedHuffman)
		User::Panic(_L("Not a 1D file"),1);

	//writeFaxFile->OpenL(_L("c:\\blank2D.fax"),64);
	filename.Copy(iSource->iOurFaxEntry.iFaxPageStore);
	filename.Append(_L("2d"));
	// the second push in OpenL doesn't cause a double deletion of writeFaxFile, since it is pushed by using TCleanupItem.
	// coverity [double_push]
	writeFaxFile->OpenL(filename,64);
	//writeFaxFile->OpenL(iSource->iOurFaxEntry.iFaxPageStore,64);
	

	for (k=0; k<iSource->iFaxPages; k++)
	{
	readFaxFile->iReadFaxPages->SetPageL(k);
	TFaxPageInfo info = readFaxFile->iReadFaxPages->CurrentPageInfo();
	if (info.iCompression != EModifiedHuffman)
		User::Panic(_L("Not a 1D file"),1);
	writeFaxFile->iWriteFaxPages->StartPage(info.iResolution, EModifiedRead);
	for (TInt n = info.iNumScanLines ; n  ; n--)
		{
		readFaxFile->iReadFaxPages->GetScanLineL(decodedScanLine);	
		writeFaxFile->iWriteFaxPages->AddScanLineL(decodedScanLine);
		}

	writeFaxFile->iWriteFaxPages->EndPageL(info.iResolution,senderId, EModifiedRead);
	}// end of for statement
		
	writeFaxFile->CommitL();
	writeFaxFile->Close();
	readFaxFile->Close();
		
	AddSourceL(filename,Prefer2D);
	iFaxSessionSettings.iTxPages = (iSource->iFaxPages/2);	// sent only the 2d version of the document
															// which means half the attached pages
	CleanupStack::PopAndDestroy(2);
	iConverting=FALSE;
}	



/***********************************************************************************/
// This function takes the received 2D file and converts it to 1D
// The 2D file will be deleted and the 1D version of the file will 
// inherit the name of the received 2D version
/************************************************************************************/
void CFaxTransfer::Convert1dL ()
	{	
	TInt err=0;
	TInt k=0;
	TBuf<64> filename;
	CWriteFaxFile* writeFaxFile;
	CReadFaxFile*  readFaxFile;
	TRawScanLine decodedScanLine;
	//TFaxBufSenderId sd;
	TFaxBufSenderId senderId;

	writeFaxFile = CWriteFaxFile::NewL();
	CleanupStack::PushL(writeFaxFile);
	readFaxFile  = CReadFaxFile::NewL();
	CleanupStack::PushL(readFaxFile);	
	iConverting=TRUE;

	//TRAP (err,readFaxFile->OpenL(iSource->iOurFaxEntry.iFaxPageStore));
	TRAP (err,readFaxFile->OpenL(iReceiveFileName));
	if (err!=KErrNone)
		User::Leave(err);
		
 	readFaxFile->iReadFaxPages->SetPageL(0);
	TFaxPageInfo info = readFaxFile->iReadFaxPages->CurrentPageInfo();
	//if (info.iCompression != EModifiedHuffman)
	if (info.iCompression != EModifiedRead)
		User::Panic(_L("Not a 2D file"),1);
	
	//filename.Copy(iSource->iOurFaxEntry.iFaxPageStore);
	filename.Copy(iReceiveFileName);
	filename.Append(_L("1d"));
	// the second push in OpenL doesn't cause a double deletion of writeFaxFile, since it is pushed by using TCleanupItem.
	// coverity [double_push]
	writeFaxFile->OpenL(filename,64);
	//	writeFaxFile->OpenL(iSource->iOurFaxEntry.iFaxPageStore,64);
	

	TInt iRxPages=readFaxFile->iReadFaxPages->NumPages();

	for (k=0; k<iRxPages; k++)
	{
	readFaxFile->iReadFaxPages->SetPageL(k);
	TFaxPageInfo info = readFaxFile->iReadFaxPages->CurrentPageInfo();
	//if (info.iCompression != EModifiedHuffman)
	if (info.iCompression != EModifiedRead)
		User::Panic(_L("Not a 2D file"),1);
	//writeFaxFile->iWriteFaxPages->StartPage(info.iResolution, EModifiedRead);
	writeFaxFile->iWriteFaxPages->StartPage(info.iResolution, EModifiedHuffman);
	for (TInt n = info.iNumScanLines ; n  ; n--)
		{
		readFaxFile->iReadFaxPages->GetScanLineL(decodedScanLine);	
		writeFaxFile->iWriteFaxPages->AddScanLineL(decodedScanLine);
		}

	//writeFaxFile->iWriteFaxPages->EndPageL(info.iResolution,senderId, EModifiedRead);
	writeFaxFile->iWriteFaxPages->EndPageL(info.iResolution,senderId, EModifiedHuffman);
	}// end of for statement
		
	writeFaxFile->CommitL();
	writeFaxFile->Close();
	readFaxFile->Close();
	
	RFs FileServer;
	err = FileServer.Connect();
	if (err !=KErrNone)
		User::Leave(err);
	User::LeaveIfError(FileServer.Delete(iReceiveFileName));

	User::LeaveIfError(FileServer.Rename(filename,iReceiveFileName));
	
	FileServer.Close();

	CleanupStack::PopAndDestroy(2);	
	iConverting=FALSE;
//	AddSourceL(filename,Prefer2D);
//	iFaxSessionSettings.iTxPages = (iSource->iFaxPages/2);	// sent only the 2d version of the document
	}	


/*

CFaxTransfer::StartThread()
	{
	TInt state = KErrNone;
	TInt heapSize = 0x14000;	
	TInt stackSize = 0x14000;

	reinterpret_cast<TAny*>(this);  // this points to a CFaxTransfer Object
	state = iConverterThread.Create ((_L ("FaxConverterThread")), FaxConverterThread, stackSize, heapSize, heapSize, this, EOwnerThread);
	if (state)
		{
		state = KFaxThreadError;
		}
	else
		{
		//aThreadStat = KRequestPending;
		//if (iClientCancel != KErrCancel)
		//iClientCancel = KRequestPending;
		//iDriverThread.Logon (aThreadStat);
		
		iConverterThread.SetPriority (EPriorityRealTime);
		iConverterThread.Resume ();
		}
	return state;
	}

TInt FaxConverterThread (TAny * session)
	{
	TInt m;
	CTrapCleanup *cleanup = CTrapCleanup::New ();
	CFaxTransfer *faxtransfer =reinterpret_cast<CFaxTransfer *>(session);
	RSemaphore aSemaphore;
	TFindSemaphore mysemaphore(_L("FaxCli*"));

    TFullName      theName (_L("FaxCliSem"));
//  RSemaphore     theSem;             // derived from RHandleBase
    
  if ((mysemaphore.Next(theName))==KErrNone)
        {
        aSemaphore.Open(mysemaphore,EOwnerThread);
        }


	TRAP(m,faxtransfer->Convert2dL());

	aSemaphore.Signal();	
	return KErrNone;
	}
*/