telephonyserverplugins/multimodetsy/hayes/CALL.CPP
branchRCL_3
changeset 20 07a122eea281
parent 19 630d2f34d719
--- a/telephonyserverplugins/multimodetsy/hayes/CALL.CPP	Tue Aug 31 16:23:08 2010 +0300
+++ b/telephonyserverplugins/multimodetsy/hayes/CALL.CPP	Wed Sep 01 12:40:21 2010 +0100
@@ -16,6 +16,7 @@
 #include <commsdattypesv1_1.h>
 #include "CALL.H"		// Header file for this source file
 #include "NOTIFY.H"
+#include "FAX.H"
 #include "ATDIAL.H"
 #include "ATANSWER.H"
 #include "ATCONNCT.H"
@@ -33,6 +34,8 @@
 #include "set_cbst.h"		// for CATSetCBST class
 #include "et_struct.h"
 
+_LIT(KFaxServerName,"FaxSvr.dll");
+
 
 //
 // CAcquireEntry class
@@ -2048,3 +2051,713 @@
 	ReqCompleted(aTsyReqHandle,KErrNone);
 	return KErrNone;
 	}
+
+// local function needed below
+
+LOCAL_C void SetFaxSessionSettings(RCall::TFaxSessionSettings& aTrg, const RCall::TFaxSessionSettings& aSrc)
+	{
+	aTrg.iMode=aSrc.iMode;
+	aTrg.iFaxRetrieveType=aSrc.iFaxRetrieveType;
+	aTrg.iFaxClass=aSrc.iFaxClass;
+	aTrg.iFaxId=aSrc.iFaxId;
+	aTrg.iMaxSpeed=aSrc.iMaxSpeed;
+	aTrg.iMinSpeed=aSrc.iMinSpeed;
+	aTrg.iPreferredECM=aSrc.iPreferredECM;
+	aTrg.iFaxOnDemandDelay=aSrc.iFaxOnDemandDelay;
+	aTrg.iTxResolution=aSrc.iTxResolution;
+	aTrg.iTxCompression=aSrc.iTxCompression;
+	aTrg.iTxPages=aSrc.iTxPages;
+	aTrg.iRxResolution=aSrc.iRxResolution;
+	aTrg.iRxResolution=aSrc.iRxResolution;
+	}
+
+//
+//	CCallMobileFax - fax call functionality
+//	At construction, phone init sequence may not have yet determined phone's capabilities so
+//	create object anyway and check in the function calls whether fax is supported by phone
+//
+
+CCallMobileFax* CCallMobileFax::NewL(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals,const TName& aName)
+	{
+	CCallMobileFax* faxCall=new(ELeave) CCallMobileFax(aATIO,aInit,aPhoneGlobals);
+	TCleanupItem newCallFaxHayesClose(CloseCall,faxCall);
+	CleanupStack::PushL(newCallFaxHayesClose);
+	faxCall->ConstructL(aName);
+	CleanupStack::Pop();
+	return faxCall;
+	}
+
+CCallMobileFax::CCallMobileFax(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+	: CCallMobile(aATIO,aInit,aPhoneGlobals),iFaxSession(NULL),iFax(NULL)
+	{}
+
+void CCallMobileFax::ConstructL(const TName& aName)
+	{
+	CCallHayes::ConstructL(aName);
+	iCallInfo.iLineOwnerName = KFaxLineName;
+	iDialFax=CATDialFax::NewL(iIo,this,iInit,iPhoneGlobals);
+	iConnectFax=CATConnectFax::NewL(iIo,this,iInit,iPhoneGlobals);
+	iAnswerFax=CATAnswerFax::NewL(iIo,this,iInit,iPhoneGlobals);
+	iHangUpFax=CATHangUpFax::NewL(iIo,this,iInit,iPhoneGlobals);
+	iFaxSettings.iMode = RCall::ETransmit;
+	iFaxSettings.iFaxRetrieveType = RCall::EFaxOnDemand;
+	iFaxSettings.iFaxClass = EClassAuto;
+	iFaxSettings.iMaxSpeed = 9600;
+	iFaxSettings.iMinSpeed = 2400;
+	iFaxSettings.iPreferredECM = EFalse;
+	iFaxSettings.iFaxOnDemandDelay = 20;
+	iFaxSettings.iTxResolution = EFaxNormal;
+	iFaxSettings.iTxCompression = EModifiedHuffman;
+	iFaxSettings.iTxPages = 0;
+	iFaxSettings.iRxResolution = EFaxNormal;
+	iFaxSettings.iRxCompression = EModifiedHuffman;
+	iFaxCompletion = new (ELeave) CFaxCompletion();
+	iFaxProgress=CreateFaxProgressChunk();
+	if(iFaxProgress==NULL)
+		User::Leave(KErrEtelFaxChunkNotCreated);
+	}
+
+CCallMobileFax::~CCallMobileFax()
+//
+//	Removes itself from array of calls in CLineMobileData
+//
+	{
+	__ASSERT_DEBUG(iFaxSession==NULL,Panic(EFaxServerNotNull));
+	DeleteFaxProgressChunk();		// This deallocates the memory pointed to by iFaxProgress
+	delete iDialFax;
+	delete iConnectFax;
+	delete iAnswerFax;
+	delete iHangUpFax;	
+	delete iFaxCompletion;
+	delete iFileHandles;
+	}
+
+void CCallMobileFax::CollateCoreCaps(const TTsyReqHandle aTsyReqHandle, TUint32* aCallCaps)
+	{
+	*aCallCaps = RCall::KCapsFax;
+	if (ValidateFaxClass(iFaxSettings.iFaxClass)==KErrNone
+		 && (!(REINTERPRET_CAST(CLineMobileFax*,Owner())->iFaxOpened==TRUE && iFax==NULL))
+		 && iPhoneGlobals->iPhoneStatus.iModemDetected==RPhone::EDetectedPresent)
+		 //	check that fax class is OK and that no other fax call has opened a fax object
+		{
+		TCallOwnership owner = CheckOwnership(aTsyReqHandle);
+		if (ValidateRequest(aTsyReqHandle,RCall::EStatusIdle)==KErrNone)
+			*aCallCaps |= (RCall::KCapsDial | RCall::KCapsConnect);
+		TInt ret=KErrNone;
+		if (owner==CCallBase::EOwnedFalse)	// call owned by another client
+			ret=KErrEtelNotCallOwner;
+		else 
+			{
+			if (!iIsForIncomingCall)	
+				{
+				if (REINTERPRET_CAST(CPhoneHayes*,Owner()->Owner())->CheckForOutstandingAnswer())
+					ret=KErrEtelAnswerAlreadyOutstanding;
+				}
+			else
+				ret=KErrEtelAnswerAlreadyOutstanding;
+			}
+		if (ret==KErrNone && (iCallInfo.iMobileStatus==RMobileCall::EStatusIdle || iCallInfo.iMobileStatus==RMobileCall::EStatusRinging))
+			*aCallCaps |= RCall::KCapsAnswer;
+		if (owner==CCallBase::EOwnedTrue && iCallInfo.iMobileStatus==RMobileCall::EStatusConnected)
+			{
+			*aCallCaps |= RCall::KCapsHangUp;
+			}
+		}
+	}
+
+TInt CCallMobileFax::OpenFax(TDesC* aTelNumber,TFaxMode aFaxMode)
+//
+//	Open CETelFaxHayes object with desired settings
+//
+	{
+	TFaxServerSessionSettings faxSettings;
+	faxSettings.iPhoneNumber.Copy(*aTelNumber);
+	faxSettings.iLogging = ETrue;
+	TInt ret = iPhoneGlobals->iConfiguration->ConfigModemString(TPtrC(KCDTypeNameFaxInitString),faxSettings.iFaxInitString);
+	if (!ret)
+		{
+		ret = iPhoneGlobals->iConfiguration->ConfigModemString(TPtrC(KCDTypeNameCsyName),faxSettings.iPortDriverName);
+		}
+	if (!ret)
+		{
+		ret = iPhoneGlobals->iConfiguration->ConfigModemString(TPtrC(KCDTypeNamePortName),faxSettings.iCommPortName);
+		}
+	if (ret)
+		return ret;
+	if(faxSettings.iFaxInitString.Length()==0)
+		faxSettings.iFaxInitString=KAT2Command;			
+	faxSettings.iMode = aFaxMode;
+	faxSettings.iFaxClass = iFaxSettings.iFaxClass;
+	faxSettings.iFaxId = iFaxSettings.iFaxId;
+	faxSettings.iMaxSpeed = iFaxSettings.iMaxSpeed;
+	faxSettings.iMinSpeed = iFaxSettings.iMinSpeed;
+	faxSettings.iPreferredECM = iFaxSettings.iPreferredECM;
+	faxSettings.iFaxOnDemandDelay = iFaxSettings.iFaxOnDemandDelay;
+	faxSettings.iTxResolution = iFaxSettings.iTxResolution;
+	faxSettings.iTxCompression = iFaxSettings.iTxCompression;
+	faxSettings.iTxPages = iFaxSettings.iTxPages;
+	faxSettings.iRxResolution = iFaxSettings.iRxResolution;
+	faxSettings.iRxCompression = iFaxSettings.iRxCompression;
+	return iFaxSession->FxOpen(faxSettings,iFaxProgress);
+	}
+
+TInt CCallMobileFax::ValidateFaxClass(TFaxClass& aFaxClass)
+	{
+	if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & KFaxCaps) == 0)
+		{
+		return KErrNotSupported;
+		}
+	switch (aFaxClass)
+		{
+	case EClassAuto:		// TSY decides what class "AUTO" refers to!
+		{
+		if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassTwoPointZero))
+			aFaxClass =  EClass2point0;
+		else if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassTwo)) 
+			aFaxClass = EClass2;
+		else if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassOne))
+			aFaxClass = EClass1;
+		break;
+		}
+	case EClass1:
+		if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassOne)==0)
+			return KErrEtelWrongModemType;
+		break;
+	case EClass1point0:
+		if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassOnePointZero)==0)
+			return KErrEtelWrongModemType;
+		break;
+	case EClass2:
+		if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassTwo)==0)
+			return KErrEtelWrongModemType;
+		break;
+	case EClass2point0:
+		if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassTwoPointZero)==0)
+			return KErrEtelWrongModemType;
+		break;
+	case EClass2point1:
+		if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassTwoPointOne)==0)
+			return KErrEtelWrongModemType;
+		break;
+	default:
+		return KErrEtelWrongModemType;
+		}
+	return KErrNone;
+	}
+
+typedef CFaxSession* (*TFaxServerEntry)();
+void CCallMobileFax::GetFaxBaseL()
+	{
+	__ASSERT_DEBUG(iFaxCompletion,Panic(EFaxCompletionPtrNull));
+	RFs fs;
+	(void)User::LeaveIfError(fs.Connect());
+
+	TInt r=iFaxServerLib.Load(KFaxServerName);
+	if (r==KErrNone)
+		{
+		// Check the Uid2
+#if defined (_UNICODE)
+		if(iFaxServerLib.Type()[1]!=TUid::Uid(KUidUnicodeDynamicFaxServer))
+			r = KErrBadLibraryEntryPoint;
+#else
+		if(iFaxServerLib.Type()[1]!=TUid::Uid(KUidDynamicFaxServer))
+			r = KErrBadLibraryEntryPoint;
+#endif
+		if (r==KErrNone)
+			{	
+			TFaxServerEntry libEntry=(TFaxServerEntry)iFaxServerLib.Lookup(1);
+			if (libEntry!=NULL)
+				{
+				TRAP(r,iFaxSession=(*libEntry)());	// libEntry may leave.
+				if (r==KErrNone)
+					{
+					LOGTEXT(_L8("Loaded Fax Server"));
+					iFaxSession->SetCallBack(iFaxCompletion);
+					}
+				else
+					iFaxServerLib.Close();
+				}
+			else
+				{
+				r = KErrBadLibraryEntryPoint;
+				iFaxServerLib.Close();
+				}
+			}
+		else
+			iFaxServerLib.Close();
+		}
+	fs.Close();
+	(void)User::LeaveIfError(r);
+	}
+
+TInt CCallMobileFax::FaxConnectHandler(const TTsyReqHandle aTsyReqHandle)
+	{
+	TInt ret = ValidateFaxClass(iFaxSettings.iFaxClass);
+	if (ret!=KErrNone)
+		{
+		(void)SetUnowned();
+		ReqCompleted(aTsyReqHandle,ret);
+		return ret;
+		}
+	if (REINTERPRET_CAST(CLineMobileFax*,Owner())->iFaxOpened==TRUE && iFax==NULL)
+		{
+		(void)SetUnowned();
+		ReqCompleted(aTsyReqHandle,KErrEtelNotFaxOwner);
+		return ret;
+		}
+	
+	TRAPD(res,GetFaxBaseL());
+	if (res!=KErrNone)
+		{
+		(void)SetUnowned();
+		ReqCompleted(aTsyReqHandle,res);
+		}
+	iPhoneGlobals->iEventSignalActive = EFalse; 
+	return res;
+	}
+
+void CCallMobileFax::FaxDial(const TTsyReqHandle aTsyReqHandle,TDesC* aTelNumber)
+//
+//	Called once any initialising has been done. Checks here that modem supports fax,
+//	and that no other CCallHayes has opened a fax object
+//
+	{
+	if (FaxConnectHandler(aTsyReqHandle)!=KErrNone)	// ReqCompleted is called inside FaxConnectHandler
+													// if there is an error
+		return;
+	TFaxMode faxMode;
+	if (iFaxSettings.iMode==RCall::ETransmit)
+		{
+		faxMode = EDialAndTransmit;
+		}
+	else	// we're receiving
+		{
+		if (iFaxSettings.iFaxRetrieveType==RCall::EFaxPoll)
+			faxMode = EDialAndReceivePoll;
+		else 
+			faxMode = EDialAndReceiveFaxBack;
+		}
+	TInt res = OpenFax(aTelNumber,faxMode);
+	if (res!=KErrNone)	// make sure cleaned up.
+		{
+		ReqCompleted(aTsyReqHandle,res);
+		return;
+		}
+	ChangeLineStatus(RCall::EStatusDialling);
+	// EStatusDialling always results in KErrNone return
+	(void) ChangeCallStatus(RMobileCall::EStatusDialling);
+	iPhoneGlobals->iNotificationStore->CheckNotification(this,EBegunConnecting);
+	iFaxCompletion->Configure(aTsyReqHandle,this);
+	iIo->Cancel();
+	iPhoneGlobals->iPhoneStatus.iPortAccess = EPortAccessDenied; // so CATIO won't queue a read
+	
+	if (faxMode == EDialAndTransmit)
+		{
+		LOGTEXT(_L8("About to call CETelFaxBase::TxConnect"));
+		//this transfers ownership of the file handles object to the fax session object.
+		iFaxSession->SetFaxHeaderFile(iFileHandles);
+		//we now aren't resonsible for its deletion.
+		iFileHandles = NULL;
+		iFaxSession->TxConnect();
+		}
+	else
+		{
+		LOGTEXT(_L8("About to call CETelFaxBase::RxConnect"));
+		iFaxSession->RxConnect();
+		}
+	}
+
+TInt CCallMobileFax::Dial(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* aTelNumber)
+//
+//	Dial a fax call
+//	Check that call is not owned by another client, and line is idle  
+//
+	{
+	TInt ret = ValidateRequest(aTsyReqHandle,RCall::EStatusIdle);
+	if (ret==KErrNone)
+		{
+		(void)SetOwnership(aTsyReqHandle);
+		SetCallParams(aCallParams);
+		LOGTEXT(_L8("FaxCall:\tSubmitting Dial Command"));
+		iDialFax->ExecuteCommand(aTsyReqHandle,aTelNumber,&iCallInfo);
+		}
+	else
+		ReqCompleted(aTsyReqHandle,ret);
+	return KErrNone;
+	}
+
+void CCallMobileFax::FaxCancelCommand(const TTsyReqHandle aTsyReqHandle)
+//
+//	Cancels the fax session (for ConnectCancel and AnswerCancel as well)
+//
+	{
+	LOGTEXT(_L8("FaxCall:\tCancel Fax call and Unload module"));
+	if(!iFaxSession)							// if iFaxSession is NULL
+		{										// then CleanUpFaxServer has already been called
+		LOGTEXT(_L8("FaxCall:\tModule already unloaded, completing..."));
+		ReqCompleted(aTsyReqHandle,KErrCancel);	// so return without further processing
+		return;
+		}
+
+	LOGTEXT(_L8("FaxCall:\tClosing down fax server module"));
+	iFaxSession->Cancel();
+	CleanUpFaxServer();
+	iIo->Read();
+	SetToIdle();
+	ReqCompleted(aTsyReqHandle,KErrCancel);
+	}
+
+TInt CCallMobileFax::DialCancel(const TTsyReqHandle aTsyReqHandle)
+	{
+	LOGTEXT2(_L8("FaxCall:\tDialCancel(%d) called"),aTsyReqHandle);
+	iDialFax->CancelCommand(aTsyReqHandle);
+	return KErrNone;
+	}
+
+void CCallMobileFax::FaxConnect(const TTsyReqHandle aTsyReqHandle)
+//
+//	Called once any initialising has been done. Checks here that modem supports fax.
+//
+	{
+	if (FaxConnectHandler(aTsyReqHandle)!=KErrNone)
+		return;
+	TFaxMode faxMode;
+	if (iFaxSettings.iMode==RCall::ETransmit)
+		faxMode = EImmediateTransmit;
+	else
+		faxMode = EImmediateReceive;
+	TBuf<1> null;
+	null.Zero();
+	TInt res = OpenFax(&null,faxMode);
+	if (res!=KErrNone)
+		{
+		ReqCompleted(aTsyReqHandle,res);
+		return;
+		}
+	ChangeLineStatus(RCall::EStatusConnecting);
+	// EStatusConnecting always returns KErrNone
+	(void)ChangeCallStatus(RMobileCall::EStatusConnecting);
+	iPhoneGlobals->iNotificationStore->CheckNotification(this,EBegunConnecting);
+	iFaxCompletion->Configure(aTsyReqHandle,this);
+	iIo->Cancel();
+	iPhoneGlobals->iPhoneStatus.iPortAccess = EPortAccessDenied; // so CATIO won't queue a read
+	if (faxMode == EImmediateTransmit)
+		iFaxSession->TxConnect();
+	else
+		iFaxSession->RxConnect();
+	}
+
+TInt CCallMobileFax::Connect(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
+//
+//	Immediate connect to a fax call
+//	Check that call is not owned by another client, and line is idle  
+//
+	{
+	TInt ret = ValidateRequest(aTsyReqHandle,RCall::EStatusIdle);
+	if (ret==KErrNone)
+		{
+		(void)SetOwnership(aTsyReqHandle);
+		SetCallParams(aCallParams);
+		LOGTEXT(_L8("FaxCall:\tSubmitting Connect Command"));
+		iConnectFax->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+		}
+	else
+		ReqCompleted(aTsyReqHandle,ret);
+	return KErrNone;
+	}
+
+TInt CCallMobileFax::ConnectCancel(const TTsyReqHandle aTsyReqHandle)
+	{
+	LOGTEXT2(_L8("FaxCall:\tConnectCancel(%d) called"),aTsyReqHandle);
+	iConnectFax->CancelCommand(aTsyReqHandle);
+	return KErrNone;
+	}
+
+void CCallMobileFax::FaxAnswer(const TTsyReqHandle aTsyReqHandle)
+	{
+	if (FaxConnectHandler(aTsyReqHandle)!=KErrNone)
+		return;
+	TFaxMode faxMode;
+	if (iFaxSettings.iMode==RCall::ETransmit)
+		faxMode = EWaitForRingAndTransmit;
+	else
+		faxMode = EWaitForRingAndReceive;
+	TBuf<1> null;
+	null.Zero();
+	TInt res = OpenFax(&null,faxMode);
+	if (res!=KErrNone)
+		{
+		ReqCompleted(aTsyReqHandle,res);
+		return;
+		}
+	LOGTEXT(_L8("FaxCall:\tAnswering Fax call"));
+	ChangeLineStatus(RCall::EStatusAnswering);
+	// EStatusAnswering always results in KerrNone return
+	(void)ChangeCallStatus(RMobileCall::EStatusAnswering);
+	CPhoneHayes* phone=STATIC_CAST(CPhoneHayes*,Owner()->Owner());
+	phone->StopRingCounter();		// RING should no longer come in
+	iPhoneGlobals->iNotificationStore->CheckNotification(this,EBegunConnecting);
+	iFaxCompletion->Configure(aTsyReqHandle,this);
+	iIo->Cancel();
+	iPhoneGlobals->iPhoneStatus.iPortAccess = EPortAccessDenied; // so CATIO won't queue a read
+	if (faxMode == EWaitForRingAndTransmit)
+		iFaxSession->TxConnect();
+	else
+		iFaxSession->RxConnect();
+	}
+
+TInt CCallMobileFax::AnswerIncomingCall(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
+//
+//	Answer a fax call
+//
+	{
+	TInt ret=KErrNone;
+	CCallBase::TCallOwnership owned = CheckOwnership(aTsyReqHandle);
+	if (owned==CCallBase::EOwnedFalse)	// call owned by another client
+		{
+		ret=KErrEtelNotCallOwner;
+		}
+	else if (REINTERPRET_CAST(CPhoneHayes*,Owner()->Owner())->CheckForOutstandingAnswer())
+		ret=KErrEtelAnswerAlreadyOutstanding;
+
+	if (ret==KErrNone)
+		{
+		CLineHayes* line = STATIC_CAST(CLineHayes*,Owner());
+		CPhoneHayes* phone=STATIC_CAST(CPhoneHayes*,line->Owner());
+		phone->CancelOtherRingingCall(line);
+		line->FreePreAllocCallIfNecessary();
+		SetCallParams(aCallParams);
+		if (iCallInfo.iMobileStatus==RMobileCall::EStatusRinging)
+			{
+			LOGTEXT(_L8("FaxCall:\tSubmitting Answer Command"));
+			iAnswerFax->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+			}
+		else	// This call is now a client-designated Incoming Call object.
+			{
+			iIsForIncomingCall=ETrue;
+			iAnswerTsyReqHandle = aTsyReqHandle;
+			}
+		return KErrNone;
+		}
+	ReqCompleted(aTsyReqHandle,ret);
+	return KErrNone;
+	}
+
+TInt CCallMobileFax::AnswerIncomingCallCancel(const TTsyReqHandle aTsyReqHandle)
+//
+//	Cancel the answer command if possible
+//
+	{
+	LOGTEXT2(_L8("FaxCall:\tAnswerCancel(%d) called"),aTsyReqHandle);
+	if (iIsForIncomingCall)
+		{
+		iIsForIncomingCall=EFalse;
+		ReqCompleted(aTsyReqHandle,KErrCancel);
+		}
+	else
+		iAnswerFax->CancelCommand(aTsyReqHandle);
+	return KErrNone;
+	}
+
+void CCallMobileFax::AnswerImmediately()
+	{
+	(void)SetOwnership(iAnswerTsyReqHandle);
+	// EStatusRinging always results in KErrNone return
+	(void)ChangeCallStatus(RMobileCall::EStatusRinging);// new 14/1/99
+	iPhoneGlobals->iNotificationStore->CheckNotification(this,ERingOccurred);
+	iIsForIncomingCall=EFalse;
+	LOGTEXT(_L8("FaxCall:\tSubmitting Answer command"));
+	iAnswerFax->ExecuteCommand(iAnswerTsyReqHandle,NULL,&iCallInfo);
+	}		
+
+void CCallMobileFax::FaxHangUp(const TTsyReqHandle aTsyReqHandle)
+//
+//	Fax server reconfigures port so no need to here.
+//
+	{
+	if (iFaxSession)
+		{
+		// EStatusDisconnecting always results in KErrNone return
+		(void)ChangeCallStatus(RMobileCall::EStatusDisconnecting);
+		ChangeLineStatus(RCall::EStatusHangingUp);
+		iPhoneGlobals->iNotificationStore->CheckNotification(this,EBegunHangingUp);
+		CleanUpFaxServer();
+		iIo->Read();
+		SetToIdle();
+		}
+	ReqCompleted(aTsyReqHandle,KErrNone);
+	}
+
+TInt CCallMobileFax::HangUp(const TTsyReqHandle aTsyReqHandle)
+//
+//	Terminate a fax call. Checks fax capability, call ownership and line status.
+//
+	{
+	if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & KFaxCaps) == 0)
+		{
+		ReqCompleted(aTsyReqHandle,KErrNotSupported);
+		return KErrNone;
+		}
+	if (CheckOwnership(aTsyReqHandle)==CCallBase::EOwnedFalse)
+		{
+		ReqCompleted(aTsyReqHandle,KErrEtelNotCallOwner);
+		return KErrNone;
+		}	
+	if (iPhoneGlobals->iPhoneStatus.iLineStatus != RCall::EStatusConnected)
+		{
+		ReqCompleted(aTsyReqHandle,KErrNone);
+		return KErrNone;
+		}
+	LOGTEXT(_L8("FaxCall:\tHanging up"));
+	iHangUpFax->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+	return KErrNone;
+	}
+
+TInt CCallMobileFax::HangUpCancel(const TTsyReqHandle aTsyReqHandle)
+	{
+	iHangUpFax->CancelCommand(aTsyReqHandle);
+	return KErrNone;
+	}
+
+TInt CCallMobileFax::RelinquishOwnership()
+//
+//	Called by server to tell TSY to either pass ownership on to another interested client
+//	or hang up immediately
+//
+	{
+	LOGTEXT(_L8("FaxCall:\tRelinquish Ownership"));
+	if(iList->iAcquireList.IsEmpty()) 
+		{
+		if (iDialFax->IsPreConnectInProgress()	  ||
+			iConnectFax->IsPreConnectInProgress() ||
+			iAnswerFax->IsPreConnectInProgress())	// fax server has not yet been started
+			{
+			iCallInfo.iClientPanicOccurred = EPanicOccurredWithoutDataPortLoan;
+			return KErrNone;
+			}
+		(void)SetUnowned();
+		TInt ret = KErrNone;
+		if (iCallInfo.iMobileStatus==RMobileCall::EStatusDialling		||
+			 iCallInfo.iMobileStatus==RMobileCall::EStatusConnecting	||
+			 iCallInfo.iMobileStatus==RMobileCall::EStatusAnswering		||
+			 iCallInfo.iMobileStatus==RMobileCall::EStatusConnected		||
+			 iCallInfo.iMobileStatus==RMobileCall::EStatusDisconnecting
+			 )
+			{
+			LOGTEXT(_L8("FaxCall:\tHanging up"));
+			ChangeLineStatus(RCall::EStatusHangingUp);
+			// EStatusDisconnecting always results in KErrNone return
+			(void)ChangeCallStatus(RMobileCall::EStatusDisconnecting);
+			CleanUpFaxServer();
+			ChangeLineStatus(RCall::EStatusIdle);
+			// EStatusIdle always results in KErrNone return
+			(void)ChangeCallStatus(RMobileCall::EStatusIdle);
+			iPhoneGlobals->iPhoneStatus.iMode = RPhone::EModeIdle;
+			iIo->Cancel();
+			TCommConfig aConfigPckg;
+			TInt ret = iPhoneGlobals->iConfiguration->PortConfig(aConfigPckg,EConfigTypeInit);
+			if (ret==KErrNone)
+				ret = iIo->ConfigurePort(aConfigPckg);
+			if (ret)
+				iPhoneGlobals->iPhoneStatus.iInitStatus = EPhoneNotInitialised;
+			else
+				iIo->Read();			// should a read be queued in this case?
+			}
+		RelinquishOwnershipCompleted(ret);
+		return KErrNone;
+		}
+	CAcquireEntry* entry=iList->iAcquireList.First();
+	if (entry) 
+		{
+		(void)SetOwnership(entry->iTsyReqHandle);
+		ReqCompleted(entry->iTsyReqHandle,KErrNone);
+		iList->Remove(entry);
+		}
+	RelinquishOwnershipCompleted(KErrNone);
+	return KErrNone;
+	}
+
+TInt CCallMobileFax::GetFaxSettings(const TTsyReqHandle aTsyReqHandle,RCall::TFaxSessionSettings* aSettings)
+//
+//	Which are stored privately in CCallMobileFax
+//
+	{	
+	LOGTEXT(_L8("FaxCall:\tGetting fax settings"));
+	SetFaxSessionSettings(*aSettings,iFaxSettings);
+	ReqCompleted(aTsyReqHandle,KErrNone);
+	return KErrNone;
+	}
+
+TInt CCallMobileFax::SetFaxSettings(const TTsyReqHandle aTsyReqHandle,const RCall::TFaxSessionSettings* aSettings)
+	{	
+	LOGTEXT(_L8("FaxCall:\tSetting fax settings"));
+	TUint phoneCaps = iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags;
+	if (aSettings->iFaxClass==EClass1 && (phoneCaps&RPhone::KCapsFaxClassOne) ||
+		aSettings->iFaxClass==EClass2 && (phoneCaps&RPhone::KCapsFaxClassTwo) ||
+		aSettings->iFaxClass==EClass2point0 && (phoneCaps&RPhone::KCapsFaxClassTwoPointZero) ||
+		aSettings->iFaxClass==EClass1point0 && (phoneCaps&RPhone::KCapsFaxClassOnePointZero) ||
+		aSettings->iFaxClass==EClass2point1 && (phoneCaps&RPhone::KCapsFaxClassTwoPointOne)  ||
+		aSettings->iFaxClass==EClassAuto)
+		{
+		SetFaxSessionSettings(iFaxSettings,*aSettings);
+		ReqCompleted(aTsyReqHandle,KErrNone);
+		}
+	else if (iPhoneGlobals->iPhoneStatus.iInitStatus!=EPhoneInitialised)
+		ReqCompleted(aTsyReqHandle,KErrEtelUnknownModemCapability);
+	else
+		ReqCompleted(aTsyReqHandle,KErrNotSupported);
+	return KErrNone;
+	}
+
+TInt CCallMobileFax::SetFaxSharedHeaderFile(const TTsyReqHandle aTsyReqHandle, CFaxSharedFileHandles* aFaxSharedFileHandles)
+	{
+	//if we already own an object delete and re-point to new one.
+	if(iFileHandles)
+		{
+		delete iFileHandles;
+		iFileHandles = NULL;
+		}
+	iFileHandles = aFaxSharedFileHandles;	
+
+	ReqCompleted(aTsyReqHandle,KErrNone);	
+	return KErrNone;
+	}
+
+CTelObject* CCallMobileFax::OpenNewObjectByNameL(const TDesC& /*aName*/)
+//
+//	Only want one CFaxHayes object to be opened per phone.
+//	Previously only the connected call could open a CFaxHayes object, so it was easy to check
+//	whether one had already been opened. Now a fax call can open a fax object at any time
+//	making it less clear how to check that no other call has opened one.
+//
+	{
+	if (iPhoneGlobals->iPhoneStatus.iLineStatus != GetCoreCallStatus())
+		{	// ie another fax call is in progress so this call cannot open a fax object
+		User::Leave(KErrEtelNotCallOwner);
+		}
+	TBool& faxOpened = REINTERPRET_CAST(CLineMobileFax*,Owner())->iFaxOpened;
+	if (faxOpened==TRUE)
+		{
+		User::Leave(KErrAlreadyExists);
+		}
+	faxOpened=ETrue;
+	iFax = CFaxHayes::NewL(this,iPhoneGlobals);
+	return iFax;
+	}
+
+void CCallMobileFax::RemoveFax(CFaxHayes* aFaxHayes)
+	{
+	if (iFax == aFaxHayes)
+		iFax=NULL;
+	REINTERPRET_CAST(CLineMobileFax*,Owner())->iFaxOpened=EFalse;
+	}
+
+void CCallMobileFax::CleanUpFaxServer()
+	{
+	LOGTEXT(_L8("Closing down Fax Server"));
+	(void)iFaxSession->FxClose();
+	iFaxServerLib.Close();
+	iFaxSession = NULL;
+	iPhoneGlobals->iPhoneStatus.iPortAccess = EPortAccessAllowed; 
+	iPhoneGlobals->iEventSignalActive = EFalse;				
+	}