diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/simtsy/src/CSimCall.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyserverplugins/simtsy/src/CSimCall.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +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* capsPckg=(TPckg*)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::NotifyHookChangeCancel"); + if(iNotifyHookChange.iNotifyPending) + { + iNotifyHookChange.iNotifyPending=EFalse; + ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrCancel); + } + LOGCALL1("<>CSimCall::NotifyMobileCallStatusChange"); + __ASSERT_ALWAYS(!iMobileNotifyStatusChange.iNotifyPending,SimPanic(ENotificationAlreadyPending)); + + iMobileNotifyStatusChange.iNotifyPending = ETrue; + iMobileNotifyStatusChange.iNotifyHandle = aTsyReqHandle; + iMobileNotifyStatusChange.iNotifyData = aStatus; + LOGCALL1("<>CSimCall::NotifyMobileCallStatusChangeCancel"); + if(iMobileNotifyStatusChange.iNotifyPending) + { + iMobileNotifyStatusChange.iNotifyPending=EFalse; + ReqCompleted(iMobileNotifyStatusChange.iNotifyHandle,KErrCancel); + } + LOGCALL1("<>CSimCall::NotifyStatusChange"); + __ASSERT_ALWAYS(!iNotifyStatusChange.iNotifyPending,SimPanic(ENotificationAlreadyPending)); + + iNotifyStatusChange.iNotifyPending = ETrue; + iNotifyStatusChange.iNotifyHandle = aTsyReqHandle; + iNotifyStatusChange.iNotifyData = aStatus; + LOGCALL1("<>CSimCall::NotifyStatusChangeCancel"); + if(iNotifyStatusChange.iNotifyPending) + { + iNotifyStatusChange.iNotifyPending=EFalse; + ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrCancel); + } + LOGCALL1("<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::GetMobileCallStatus"); + *aCallStatus=iState; + ReqCompleted(aTsyReqHandle,KErrNone); + LOGCALL1("<>CSimCall::GetCallDuration"); + + iCallDurationHandler->GetDuration(aTime); + + ReqCompleted(aTsyReqHandle,KErrNone); + LOGCALL1("<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* mobileCallCapsPckg=(TPckg*)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::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* mobileCallCapsPckg=(TPckg*)iNotifyMobileCapsChange.iNotifyData; + RMobileCall::TMobileCallCapsV1& mobileCallCaps=(*mobileCallCapsPckg)(); + + mobileCallCaps.iCallControlCaps=iCaps; // None of the extended caps are supported. + mobileCallCaps.iCallEventCaps=0; + ReqCompleted(iNotifyMobileCapsChange.iNotifyHandle,KErrNone); + } + } + + LOGCALL2("<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(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::NotifyRemotePartyInfoChangeCancel"); + if(iNotifyRemotePartyInfoTimer && iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyPending) + { + iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyPending=EFalse; + ReqCompleted(iNotifyRemotePartyInfoTimer->iNotifyRemotePartyInfo.iNotifyHandle,KErrCancel); + } + LOGCALL1("<