--- 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;
+ }
+ }