--- a/telephonyserverplugins/simtsy/src/CSimCall.cpp Mon May 03 13:37:20 2010 +0300
+++ b/telephonyserverplugins/simtsy/src/CSimCall.cpp Thu May 06 15:10:38 2010 +0100
@@ -1,1050 +1,1050 @@
-// 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 call classes. The call classes
-// process the call-based requests made by ETel clients and passed down to the TSY by the
-// ETel Server.
-//
-//
-
-/**
- @file
-*/
-
-#include "CSimCall.h"
-#include "CSimPhone.h"
-#include "Simlog.h"
-
-void CSimCall::CloseCall(TAny* aObj)
-/**
-* Utility func for cleanup stack
-*
-* @param aObj a pointer to the CObject to close
-*/
- {
- ((CObject*)aObj)->Close();
- }
-
-CSimCall::CSimCall(CSimLine* aLine,const TName& aName, CSimPhone* aPhone)
- : iState(RMobileCall::EStatusIdle),iLine(aLine),
- iHookState(ConvertStateToHook(iState)), iPhone(aPhone)
- {
- iNotifyStatusChange.iNotifyPending = EFalse;
- iMobileNotifyStatusChange.iNotifyPending = EFalse;
- iAnswerIncomingCall.iNotifyPending = EFalse;
- iName.Copy(aName);
- }
-
-void CSimCall::ConstructL()
-/**
-* Standard constructor
-*/
- {
- iCallDurationHandler = CSimCallDuration::NewL(this);
- iNotifyRemotePartyInfoTimer = CSimCallRemotePartyInfoChange::NewL(this);
- }
-
-
-CSimCall::~CSimCall()
-/**
-* Standard destructor
-*/
- {
- iLine->CallDestructor(this);
- delete iCallDurationHandler;
- delete iNotifyRemotePartyInfoTimer;
- }
-
-CTelObject::TReqMode CSimCall::ReqModeL(const TInt aIpc)
-/**
-* This function returns the Request Mode for the request with the passed IPC value.
-* The ETel Server provides a function for returning the standard request modes for
-* the Core API requests.
-* Multimode API requests mode are handled here.
-*
-* @param aIpc the IPc number representing the client request
-* @return CTelObject::TReqMode the request mode to be used for this IPc number
-* @leave Leaves if the IPc number is not found
-*/
- {
- // ReqModeL is called from the server's CTelObject::ReqAnalyserL
- // in order to check the type of request it has
-
- CTelObject::TReqMode reqMode=0;
- LOGCALL2("CSimCall::ReqModeL called with IPC number %d",aIpc);
- switch (aIpc)
- {
- //
- // No Flow Control NOR Multiple Completion
- //
- case EMobileCallGetMobileDataCallCaps:
- case EMobileCallGetMobileCallCaps:
- case EMobileCallGetMobileCallStatus:
- case EMobileCallGetMobileCallInfo:
- case EMobileCallDialEmergencyCall:
- case EMobileCallGetMobileDataCallRLPRange:
- case EMobileCallSetDynamicHscsdParams:
- case EMobileCallGetCurrentHscsdInfo:
- case EMobileCallHold:
- case EMobileCallResume:
- case EMobileCallSwap:
- case EMobileCallAnswerISV:
- break;
-
- //
- // Flow Control Obeyed
- //
- case EMobileCallDialISV:
- reqMode=KReqModeFlowControlObeyed;
- break;
-
- //
- // Multiple Completion Services with Immediate Server Repost
- // (Usually Notifications)
- //
-
- case EMobileCallNotifyHscsdInfoChange:
- case EMobileCallNotifyMobileCallStatusChange:
- case EMobileCallNotifyMobileCallCapsChange:
- case EMobileCallNotifyRemotePartyInfoChange:
- reqMode=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
- break;
-
- default:
- reqMode=CCallBase::ReqModeL(aIpc);
- break;
- }
- return reqMode;
- }
-
-TInt CSimCall::NumberOfSlotsL(const TInt aIpc)
-/**
-* NumberOfSlotsL is called by the server when it is registering a new notification
-* It enables the TSY to tell the server how many buffer slots to allocate for
-* "repost immediately" notifications that may trigger before clients collect them
-*
-* @param aIpc the IPc number representing the client request
-* @return TInt the number of slots required
-* @leave Leaves if the IPc number is not found
-*/
- {
- switch (aIpc)
- {
- case EMobileCallNotifyHscsdInfoChange:
- case EMobileCallNotifyMobileDataCallCapsChange:
- case EMobileCallNotifyMobileCallStatusChange:
- case EMobileCallNotifyMobileCallCapsChange:
- case EMobileCallNotifyRemotePartyInfoChange:
- LOGCALL1("CSimCall: Registered with default number of slots");
- return KDefaultNumberOfSlots;
- default:
- LOGCALL1("CSimCall::NumberOfSlotsL: No match for IPC, defering to base function");
- break;
- }
- return CCallBase::NumberOfSlotsL(aIpc);
- }
-
-
-TInt CSimCall::RegisterNotification(const TInt /*aIpc*/)
-/**
-* The ETel Server calls this function when the first client makes a notification
-* request. If supported by the underlying protocol controlling the
-* signalling stack, this can be used to start requesting updates for the relevant service.
-*/
- {
- return KErrNone;
- }
-
-TInt CSimCall::DeregisterNotification(const TInt /*aIpc*/)
-/**
-* The ETel Server calls this function when the last client that had previously
-* made a notification request closes its ETel Server handle. If supported by
-* the underlying protocol controlling the signalling stack, this can be used
-* to stop requesting updates for the relevant service.
-*/
- {
- return KErrNone;
- }
-
-
-void CSimCall::Init()
-/**
-* This function can be used to perform any necessary synchronous initialisation.
-*/
- {}
-
-TInt CSimCall::GetCaps(const TTsyReqHandle aTsyReqHandle,RCall::TCaps* aCallCaps)
-/**
-* Retrieve the Call capabilities
-*
-* @param aTsyReqHandle TSY handle associated with this request.s
-* @param aCallCaps Pointer to the call capability
-* @return KErrNone
-*/
- {
- aCallCaps->iFlags=iCaps;
- ReqCompleted(aTsyReqHandle,KErrNone);
- return KErrNone;
- }
-
-TInt CSimCall::NotifyCapsChange(const TTsyReqHandle aTsyReqHandle, RCall::TCaps* aCaps)
-/**
-* Register a client's interest in being notified when the call caps change.
-* @param aTsyReqHandle The TSY handle associated with this request.
-* @param aCaps The capability structure that will be populated with the new capability
-* information.
-* @return TInt Standard error code.
-*/
- {
- __ASSERT_ALWAYS(!iNotifyCapsChange.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
- iNotifyCapsChange.iNotifyPending=ETrue;
- iNotifyCapsChange.iNotifyHandle=aTsyReqHandle;
- iNotifyCapsChange.iNotifyData=aCaps;
- return KErrNone;
- }
-
-TInt CSimCall::NotifyCapsChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancel a client's interest in being notified when the call capabilities change.
-*/
- {
- if(iNotifyCapsChange.iNotifyPending)
- {
- iNotifyCapsChange.iNotifyPending=EFalse;
- ReqCompleted(iNotifyCapsChange.iNotifyHandle,KErrCancel);
- }
- return KErrNone;
- }
-
-TInt CSimCall::GetMobileCallCaps(const TTsyReqHandle aTsyReqHandle, TDes8* aCaps)
-/**
-* Retrieve the Mobile Call capabilities
-*
-* @param aTsyReqHandle TSY handle associated with this request.
-* @param aCaps Pointer to the call capability
-* @return KErrNone
-*/
- {
- TPckg<RMobileCall::TMobileCallCapsV1>* capsPckg=(TPckg<RMobileCall::TMobileCallCapsV1>*)aCaps;
- RMobileCall::TMobileCallCapsV1& caps=(*capsPckg)();
-
- // Check that the data structure is supported by the simulated TSY version
- TInt err = iPhone->CheckSimTsyVersion(caps);
- if(err != KErrNone)
- {
- ReqCompleted(aTsyReqHandle, err);
- return KErrNone;
- }
-
- caps.iCallControlCaps=iCaps; // None of the extended caps are supported.
- caps.iCallEventCaps=0;
- ReqCompleted(aTsyReqHandle,KErrNone);
- return KErrNone;
- }
-
-TInt CSimCall::NotifyMobileCallCapsChange(const TTsyReqHandle aTsyReqHandle, TDes8* aCaps)
-/**
-* Register a client's interest in being notified when the RMobileCall capabilities change.
-* @param aTsyReqHandle The TSY handle associated with this request.
-* @param aCaps The capability structure that will be populated with the new capability
-* information.
-* @return TInt Standard error code.
-*/
- {
- __ASSERT_ALWAYS(!iNotifyMobileCapsChange.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
- iNotifyMobileCapsChange.iNotifyPending=ETrue;
- iNotifyMobileCapsChange.iNotifyHandle=aTsyReqHandle;
- iNotifyMobileCapsChange.iNotifyData=aCaps;
- return KErrNone;
- }
-
-TInt CSimCall::NotifyMobileCallCapsChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancel a client's interest in being notified when the RMobileCall capabilities change.
-*/
- {
- if(iNotifyMobileCapsChange.iNotifyPending)
- {
- iNotifyMobileCapsChange.iNotifyPending=EFalse;
- ReqCompleted(iNotifyMobileCapsChange.iNotifyHandle,KErrCancel);
- }
- return KErrNone;
- }
-
-TInt CSimCall::NotifyHookChange(const TTsyReqHandle aTsyReqHandle, RCall::THookStatus* aHookStatus)
-/**
-* Record a client's interst in being notified when the hook changes state.
-*
-* @param aTsyReqHandle Tsy Request handle for the client request
-* @param aHookStatus pointer to the hook status
-* @return KErrNone
-*/
- {
- LOGCALL1(">>CSimCall::NotifyHookChange");
- iNotifyHookChange.iNotifyPending = ETrue;
- iNotifyHookChange.iNotifyHandle = aTsyReqHandle;
- iNotifyHookChange.iNotifyData = aHookStatus;
- LOGCALL1("<<CSimCall::NotifyHookChange");
- return KErrNone;
- }
-
-TInt CSimCall::NotifyHookChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancel a client's interest in being notified when the hook state changes.
-*
-* @param aTsyReqHandle Tsy Request handle for the client cancel request
-* @return KErrNone
-*/
- {
- LOGCALL1(">>CSimCall::NotifyHookChangeCancel");
- if(iNotifyHookChange.iNotifyPending)
- {
- iNotifyHookChange.iNotifyPending=EFalse;
- ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrCancel);
- }
- LOGCALL1("<<CSimCall::NotifyHookChangeCancel");
- return KErrNone;
- }
-
-TInt CSimCall::NotifyMobileCallStatusChange(const TTsyReqHandle aTsyReqHandle,RMobileCall::TMobileCallStatus* aStatus)
-/**
-* Record a client's interest in being notified when the call status changes.
-* First check that there isn't already a notification pending (the ETel Server should protect
-* against this) and then record the information necessary to complete the request later, when
-* the status does actually change.
-*
-* @param aTsyReqHandle Tsy Request handle for the client request
-* @param aStatus pointer to the call status
-* @return KErrNone
-*/
- {
- LOGCALL1(">>CSimCall::NotifyMobileCallStatusChange");
- __ASSERT_ALWAYS(!iMobileNotifyStatusChange.iNotifyPending,SimPanic(ENotificationAlreadyPending));
-
- iMobileNotifyStatusChange.iNotifyPending = ETrue;
- iMobileNotifyStatusChange.iNotifyHandle = aTsyReqHandle;
- iMobileNotifyStatusChange.iNotifyData = aStatus;
- LOGCALL1("<<CSimCall::NotifyMobileCallStatusChange");
- return KErrNone;
- }
-
-TInt CSimCall::NotifyMobileCallStatusChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancel a client's interest in being notified when the call status changes.
-* This is acheived simply by resetting the flag that indicates a notification is pending.
-*
-* @param aTsyReqHandle Tsy Request handle for the client cancel request
-* @return KErrNone
-*/
- {
- LOGCALL1(">>CSimCall::NotifyMobileCallStatusChangeCancel");
- if(iMobileNotifyStatusChange.iNotifyPending)
- {
- iMobileNotifyStatusChange.iNotifyPending=EFalse;
- ReqCompleted(iMobileNotifyStatusChange.iNotifyHandle,KErrCancel);
- }
- LOGCALL1("<<CSimCall::NotifyMobileCallStatusChangeCancel");
- return KErrNone;
- }
-
-
-TInt CSimCall::NotifyStatusChange(const TTsyReqHandle aTsyReqHandle,RCall::TStatus* aStatus)
-/**
-* Record a client's interest in being notified when the call status changes.
-* First check that there isn't already a notification pending (the ETel Server should protect
-* against this) and then record the information necessary to complete the request later, when
-* the status does actually change.
-*
-* @param aTsyReqHandle Tsy Request handle for the client request
-* @param aStatus pointer to the call status
-* @return KErrNone
-*/
- {
- LOGCALL1(">>CSimCall::NotifyStatusChange");
- __ASSERT_ALWAYS(!iNotifyStatusChange.iNotifyPending,SimPanic(ENotificationAlreadyPending));
-
- iNotifyStatusChange.iNotifyPending = ETrue;
- iNotifyStatusChange.iNotifyHandle = aTsyReqHandle;
- iNotifyStatusChange.iNotifyData = aStatus;
- LOGCALL1("<<CSimCall::NotifyStatusChange");
- return KErrNone;
- }
-
-TInt CSimCall::NotifyStatusChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancel a client's interest in being notified when the call status changes.
-* This is acheived simply by resetting the flag that indicates a notification is pending.
-*
-* @param aTsyReqHandle Tsy Request handle for the client cancel request
-* @return KErrNone
-*/
- {
- LOGCALL1(">>CSimCall::NotifyStatusChangeCancel");
- if(iNotifyStatusChange.iNotifyPending)
- {
- iNotifyStatusChange.iNotifyPending=EFalse;
- ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrCancel);
- }
- LOGCALL1("<<CSimCall::NotifyStatusChangeCancel");
- return KErrNone;
- }
-
-
-
-TInt CSimCall::NotifyDurationChange(const TTsyReqHandle aTsyReqHandle,TTimeIntervalSeconds* aTime)
-/**
-* Record a client's interest in being notified when the call duration changes.
-*
-* @param aTsyReqHandle
-* @param aTime
-* @return KErrNone or symbian wide error code
-*/
- {
- iCallDurationHandler->StartNotification(aTsyReqHandle, aTime);
- return KErrNone;
- }
-
-TInt CSimCall::NotifyDurationChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Not Supported in this TSY
-*/
- {
- iCallDurationHandler->StopNotification();
- return KErrNone;
- }
-
-TInt CSimCall::GetInfo(const TTsyReqHandle aTsyReqHandle, RCall::TCallInfo* aCallInfo)
-/**
-* Retrieve the Call Information.
-*
-* @param aTsyReqHandle
-* @param aCallInfo pointer to the call information to be returned to client
-* @return KErrNone
-*/
- {
- aCallInfo->iCallName.Copy(iName);
- aCallInfo->iLineName.Copy(iLine->iLineName);
- aCallInfo->iHookStatus=ConvertStateToHook(iState);
- aCallInfo->iStatus=GetCoreCallStatus();
- aCallInfo->iDuration=0;
- ReqCompleted(aTsyReqHandle,KErrNone);
- return KErrNone;
- }
-
-TInt CSimCall::GetMobileCallInfo(const TTsyReqHandle aTsyReqHandle, TDes8* aMobileCallInfo)
-/**
-* Retrieve the Mobile Call Information
-*
-* @param aTsyReqHandle
-* @param aCallInfo pointer to the call information to be returned to client
-* @return KErrNone
-*/
- {
- RMobileCall::TMobileCallInfoV1Pckg* mobileCallInfoV1=(RMobileCall::TMobileCallInfoV1Pckg*)aMobileCallInfo;
- RMobileCall::TMobileCallInfoV1& mobileCallInfo=(*mobileCallInfoV1)();
-
- // Check that the data structure is supported by the simulated TSY version
- TInt err = iPhone->CheckSimTsyVersion(mobileCallInfo);
- if(err != KErrNone)
- {
- ReqCompleted(aTsyReqHandle, err);
- return KErrNone;
- }
-
- TUint caps=Caps();
- if(caps&RCall::KCapsVoice)
- mobileCallInfo.iService=RMobilePhone::EVoiceService;
- else if(caps&RCall::KCapsData)
- mobileCallInfo.iService=RMobilePhone::ECircuitDataService;
- else if(caps&RCall::KCapsFax)
- mobileCallInfo.iService=RMobilePhone::EFaxService;
- else
- mobileCallInfo.iService=RMobilePhone::EServiceUnspecified;
-
- mobileCallInfo.iValid=0x0;
- mobileCallInfo.iStatus=iState;
- mobileCallInfo.iCallName.Copy(iName);
- mobileCallInfo.iLineName.Copy(iLine->iLineName);
- LOGCALL2("CSimCall::GetMobileCallInfo request completed with %d",iState);
- ReqCompleted(aTsyReqHandle,KErrNone);
- return KErrNone;
- }
-
-RCall::TStatus CSimCall::GetCoreCallStatus()
-/**
-* Converts Multimode call status (RMobileCall::TMobileCallStatus) to
-* Core call Status (RCall::TStatus)
-*
-* @return RCall::TStatus The core call status
-*/
- {
-// All status enums with values of Disconnecting and below are identical in
-// ETelMM and Core, so the mapping function is simple.
- RCall::TStatus coreStatus;
- if (iState <= RMobileCall::EStatusDisconnecting)
- coreStatus = (RCall::TStatus)iState;
- else
- switch (iState)
- {
- case RMobileCall::EStatusReconnectPending:
- case RMobileCall::EStatusHold:
- coreStatus = RCall::EStatusConnected;
- break;
- case RMobileCall::EStatusWaitingAlternatingCallSwitch:
- coreStatus = RCall::EStatusIdle;
- break;
- default:
- coreStatus = RCall::EStatusUnknown;
- break;
- }
- return coreStatus;
- }
-
-TInt CSimCall::GetStatus(const TTsyReqHandle aTsyReqHandle, RCall::TStatus* aCallStatus)
-/**
-* Return the current call state. (Core API request)
-*
-* @param aTsyReqHandle
-* @param aCallStatus pointer to the call status
-* @return KErrNone
-*/
- {
- LOGCALL1(">>CSimCall::GetStatus");
- *aCallStatus=GetCoreCallStatus();
- ReqCompleted(aTsyReqHandle,KErrNone);
- LOGCALL1("<<CSimCall::GetStatus");
- return KErrNone;
- }
-
-TInt CSimCall::GetMobileCallStatus(const TTsyReqHandle aTsyReqHandle, RMobileCall::TMobileCallStatus* aCallStatus)
-/**
-* Return the current call state. (Multimode API request)
-*
-* @param aTsyReqHandle
-* @param aCallStatus pointer to the call status
-* @return KErrNone
-*/
- {
- LOGCALL1(">>CSimCall::GetMobileCallStatus");
- *aCallStatus=iState;
- ReqCompleted(aTsyReqHandle,KErrNone);
- LOGCALL1("<<CSimCall::GetMobileCallStatus");
- return KErrNone;
- }
-
-TInt CSimCall::TransferOwnership(const TTsyReqHandle aTsyReqHandle)
-/**
-* Transfer call ownership
-* Not supported in this version of the Simulator TSY
-*/
- {
- ReqCompleted(aTsyReqHandle,KErrNotSupported);
- return KErrNone;
- }
-
-TInt CSimCall::AcquireOwnership(const TTsyReqHandle aTsyReqHandle)
-/**
-* Acquires call ownership
-* Not supported in this version of the Simulator TSY
-*/
- {
- ReqCompleted(aTsyReqHandle,KErrNotSupported);
- return KErrNone;
- }
-
-TInt CSimCall::AcquireOwnershipCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* cancel AcquireOwnership request
-* Not supported in this version of the Simulator TSY
-*/
- {
- return KErrNone;
- }
-
-TInt CSimCall::GetCallDuration(const TTsyReqHandle aTsyReqHandle, TTimeIntervalSeconds* aTime)
-/**
-* Retrieves the last call duration
-* Not supported in this version of the Simulator TSY
-*/
- {
- LOGCALL1(">>CSimCall::GetCallDuration");
-
- iCallDurationHandler->GetDuration(aTime);
-
- ReqCompleted(aTsyReqHandle,KErrNone);
- LOGCALL1("<<CSimCall::GetCallDuration");
- return KErrNone;
- }
-
-TInt CSimCall::RecoverDataPortAndRelinquishOwnership()
-/**
-* Recovers the comm port.
-* This is a data call specific request so not supported here.
-*/
- {
- return KErrNotSupported;
- }
-
-TInt CSimCall::GetFaxSettings(const TTsyReqHandle,RCall::TFaxSessionSettings*)
-/**
-* Retrieves the last fax settings
-* Not supported in this version of the Simulator TSY
-*/
- {
- return KErrNotSupported;
- }
-
-TInt CSimCall::SetFaxSettings(const TTsyReqHandle,const RCall::TFaxSessionSettings*)
-/**
-* Sets the fax settings
-* Not supported in this version of the Simulator TSY
-*/
- {
- return KErrNotSupported;
- }
-
-CTelObject* CSimCall::OpenNewObjectByNameL(const TDesC& /*aName*/)
-/**
-* Only Fax Calls can be opened from the Call object, KErrNotSupported is returned.
-*/
-
- {
- User::Leave(KErrNotSupported);
- return NULL;
- }
-
-CTelObject* CSimCall::OpenNewObjectL(TDes& /*aNewName*/)
-/**
-* Only Fax objects can be opened from the Call object, and we are not supporting fax calls
-* in this TSY. KErrNotSupported is returned.
-*/
- {
- User::Leave(KErrNotSupported);
- return NULL;
- }
-
-TBool CSimCall::Used()
- {
- return (AccessCount()>1);
- }
-
-void CSimCall::SetUsed()
- {
- (void)Open();
- }
-
-void CSimCall::SetUnused()
- {
- Close();
- }
-
-TInt CSimCall::ChangeStateL(RMobileCall::TMobileCallStatus aNewState,TBool aSwap, TBool aNoPropagation)
-/**
-* Attempt to change state.
-* First validate that the requested state change is ok. If it is then proceed to change
-* the state and complete any pending state change notification.
-*
-* @param aState the new state to change to
-* @param aSwap indicates that state change takes place as a consequence of swap operation on the call
-* @param aNoPropagation indicates whether change propagate to the holder line object
-* @return Error indication if change of state is successful or not
-*/
- {
- LOGCALL3(">>CSimCall::ChangeState 0x%08x [newState=%d] entry", this,aNewState);
-
- if(!aNoPropagation)
- {
- TInt ret=iLine->ChangeStateL(aNewState,aSwap,this);
- if(ret!=KErrNone)
- return ret;
- }
-
-// Check for call duration change
- if (!iCallDurationHandler)
- iCallDurationHandler=CSimCallDuration::NewL(this);
- if ((iState != RMobileCall::EStatusConnected) && (iState != RMobileCall::EStatusHold) && (aNewState == RMobileCall::EStatusConnected))
- iCallDurationHandler->StartDuration();
- else if ((aNewState != RMobileCall::EStatusConnected) && (aNewState != RMobileCall::EStatusHold) && ((iState == RMobileCall::EStatusConnected) || (iState == RMobileCall::EStatusHold)))
- iCallDurationHandler->StopDuration();
-
-// Actually change the state.
- iState=aNewState;
-
-// Check for a pending state change notification (core)
- if(iNotifyStatusChange.iNotifyPending)
- {
- iNotifyStatusChange.iNotifyPending=EFalse;
- *(RCall::TStatus*)iNotifyStatusChange.iNotifyData=GetCoreCallStatus();
- ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrNone);
- }
-
-// Check for a pending state change notification (multimode)
- if(iMobileNotifyStatusChange.iNotifyPending)
- {
- iMobileNotifyStatusChange.iNotifyPending=EFalse;
- *(RMobileCall::TMobileCallStatus*)iMobileNotifyStatusChange.iNotifyData=iState;
- ReqCompleted(iMobileNotifyStatusChange.iNotifyHandle,KErrNone);
- }
-
-// Check for a pending hook change notification.
- RCall::THookStatus hookStatus=ConvertStateToHook(iState);
- if(iHookState!=hookStatus)
- {
- iHookState=hookStatus;
- if(iNotifyHookChange.iNotifyPending)
- {
- iNotifyHookChange.iNotifyPending=EFalse;
- *(RCall::THookStatus*)iNotifyHookChange.iNotifyData=iHookState;
- ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrNone);
- }
- }
-
-// Check for a possible change in capabilities.
- TUint caps=Caps();
- if(iCaps!=caps)
- {
- iCaps=caps;
- if(iNotifyCapsChange.iNotifyPending)
- {
- iNotifyCapsChange.iNotifyPending=EFalse;
- ((RCall::TCaps*)iNotifyCapsChange.iNotifyData)->iFlags=iCaps;
- ReqCompleted(iNotifyCapsChange.iNotifyHandle,KErrNone);
- }
- if(iNotifyMobileCapsChange.iNotifyPending)
- {
- iNotifyMobileCapsChange.iNotifyPending=EFalse;
- TPckg<RMobileCall::TMobileCallCapsV1>* mobileCallCapsPckg=(TPckg<RMobileCall::TMobileCallCapsV1>*)iNotifyMobileCapsChange.iNotifyData;
- RMobileCall::TMobileCallCapsV1& mobileCallCaps=(*mobileCallCapsPckg)();
-
- mobileCallCaps.iCallControlCaps=iCaps; // None of the extended caps are supported.
- mobileCallCaps.iCallEventCaps=0;
- ReqCompleted(iNotifyMobileCapsChange.iNotifyHandle,KErrNone);
- }
- }
- if((aNewState == RMobileCall::EStatusConnected && !aSwap)|| aNewState == RMobileCall::EStatusDisconnecting)
- iLine->UpdatePhoneNotifiers(this,aNewState);
-
- LOGCALL2("<<CSimCall::ChangeState exit %d",iState);
- return KErrNone;
- }
-
-
-void CSimCall::UpdateNotifiers()
-/**
- Update notifiers of other voice call when it gets swapped
-*/
- {
- LOGCALL2(">>CSimCall::UpdateNotifiers 0x%08x entry", this);
-
-// Check for call duration change
- if (!iCallDurationHandler)
- {
- TRAP_IGNORE(iCallDurationHandler=CSimCallDuration::NewL(this));
- }
-
-
-// Check for a pending state change notification (core)
- if(iNotifyStatusChange.iNotifyPending)
- {
- iNotifyStatusChange.iNotifyPending=EFalse;
- *(RCall::TStatus*)iNotifyStatusChange.iNotifyData=GetCoreCallStatus();
- ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrNone);
- }
-
-// Check for a pending state change notification (multimode)
- if(iMobileNotifyStatusChange.iNotifyPending)
- {
- iMobileNotifyStatusChange.iNotifyPending=EFalse;
- *(RMobileCall::TMobileCallStatus*)iMobileNotifyStatusChange.iNotifyData=iState;
- ReqCompleted(iMobileNotifyStatusChange.iNotifyHandle,KErrNone);
- }
-
-// Check for a pending hook change notification.
- RCall::THookStatus hookStatus=ConvertStateToHook(iState);
- if(iHookState!=hookStatus)
- {
- iHookState=hookStatus;
- if(iNotifyHookChange.iNotifyPending)
- {
- iNotifyHookChange.iNotifyPending=EFalse;
- *(RCall::THookStatus*)iNotifyHookChange.iNotifyData=iHookState;
- ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrNone);
- }
- }
-
-// Check for a possible change in capabilities.
- TUint caps=Caps();
- if(iCaps!=caps)
- {
- iCaps=caps;
- if(iNotifyCapsChange.iNotifyPending)
- {
- iNotifyCapsChange.iNotifyPending=EFalse;
- ((RCall::TCaps*)iNotifyCapsChange.iNotifyData)->iFlags=iCaps;
- ReqCompleted(iNotifyCapsChange.iNotifyHandle,KErrNone);
- }
- if(iNotifyMobileCapsChange.iNotifyPending)
- {
- iNotifyMobileCapsChange.iNotifyPending=EFalse;
- TPckg<RMobileCall::TMobileCallCapsV1>* mobileCallCapsPckg=(TPckg<RMobileCall::TMobileCallCapsV1>*)iNotifyMobileCapsChange.iNotifyData;
- RMobileCall::TMobileCallCapsV1& mobileCallCaps=(*mobileCallCapsPckg)();
-
- mobileCallCaps.iCallControlCaps=iCaps; // None of the extended caps are supported.
- mobileCallCaps.iCallEventCaps=0;
- ReqCompleted(iNotifyMobileCapsChange.iNotifyHandle,KErrNone);
- }
- }
-
- LOGCALL2("<<CSimCall::UpdateNotifiers exit %d",iState);
- }
-
-TInt CSimCall::ActionEvent(TCallEvent /*aEvent*/, TInt /*aStatus*/)
-/**
-* This is an empty shell function. Each line should implement its own
-* state machine.
-*/
- {
- return KErrNotSupported;
- }
-
-void CSimCall::GenerateCoreCallCaps(TUint& aCaps)
-/**
- * Populate the variable capabilities that are dependant upon the call state.
- * @param TUint The capability variable that will be populated with the core capabilities.
- */
- {
- if(iState==RMobileCall::EStatusIdle)
- aCaps |= RCall::KCapsDial;
-
- if(iState==RMobileCall::EStatusConnected)
- aCaps |= RCall::KCapsHangUp;
-
- if((iLine->IsAnswerCallObjectSpare())&&(iState==RMobileCall::EStatusIdle))
- aCaps |= RCall::KCapsAnswer;
- }
-
-void CSimCall::ResetIfRingingL()
- {
- if(iState==RMobileCall::EStatusRinging)
- __ASSERT_ALWAYS(ChangeStateL(RMobileCall::EStatusIdle,EFalse,ETrue) == KErrNone, SimPanic(EGeneral));
- }
-
-void CSimCallDuration::TimerCallBack(TInt /*aId*/)
- {
- //increase duration by 1 sec
- iCallDuration=static_cast<TTimeIntervalSeconds>(iCallDuration.Int()+1);
-
- if(iNotifyDurationChange.iNotifyPending)
- {
- *(TTimeIntervalSeconds*)iNotifyDurationChange.iNotifyData=iCallDuration;
- iNotifyDurationChange.iNotifyPending=EFalse;
- iCall->ReqCompleted(iNotifyDurationChange.iNotifyHandle,KErrNone);
- }
- iDurationTimer->Start(1 , this);
- }
-
-CSimCallDuration* CSimCallDuration::NewL(CSimCall* aCall)
-/**
- * Standard two-phase constructor.
- * @param aPhone The parent phone object.
- * @return CSimCallDuration The new CallDuration class
- */
- {
- CSimCallDuration* self=new(ELeave) CSimCallDuration(aCall);
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop();
- return self;
- }
-
-CSimCallDuration::CSimCallDuration(CSimCall* aCall)
- :iCallDuration(0),iCall(aCall)
-/**
- * Trivial first phase construction.
- * @param aPhone The parent phone object.
- */
- {
- iNotifyDurationChange.iNotifyPending=EFalse;
- iNotifyDurationChange.iNotifyData=0;
- }
-
-
-void CSimCallDuration::ConstructL()
- {
- iDurationTimer = CSimTimer::NewL(iCall->iLine->iPhone);
- }
-
-
-CSimCallDuration::~CSimCallDuration()
-/**
- * Standard destructor. Destroy the heap-based object owned by this object.
- */
- {
- if (iDurationTimer)
- {
- if (iDurationTimer->IsActive())
- iDurationTimer->Cancel();
- delete iDurationTimer;
- }
- }
-
-void CSimCallDuration::StartDuration()
- {
- iCallDuration = 0;
- iDurationTimer->Start(1 , this);
- }
-
-void CSimCallDuration::StopDuration()
- {
- if (iDurationTimer)
- {
- if (iDurationTimer->IsActive())
- iDurationTimer->Cancel();
- }
- }
-
-void CSimCallDuration::StartNotification(TTsyReqHandle aTsyReqHandle, TTimeIntervalSeconds* aTime)
- {
- __ASSERT_ALWAYS(!iNotifyDurationChange.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
- iNotifyDurationChange.iNotifyData=aTime;
- iNotifyDurationChange.iNotifyPending=ETrue;
- iNotifyDurationChange.iNotifyHandle=aTsyReqHandle;
- }
-
-void CSimCallDuration::StopNotification()
- {
- if(iNotifyDurationChange.iNotifyPending)
- {
- iNotifyDurationChange.iNotifyPending=EFalse;
- iCall->ReqCompleted(iNotifyDurationChange.iNotifyHandle,KErrCancel);
- }
- }
-
-void CSimCallDuration::GetDuration(TTimeIntervalSeconds* aTime)
- {
- *aTime = iCallDuration;
- }
-
-CSimCallRemotePartyInfoChange* CSimCallRemotePartyInfoChange::NewL(CSimCall* aCall)
-/**
- * Standard two-phase constructor.
- * @param aCall on upon remote party info is needed
- * @return CSimCallRemotePartyInfoChange
- */
- {
- CSimCallRemotePartyInfoChange* self=new(ELeave) CSimCallRemotePartyInfoChange(aCall);
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop();
- return self;
- }
-
-CSimCallRemotePartyInfoChange::CSimCallRemotePartyInfoChange(CSimCall* aCall)
- :iCall(aCall)
-/**
- * Trivial first phase construction.
- * @param aCall is call object upon remote party info is needed.
- */
- {
- iNotifyRemotePartyInfo.iNotifyPending=EFalse;
- iNotifyRemotePartyInfo.iNotifyData=0;
- }
-
-
-void CSimCallRemotePartyInfoChange::ConstructL()
- {
- iRemoteInfoTimer = CSimTimer::NewL(iCall->iLine->iPhone);
- }
-
-void CSimCallRemotePartyInfoChange::Start()
- {
- iRemoteInfoTimer->Start(iDelay, this);
- }
-
-CSimCallRemotePartyInfoChange::~CSimCallRemotePartyInfoChange()
-/**
- * Standard destructor. Destroy the heap-based object owned by this object.
- */
- {
- if (iRemoteInfoTimer)
- {
- if (iRemoteInfoTimer->IsActive())
- iRemoteInfoTimer->Cancel();
- delete iRemoteInfoTimer;
- }
- }
-
-void CSimCallRemotePartyInfoChange::TimerCallBack(TInt /*aId*/)
- {
- if(iRemotePartyInfoV1.iRemoteIdStatus != RMobileCall::ERemoteIdentityUnknown && iNotifyRemotePartyInfo.iNotifyPending)
- {
- iNotifyRemotePartyInfo.iNotifyPending=EFalse;
- *(RMobileCall::TMobileCallRemotePartyInfoV1*)iNotifyRemotePartyInfo.iNotifyData=iRemotePartyInfoV1;
- iCall->ReqCompleted(iNotifyRemotePartyInfo.iNotifyHandle,KErrNone);
- }
- }
-
-TInt CSimCall::NotifyRemotePartyInfoChange(const TTsyReqHandle aTsyReqHandle, TDes8* aRemoteParty)
-/**
-* Record a client's interest in being notified when the remote party info changes.
-* First check that there isn't already a notification pending (the ETel Server should protect
-* against this) and then record the information necessary to complete the request later, when
-* the status does actually change.
-*
-* @param aTsyReqHandle Tsy Request handle for the client request
-* @param aStatus pointer to the call status
-* @return KErrNone
-*/
- {
- LOGCALL1(">>CSimCall::NotifyRemotePartyInfoChange");
- __ASSERT_ALWAYS(iNotifyRemotePartyInfoTimer, SimPanic(EOjectNotConstructed));
- __ASSERT_ALWAYS(!iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyPending,SimPanic(ENotificationAlreadyPending));
-
- RMobileCall::TMobileCallRemotePartyInfoV1Pckg* remotepartyPckg = (RMobileCall::TMobileCallRemotePartyInfoV1Pckg*) aRemoteParty;
- RMobileCall::TMobileCallRemotePartyInfoV1& remoteparty = (*remotepartyPckg)();
-
- // Check that the data structure is supported by the simulated TSY version
- TInt err = iPhone->CheckSimTsyVersion(remoteparty);
- if(err != KErrNone)
- {
- ReqCompleted(aTsyReqHandle, err);
- return KErrNone;
- }
-
- //start timer
- iNotifyRemotePartyInfoTimer->Start();
-
- iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyPending = ETrue;
- iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyHandle = aTsyReqHandle;
- iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyData = &remoteparty;
- LOGCALL1("<<CSimCall::NotifyRemotePartyInfoChange");
- return KErrNone;
- }
-
-TInt CSimCall::NotifyRemotePartyInfoChangeCancel()
-/**
-* Cancel a client's interest in being notified when the remote party info changes.
-* This is acheived simply by resetting the flag that indicates a notification is pending.
-*
-* @return KErrNone
-*/
- {
- LOGCALL1(">>CSimCall::NotifyRemotePartyInfoChangeCancel");
- if(iNotifyRemotePartyInfoTimer && iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyPending)
- {
- iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyPending=EFalse;
- ReqCompleted(iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyHandle,KErrCancel);
- }
- LOGCALL1("<<CSimCall::NotifyRemotePartyInfoChangeCancel");
- return KErrNone;
- }
+// 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 call classes. The call classes
+// process the call-based requests made by ETel clients and passed down to the TSY by the
+// ETel Server.
+//
+//
+
+/**
+ @file
+*/
+
+#include "CSimCall.h"
+#include "CSimPhone.h"
+#include "Simlog.h"
+
+void CSimCall::CloseCall(TAny* aObj)
+/**
+* Utility func for cleanup stack
+*
+* @param aObj a pointer to the CObject to close
+*/
+ {
+ ((CObject*)aObj)->Close();
+ }
+
+CSimCall::CSimCall(CSimLine* aLine,const TName& aName, CSimPhone* aPhone)
+ : iState(RMobileCall::EStatusIdle),iLine(aLine),
+ iHookState(ConvertStateToHook(iState)), iPhone(aPhone)
+ {
+ iNotifyStatusChange.iNotifyPending = EFalse;
+ iMobileNotifyStatusChange.iNotifyPending = EFalse;
+ iAnswerIncomingCall.iNotifyPending = EFalse;
+ iName.Copy(aName);
+ }
+
+void CSimCall::ConstructL()
+/**
+* Standard constructor
+*/
+ {
+ iCallDurationHandler = CSimCallDuration::NewL(this);
+ iNotifyRemotePartyInfoTimer = CSimCallRemotePartyInfoChange::NewL(this);
+ }
+
+
+CSimCall::~CSimCall()
+/**
+* Standard destructor
+*/
+ {
+ iLine->CallDestructor(this);
+ delete iCallDurationHandler;
+ delete iNotifyRemotePartyInfoTimer;
+ }
+
+CTelObject::TReqMode CSimCall::ReqModeL(const TInt aIpc)
+/**
+* This function returns the Request Mode for the request with the passed IPC value.
+* The ETel Server provides a function for returning the standard request modes for
+* the Core API requests.
+* Multimode API requests mode are handled here.
+*
+* @param aIpc the IPc number representing the client request
+* @return CTelObject::TReqMode the request mode to be used for this IPc number
+* @leave Leaves if the IPc number is not found
+*/
+ {
+ // ReqModeL is called from the server's CTelObject::ReqAnalyserL
+ // in order to check the type of request it has
+
+ CTelObject::TReqMode reqMode=0;
+ LOGCALL2("CSimCall::ReqModeL called with IPC number %d",aIpc);
+ switch (aIpc)
+ {
+ //
+ // No Flow Control NOR Multiple Completion
+ //
+ case EMobileCallGetMobileDataCallCaps:
+ case EMobileCallGetMobileCallCaps:
+ case EMobileCallGetMobileCallStatus:
+ case EMobileCallGetMobileCallInfo:
+ case EMobileCallDialEmergencyCall:
+ case EMobileCallGetMobileDataCallRLPRange:
+ case EMobileCallSetDynamicHscsdParams:
+ case EMobileCallGetCurrentHscsdInfo:
+ case EMobileCallHold:
+ case EMobileCallResume:
+ case EMobileCallSwap:
+ case EMobileCallAnswerISV:
+ break;
+
+ //
+ // Flow Control Obeyed
+ //
+ case EMobileCallDialISV:
+ reqMode=KReqModeFlowControlObeyed;
+ break;
+
+ //
+ // Multiple Completion Services with Immediate Server Repost
+ // (Usually Notifications)
+ //
+
+ case EMobileCallNotifyHscsdInfoChange:
+ case EMobileCallNotifyMobileCallStatusChange:
+ case EMobileCallNotifyMobileCallCapsChange:
+ case EMobileCallNotifyRemotePartyInfoChange:
+ reqMode=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
+ break;
+
+ default:
+ reqMode=CCallBase::ReqModeL(aIpc);
+ break;
+ }
+ return reqMode;
+ }
+
+TInt CSimCall::NumberOfSlotsL(const TInt aIpc)
+/**
+* NumberOfSlotsL is called by the server when it is registering a new notification
+* It enables the TSY to tell the server how many buffer slots to allocate for
+* "repost immediately" notifications that may trigger before clients collect them
+*
+* @param aIpc the IPc number representing the client request
+* @return TInt the number of slots required
+* @leave Leaves if the IPc number is not found
+*/
+ {
+ switch (aIpc)
+ {
+ case EMobileCallNotifyHscsdInfoChange:
+ case EMobileCallNotifyMobileDataCallCapsChange:
+ case EMobileCallNotifyMobileCallStatusChange:
+ case EMobileCallNotifyMobileCallCapsChange:
+ case EMobileCallNotifyRemotePartyInfoChange:
+ LOGCALL1("CSimCall: Registered with default number of slots");
+ return KDefaultNumberOfSlots;
+ default:
+ LOGCALL1("CSimCall::NumberOfSlotsL: No match for IPC, defering to base function");
+ break;
+ }
+ return CCallBase::NumberOfSlotsL(aIpc);
+ }
+
+
+TInt CSimCall::RegisterNotification(const TInt /*aIpc*/)
+/**
+* The ETel Server calls this function when the first client makes a notification
+* request. If supported by the underlying protocol controlling the
+* signalling stack, this can be used to start requesting updates for the relevant service.
+*/
+ {
+ return KErrNone;
+ }
+
+TInt CSimCall::DeregisterNotification(const TInt /*aIpc*/)
+/**
+* The ETel Server calls this function when the last client that had previously
+* made a notification request closes its ETel Server handle. If supported by
+* the underlying protocol controlling the signalling stack, this can be used
+* to stop requesting updates for the relevant service.
+*/
+ {
+ return KErrNone;
+ }
+
+
+void CSimCall::Init()
+/**
+* This function can be used to perform any necessary synchronous initialisation.
+*/
+ {}
+
+TInt CSimCall::GetCaps(const TTsyReqHandle aTsyReqHandle,RCall::TCaps* aCallCaps)
+/**
+* Retrieve the Call capabilities
+*
+* @param aTsyReqHandle TSY handle associated with this request.s
+* @param aCallCaps Pointer to the call capability
+* @return KErrNone
+*/
+ {
+ aCallCaps->iFlags=iCaps;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyCapsChange(const TTsyReqHandle aTsyReqHandle, RCall::TCaps* aCaps)
+/**
+* Register a client's interest in being notified when the call caps change.
+* @param aTsyReqHandle The TSY handle associated with this request.
+* @param aCaps The capability structure that will be populated with the new capability
+* information.
+* @return TInt Standard error code.
+*/
+ {
+ __ASSERT_ALWAYS(!iNotifyCapsChange.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
+ iNotifyCapsChange.iNotifyPending=ETrue;
+ iNotifyCapsChange.iNotifyHandle=aTsyReqHandle;
+ iNotifyCapsChange.iNotifyData=aCaps;
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyCapsChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancel a client's interest in being notified when the call capabilities change.
+*/
+ {
+ if(iNotifyCapsChange.iNotifyPending)
+ {
+ iNotifyCapsChange.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyCapsChange.iNotifyHandle,KErrCancel);
+ }
+ return KErrNone;
+ }
+
+TInt CSimCall::GetMobileCallCaps(const TTsyReqHandle aTsyReqHandle, TDes8* aCaps)
+/**
+* Retrieve the Mobile Call capabilities
+*
+* @param aTsyReqHandle TSY handle associated with this request.
+* @param aCaps Pointer to the call capability
+* @return KErrNone
+*/
+ {
+ TPckg<RMobileCall::TMobileCallCapsV1>* capsPckg=(TPckg<RMobileCall::TMobileCallCapsV1>*)aCaps;
+ RMobileCall::TMobileCallCapsV1& caps=(*capsPckg)();
+
+ // Check that the data structure is supported by the simulated TSY version
+ TInt err = iPhone->CheckSimTsyVersion(caps);
+ if(err != KErrNone)
+ {
+ ReqCompleted(aTsyReqHandle, err);
+ return KErrNone;
+ }
+
+ caps.iCallControlCaps=iCaps; // None of the extended caps are supported.
+ caps.iCallEventCaps=0;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyMobileCallCapsChange(const TTsyReqHandle aTsyReqHandle, TDes8* aCaps)
+/**
+* Register a client's interest in being notified when the RMobileCall capabilities change.
+* @param aTsyReqHandle The TSY handle associated with this request.
+* @param aCaps The capability structure that will be populated with the new capability
+* information.
+* @return TInt Standard error code.
+*/
+ {
+ __ASSERT_ALWAYS(!iNotifyMobileCapsChange.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
+ iNotifyMobileCapsChange.iNotifyPending=ETrue;
+ iNotifyMobileCapsChange.iNotifyHandle=aTsyReqHandle;
+ iNotifyMobileCapsChange.iNotifyData=aCaps;
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyMobileCallCapsChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancel a client's interest in being notified when the RMobileCall capabilities change.
+*/
+ {
+ if(iNotifyMobileCapsChange.iNotifyPending)
+ {
+ iNotifyMobileCapsChange.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyMobileCapsChange.iNotifyHandle,KErrCancel);
+ }
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyHookChange(const TTsyReqHandle aTsyReqHandle, RCall::THookStatus* aHookStatus)
+/**
+* Record a client's interst in being notified when the hook changes state.
+*
+* @param aTsyReqHandle Tsy Request handle for the client request
+* @param aHookStatus pointer to the hook status
+* @return KErrNone
+*/
+ {
+ LOGCALL1(">>CSimCall::NotifyHookChange");
+ iNotifyHookChange.iNotifyPending = ETrue;
+ iNotifyHookChange.iNotifyHandle = aTsyReqHandle;
+ iNotifyHookChange.iNotifyData = aHookStatus;
+ LOGCALL1("<<CSimCall::NotifyHookChange");
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyHookChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancel a client's interest in being notified when the hook state changes.
+*
+* @param aTsyReqHandle Tsy Request handle for the client cancel request
+* @return KErrNone
+*/
+ {
+ LOGCALL1(">>CSimCall::NotifyHookChangeCancel");
+ if(iNotifyHookChange.iNotifyPending)
+ {
+ iNotifyHookChange.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrCancel);
+ }
+ LOGCALL1("<<CSimCall::NotifyHookChangeCancel");
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyMobileCallStatusChange(const TTsyReqHandle aTsyReqHandle,RMobileCall::TMobileCallStatus* aStatus)
+/**
+* Record a client's interest in being notified when the call status changes.
+* First check that there isn't already a notification pending (the ETel Server should protect
+* against this) and then record the information necessary to complete the request later, when
+* the status does actually change.
+*
+* @param aTsyReqHandle Tsy Request handle for the client request
+* @param aStatus pointer to the call status
+* @return KErrNone
+*/
+ {
+ LOGCALL1(">>CSimCall::NotifyMobileCallStatusChange");
+ __ASSERT_ALWAYS(!iMobileNotifyStatusChange.iNotifyPending,SimPanic(ENotificationAlreadyPending));
+
+ iMobileNotifyStatusChange.iNotifyPending = ETrue;
+ iMobileNotifyStatusChange.iNotifyHandle = aTsyReqHandle;
+ iMobileNotifyStatusChange.iNotifyData = aStatus;
+ LOGCALL1("<<CSimCall::NotifyMobileCallStatusChange");
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyMobileCallStatusChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancel a client's interest in being notified when the call status changes.
+* This is acheived simply by resetting the flag that indicates a notification is pending.
+*
+* @param aTsyReqHandle Tsy Request handle for the client cancel request
+* @return KErrNone
+*/
+ {
+ LOGCALL1(">>CSimCall::NotifyMobileCallStatusChangeCancel");
+ if(iMobileNotifyStatusChange.iNotifyPending)
+ {
+ iMobileNotifyStatusChange.iNotifyPending=EFalse;
+ ReqCompleted(iMobileNotifyStatusChange.iNotifyHandle,KErrCancel);
+ }
+ LOGCALL1("<<CSimCall::NotifyMobileCallStatusChangeCancel");
+ return KErrNone;
+ }
+
+
+TInt CSimCall::NotifyStatusChange(const TTsyReqHandle aTsyReqHandle,RCall::TStatus* aStatus)
+/**
+* Record a client's interest in being notified when the call status changes.
+* First check that there isn't already a notification pending (the ETel Server should protect
+* against this) and then record the information necessary to complete the request later, when
+* the status does actually change.
+*
+* @param aTsyReqHandle Tsy Request handle for the client request
+* @param aStatus pointer to the call status
+* @return KErrNone
+*/
+ {
+ LOGCALL1(">>CSimCall::NotifyStatusChange");
+ __ASSERT_ALWAYS(!iNotifyStatusChange.iNotifyPending,SimPanic(ENotificationAlreadyPending));
+
+ iNotifyStatusChange.iNotifyPending = ETrue;
+ iNotifyStatusChange.iNotifyHandle = aTsyReqHandle;
+ iNotifyStatusChange.iNotifyData = aStatus;
+ LOGCALL1("<<CSimCall::NotifyStatusChange");
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyStatusChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancel a client's interest in being notified when the call status changes.
+* This is acheived simply by resetting the flag that indicates a notification is pending.
+*
+* @param aTsyReqHandle Tsy Request handle for the client cancel request
+* @return KErrNone
+*/
+ {
+ LOGCALL1(">>CSimCall::NotifyStatusChangeCancel");
+ if(iNotifyStatusChange.iNotifyPending)
+ {
+ iNotifyStatusChange.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrCancel);
+ }
+ LOGCALL1("<<CSimCall::NotifyStatusChangeCancel");
+ return KErrNone;
+ }
+
+
+
+TInt CSimCall::NotifyDurationChange(const TTsyReqHandle aTsyReqHandle,TTimeIntervalSeconds* aTime)
+/**
+* Record a client's interest in being notified when the call duration changes.
+*
+* @param aTsyReqHandle
+* @param aTime
+* @return KErrNone or symbian wide error code
+*/
+ {
+ iCallDurationHandler->StartNotification(aTsyReqHandle, aTime);
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyDurationChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Not Supported in this TSY
+*/
+ {
+ iCallDurationHandler->StopNotification();
+ return KErrNone;
+ }
+
+TInt CSimCall::GetInfo(const TTsyReqHandle aTsyReqHandle, RCall::TCallInfo* aCallInfo)
+/**
+* Retrieve the Call Information.
+*
+* @param aTsyReqHandle
+* @param aCallInfo pointer to the call information to be returned to client
+* @return KErrNone
+*/
+ {
+ aCallInfo->iCallName.Copy(iName);
+ aCallInfo->iLineName.Copy(iLine->iLineName);
+ aCallInfo->iHookStatus=ConvertStateToHook(iState);
+ aCallInfo->iStatus=GetCoreCallStatus();
+ aCallInfo->iDuration=0;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CSimCall::GetMobileCallInfo(const TTsyReqHandle aTsyReqHandle, TDes8* aMobileCallInfo)
+/**
+* Retrieve the Mobile Call Information
+*
+* @param aTsyReqHandle
+* @param aCallInfo pointer to the call information to be returned to client
+* @return KErrNone
+*/
+ {
+ RMobileCall::TMobileCallInfoV1Pckg* mobileCallInfoV1=(RMobileCall::TMobileCallInfoV1Pckg*)aMobileCallInfo;
+ RMobileCall::TMobileCallInfoV1& mobileCallInfo=(*mobileCallInfoV1)();
+
+ // Check that the data structure is supported by the simulated TSY version
+ TInt err = iPhone->CheckSimTsyVersion(mobileCallInfo);
+ if(err != KErrNone)
+ {
+ ReqCompleted(aTsyReqHandle, err);
+ return KErrNone;
+ }
+
+ TUint caps=Caps();
+ if(caps&RCall::KCapsVoice)
+ mobileCallInfo.iService=RMobilePhone::EVoiceService;
+ else if(caps&RCall::KCapsData)
+ mobileCallInfo.iService=RMobilePhone::ECircuitDataService;
+ else if(caps&RCall::KCapsFax)
+ mobileCallInfo.iService=RMobilePhone::EFaxService;
+ else
+ mobileCallInfo.iService=RMobilePhone::EServiceUnspecified;
+
+ mobileCallInfo.iValid=0x0;
+ mobileCallInfo.iStatus=iState;
+ mobileCallInfo.iCallName.Copy(iName);
+ mobileCallInfo.iLineName.Copy(iLine->iLineName);
+ LOGCALL2("CSimCall::GetMobileCallInfo request completed with %d",iState);
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+RCall::TStatus CSimCall::GetCoreCallStatus()
+/**
+* Converts Multimode call status (RMobileCall::TMobileCallStatus) to
+* Core call Status (RCall::TStatus)
+*
+* @return RCall::TStatus The core call status
+*/
+ {
+// All status enums with values of Disconnecting and below are identical in
+// ETelMM and Core, so the mapping function is simple.
+ RCall::TStatus coreStatus;
+ if (iState <= RMobileCall::EStatusDisconnecting)
+ coreStatus = (RCall::TStatus)iState;
+ else
+ switch (iState)
+ {
+ case RMobileCall::EStatusReconnectPending:
+ case RMobileCall::EStatusHold:
+ coreStatus = RCall::EStatusConnected;
+ break;
+ case RMobileCall::EStatusWaitingAlternatingCallSwitch:
+ coreStatus = RCall::EStatusIdle;
+ break;
+ default:
+ coreStatus = RCall::EStatusUnknown;
+ break;
+ }
+ return coreStatus;
+ }
+
+TInt CSimCall::GetStatus(const TTsyReqHandle aTsyReqHandle, RCall::TStatus* aCallStatus)
+/**
+* Return the current call state. (Core API request)
+*
+* @param aTsyReqHandle
+* @param aCallStatus pointer to the call status
+* @return KErrNone
+*/
+ {
+ LOGCALL1(">>CSimCall::GetStatus");
+ *aCallStatus=GetCoreCallStatus();
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ LOGCALL1("<<CSimCall::GetStatus");
+ return KErrNone;
+ }
+
+TInt CSimCall::GetMobileCallStatus(const TTsyReqHandle aTsyReqHandle, RMobileCall::TMobileCallStatus* aCallStatus)
+/**
+* Return the current call state. (Multimode API request)
+*
+* @param aTsyReqHandle
+* @param aCallStatus pointer to the call status
+* @return KErrNone
+*/
+ {
+ LOGCALL1(">>CSimCall::GetMobileCallStatus");
+ *aCallStatus=iState;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ LOGCALL1("<<CSimCall::GetMobileCallStatus");
+ return KErrNone;
+ }
+
+TInt CSimCall::TransferOwnership(const TTsyReqHandle aTsyReqHandle)
+/**
+* Transfer call ownership
+* Not supported in this version of the Simulator TSY
+*/
+ {
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+
+TInt CSimCall::AcquireOwnership(const TTsyReqHandle aTsyReqHandle)
+/**
+* Acquires call ownership
+* Not supported in this version of the Simulator TSY
+*/
+ {
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+
+TInt CSimCall::AcquireOwnershipCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* cancel AcquireOwnership request
+* Not supported in this version of the Simulator TSY
+*/
+ {
+ return KErrNone;
+ }
+
+TInt CSimCall::GetCallDuration(const TTsyReqHandle aTsyReqHandle, TTimeIntervalSeconds* aTime)
+/**
+* Retrieves the last call duration
+* Not supported in this version of the Simulator TSY
+*/
+ {
+ LOGCALL1(">>CSimCall::GetCallDuration");
+
+ iCallDurationHandler->GetDuration(aTime);
+
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ LOGCALL1("<<CSimCall::GetCallDuration");
+ return KErrNone;
+ }
+
+TInt CSimCall::RecoverDataPortAndRelinquishOwnership()
+/**
+* Recovers the comm port.
+* This is a data call specific request so not supported here.
+*/
+ {
+ return KErrNotSupported;
+ }
+
+TInt CSimCall::GetFaxSettings(const TTsyReqHandle,RCall::TFaxSessionSettings*)
+/**
+* Retrieves the last fax settings
+* Not supported in this version of the Simulator TSY
+*/
+ {
+ return KErrNotSupported;
+ }
+
+TInt CSimCall::SetFaxSettings(const TTsyReqHandle,const RCall::TFaxSessionSettings*)
+/**
+* Sets the fax settings
+* Not supported in this version of the Simulator TSY
+*/
+ {
+ return KErrNotSupported;
+ }
+
+CTelObject* CSimCall::OpenNewObjectByNameL(const TDesC& /*aName*/)
+/**
+* Only Fax Calls can be opened from the Call object, KErrNotSupported is returned.
+*/
+
+ {
+ User::Leave(KErrNotSupported);
+ return NULL;
+ }
+
+CTelObject* CSimCall::OpenNewObjectL(TDes& /*aNewName*/)
+/**
+* Only Fax objects can be opened from the Call object, and we are not supporting fax calls
+* in this TSY. KErrNotSupported is returned.
+*/
+ {
+ User::Leave(KErrNotSupported);
+ return NULL;
+ }
+
+TBool CSimCall::Used()
+ {
+ return (AccessCount()>1);
+ }
+
+void CSimCall::SetUsed()
+ {
+ (void)Open();
+ }
+
+void CSimCall::SetUnused()
+ {
+ Close();
+ }
+
+TInt CSimCall::ChangeStateL(RMobileCall::TMobileCallStatus aNewState,TBool aSwap, TBool aNoPropagation)
+/**
+* Attempt to change state.
+* First validate that the requested state change is ok. If it is then proceed to change
+* the state and complete any pending state change notification.
+*
+* @param aState the new state to change to
+* @param aSwap indicates that state change takes place as a consequence of swap operation on the call
+* @param aNoPropagation indicates whether change propagate to the holder line object
+* @return Error indication if change of state is successful or not
+*/
+ {
+ LOGCALL3(">>CSimCall::ChangeState 0x%08x [newState=%d] entry", this,aNewState);
+
+ if(!aNoPropagation)
+ {
+ TInt ret=iLine->ChangeStateL(aNewState,aSwap,this);
+ if(ret!=KErrNone)
+ return ret;
+ }
+
+// Check for call duration change
+ if (!iCallDurationHandler)
+ iCallDurationHandler=CSimCallDuration::NewL(this);
+ if ((iState != RMobileCall::EStatusConnected) && (iState != RMobileCall::EStatusHold) && (aNewState == RMobileCall::EStatusConnected))
+ iCallDurationHandler->StartDuration();
+ else if ((aNewState != RMobileCall::EStatusConnected) && (aNewState != RMobileCall::EStatusHold) && ((iState == RMobileCall::EStatusConnected) || (iState == RMobileCall::EStatusHold)))
+ iCallDurationHandler->StopDuration();
+
+// Actually change the state.
+ iState=aNewState;
+
+// Check for a pending state change notification (core)
+ if(iNotifyStatusChange.iNotifyPending)
+ {
+ iNotifyStatusChange.iNotifyPending=EFalse;
+ *(RCall::TStatus*)iNotifyStatusChange.iNotifyData=GetCoreCallStatus();
+ ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrNone);
+ }
+
+// Check for a pending state change notification (multimode)
+ if(iMobileNotifyStatusChange.iNotifyPending)
+ {
+ iMobileNotifyStatusChange.iNotifyPending=EFalse;
+ *(RMobileCall::TMobileCallStatus*)iMobileNotifyStatusChange.iNotifyData=iState;
+ ReqCompleted(iMobileNotifyStatusChange.iNotifyHandle,KErrNone);
+ }
+
+// Check for a pending hook change notification.
+ RCall::THookStatus hookStatus=ConvertStateToHook(iState);
+ if(iHookState!=hookStatus)
+ {
+ iHookState=hookStatus;
+ if(iNotifyHookChange.iNotifyPending)
+ {
+ iNotifyHookChange.iNotifyPending=EFalse;
+ *(RCall::THookStatus*)iNotifyHookChange.iNotifyData=iHookState;
+ ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrNone);
+ }
+ }
+
+// Check for a possible change in capabilities.
+ TUint caps=Caps();
+ if(iCaps!=caps)
+ {
+ iCaps=caps;
+ if(iNotifyCapsChange.iNotifyPending)
+ {
+ iNotifyCapsChange.iNotifyPending=EFalse;
+ ((RCall::TCaps*)iNotifyCapsChange.iNotifyData)->iFlags=iCaps;
+ ReqCompleted(iNotifyCapsChange.iNotifyHandle,KErrNone);
+ }
+ if(iNotifyMobileCapsChange.iNotifyPending)
+ {
+ iNotifyMobileCapsChange.iNotifyPending=EFalse;
+ TPckg<RMobileCall::TMobileCallCapsV1>* mobileCallCapsPckg=(TPckg<RMobileCall::TMobileCallCapsV1>*)iNotifyMobileCapsChange.iNotifyData;
+ RMobileCall::TMobileCallCapsV1& mobileCallCaps=(*mobileCallCapsPckg)();
+
+ mobileCallCaps.iCallControlCaps=iCaps; // None of the extended caps are supported.
+ mobileCallCaps.iCallEventCaps=0;
+ ReqCompleted(iNotifyMobileCapsChange.iNotifyHandle,KErrNone);
+ }
+ }
+ if((aNewState == RMobileCall::EStatusConnected && !aSwap)|| aNewState == RMobileCall::EStatusDisconnecting)
+ iLine->UpdatePhoneNotifiers(this,aNewState);
+
+ LOGCALL2("<<CSimCall::ChangeState exit %d",iState);
+ return KErrNone;
+ }
+
+
+void CSimCall::UpdateNotifiers()
+/**
+ Update notifiers of other voice call when it gets swapped
+*/
+ {
+ LOGCALL2(">>CSimCall::UpdateNotifiers 0x%08x entry", this);
+
+// Check for call duration change
+ if (!iCallDurationHandler)
+ {
+ TRAP_IGNORE(iCallDurationHandler=CSimCallDuration::NewL(this));
+ }
+
+
+// Check for a pending state change notification (core)
+ if(iNotifyStatusChange.iNotifyPending)
+ {
+ iNotifyStatusChange.iNotifyPending=EFalse;
+ *(RCall::TStatus*)iNotifyStatusChange.iNotifyData=GetCoreCallStatus();
+ ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrNone);
+ }
+
+// Check for a pending state change notification (multimode)
+ if(iMobileNotifyStatusChange.iNotifyPending)
+ {
+ iMobileNotifyStatusChange.iNotifyPending=EFalse;
+ *(RMobileCall::TMobileCallStatus*)iMobileNotifyStatusChange.iNotifyData=iState;
+ ReqCompleted(iMobileNotifyStatusChange.iNotifyHandle,KErrNone);
+ }
+
+// Check for a pending hook change notification.
+ RCall::THookStatus hookStatus=ConvertStateToHook(iState);
+ if(iHookState!=hookStatus)
+ {
+ iHookState=hookStatus;
+ if(iNotifyHookChange.iNotifyPending)
+ {
+ iNotifyHookChange.iNotifyPending=EFalse;
+ *(RCall::THookStatus*)iNotifyHookChange.iNotifyData=iHookState;
+ ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrNone);
+ }
+ }
+
+// Check for a possible change in capabilities.
+ TUint caps=Caps();
+ if(iCaps!=caps)
+ {
+ iCaps=caps;
+ if(iNotifyCapsChange.iNotifyPending)
+ {
+ iNotifyCapsChange.iNotifyPending=EFalse;
+ ((RCall::TCaps*)iNotifyCapsChange.iNotifyData)->iFlags=iCaps;
+ ReqCompleted(iNotifyCapsChange.iNotifyHandle,KErrNone);
+ }
+ if(iNotifyMobileCapsChange.iNotifyPending)
+ {
+ iNotifyMobileCapsChange.iNotifyPending=EFalse;
+ TPckg<RMobileCall::TMobileCallCapsV1>* mobileCallCapsPckg=(TPckg<RMobileCall::TMobileCallCapsV1>*)iNotifyMobileCapsChange.iNotifyData;
+ RMobileCall::TMobileCallCapsV1& mobileCallCaps=(*mobileCallCapsPckg)();
+
+ mobileCallCaps.iCallControlCaps=iCaps; // None of the extended caps are supported.
+ mobileCallCaps.iCallEventCaps=0;
+ ReqCompleted(iNotifyMobileCapsChange.iNotifyHandle,KErrNone);
+ }
+ }
+
+ LOGCALL2("<<CSimCall::UpdateNotifiers exit %d",iState);
+ }
+
+TInt CSimCall::ActionEvent(TCallEvent /*aEvent*/, TInt /*aStatus*/)
+/**
+* This is an empty shell function. Each line should implement its own
+* state machine.
+*/
+ {
+ return KErrNotSupported;
+ }
+
+void CSimCall::GenerateCoreCallCaps(TUint& aCaps)
+/**
+ * Populate the variable capabilities that are dependant upon the call state.
+ * @param TUint The capability variable that will be populated with the core capabilities.
+ */
+ {
+ if(iState==RMobileCall::EStatusIdle)
+ aCaps |= RCall::KCapsDial;
+
+ if(iState==RMobileCall::EStatusConnected)
+ aCaps |= RCall::KCapsHangUp;
+
+ if((iLine->IsAnswerCallObjectSpare())&&(iState==RMobileCall::EStatusIdle))
+ aCaps |= RCall::KCapsAnswer;
+ }
+
+void CSimCall::ResetIfRingingL()
+ {
+ if(iState==RMobileCall::EStatusRinging)
+ __ASSERT_ALWAYS(ChangeStateL(RMobileCall::EStatusIdle,EFalse,ETrue) == KErrNone, SimPanic(EGeneral));
+ }
+
+void CSimCallDuration::TimerCallBack(TInt /*aId*/)
+ {
+ //increase duration by 1 sec
+ iCallDuration=static_cast<TTimeIntervalSeconds>(iCallDuration.Int()+1);
+
+ if(iNotifyDurationChange.iNotifyPending)
+ {
+ *(TTimeIntervalSeconds*)iNotifyDurationChange.iNotifyData=iCallDuration;
+ iNotifyDurationChange.iNotifyPending=EFalse;
+ iCall->ReqCompleted(iNotifyDurationChange.iNotifyHandle,KErrNone);
+ }
+ iDurationTimer->Start(1 , this);
+ }
+
+CSimCallDuration* CSimCallDuration::NewL(CSimCall* aCall)
+/**
+ * Standard two-phase constructor.
+ * @param aPhone The parent phone object.
+ * @return CSimCallDuration The new CallDuration class
+ */
+ {
+ CSimCallDuration* self=new(ELeave) CSimCallDuration(aCall);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CSimCallDuration::CSimCallDuration(CSimCall* aCall)
+ :iCallDuration(0),iCall(aCall)
+/**
+ * Trivial first phase construction.
+ * @param aPhone The parent phone object.
+ */
+ {
+ iNotifyDurationChange.iNotifyPending=EFalse;
+ iNotifyDurationChange.iNotifyData=0;
+ }
+
+
+void CSimCallDuration::ConstructL()
+ {
+ iDurationTimer = CSimTimer::NewL(iCall->iLine->iPhone);
+ }
+
+
+CSimCallDuration::~CSimCallDuration()
+/**
+ * Standard destructor. Destroy the heap-based object owned by this object.
+ */
+ {
+ if (iDurationTimer)
+ {
+ if (iDurationTimer->IsActive())
+ iDurationTimer->Cancel();
+ delete iDurationTimer;
+ }
+ }
+
+void CSimCallDuration::StartDuration()
+ {
+ iCallDuration = 0;
+ iDurationTimer->Start(1 , this);
+ }
+
+void CSimCallDuration::StopDuration()
+ {
+ if (iDurationTimer)
+ {
+ if (iDurationTimer->IsActive())
+ iDurationTimer->Cancel();
+ }
+ }
+
+void CSimCallDuration::StartNotification(TTsyReqHandle aTsyReqHandle, TTimeIntervalSeconds* aTime)
+ {
+ __ASSERT_ALWAYS(!iNotifyDurationChange.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
+ iNotifyDurationChange.iNotifyData=aTime;
+ iNotifyDurationChange.iNotifyPending=ETrue;
+ iNotifyDurationChange.iNotifyHandle=aTsyReqHandle;
+ }
+
+void CSimCallDuration::StopNotification()
+ {
+ if(iNotifyDurationChange.iNotifyPending)
+ {
+ iNotifyDurationChange.iNotifyPending=EFalse;
+ iCall->ReqCompleted(iNotifyDurationChange.iNotifyHandle,KErrCancel);
+ }
+ }
+
+void CSimCallDuration::GetDuration(TTimeIntervalSeconds* aTime)
+ {
+ *aTime = iCallDuration;
+ }
+
+CSimCallRemotePartyInfoChange* CSimCallRemotePartyInfoChange::NewL(CSimCall* aCall)
+/**
+ * Standard two-phase constructor.
+ * @param aCall on upon remote party info is needed
+ * @return CSimCallRemotePartyInfoChange
+ */
+ {
+ CSimCallRemotePartyInfoChange* self=new(ELeave) CSimCallRemotePartyInfoChange(aCall);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CSimCallRemotePartyInfoChange::CSimCallRemotePartyInfoChange(CSimCall* aCall)
+ :iCall(aCall)
+/**
+ * Trivial first phase construction.
+ * @param aCall is call object upon remote party info is needed.
+ */
+ {
+ iNotifyRemotePartyInfo.iNotifyPending=EFalse;
+ iNotifyRemotePartyInfo.iNotifyData=0;
+ }
+
+
+void CSimCallRemotePartyInfoChange::ConstructL()
+ {
+ iRemoteInfoTimer = CSimTimer::NewL(iCall->iLine->iPhone);
+ }
+
+void CSimCallRemotePartyInfoChange::Start()
+ {
+ iRemoteInfoTimer->Start(iDelay, this);
+ }
+
+CSimCallRemotePartyInfoChange::~CSimCallRemotePartyInfoChange()
+/**
+ * Standard destructor. Destroy the heap-based object owned by this object.
+ */
+ {
+ if (iRemoteInfoTimer)
+ {
+ if (iRemoteInfoTimer->IsActive())
+ iRemoteInfoTimer->Cancel();
+ delete iRemoteInfoTimer;
+ }
+ }
+
+void CSimCallRemotePartyInfoChange::TimerCallBack(TInt /*aId*/)
+ {
+ if(iRemotePartyInfoV1.iRemoteIdStatus != RMobileCall::ERemoteIdentityUnknown && iNotifyRemotePartyInfo.iNotifyPending)
+ {
+ iNotifyRemotePartyInfo.iNotifyPending=EFalse;
+ *(RMobileCall::TMobileCallRemotePartyInfoV1*)iNotifyRemotePartyInfo.iNotifyData=iRemotePartyInfoV1;
+ iCall->ReqCompleted(iNotifyRemotePartyInfo.iNotifyHandle,KErrNone);
+ }
+ }
+
+TInt CSimCall::NotifyRemotePartyInfoChange(const TTsyReqHandle aTsyReqHandle, TDes8* aRemoteParty)
+/**
+* Record a client's interest in being notified when the remote party info changes.
+* First check that there isn't already a notification pending (the ETel Server should protect
+* against this) and then record the information necessary to complete the request later, when
+* the status does actually change.
+*
+* @param aTsyReqHandle Tsy Request handle for the client request
+* @param aStatus pointer to the call status
+* @return KErrNone
+*/
+ {
+ LOGCALL1(">>CSimCall::NotifyRemotePartyInfoChange");
+ __ASSERT_ALWAYS(iNotifyRemotePartyInfoTimer, SimPanic(EOjectNotConstructed));
+ __ASSERT_ALWAYS(!iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyPending,SimPanic(ENotificationAlreadyPending));
+
+ RMobileCall::TMobileCallRemotePartyInfoV1Pckg* remotepartyPckg = (RMobileCall::TMobileCallRemotePartyInfoV1Pckg*) aRemoteParty;
+ RMobileCall::TMobileCallRemotePartyInfoV1& remoteparty = (*remotepartyPckg)();
+
+ // Check that the data structure is supported by the simulated TSY version
+ TInt err = iPhone->CheckSimTsyVersion(remoteparty);
+ if(err != KErrNone)
+ {
+ ReqCompleted(aTsyReqHandle, err);
+ return KErrNone;
+ }
+
+ //start timer
+ iNotifyRemotePartyInfoTimer->Start();
+
+ iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyPending = ETrue;
+ iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyHandle = aTsyReqHandle;
+ iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyData = &remoteparty;
+ LOGCALL1("<<CSimCall::NotifyRemotePartyInfoChange");
+ return KErrNone;
+ }
+
+TInt CSimCall::NotifyRemotePartyInfoChangeCancel()
+/**
+* Cancel a client's interest in being notified when the remote party info changes.
+* This is acheived simply by resetting the flag that indicates a notification is pending.
+*
+* @return KErrNone
+*/
+ {
+ LOGCALL1(">>CSimCall::NotifyRemotePartyInfoChangeCancel");
+ if(iNotifyRemotePartyInfoTimer && iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyPending)
+ {
+ iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyHandle,KErrCancel);
+ }
+ LOGCALL1("<<CSimCall::NotifyRemotePartyInfoChangeCancel");
+ return KErrNone;
+ }