diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyserverplugins/simtsy/src/CSimCall.cpp --- 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* 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("<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("<