telephonyserverplugins/simtsy/src/CSimVoiceCall.cpp
branchopencode
changeset 24 6638e7f4bd8f
parent 0 3553901f7fa8
--- a/telephonyserverplugins/simtsy/src/CSimVoiceCall.cpp	Mon May 03 13:37:20 2010 +0300
+++ b/telephonyserverplugins/simtsy/src/CSimVoiceCall.cpp	Thu May 06 15:10:38 2010 +0100
@@ -1,1171 +1,1171 @@
-// Copyright (c) 2001-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:
-// This file contains the implementation of the Simulator TSY Voice Call functionality.  
-// The Call classes process the Call-based requests made by ETel clients 
-// and passed down to the TSY by the ETel Server.
-// 
-//
-
-/**
- @file
-*/
-
-#include <testconfigfileparser.h>
-
-#include "CSimVoiceCall.h"
-#include "CSimPhone.h"
-#include "CSimDtmf.h"
-#include "Simlog.h"
-#include "CSimTsyMode.h"
-
-CSimVoiceCall* CSimVoiceCall::NewL(CSimLine* aLine,const TDesC& aName, CSimPhone* aPhone)
-/**
-* Standard two phase constructor.
-*
-* @param aLine pointer to the Line object.
-* @param aName name of the call to be constructed
-* @return CSimVoiceCall  pointer to the voice call object created
-* @leave Leaves if no memory or object is not created for any reason
-*/
-	{
-	CSimVoiceCall* voiceCall=new(ELeave) CSimVoiceCall(aLine,aName,aPhone);
-	TCleanupItem newCallVoiceClose(CloseCall,voiceCall);
-	CleanupStack::PushL(newCallVoiceClose);
-	voiceCall->ConstructL();
-	CleanupStack::Pop();
-	return voiceCall;
-	}
-
-CSimVoiceCall::CSimVoiceCall(CSimLine* aLine,const TDesC& aName, CSimPhone* aPhone)
-	: CSimCall(aLine,aName,aPhone)
-/**
-* Trivial constructor. Calls CSimCall to initialise its members
-*/
-	{
-	}
-
-void CSimVoiceCall::ConstructL()
-/**
-* Second phase of 2-Phase Constructor
-* Retrieves all the pausing duration tags from the config file
-*
-* @param aName name of the voice call to be constructed
-*/
-	{
-	LOGVOICE1("Starting to parse Voice Call config parameters...");
-	iCaps=Caps();
-	iDiallingPause=iLine->CfgFile()->ItemValue(KDiallingPauseDuration,KDefaultDiallingPauseDuration);
-	iConnectingPause=iLine->CfgFile()->ItemValue(KConnectingPauseDuration,KDefaultConnectingPauseDuration);
-	iDisconnectingPause=iLine->CfgFile()->ItemValue(KDisconnectingPauseDuration,KDefaultDisconnectingPauseDuration);
-	iAnswerIncomingPause=iLine->CfgFile()->ItemValue(KAnswerIncomingPauseDuration,KDefaultAnswerIncomingPauseDuration);
-	iRemoteHangupPause=iLine->CfgFile()->ItemValue(KRemoteHangupPauseDuration,KDefaultRemoteHangupPauseDuration);
-
-	iTimer=CSimTimer::NewL(iLine->iPhone);
-	CSimCall::ConstructL();
-	
-	//If present read in remote party info tag
-	TPtrC8 callingname, remotenumber;
-	TInt delay=0;
-	const CTestConfigItem* item=NULL;
-	item=iLine->CfgFile()->Item(KNotifyRemotePartyInfo);
-	TInt ret;
-	if (item)
-		{
-		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,delay);
-		if(ret!=KErrNone)
-			{
-			LOGPARSERR("delay",ret,0,&KNotifyRemotePartyInfo);
-			}
-		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,callingname);
-		if(ret!=KErrNone)
-			{
-			LOGPARSERR("callingname",ret,1,&KNotifyRemotePartyInfo);
-			}
-		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,remotenumber);
-		if(ret!=KErrNone)
-			{
-			LOGPARSERR("remotenumber",ret,2,&KNotifyRemotePartyInfo);
-			}
-		
-		iNotifyRemotePartyInfoTimer->iDelay = delay;
-		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iDirection = RMobileCall::EDirectionUnknown;
-		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iCallingName.Copy(callingname);
-		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iTelNumber.Copy(remotenumber);	
-		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iTypeOfNumber = RMobilePhone::EInternationalNumber;
-		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iNumberPlan = RMobilePhone::EIsdnNumberPlan;
-		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus = RMobileCall::ERemoteIdentityAvailable;					
-		}
-	else
-		{
-		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus = RMobileCall::ERemoteIdentityUnknown;
-		}
-	
-	LOGVOICE1("...Finished parsing Voice Call config parameters...");
-	}
-
-CSimVoiceCall::~CSimVoiceCall()
-/**
-* Destroy all the objects constructed.
-* CSimTimer and CSimSysAgent objects are destroyed here
-*/
-	{
-	delete iTimer;
-	if(iAnswerIncomingCall.iNotifyPending)
-		iLine->ResetAutoAnswerCallObject(this);
-	}
-
-TInt CSimVoiceCall::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc,const TDataPackage& aPackage)
-/**
-* ExtFunc is called by the server when it has a "extended", i.e. non-core ETel request 
-* for the TSY to process
-* A request handle, request type and request data are passed to the TSY
-*
-* @param aTsyReqHandle
-* @param aIpc IPc number representing the request
-* @param aPackage data for the request
-* @return KErrNone
-*/
-	{
-	TAny* dataPtr=aPackage.Ptr1();
-
-	// The request data has to extracted from TDataPackage and the TAny* pointers have to
-	// be "cast" to the expected request data type
-
-	switch (aIpc)
-		{
-	//
-	// No Flow Control NOR Multiple Completion
-	//
-	case EMobileCallGetMobileCallCaps:
-		return GetMobileCallCaps(aTsyReqHandle,aPackage.Des1n());
-
-	case EMobileCallGetMobileCallStatus:
-		return GetMobileCallStatus(aTsyReqHandle,
-			REINTERPRET_CAST(RMobileCall::TMobileCallStatus*,dataPtr));
-
-	case EMobileCallGetMobileCallInfo:
-		return GetMobileCallInfo(aTsyReqHandle,aPackage.Des1n());
-
-	case EMobileCallDialEmergencyCall:
-		return DialEmergencyCall(aTsyReqHandle,aPackage.Des1u());
-
-	case EMobileCallHold:
-		return Hold(aTsyReqHandle);
-
-	case EMobileCallResume:
-		return Resume(aTsyReqHandle);
-
-	case EMobileCallSwap:
-		return Swap(aTsyReqHandle);
-	
-	case EMobileCallDialISV:
-		return DialISV(aTsyReqHandle, aPackage.Des1n(), aPackage.Des2u());
-
-	case EMobileCallAnswerISV:
-		TInt retVal;
-		TRAPD(errVal, retVal=AnswerIncomingCallISVL(aTsyReqHandle, aPackage.Des1n()));
-		if (errVal != KErrNone)
-			{
-			return errVal;
-			}
-		else
-			{
-			return retVal;	
-			}
-		
-	//
-	// Multiple Completion Services with Immediate Server Repost
-	// (Usually Notifications)
-	//
-	case EMobileCallNotifyMobileCallStatusChange:
-		return NotifyMobileCallStatusChange(aTsyReqHandle,
-			REINTERPRET_CAST(RMobileCall::TMobileCallStatus*, dataPtr));
-
-	case EMobileCallNotifyMobileCallCapsChange:
-		return NotifyMobileCallCapsChange(aTsyReqHandle, aPackage.Des1n());
-		
-	case EMobileCallNotifyRemotePartyInfoChange:
-		return NotifyRemotePartyInfoChange(aTsyReqHandle, aPackage.Des1n());		
-
-	default:
-		break;
-		}
-	return KErrNotSupported;
-	}
-
-TInt CSimVoiceCall::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
-/**
- * Cancel an outstanding request.
- * @param aIpc The IPC number of the request that must be cancelled.  Note: this is not the
- *             IPC number of the cancel request itself.
- * @param aTsyReqHandle The TSY Request Handle of the request to be cancelled.
- */
-	{
-	switch(aIpc)
-		{
-	case EMobileCallNotifyMobileCallStatusChange:
-		return NotifyMobileCallStatusChangeCancel(aTsyReqHandle);
-
-	case EMobileCallNotifyMobileCallCapsChange:
-		return NotifyMobileCallCapsChangeCancel(aTsyReqHandle);
-
-	case EMobileCallDialEmergencyCall:
-		return DialEmergencyCallCancel(aTsyReqHandle);
-
-	case EMobileCallHold:
-		return HoldCancel(aTsyReqHandle);
-
-	case EMobileCallResume:
-		return ResumeCancel(aTsyReqHandle);
-
-	case EMobileCallSwap:
-		return SwapCancel(aTsyReqHandle);
-		
-	case EMobileCallNotifyRemotePartyInfoChange:
-		return NotifyRemotePartyInfoChangeCancel();
-		
-	case EMobileCallDialISV:
-		return DialISVCancel(aTsyReqHandle);
-		
-	case EMobileCallAnswerISV:
-		return AnswerIncomingCallISVCancel(aTsyReqHandle);       
-	default:
-		break;
-		}
-
-	return CCallBase::CancelService(aIpc,aTsyReqHandle);
-	}
-
-TInt CSimVoiceCall::DialEmergencyCall(const TTsyReqHandle aTsyReqHandle,TDesC* aTelNumber)
-/**
-* Process a client's emergency call request.
-*
-* @param aTsyReqHandle
-* @param aTelNumber The telephone number to dial
-* @return KErrNone
-*/
-	{
-	return Dial(aTsyReqHandle,NULL,aTelNumber);
-	}
-
-TInt CSimVoiceCall::DialEmergencyCallCancel(const TTsyReqHandle aTsyReqHandle)
-/**
-* Cancels an emergency call request.
-*
-* @param aTsyReqHandle
-* @return KErrNone if successfully cancelled
-*/
-	{
-	return DialCancel(aTsyReqHandle);
-	}
-
-TInt CSimVoiceCall::Dial(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* /*aTelNumber*/)
-/**
-* Process a client's dial request.
-*
-* @param aTsyReqHandle
-* @param aCallParams  the call parameters
-* @param aTelNumber The telephone number to dial
-* @return KErrNone
-*/
-	{
-	LOGVOICE1(">>CSimVoiceCall::Dial");
-	// Note: The telephone number and call parameters should be validated against config file
-	//       values here.
-	
-	//see where the dial request has orignated from
-	if(aCallParams)
-		{
-		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
-		RCall::TCallParams& callparams=(*callparamsPckg)();
-		
-		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
-			{
-			LOGVOICE1("<<CSimVoiceCall::Dial request from Etel 3rd Party client.");
-			}
-		}
-
-	iDialRequestHandle=aTsyReqHandle;
-	TInt ret;
-	ret = ActionEvent(ECallEventDial,KErrNone);
-	LOGVOICE1("<<CSimVoiceCall::Dial");
-	return ret;
-	}
-	
-TInt CSimVoiceCall::DialCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancels a dial Request
-*
-* @param aTsyReqHandle
-* @return KErrNone if successfully cancelled
-*/
-	{
-	LOGVOICE1(">>CSimVoiceCall::DialCancel");
-	switch(iState)
-		{
-	case RMobileCall::EStatusIdle:
-		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
-		break;
-
-	case RMobileCall::EStatusDialling:
-	case RMobileCall::EStatusConnecting:
-		iTimer->DoCancel();
-		// Can ignore for cancel
-		TInt err;
-		err = KErrNone;
-		TRAP(err, (void)ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
-		if (err != KErrNone)
-			{
-			ReqCompleted(iDialRequestHandle, err);
-			}
-		else
-			{
-			ReqCompleted(iDialRequestHandle, KErrCancel);
-			}
-		break;
-
-	case RMobileCall::EStatusConnected:
-		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
-		break;
-
-	default:
-		break;
-		}
-	LOGVOICE1("<<CSimVoiceCall::DialCancel");
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::DialISV(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* /*aTelNumber*/)
-/**
-* Process an EtelISV client's dial request.
-*
-* @param aTsyReqHandle
-* @param aCallParams  the call parameters
-* @param aTelNumber The telephone number to dial
-* @return KErrNone
-*/
-	{
-	LOGVOICE1(">>CSimVoiceCall::DialISV");
-	// Note: The telephone number and call parameters should be validated against config file
-	//       values here.
-	
-	//see where the dial request has orignated from
-	if(aCallParams)
-		{
-		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
-		RCall::TCallParams& callparams=(*callparamsPckg)();
-		
-		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
-			{
-			LOGVOICE1("<<CSimVoiceCall::Dial request from Etel 3rd Party client.");
-			}
-		}
-
-	iDialRequestHandle=aTsyReqHandle;
-	TInt ret;
-	ret = ActionEvent(ECallEventDial,KErrNone);
-	LOGVOICE1("<<CSimVoiceCall::DialISV");
-	return ret;
-	}
-
-TInt CSimVoiceCall::DialISVCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancels an EtelISV originated dial Request
-*
-* @param aTsyReqHandle
-* @return KErrNone if successfully cancelled
-*/
-	{
-	LOGVOICE1(">>CSimVoiceCall::DialISVCancel");
-	switch(iState)
-		{
-	case RMobileCall::EStatusIdle:
-		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
-		break;
-
-	case RMobileCall::EStatusDialling:
-	case RMobileCall::EStatusConnecting:
-		iTimer->DoCancel();
-		// Can ignore for cancel
-		TInt err;
-		err = KErrNone;
-		TRAP(err, (void)ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
-		if (err != KErrNone)
-			{
-			ReqCompleted(iDialRequestHandle, err);
-			}
-		else
-			{
-			ReqCompleted(iDialRequestHandle, KErrCancel);
-			}
-		break;
-
-	case RMobileCall::EStatusConnected:
-		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
-		break;
-
-	default:
-		break;
-		}
-	LOGVOICE1("<<CSimVoiceCall::DialISVCancel");
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::AnswerIncomingCall(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
-/**
-* Register a client's interest in answering the next incoming call.
-* First register interest in incoming calls with the line, then, if a call
-* is already ringing, start the answer procedure.
-*
-* @param aTsyReqHandle
-* @param aCallParams  the call parameters
-* @return KErrNone
-*/
-	{
-	LOGVOICE3(">>CSimVoiceCall::AnswerIncomingCall  0x%08x, state %d entry ",this,iState);
-	
-	//see where the answer request has orignated from
-	if(aCallParams)
-		{
-		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
-		RCall::TCallParams& callparams=(*callparamsPckg)();
-		
-		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
-			{
-			LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCall request from Etel 3rd Party client.");
-			}
-		}
-	
-	TInt ret=iLine->SetAutoAnswerCallObject(this);
-	if(ret!=KErrNone)
-		{
-		ReqCompleted(aTsyReqHandle,ret);
-		return KErrNone;
-		}
-
-	iAnswerIncomingCall.iNotifyPending=ETrue;
-	iAnswerIncomingCall.iNotifyHandle=aTsyReqHandle;
-
-	if(iState==RMobileCall::EStatusRinging)
-			ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);	
-	else if(iLine->iState==RMobileCall::EStatusRinging)
-		{		
-		TRAPD(errVal, ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
-		if (errVal != KErrNone)
-			{
-			ret = errVal;
-			}
-
-		if(ret==KErrNone)
-			ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);		
-		}
-	LOGVOICE3("<<CSimVoiceCall::AnswerIncomingCall  0x%08x, state %d exit",this,iState);
-	return ret;
-	}
-
-TInt CSimVoiceCall::AnswerIncomingCallCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancels a AnswerIncomingCall Request
-*
-* @param aTsyReqHandle
-* @return KErrNone if successfully cancelled
-*/
-	{
-	LOGVOICE1(">>CSimVoiceCall::AnswerIncomingCallCancel");
-	if(iAnswerIncomingCall.iNotifyPending)
-		{
-		iAnswerIncomingCall.iNotifyPending=EFalse;
-		iLine->ResetAutoAnswerCallObject(this);
-		ReqCompleted(iAnswerIncomingCall.iNotifyHandle,KErrCancel);
-		}
-	LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCallCancel");
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::AnswerIncomingCallISVL(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
-/**
-* Register an EtelISV client's interest in answering the next incoming call.
-* First register interest in incoming calls with the line, then, if a call
-* is already ringing, start the answer procedure.
-*
-* @param aTsyReqHandle
-* @param aCallParams  the call parameters
-* @return KErrNone
-*/
-	{
-	LOGVOICE3(">>CSimVoiceCall::AnswerIncomingCallISV  0x%08x, state %d entry ",this,iState);
-	
-	//see where the answer request has orignated from
-	if(aCallParams)
-		{
-		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
-		RCall::TCallParams& callparams=(*callparamsPckg)();
-		
-		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
-			{
-			LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCallISV request from Etel 3rd Party client.");
-			}
-		}
-	
-	TInt ret=iLine->SetAutoAnswerCallObject(this);
-	if(ret!=KErrNone)
-		{
-		ReqCompleted(aTsyReqHandle,ret);
-		return KErrNone;
-		}
-
-	iAnswerIncomingCall.iNotifyPending=ETrue;
-	iAnswerIncomingCall.iNotifyHandle=aTsyReqHandle;
-
-	if(iState==RMobileCall::EStatusRinging)
-			ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);	
-	else if(iLine->iState==RMobileCall::EStatusRinging)
-			{
-			TRAPD(leaveValue, ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
-			if (leaveValue != KErrNone)
-				{
-				return leaveValue;
-				}
-
-			if (ret == KErrNone)
-                {
-				ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);		
-	 		    }		
-		}
-	LOGVOICE3("<<CSimVoiceCall::AnswerIncomingCallISV  0x%08x, state %d exit",this,iState);
-	return ret;
-	}
-
-TInt CSimVoiceCall::AnswerIncomingCallISVCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancels an EtelISV originated AnswerIncomingCall Request
-*
-* @param aTsyReqHandle
-* @return KErrNone if successfully cancelled
-*/
-	{
-	LOGVOICE1(">>CSimVoiceCall::AnswerIncomingCallISVCancel");
-	if(iAnswerIncomingCall.iNotifyPending)
-		{
-		iAnswerIncomingCall.iNotifyPending=EFalse;
-		iLine->ResetAutoAnswerCallObject(this);
-		ReqCompleted(iAnswerIncomingCall.iNotifyHandle,KErrCancel);
-		}
-	LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCallISVCancel");
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::Connect(const TTsyReqHandle aTsyReqHandle,const TDesC8* /*aCallParams*/)
-	{
-	ReqCompleted(aTsyReqHandle,KErrNotSupported);
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::ConnectCancel(const TTsyReqHandle aTsyReqHandle)
-	{
-	ReqCompleted(aTsyReqHandle,KErrNotSupported);
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::HangUp(const TTsyReqHandle aTsyReqHandle)
-/**
-* Process a client's HangUp request.
-*
-* @param aTsyReqHandle
-* @return KErrNone
-*/
-	{
-	LOGVOICE1(">>CSimVoiceCall::HangUp");
-	iHangUpRequestHandle=aTsyReqHandle;
-	TInt ret=ActionEvent(ECallEventHangUp,KErrNone);
-	if(ret!=KErrNone)
-		ReqCompleted(aTsyReqHandle,ret);
-	LOGVOICE1("<<CSimVoiceCall::HangUp");
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::HangUpCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancels a HangUp Request
-*
-* @param aTsyReqHandle
-* @return KErrNone if successfully cancelled
-*/
-	{
-	LOGVOICE1(">>CSimVoiceCall::HangUpCancel");
-	switch(iState)
-		{
-	case RMobileCall::EStatusIdle:
-		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
-		break;
-
-	case RMobileCall::EStatusDisconnecting:
-		iTimer->DoCancel();
-		// Can ignore for cancel
-		TInt err;
-		err = KErrNone;
-		TRAP(err, (void)ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
-		if (err != KErrNone)
-			{
-			ReqCompleted(iHangUpRequestHandle, err);
-			}
-		else
-			{
-			ReqCompleted(iHangUpRequestHandle, KErrCancel);
-			}
-		break;
-
-	default:
-		break;
-		}
-	LOGVOICE1("<<CSimVoiceCall::HangUpCancel");
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::RelinquishOwnership()
-	{
-	return KErrNotSupported;
-	}
-
-TInt CSimVoiceCall::GetBearerServiceInfo(const TTsyReqHandle aTsyReqHandle,RCall::TBearerService* /*aBearerService*/)
-/**
-* Retrieves the bearer service info
-* Not supported for voice calls
-*/
-	{
-	ReqCompleted(aTsyReqHandle,KErrNotSupported);
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::GetCallParams(const TTsyReqHandle aTsyReqHandle, TDes8* /*aParams*/)
-/**
-* Retrives the call parameters
-* Not supported for voice calls
-*/
-	{
-	ReqCompleted(aTsyReqHandle,KErrNotSupported);
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::LoanDataPort(const TTsyReqHandle,RCall::TCommPort*)
-/**
-* Loans the comm port.
-* This is a data call specific request so not supported here.
-*/
-	{
-	return KErrNotSupported;
-	}
-/**
-* Cancels the LoanDataPort request.
-* This is a data call specific request so not supported here.
-*/
-
-TInt CSimVoiceCall::LoanDataPortCancel(const TTsyReqHandle)
-	{
-	return KErrNotSupported;
-	}
-
-TInt CSimVoiceCall::RecoverDataPort(const TTsyReqHandle)
-/**
-* Recovers the comm port.
-* This is a data call specific request so not supported here.
-*/
-	{
-	return KErrNotSupported;
-	}
-
-TInt CSimVoiceCall::Hold(const TTsyReqHandle aReqHandle)
-/**
- * Put the call on hold.
- * @param aReqHandle	The request handle associated with this call.
- * @return TInt			Standard error value.
- */
-	{
-	if(iState!=RMobileCall::EStatusConnected)
-		{
-		ReqCompleted(aReqHandle,KErrEtelCallNotActive);
-		return KErrNone;
-		}
-	iHoldResumeRequestHandle=aReqHandle;
-	TInt ret=ActionEvent(ECallEventHold,KErrNone);
-	return ret;
-	}
-
-TInt CSimVoiceCall::HoldCancel(const TTsyReqHandle)
-/**
- * Cancel a Hold request.  Since hold is completed synchronously, this function is empty.
- */
-	{
-	return KErrNone;
-	}
-	
-/**
- * Cancel a NotifyConnectConfirmation request. It is possible to cancel
- * a pending notification if the client did not issue a Dial request.
- * @param aReqHandle	The request handle associated with this call.
- */
-TInt CSimVoiceCall::NotifyConnectConfirmationCancel(const TTsyReqHandle aReqHandle)
-	{
-	if (iNotifyConnectConfirmReqHandle==aReqHandle)
-		{
-		iNotifyConnectConfirmReqHandle = NULL;
-		}
-	ReqCompleted(aReqHandle,KErrCancel);
-	return KErrNone;
-	}
-
-/**
- * Resume a pending MO Connection.
- * @param aReqHandle	The request handle associated with this call.
- * @param aConnectContinue	Boolean to indicate whether to continue/terminate 
- *							the call connection.
- * @return TInt			Standard error value.
- */
-TInt CSimVoiceCall::ResumeConnect(const TTsyReqHandle aReqHandle, const TBool * aConnectContinue)
-	{
-	TInt ret=KErrNone;
-	
-	if(iWaitForConnectConfirm)
-		{
-		// synchronous operation for either case
-		if (*aConnectContinue)
-			{
-			// okay to continue, initiate dialing, this will
-			// change the state
-			ret=ActionEvent(ECallEventConnectContinue,KErrNone);
-			}
-		else
-			{
-			// terminate the call...
-	
-			// there must be a dial request previously issue,
-			// but we never send the dial request down to call-stack,
-			// and we did not invoke the dial timer, so it will
-			// never expire, so we complete the dial request here
-			ReqCompleted(iDialRequestHandle,KErrNone);
-			}
-			
-		// complete the resume request
-		ReqCompleted(aReqHandle,ret);
-		}
-	else
-		{
-		// client did not issue dial request previously, this request
-		// is received in the wrong state, reject this request
-		ReqCompleted(aReqHandle,KErrAccessDenied);
-		}
-	return ret;
-	}
-	
-/**
- * Cancel a ResumeConnect request.  Since resume is completed synchronously, this function is empty.
- */
-TInt CSimVoiceCall::ResumeConnectCancel(const TTsyReqHandle)
-	{
-	return KErrNone;
-	}
-
-
-TInt CSimVoiceCall::Resume(const TTsyReqHandle aReqHandle)
-/**
- * Put the call on resume.
- * @param aReqHandle	The request handle associated with this call.
- * @return TInt			Standard error value.
- */
-	{
-	if(iState!=RMobileCall::EStatusHold)
-		{
-		ReqCompleted(aReqHandle,KErrAccessDenied);
-		return KErrNone;
-		}
-	iHoldResumeRequestHandle=aReqHandle;
-	TInt ret=ActionEvent(ECallEventResume,KErrNone);
-	return ret;
-	}
-
-
-TInt CSimVoiceCall::ResumeCancel(const TTsyReqHandle)
-/**
- * Cancel a Resume request.  Since resume is completed synchronously, this function is empty.
- */
-	{
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::Swap(const TTsyReqHandle aReqHandle)
-/**
- * If the call is active, put it on hold.  If its on hold, resume it.
- * @param aReqHandle	The request handle associated with this call.
- * @return TInt			Standard error value.
- */
-	{
-	TCallEvent event;
-	if(iState==RMobileCall::EStatusConnected)
-		{
-		event=ECallEventHold;		
-		}
-	else if(iState==RMobileCall::EStatusHold)
-		{	
-		event=ECallEventResume;
-		}
-	else
-		{
-		ReqCompleted(aReqHandle,KErrEtelCallNotActive);
-		return KErrNone;
-		}
-
-	iHoldResumeRequestHandle=aReqHandle;
-	TInt ret=ActionEvent(event,ECallEventSwap);	
-	return ret;
-	}
-
-TInt CSimVoiceCall::SwapCancel(const TTsyReqHandle)
-/**
- * Cancel a Swap request.  Since swap is completed synchronously, this function is empty.
- */
-	{
-	return KErrNone;
-	}
-
-TInt CSimVoiceCall::ActionEvent(TCallEvent aEvent,TInt aOtherArgument)
-/**
-* Entry point when an event has occured that may advance the state machine.
-* The aEvent parameter describes the event.
-*
-* This function contains the main state machine for the voice call.  The outer layer
-* switches on the event type.  Where appropriate, there are inner layer switches
-* or conditional statements to handle the different responses that may be required to
-* the same event occurring in different states.
-*
-* @param aEvent The Call event to handle
-* @return value represents the error state caused by the attempted state machine jump.
-*/
-	{
-	TInt ret=KErrNone;
-	__ASSERT_ALWAYS(iState!=RMobileCall::EStatusUnknown,SimPanic(ECallStatusUnknownIllegal));
-	__ASSERT_ALWAYS(aEvent!=ECallEventNtRasConnected,SimPanic(ECallEventIllegal));
-	LOGVOICE3(">>CSimVoiceCall::ActionEvent 0x%08x %d",this,iState);
-
-	switch(aEvent)
-		{
-	case ECallEventDial:
-		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventDial]");
-		if(iState==RMobileCall::EStatusIdle)
-			{			
-			TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusDialling,EFalse,EFalse));
-			if(ret==KErrNone)
-				iTimer->Start(iDiallingPause,this);
-			}
-		else
-			return KErrEtelCallAlreadyActive;
-		break;
-
-	case ECallEventHangUp:
-		{
-		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventHangUp]");
-		switch(iState)
-			{
-		case RMobileCall::EStatusDialling:
-		case RMobileCall::EStatusRinging:
-		case RMobileCall::EStatusAnswering:
-		case RMobileCall::EStatusConnecting:
-		case RMobileCall::EStatusConnected:
-		case RMobileCall::EStatusHold:
-			TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusDisconnecting,EFalse,EFalse));
-			if(ret==KErrNone)
-				iTimer->Start(iDisconnectingPause,this);
-			if(iSimDtmf)
-				{
-				iSimDtmf->CallClosureCallback();
-				iSimDtmf=NULL;
-				}
-			break;
-		default:
-			return KErrEtelCallNotActive;
-			}
-		}
-		break;
-
-	case ECallEventIncomingCall:
-		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventIncomingCall]");
-		if(iState==RMobileCall::EStatusIdle)
-			{
-			if(iAnswerIncomingCall.iNotifyPending)
-				{
-				TRAP(ret,	 ret=ProcessAnswerIncomingCallL());
-				}
-			else
-				{
-				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
-				if(ret!=KErrNone)
-					return ret;
-				}
-			}
-		else
-			return KErrEtelCallAlreadyActive;
-		break;
-
-	case ECallEventAnswerIncoming:
-		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventAnswerIncoming]");
-		if(iState==RMobileCall::EStatusRinging)
-			{
-			TRAP(ret, ret=ProcessAnswerIncomingCallL());
-			if(ret!=KErrNone)
-				{
-				return ret;
-				}
-			}
-		else
-			SimPanic(EIllegalStateInconsistancy);		// This is checked before calling ActionEvent
-		break;
-
-	case ECallEventRemoteHangup:
-		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventRemoteHangup]");
-		if(iState==RMobileCall::EStatusConnected)
-			{
-			TRAP(ret, ret=ProcessRemoteHangupL());
-			if(ret!=KErrNone)
-				{
-				return ret;
-				}
-			}
-		else
-			SimPanic(EIllegalStateInconsistancy);		// This is checked before calling ActionEvent
-		break;
-
-	case ECallEventTimeOut:
-			{
-			LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventTimeOut]");
-			switch(iState)
-				{
-			case RMobileCall::EStatusDialling:
-				LOGVOICE1(">>CSimVoiceCall::State = [EStatusDialling]");
-				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnecting,EFalse,EFalse));
-				if(ret==KErrNone)
-					iTimer->Start(iConnectingPause,this);
-				return ret;
-			
-			case RMobileCall::EStatusConnecting:
-				LOGVOICE1(">>CSimVoiceCall::State = [EStatusConnecting]");
-				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
-				UpdateRemotePartyInfoDirection(RMobileCall::EStatusConnecting);
-				ReqCompleted(iDialRequestHandle,ret);
-				return ret;
-				
-			case RMobileCall::EStatusDisconnecting:
-				LOGVOICE1(">>CSimVoiceCall::State = [EStatusDisconnecting]");
-				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
-				ReqCompleted(iHangUpRequestHandle,ret);
-				return ret;
-				
-			case RMobileCall::EStatusAnswering:
-				LOGVOICE1(">>CSimVoiceCall::State = [EStatusAnswering]");
-				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
-				UpdateRemotePartyInfoDirection(RMobileCall::EStatusAnswering);
-				ReqCompleted(iAnswerIncomingCall.iNotifyHandle,ret);
-				return ret;
-
-			default:
-				break;
-				}
-			}
-		break;
-	case ECallEventHold:
-		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventHold]");
-		__ASSERT_ALWAYS(iState==RMobileCall::EStatusConnected,SimPanic(EIllegalStateInconsistancy));
-		TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusHold,aOtherArgument == ECallEventSwap,EFalse));
-		if (ret == KErrNone)
-			ReqCompleted(iHoldResumeRequestHandle,ret);
-		break;
-
-	case ECallEventResume:
-		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventResume]");
-		__ASSERT_ALWAYS(iState==RMobileCall::EStatusHold,SimPanic(EIllegalStateInconsistancy));
-		TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,aOtherArgument == ECallEventSwap,EFalse));
-		if (ret == KErrNone)
-			ReqCompleted(iHoldResumeRequestHandle,ret);
-		break;
-
-	case ECallEventConnectContinue:
-		SimPanic(EIllegalVoiceCallEvent);	// All other events not legal for voice call.
-		break;
-	default:
-		SimPanic(EIllegalVoiceCallEvent);	// All other events not legal for voice call.
-		break;
-		}
-
-	return ret;
-	}
-
-
-void CSimVoiceCall::TimerCallBack(TInt /*aId*/)
-/**
-* Timer callback function.  When the timer goes off, it will call back into this
-* function for further processing.
-*/
-	{
-	LOGVOICE1(">>CSimVoiceCall::TimerCallBack");
-	TInt ret=ActionEvent(ECallEventTimeOut,KErrNone);
-	__ASSERT_ALWAYS(ret==KErrNone,SimPanic(ETimeOutEventActionFailed));
-	LOGVOICE1("<<CSimVoiceCall::TimerCallBack");
-	}
-
-TInt CSimVoiceCall::ProcessAnswerIncomingCallL()
-/**
-* Answers an Incoming Call.
-* First the call state must be changed to "answering", then the flag indicating
-* that an answer incoming call request is no longer pending.  Finally, a new
-* call object must be assigned to receive the details of the next incoming call.
-*/
-	{
-	LOGVOICE3(">>CSimVoiceCall::ProcessAnswerIncomingCall %d",iState,this);
-	TInt ret=ChangeStateL(RMobileCall::EStatusAnswering,EFalse,EFalse);
-	if(ret!=KErrNone)
-		return ret;
-	iTimer->Start(iAnswerIncomingPause,this);
-	iAnswerIncomingCall.iNotifyPending=EFalse;
-	iLine->ResetAutoAnswerCallObject(this);
-	LOGVOICE1("<<CSimVoiceCall::ProcessAnswerIncomingCall");
-	return ret;
-	}
-
-TInt CSimVoiceCall::ProcessRemoteHangupL()
-/**
-* Hangs up a call remotely.
-* First the call state must be changed to "disconnecting", then the flag indicating
-* that a remote hangup request is no longer pending.  Finally, a new
-* call object must be assigned to receive the next remote hangup request.
-*/
-	{
-	LOGVOICE3(">>CSimVoiceCall::ProcessRemoteHangupL %d",iState,this);
-	TInt ret=ChangeStateL(RMobileCall::EStatusDisconnecting,EFalse,EFalse);
-	if(ret!=KErrNone)
-		return ret;
-	iTimer->Start(iRemoteHangupPause,this);
-	iLine->ResetRemoteHangupCallObject(this);
-	LOGVOICE1("<<CSimVoiceCall::ProcessRemoteHangupL");
-	return ret;
-	}
-
-void CSimVoiceCall::SetDtmfSession(CSimDtmf* aSimDtmf)
-/**
- * Set the DTMF session pointer.
- */
-	{
-	__ASSERT_ALWAYS(iState==RMobileCall::EStatusConnected,SimPanic(EIllegalDtmfReq));
-	iSimDtmf=aSimDtmf;
-	}
-
-CSimDtmf* CSimVoiceCall::GetDtmfSession()
-/**
- * Retrieve the DTMF session pointer.
- */
-	{
-	return iSimDtmf;
-	}
-
-
-TUint CSimVoiceCall::Caps()
-/**
- * Return the current capabilities of this call.
- * @return TUint	Current call capabilities.
- */
-	{
-	TUint caps=RCall::KCapsVoice;
-	if(iState!=RMobileCall::EStatusIdle)
-		{
-		if(iState==RMobileCall::EStatusConnected)
-			{
-			caps |= RCall::KCapsHangUp;
-			// If there is only a single call and its state is connected then the hold capability 
-			// should be set.
-			// If there is more than one call then only the swap capability should be set as hold 
-			// and resume apply only to single calls.
-		
-			TInt i=0;
-			TBool singleCall = ETrue;
-			TInt count=	iLine->iCalls->Count();
-		
-			while(singleCall && i<count)
-				{
- 				if(iLine->iCalls->At(i) != this && (iLine->iCalls->At(i)->iState == RMobileCall::EStatusConnected || iLine->iCalls->At(i)->iState == RMobileCall::EStatusHold))
-					singleCall = EFalse;
-				i++;
-				}	
-			
-			if (singleCall)
-				caps |= RMobileCall::KCapsHold;
-			// Swap capability is applicable to single and multiple call
-			// scenarios
-			caps |= RMobileCall::KCapsSwap;
-			}
-		else if(iState==RMobileCall::EStatusHold)
-			{
-			caps |= RCall::KCapsHangUp;
-
-			TBool otherConnected = EFalse;
-			TInt count=	iLine->iCalls->Count();
-			TInt i=0;
-			while (!otherConnected && i<count)
-				{
- 				if(iLine->iCalls->At(i) != this && (iLine->iCalls->At(i)->iState == RMobileCall::EStatusConnected || iLine->iCalls->At(i)->iState == RMobileCall::EStatusHold))
-					otherConnected = ETrue;
-				i++;
-				}	
-			if(otherConnected)
-				{
-				caps |= RMobileCall::KCapsSwap;
-				}
-			else
-				{
-				caps |= RMobileCall::KCapsResume;
-				caps |= RMobileCall::KCapsSwap;
-				}					
-			}
-		else if (iState==RMobileCall::EStatusRinging)
-			{
-			if((iLine->IsAnswerCallObjectSpare()))
-				caps |= RCall::KCapsAnswer;	
-			}
-		}
-	else
-		{
-		if(iLine->iState==RMobileCall::EStatusIdle || iLine->iState==RMobileCall::EStatusHold)
-			{
-			caps |= RCall::KCapsDial;
-			if((iLine->IsAnswerCallObjectSpare()))
-				caps |= RCall::KCapsAnswer;
-			}
-		else if (iLine->iState==RMobileCall::EStatusRinging)
-			{
-			if((iLine->IsAnswerCallObjectSpare()))
-				caps |= RCall::KCapsAnswer;			
-			}
-		}
-	return caps;
-	}
-
-void CSimVoiceCall::UpdateRemotePartyInfoDirection(RMobileCall::TMobileCallStatus aPreviousStatus)
-/**
-Update the direction of the call for the remote party info member
-*/
-	{
-	if(iNotifyRemotePartyInfoTimer && iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus != RMobileCall::ERemoteIdentityUnknown)	
-		{
-		if(aPreviousStatus == RMobileCall::EStatusAnswering)
-			iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iDirection = RMobileCall::EMobileTerminated;
-		else
-			iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iDirection = RMobileCall::EMobileOriginated;
-		}			
-	}
+// Copyright (c) 2001-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:
+// This file contains the implementation of the Simulator TSY Voice Call functionality.  
+// The Call classes process the Call-based requests made by ETel clients 
+// and passed down to the TSY by the ETel Server.
+// 
+//
+
+/**
+ @file
+*/
+
+#include <testconfigfileparser.h>
+
+#include "CSimVoiceCall.h"
+#include "CSimPhone.h"
+#include "CSimDtmf.h"
+#include "Simlog.h"
+#include "CSimTsyMode.h"
+
+CSimVoiceCall* CSimVoiceCall::NewL(CSimLine* aLine,const TDesC& aName, CSimPhone* aPhone)
+/**
+* Standard two phase constructor.
+*
+* @param aLine pointer to the Line object.
+* @param aName name of the call to be constructed
+* @return CSimVoiceCall  pointer to the voice call object created
+* @leave Leaves if no memory or object is not created for any reason
+*/
+	{
+	CSimVoiceCall* voiceCall=new(ELeave) CSimVoiceCall(aLine,aName,aPhone);
+	TCleanupItem newCallVoiceClose(CloseCall,voiceCall);
+	CleanupStack::PushL(newCallVoiceClose);
+	voiceCall->ConstructL();
+	CleanupStack::Pop();
+	return voiceCall;
+	}
+
+CSimVoiceCall::CSimVoiceCall(CSimLine* aLine,const TDesC& aName, CSimPhone* aPhone)
+	: CSimCall(aLine,aName,aPhone)
+/**
+* Trivial constructor. Calls CSimCall to initialise its members
+*/
+	{
+	}
+
+void CSimVoiceCall::ConstructL()
+/**
+* Second phase of 2-Phase Constructor
+* Retrieves all the pausing duration tags from the config file
+*
+* @param aName name of the voice call to be constructed
+*/
+	{
+	LOGVOICE1("Starting to parse Voice Call config parameters...");
+	iCaps=Caps();
+	iDiallingPause=iLine->CfgFile()->ItemValue(KDiallingPauseDuration,KDefaultDiallingPauseDuration);
+	iConnectingPause=iLine->CfgFile()->ItemValue(KConnectingPauseDuration,KDefaultConnectingPauseDuration);
+	iDisconnectingPause=iLine->CfgFile()->ItemValue(KDisconnectingPauseDuration,KDefaultDisconnectingPauseDuration);
+	iAnswerIncomingPause=iLine->CfgFile()->ItemValue(KAnswerIncomingPauseDuration,KDefaultAnswerIncomingPauseDuration);
+	iRemoteHangupPause=iLine->CfgFile()->ItemValue(KRemoteHangupPauseDuration,KDefaultRemoteHangupPauseDuration);
+
+	iTimer=CSimTimer::NewL(iLine->iPhone);
+	CSimCall::ConstructL();
+	
+	//If present read in remote party info tag
+	TPtrC8 callingname, remotenumber;
+	TInt delay=0;
+	const CTestConfigItem* item=NULL;
+	item=iLine->CfgFile()->Item(KNotifyRemotePartyInfo);
+	TInt ret;
+	if (item)
+		{
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,delay);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("delay",ret,0,&KNotifyRemotePartyInfo);
+			}
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,callingname);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("callingname",ret,1,&KNotifyRemotePartyInfo);
+			}
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,remotenumber);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("remotenumber",ret,2,&KNotifyRemotePartyInfo);
+			}
+		
+		iNotifyRemotePartyInfoTimer->iDelay = delay;
+		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iDirection = RMobileCall::EDirectionUnknown;
+		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iCallingName.Copy(callingname);
+		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iTelNumber.Copy(remotenumber);	
+		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iTypeOfNumber = RMobilePhone::EInternationalNumber;
+		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iNumberPlan = RMobilePhone::EIsdnNumberPlan;
+		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus = RMobileCall::ERemoteIdentityAvailable;					
+		}
+	else
+		{
+		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus = RMobileCall::ERemoteIdentityUnknown;
+		}
+	
+	LOGVOICE1("...Finished parsing Voice Call config parameters...");
+	}
+
+CSimVoiceCall::~CSimVoiceCall()
+/**
+* Destroy all the objects constructed.
+* CSimTimer and CSimSysAgent objects are destroyed here
+*/
+	{
+	delete iTimer;
+	if(iAnswerIncomingCall.iNotifyPending)
+		iLine->ResetAutoAnswerCallObject(this);
+	}
+
+TInt CSimVoiceCall::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc,const TDataPackage& aPackage)
+/**
+* ExtFunc is called by the server when it has a "extended", i.e. non-core ETel request 
+* for the TSY to process
+* A request handle, request type and request data are passed to the TSY
+*
+* @param aTsyReqHandle
+* @param aIpc IPc number representing the request
+* @param aPackage data for the request
+* @return KErrNone
+*/
+	{
+	TAny* dataPtr=aPackage.Ptr1();
+
+	// The request data has to extracted from TDataPackage and the TAny* pointers have to
+	// be "cast" to the expected request data type
+
+	switch (aIpc)
+		{
+	//
+	// No Flow Control NOR Multiple Completion
+	//
+	case EMobileCallGetMobileCallCaps:
+		return GetMobileCallCaps(aTsyReqHandle,aPackage.Des1n());
+
+	case EMobileCallGetMobileCallStatus:
+		return GetMobileCallStatus(aTsyReqHandle,
+			REINTERPRET_CAST(RMobileCall::TMobileCallStatus*,dataPtr));
+
+	case EMobileCallGetMobileCallInfo:
+		return GetMobileCallInfo(aTsyReqHandle,aPackage.Des1n());
+
+	case EMobileCallDialEmergencyCall:
+		return DialEmergencyCall(aTsyReqHandle,aPackage.Des1u());
+
+	case EMobileCallHold:
+		return Hold(aTsyReqHandle);
+
+	case EMobileCallResume:
+		return Resume(aTsyReqHandle);
+
+	case EMobileCallSwap:
+		return Swap(aTsyReqHandle);
+	
+	case EMobileCallDialISV:
+		return DialISV(aTsyReqHandle, aPackage.Des1n(), aPackage.Des2u());
+
+	case EMobileCallAnswerISV:
+		TInt retVal;
+		TRAPD(errVal, retVal=AnswerIncomingCallISVL(aTsyReqHandle, aPackage.Des1n()));
+		if (errVal != KErrNone)
+			{
+			return errVal;
+			}
+		else
+			{
+			return retVal;	
+			}
+		
+	//
+	// Multiple Completion Services with Immediate Server Repost
+	// (Usually Notifications)
+	//
+	case EMobileCallNotifyMobileCallStatusChange:
+		return NotifyMobileCallStatusChange(aTsyReqHandle,
+			REINTERPRET_CAST(RMobileCall::TMobileCallStatus*, dataPtr));
+
+	case EMobileCallNotifyMobileCallCapsChange:
+		return NotifyMobileCallCapsChange(aTsyReqHandle, aPackage.Des1n());
+		
+	case EMobileCallNotifyRemotePartyInfoChange:
+		return NotifyRemotePartyInfoChange(aTsyReqHandle, aPackage.Des1n());		
+
+	default:
+		break;
+		}
+	return KErrNotSupported;
+	}
+
+TInt CSimVoiceCall::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
+/**
+ * Cancel an outstanding request.
+ * @param aIpc The IPC number of the request that must be cancelled.  Note: this is not the
+ *             IPC number of the cancel request itself.
+ * @param aTsyReqHandle The TSY Request Handle of the request to be cancelled.
+ */
+	{
+	switch(aIpc)
+		{
+	case EMobileCallNotifyMobileCallStatusChange:
+		return NotifyMobileCallStatusChangeCancel(aTsyReqHandle);
+
+	case EMobileCallNotifyMobileCallCapsChange:
+		return NotifyMobileCallCapsChangeCancel(aTsyReqHandle);
+
+	case EMobileCallDialEmergencyCall:
+		return DialEmergencyCallCancel(aTsyReqHandle);
+
+	case EMobileCallHold:
+		return HoldCancel(aTsyReqHandle);
+
+	case EMobileCallResume:
+		return ResumeCancel(aTsyReqHandle);
+
+	case EMobileCallSwap:
+		return SwapCancel(aTsyReqHandle);
+		
+	case EMobileCallNotifyRemotePartyInfoChange:
+		return NotifyRemotePartyInfoChangeCancel();
+		
+	case EMobileCallDialISV:
+		return DialISVCancel(aTsyReqHandle);
+		
+	case EMobileCallAnswerISV:
+		return AnswerIncomingCallISVCancel(aTsyReqHandle);       
+	default:
+		break;
+		}
+
+	return CCallBase::CancelService(aIpc,aTsyReqHandle);
+	}
+
+TInt CSimVoiceCall::DialEmergencyCall(const TTsyReqHandle aTsyReqHandle,TDesC* aTelNumber)
+/**
+* Process a client's emergency call request.
+*
+* @param aTsyReqHandle
+* @param aTelNumber The telephone number to dial
+* @return KErrNone
+*/
+	{
+	return Dial(aTsyReqHandle,NULL,aTelNumber);
+	}
+
+TInt CSimVoiceCall::DialEmergencyCallCancel(const TTsyReqHandle aTsyReqHandle)
+/**
+* Cancels an emergency call request.
+*
+* @param aTsyReqHandle
+* @return KErrNone if successfully cancelled
+*/
+	{
+	return DialCancel(aTsyReqHandle);
+	}
+
+TInt CSimVoiceCall::Dial(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* /*aTelNumber*/)
+/**
+* Process a client's dial request.
+*
+* @param aTsyReqHandle
+* @param aCallParams  the call parameters
+* @param aTelNumber The telephone number to dial
+* @return KErrNone
+*/
+	{
+	LOGVOICE1(">>CSimVoiceCall::Dial");
+	// Note: The telephone number and call parameters should be validated against config file
+	//       values here.
+	
+	//see where the dial request has orignated from
+	if(aCallParams)
+		{
+		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
+		RCall::TCallParams& callparams=(*callparamsPckg)();
+		
+		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
+			{
+			LOGVOICE1("<<CSimVoiceCall::Dial request from Etel 3rd Party client.");
+			}
+		}
+
+	iDialRequestHandle=aTsyReqHandle;
+	TInt ret;
+	ret = ActionEvent(ECallEventDial,KErrNone);
+	LOGVOICE1("<<CSimVoiceCall::Dial");
+	return ret;
+	}
+	
+TInt CSimVoiceCall::DialCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancels a dial Request
+*
+* @param aTsyReqHandle
+* @return KErrNone if successfully cancelled
+*/
+	{
+	LOGVOICE1(">>CSimVoiceCall::DialCancel");
+	switch(iState)
+		{
+	case RMobileCall::EStatusIdle:
+		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
+		break;
+
+	case RMobileCall::EStatusDialling:
+	case RMobileCall::EStatusConnecting:
+		iTimer->DoCancel();
+		// Can ignore for cancel
+		TInt err;
+		err = KErrNone;
+		TRAP(err, (void)ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
+		if (err != KErrNone)
+			{
+			ReqCompleted(iDialRequestHandle, err);
+			}
+		else
+			{
+			ReqCompleted(iDialRequestHandle, KErrCancel);
+			}
+		break;
+
+	case RMobileCall::EStatusConnected:
+		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
+		break;
+
+	default:
+		break;
+		}
+	LOGVOICE1("<<CSimVoiceCall::DialCancel");
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::DialISV(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* /*aTelNumber*/)
+/**
+* Process an EtelISV client's dial request.
+*
+* @param aTsyReqHandle
+* @param aCallParams  the call parameters
+* @param aTelNumber The telephone number to dial
+* @return KErrNone
+*/
+	{
+	LOGVOICE1(">>CSimVoiceCall::DialISV");
+	// Note: The telephone number and call parameters should be validated against config file
+	//       values here.
+	
+	//see where the dial request has orignated from
+	if(aCallParams)
+		{
+		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
+		RCall::TCallParams& callparams=(*callparamsPckg)();
+		
+		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
+			{
+			LOGVOICE1("<<CSimVoiceCall::Dial request from Etel 3rd Party client.");
+			}
+		}
+
+	iDialRequestHandle=aTsyReqHandle;
+	TInt ret;
+	ret = ActionEvent(ECallEventDial,KErrNone);
+	LOGVOICE1("<<CSimVoiceCall::DialISV");
+	return ret;
+	}
+
+TInt CSimVoiceCall::DialISVCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancels an EtelISV originated dial Request
+*
+* @param aTsyReqHandle
+* @return KErrNone if successfully cancelled
+*/
+	{
+	LOGVOICE1(">>CSimVoiceCall::DialISVCancel");
+	switch(iState)
+		{
+	case RMobileCall::EStatusIdle:
+		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
+		break;
+
+	case RMobileCall::EStatusDialling:
+	case RMobileCall::EStatusConnecting:
+		iTimer->DoCancel();
+		// Can ignore for cancel
+		TInt err;
+		err = KErrNone;
+		TRAP(err, (void)ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
+		if (err != KErrNone)
+			{
+			ReqCompleted(iDialRequestHandle, err);
+			}
+		else
+			{
+			ReqCompleted(iDialRequestHandle, KErrCancel);
+			}
+		break;
+
+	case RMobileCall::EStatusConnected:
+		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
+		break;
+
+	default:
+		break;
+		}
+	LOGVOICE1("<<CSimVoiceCall::DialISVCancel");
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::AnswerIncomingCall(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
+/**
+* Register a client's interest in answering the next incoming call.
+* First register interest in incoming calls with the line, then, if a call
+* is already ringing, start the answer procedure.
+*
+* @param aTsyReqHandle
+* @param aCallParams  the call parameters
+* @return KErrNone
+*/
+	{
+	LOGVOICE3(">>CSimVoiceCall::AnswerIncomingCall  0x%08x, state %d entry ",this,iState);
+	
+	//see where the answer request has orignated from
+	if(aCallParams)
+		{
+		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
+		RCall::TCallParams& callparams=(*callparamsPckg)();
+		
+		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
+			{
+			LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCall request from Etel 3rd Party client.");
+			}
+		}
+	
+	TInt ret=iLine->SetAutoAnswerCallObject(this);
+	if(ret!=KErrNone)
+		{
+		ReqCompleted(aTsyReqHandle,ret);
+		return KErrNone;
+		}
+
+	iAnswerIncomingCall.iNotifyPending=ETrue;
+	iAnswerIncomingCall.iNotifyHandle=aTsyReqHandle;
+
+	if(iState==RMobileCall::EStatusRinging)
+			ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);	
+	else if(iLine->iState==RMobileCall::EStatusRinging)
+		{		
+		TRAPD(errVal, ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
+		if (errVal != KErrNone)
+			{
+			ret = errVal;
+			}
+
+		if(ret==KErrNone)
+			ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);		
+		}
+	LOGVOICE3("<<CSimVoiceCall::AnswerIncomingCall  0x%08x, state %d exit",this,iState);
+	return ret;
+	}
+
+TInt CSimVoiceCall::AnswerIncomingCallCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancels a AnswerIncomingCall Request
+*
+* @param aTsyReqHandle
+* @return KErrNone if successfully cancelled
+*/
+	{
+	LOGVOICE1(">>CSimVoiceCall::AnswerIncomingCallCancel");
+	if(iAnswerIncomingCall.iNotifyPending)
+		{
+		iAnswerIncomingCall.iNotifyPending=EFalse;
+		iLine->ResetAutoAnswerCallObject(this);
+		ReqCompleted(iAnswerIncomingCall.iNotifyHandle,KErrCancel);
+		}
+	LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCallCancel");
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::AnswerIncomingCallISVL(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
+/**
+* Register an EtelISV client's interest in answering the next incoming call.
+* First register interest in incoming calls with the line, then, if a call
+* is already ringing, start the answer procedure.
+*
+* @param aTsyReqHandle
+* @param aCallParams  the call parameters
+* @return KErrNone
+*/
+	{
+	LOGVOICE3(">>CSimVoiceCall::AnswerIncomingCallISV  0x%08x, state %d entry ",this,iState);
+	
+	//see where the answer request has orignated from
+	if(aCallParams)
+		{
+		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
+		RCall::TCallParams& callparams=(*callparamsPckg)();
+		
+		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
+			{
+			LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCallISV request from Etel 3rd Party client.");
+			}
+		}
+	
+	TInt ret=iLine->SetAutoAnswerCallObject(this);
+	if(ret!=KErrNone)
+		{
+		ReqCompleted(aTsyReqHandle,ret);
+		return KErrNone;
+		}
+
+	iAnswerIncomingCall.iNotifyPending=ETrue;
+	iAnswerIncomingCall.iNotifyHandle=aTsyReqHandle;
+
+	if(iState==RMobileCall::EStatusRinging)
+			ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);	
+	else if(iLine->iState==RMobileCall::EStatusRinging)
+			{
+			TRAPD(leaveValue, ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
+			if (leaveValue != KErrNone)
+				{
+				return leaveValue;
+				}
+
+			if (ret == KErrNone)
+                {
+				ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);		
+	 		    }		
+		}
+	LOGVOICE3("<<CSimVoiceCall::AnswerIncomingCallISV  0x%08x, state %d exit",this,iState);
+	return ret;
+	}
+
+TInt CSimVoiceCall::AnswerIncomingCallISVCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancels an EtelISV originated AnswerIncomingCall Request
+*
+* @param aTsyReqHandle
+* @return KErrNone if successfully cancelled
+*/
+	{
+	LOGVOICE1(">>CSimVoiceCall::AnswerIncomingCallISVCancel");
+	if(iAnswerIncomingCall.iNotifyPending)
+		{
+		iAnswerIncomingCall.iNotifyPending=EFalse;
+		iLine->ResetAutoAnswerCallObject(this);
+		ReqCompleted(iAnswerIncomingCall.iNotifyHandle,KErrCancel);
+		}
+	LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCallISVCancel");
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::Connect(const TTsyReqHandle aTsyReqHandle,const TDesC8* /*aCallParams*/)
+	{
+	ReqCompleted(aTsyReqHandle,KErrNotSupported);
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::ConnectCancel(const TTsyReqHandle aTsyReqHandle)
+	{
+	ReqCompleted(aTsyReqHandle,KErrNotSupported);
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::HangUp(const TTsyReqHandle aTsyReqHandle)
+/**
+* Process a client's HangUp request.
+*
+* @param aTsyReqHandle
+* @return KErrNone
+*/
+	{
+	LOGVOICE1(">>CSimVoiceCall::HangUp");
+	iHangUpRequestHandle=aTsyReqHandle;
+	TInt ret=ActionEvent(ECallEventHangUp,KErrNone);
+	if(ret!=KErrNone)
+		ReqCompleted(aTsyReqHandle,ret);
+	LOGVOICE1("<<CSimVoiceCall::HangUp");
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::HangUpCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancels a HangUp Request
+*
+* @param aTsyReqHandle
+* @return KErrNone if successfully cancelled
+*/
+	{
+	LOGVOICE1(">>CSimVoiceCall::HangUpCancel");
+	switch(iState)
+		{
+	case RMobileCall::EStatusIdle:
+		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
+		break;
+
+	case RMobileCall::EStatusDisconnecting:
+		iTimer->DoCancel();
+		// Can ignore for cancel
+		TInt err;
+		err = KErrNone;
+		TRAP(err, (void)ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
+		if (err != KErrNone)
+			{
+			ReqCompleted(iHangUpRequestHandle, err);
+			}
+		else
+			{
+			ReqCompleted(iHangUpRequestHandle, KErrCancel);
+			}
+		break;
+
+	default:
+		break;
+		}
+	LOGVOICE1("<<CSimVoiceCall::HangUpCancel");
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::RelinquishOwnership()
+	{
+	return KErrNotSupported;
+	}
+
+TInt CSimVoiceCall::GetBearerServiceInfo(const TTsyReqHandle aTsyReqHandle,RCall::TBearerService* /*aBearerService*/)
+/**
+* Retrieves the bearer service info
+* Not supported for voice calls
+*/
+	{
+	ReqCompleted(aTsyReqHandle,KErrNotSupported);
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::GetCallParams(const TTsyReqHandle aTsyReqHandle, TDes8* /*aParams*/)
+/**
+* Retrives the call parameters
+* Not supported for voice calls
+*/
+	{
+	ReqCompleted(aTsyReqHandle,KErrNotSupported);
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::LoanDataPort(const TTsyReqHandle,RCall::TCommPort*)
+/**
+* Loans the comm port.
+* This is a data call specific request so not supported here.
+*/
+	{
+	return KErrNotSupported;
+	}
+/**
+* Cancels the LoanDataPort request.
+* This is a data call specific request so not supported here.
+*/
+
+TInt CSimVoiceCall::LoanDataPortCancel(const TTsyReqHandle)
+	{
+	return KErrNotSupported;
+	}
+
+TInt CSimVoiceCall::RecoverDataPort(const TTsyReqHandle)
+/**
+* Recovers the comm port.
+* This is a data call specific request so not supported here.
+*/
+	{
+	return KErrNotSupported;
+	}
+
+TInt CSimVoiceCall::Hold(const TTsyReqHandle aReqHandle)
+/**
+ * Put the call on hold.
+ * @param aReqHandle	The request handle associated with this call.
+ * @return TInt			Standard error value.
+ */
+	{
+	if(iState!=RMobileCall::EStatusConnected)
+		{
+		ReqCompleted(aReqHandle,KErrEtelCallNotActive);
+		return KErrNone;
+		}
+	iHoldResumeRequestHandle=aReqHandle;
+	TInt ret=ActionEvent(ECallEventHold,KErrNone);
+	return ret;
+	}
+
+TInt CSimVoiceCall::HoldCancel(const TTsyReqHandle)
+/**
+ * Cancel a Hold request.  Since hold is completed synchronously, this function is empty.
+ */
+	{
+	return KErrNone;
+	}
+	
+/**
+ * Cancel a NotifyConnectConfirmation request. It is possible to cancel
+ * a pending notification if the client did not issue a Dial request.
+ * @param aReqHandle	The request handle associated with this call.
+ */
+TInt CSimVoiceCall::NotifyConnectConfirmationCancel(const TTsyReqHandle aReqHandle)
+	{
+	if (iNotifyConnectConfirmReqHandle==aReqHandle)
+		{
+		iNotifyConnectConfirmReqHandle = NULL;
+		}
+	ReqCompleted(aReqHandle,KErrCancel);
+	return KErrNone;
+	}
+
+/**
+ * Resume a pending MO Connection.
+ * @param aReqHandle	The request handle associated with this call.
+ * @param aConnectContinue	Boolean to indicate whether to continue/terminate 
+ *							the call connection.
+ * @return TInt			Standard error value.
+ */
+TInt CSimVoiceCall::ResumeConnect(const TTsyReqHandle aReqHandle, const TBool * aConnectContinue)
+	{
+	TInt ret=KErrNone;
+	
+	if(iWaitForConnectConfirm)
+		{
+		// synchronous operation for either case
+		if (*aConnectContinue)
+			{
+			// okay to continue, initiate dialing, this will
+			// change the state
+			ret=ActionEvent(ECallEventConnectContinue,KErrNone);
+			}
+		else
+			{
+			// terminate the call...
+	
+			// there must be a dial request previously issue,
+			// but we never send the dial request down to call-stack,
+			// and we did not invoke the dial timer, so it will
+			// never expire, so we complete the dial request here
+			ReqCompleted(iDialRequestHandle,KErrNone);
+			}
+			
+		// complete the resume request
+		ReqCompleted(aReqHandle,ret);
+		}
+	else
+		{
+		// client did not issue dial request previously, this request
+		// is received in the wrong state, reject this request
+		ReqCompleted(aReqHandle,KErrAccessDenied);
+		}
+	return ret;
+	}
+	
+/**
+ * Cancel a ResumeConnect request.  Since resume is completed synchronously, this function is empty.
+ */
+TInt CSimVoiceCall::ResumeConnectCancel(const TTsyReqHandle)
+	{
+	return KErrNone;
+	}
+
+
+TInt CSimVoiceCall::Resume(const TTsyReqHandle aReqHandle)
+/**
+ * Put the call on resume.
+ * @param aReqHandle	The request handle associated with this call.
+ * @return TInt			Standard error value.
+ */
+	{
+	if(iState!=RMobileCall::EStatusHold)
+		{
+		ReqCompleted(aReqHandle,KErrAccessDenied);
+		return KErrNone;
+		}
+	iHoldResumeRequestHandle=aReqHandle;
+	TInt ret=ActionEvent(ECallEventResume,KErrNone);
+	return ret;
+	}
+
+
+TInt CSimVoiceCall::ResumeCancel(const TTsyReqHandle)
+/**
+ * Cancel a Resume request.  Since resume is completed synchronously, this function is empty.
+ */
+	{
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::Swap(const TTsyReqHandle aReqHandle)
+/**
+ * If the call is active, put it on hold.  If its on hold, resume it.
+ * @param aReqHandle	The request handle associated with this call.
+ * @return TInt			Standard error value.
+ */
+	{
+	TCallEvent event;
+	if(iState==RMobileCall::EStatusConnected)
+		{
+		event=ECallEventHold;		
+		}
+	else if(iState==RMobileCall::EStatusHold)
+		{	
+		event=ECallEventResume;
+		}
+	else
+		{
+		ReqCompleted(aReqHandle,KErrEtelCallNotActive);
+		return KErrNone;
+		}
+
+	iHoldResumeRequestHandle=aReqHandle;
+	TInt ret=ActionEvent(event,ECallEventSwap);	
+	return ret;
+	}
+
+TInt CSimVoiceCall::SwapCancel(const TTsyReqHandle)
+/**
+ * Cancel a Swap request.  Since swap is completed synchronously, this function is empty.
+ */
+	{
+	return KErrNone;
+	}
+
+TInt CSimVoiceCall::ActionEvent(TCallEvent aEvent,TInt aOtherArgument)
+/**
+* Entry point when an event has occured that may advance the state machine.
+* The aEvent parameter describes the event.
+*
+* This function contains the main state machine for the voice call.  The outer layer
+* switches on the event type.  Where appropriate, there are inner layer switches
+* or conditional statements to handle the different responses that may be required to
+* the same event occurring in different states.
+*
+* @param aEvent The Call event to handle
+* @return value represents the error state caused by the attempted state machine jump.
+*/
+	{
+	TInt ret=KErrNone;
+	__ASSERT_ALWAYS(iState!=RMobileCall::EStatusUnknown,SimPanic(ECallStatusUnknownIllegal));
+	__ASSERT_ALWAYS(aEvent!=ECallEventNtRasConnected,SimPanic(ECallEventIllegal));
+	LOGVOICE3(">>CSimVoiceCall::ActionEvent 0x%08x %d",this,iState);
+
+	switch(aEvent)
+		{
+	case ECallEventDial:
+		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventDial]");
+		if(iState==RMobileCall::EStatusIdle)
+			{			
+			TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusDialling,EFalse,EFalse));
+			if(ret==KErrNone)
+				iTimer->Start(iDiallingPause,this);
+			}
+		else
+			return KErrEtelCallAlreadyActive;
+		break;
+
+	case ECallEventHangUp:
+		{
+		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventHangUp]");
+		switch(iState)
+			{
+		case RMobileCall::EStatusDialling:
+		case RMobileCall::EStatusRinging:
+		case RMobileCall::EStatusAnswering:
+		case RMobileCall::EStatusConnecting:
+		case RMobileCall::EStatusConnected:
+		case RMobileCall::EStatusHold:
+			TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusDisconnecting,EFalse,EFalse));
+			if(ret==KErrNone)
+				iTimer->Start(iDisconnectingPause,this);
+			if(iSimDtmf)
+				{
+				iSimDtmf->CallClosureCallback();
+				iSimDtmf=NULL;
+				}
+			break;
+		default:
+			return KErrEtelCallNotActive;
+			}
+		}
+		break;
+
+	case ECallEventIncomingCall:
+		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventIncomingCall]");
+		if(iState==RMobileCall::EStatusIdle)
+			{
+			if(iAnswerIncomingCall.iNotifyPending)
+				{
+				TRAP(ret,	 ret=ProcessAnswerIncomingCallL());
+				}
+			else
+				{
+				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
+				if(ret!=KErrNone)
+					return ret;
+				}
+			}
+		else
+			return KErrEtelCallAlreadyActive;
+		break;
+
+	case ECallEventAnswerIncoming:
+		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventAnswerIncoming]");
+		if(iState==RMobileCall::EStatusRinging)
+			{
+			TRAP(ret, ret=ProcessAnswerIncomingCallL());
+			if(ret!=KErrNone)
+				{
+				return ret;
+				}
+			}
+		else
+			SimPanic(EIllegalStateInconsistancy);		// This is checked before calling ActionEvent
+		break;
+
+	case ECallEventRemoteHangup:
+		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventRemoteHangup]");
+		if(iState==RMobileCall::EStatusConnected)
+			{
+			TRAP(ret, ret=ProcessRemoteHangupL());
+			if(ret!=KErrNone)
+				{
+				return ret;
+				}
+			}
+		else
+			SimPanic(EIllegalStateInconsistancy);		// This is checked before calling ActionEvent
+		break;
+
+	case ECallEventTimeOut:
+			{
+			LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventTimeOut]");
+			switch(iState)
+				{
+			case RMobileCall::EStatusDialling:
+				LOGVOICE1(">>CSimVoiceCall::State = [EStatusDialling]");
+				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnecting,EFalse,EFalse));
+				if(ret==KErrNone)
+					iTimer->Start(iConnectingPause,this);
+				return ret;
+			
+			case RMobileCall::EStatusConnecting:
+				LOGVOICE1(">>CSimVoiceCall::State = [EStatusConnecting]");
+				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
+				UpdateRemotePartyInfoDirection(RMobileCall::EStatusConnecting);
+				ReqCompleted(iDialRequestHandle,ret);
+				return ret;
+				
+			case RMobileCall::EStatusDisconnecting:
+				LOGVOICE1(">>CSimVoiceCall::State = [EStatusDisconnecting]");
+				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
+				ReqCompleted(iHangUpRequestHandle,ret);
+				return ret;
+				
+			case RMobileCall::EStatusAnswering:
+				LOGVOICE1(">>CSimVoiceCall::State = [EStatusAnswering]");
+				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
+				UpdateRemotePartyInfoDirection(RMobileCall::EStatusAnswering);
+				ReqCompleted(iAnswerIncomingCall.iNotifyHandle,ret);
+				return ret;
+
+			default:
+				break;
+				}
+			}
+		break;
+	case ECallEventHold:
+		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventHold]");
+		__ASSERT_ALWAYS(iState==RMobileCall::EStatusConnected,SimPanic(EIllegalStateInconsistancy));
+		TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusHold,aOtherArgument == ECallEventSwap,EFalse));
+		if (ret == KErrNone)
+			ReqCompleted(iHoldResumeRequestHandle,ret);
+		break;
+
+	case ECallEventResume:
+		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventResume]");
+		__ASSERT_ALWAYS(iState==RMobileCall::EStatusHold,SimPanic(EIllegalStateInconsistancy));
+		TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,aOtherArgument == ECallEventSwap,EFalse));
+		if (ret == KErrNone)
+			ReqCompleted(iHoldResumeRequestHandle,ret);
+		break;
+
+	case ECallEventConnectContinue:
+		SimPanic(EIllegalVoiceCallEvent);	// All other events not legal for voice call.
+		break;
+	default:
+		SimPanic(EIllegalVoiceCallEvent);	// All other events not legal for voice call.
+		break;
+		}
+
+	return ret;
+	}
+
+
+void CSimVoiceCall::TimerCallBack(TInt /*aId*/)
+/**
+* Timer callback function.  When the timer goes off, it will call back into this
+* function for further processing.
+*/
+	{
+	LOGVOICE1(">>CSimVoiceCall::TimerCallBack");
+	TInt ret=ActionEvent(ECallEventTimeOut,KErrNone);
+	__ASSERT_ALWAYS(ret==KErrNone,SimPanic(ETimeOutEventActionFailed));
+	LOGVOICE1("<<CSimVoiceCall::TimerCallBack");
+	}
+
+TInt CSimVoiceCall::ProcessAnswerIncomingCallL()
+/**
+* Answers an Incoming Call.
+* First the call state must be changed to "answering", then the flag indicating
+* that an answer incoming call request is no longer pending.  Finally, a new
+* call object must be assigned to receive the details of the next incoming call.
+*/
+	{
+	LOGVOICE3(">>CSimVoiceCall::ProcessAnswerIncomingCall %d",iState,this);
+	TInt ret=ChangeStateL(RMobileCall::EStatusAnswering,EFalse,EFalse);
+	if(ret!=KErrNone)
+		return ret;
+	iTimer->Start(iAnswerIncomingPause,this);
+	iAnswerIncomingCall.iNotifyPending=EFalse;
+	iLine->ResetAutoAnswerCallObject(this);
+	LOGVOICE1("<<CSimVoiceCall::ProcessAnswerIncomingCall");
+	return ret;
+	}
+
+TInt CSimVoiceCall::ProcessRemoteHangupL()
+/**
+* Hangs up a call remotely.
+* First the call state must be changed to "disconnecting", then the flag indicating
+* that a remote hangup request is no longer pending.  Finally, a new
+* call object must be assigned to receive the next remote hangup request.
+*/
+	{
+	LOGVOICE3(">>CSimVoiceCall::ProcessRemoteHangupL %d",iState,this);
+	TInt ret=ChangeStateL(RMobileCall::EStatusDisconnecting,EFalse,EFalse);
+	if(ret!=KErrNone)
+		return ret;
+	iTimer->Start(iRemoteHangupPause,this);
+	iLine->ResetRemoteHangupCallObject(this);
+	LOGVOICE1("<<CSimVoiceCall::ProcessRemoteHangupL");
+	return ret;
+	}
+
+void CSimVoiceCall::SetDtmfSession(CSimDtmf* aSimDtmf)
+/**
+ * Set the DTMF session pointer.
+ */
+	{
+	__ASSERT_ALWAYS(iState==RMobileCall::EStatusConnected,SimPanic(EIllegalDtmfReq));
+	iSimDtmf=aSimDtmf;
+	}
+
+CSimDtmf* CSimVoiceCall::GetDtmfSession()
+/**
+ * Retrieve the DTMF session pointer.
+ */
+	{
+	return iSimDtmf;
+	}
+
+
+TUint CSimVoiceCall::Caps()
+/**
+ * Return the current capabilities of this call.
+ * @return TUint	Current call capabilities.
+ */
+	{
+	TUint caps=RCall::KCapsVoice;
+	if(iState!=RMobileCall::EStatusIdle)
+		{
+		if(iState==RMobileCall::EStatusConnected)
+			{
+			caps |= RCall::KCapsHangUp;
+			// If there is only a single call and its state is connected then the hold capability 
+			// should be set.
+			// If there is more than one call then only the swap capability should be set as hold 
+			// and resume apply only to single calls.
+		
+			TInt i=0;
+			TBool singleCall = ETrue;
+			TInt count=	iLine->iCalls->Count();
+		
+			while(singleCall && i<count)
+				{
+ 				if(iLine->iCalls->At(i) != this && (iLine->iCalls->At(i)->iState == RMobileCall::EStatusConnected || iLine->iCalls->At(i)->iState == RMobileCall::EStatusHold))
+					singleCall = EFalse;
+				i++;
+				}	
+			
+			if (singleCall)
+				caps |= RMobileCall::KCapsHold;
+			// Swap capability is applicable to single and multiple call
+			// scenarios
+			caps |= RMobileCall::KCapsSwap;
+			}
+		else if(iState==RMobileCall::EStatusHold)
+			{
+			caps |= RCall::KCapsHangUp;
+
+			TBool otherConnected = EFalse;
+			TInt count=	iLine->iCalls->Count();
+			TInt i=0;
+			while (!otherConnected && i<count)
+				{
+ 				if(iLine->iCalls->At(i) != this && (iLine->iCalls->At(i)->iState == RMobileCall::EStatusConnected || iLine->iCalls->At(i)->iState == RMobileCall::EStatusHold))
+					otherConnected = ETrue;
+				i++;
+				}	
+			if(otherConnected)
+				{
+				caps |= RMobileCall::KCapsSwap;
+				}
+			else
+				{
+				caps |= RMobileCall::KCapsResume;
+				caps |= RMobileCall::KCapsSwap;
+				}					
+			}
+		else if (iState==RMobileCall::EStatusRinging)
+			{
+			if((iLine->IsAnswerCallObjectSpare()))
+				caps |= RCall::KCapsAnswer;	
+			}
+		}
+	else
+		{
+		if(iLine->iState==RMobileCall::EStatusIdle || iLine->iState==RMobileCall::EStatusHold)
+			{
+			caps |= RCall::KCapsDial;
+			if((iLine->IsAnswerCallObjectSpare()))
+				caps |= RCall::KCapsAnswer;
+			}
+		else if (iLine->iState==RMobileCall::EStatusRinging)
+			{
+			if((iLine->IsAnswerCallObjectSpare()))
+				caps |= RCall::KCapsAnswer;			
+			}
+		}
+	return caps;
+	}
+
+void CSimVoiceCall::UpdateRemotePartyInfoDirection(RMobileCall::TMobileCallStatus aPreviousStatus)
+/**
+Update the direction of the call for the remote party info member
+*/
+	{
+	if(iNotifyRemotePartyInfoTimer && iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus != RMobileCall::ERemoteIdentityUnknown)	
+		{
+		if(aPreviousStatus == RMobileCall::EStatusAnswering)
+			iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iDirection = RMobileCall::EMobileTerminated;
+		else
+			iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iDirection = RMobileCall::EMobileOriginated;
+		}			
+	}