diff -r 000000000000 -r ff3b6d0fd310 convergedcallengine/cce/src/cccecall.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/convergedcallengine/cce/src/cccecall.cpp Tue Feb 02 01:11:09 2010 +0200 @@ -0,0 +1,2538 @@ +/* +* Copyright (c) 2006-2008 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: Base class of call object +* +*/ + + +// INCLUDE FILES +#include "cccecall.h" +#include // GSM error codes +#include +#include +#include + +#include + +#include "mccptransferprovider.h" +#include "mccpcall.h" +#include "mccecallobserver.h" +#include "ccce.h" +#include "cccelogger.h" +#include "ccceutility.h" +#include "cccedurationtimer.h" +#include "mccpcscall.h" +#include "cccecallcontainer.h" +#include "cccetransfercontroller.h" +#include "ccceconferencecall.h" +#include "mccpforwardprovider.h" +#include "cccecallobserverasynchroniser.h" +#include "tccecallindex.h" + +// ======== MEMBER FUNCTIONS ======== +// --------------------------------------------------------------------------- +// Constructor +// --------------------------------------------------------------------------- +// +CCCECall::CCCECall( CCCECallContainer& aCallContainer, TInt aCallId ) : + iCallId( aCallId ), + iCallContainer( aCallContainer ), + iCallIndex( KInvalidCallIndex ) + { + Reset(); + } + +// --------------------------------------------------------------------------- +// Construct object +// --------------------------------------------------------------------------- +// +void CCCECall::ConstructL() + { + FeatureManager::InitializeLibL(); + iCCEDurationTimer = CCCEDurationTimer::NewL(); + iObserver = CCCECallObserverAsynchroniser::NewL(); + } + +// --------------------------------------------------------------------------- +// Default Symbian constructor (object is left into cleanupstack) +// --------------------------------------------------------------------------- +// +CCCECall* CCCECall::NewLC( CCCECallContainer& aCallContainer, TInt aCallId ) + { + CCCECall* self = new( ELeave ) CCCECall( aCallContainer, aCallId ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CCCECall::~CCCECall() + { + Reset(); + delete iCCEDurationTimer; + delete iObserver; + delete iCallParameters; + FeatureManager::UnInitializeLib(); + } + +// --------------------------------------------------------------------------- +// SetObserver( MCCECallObserver& aObserver ) +// --------------------------------------------------------------------------- +// +void CCCECall::SetObserver( const MCCECallObserver& aObserver ) + { + CCELOGSTRING2("id:%d CCCECall::SetObserver()", iCallId); + + iObserver->SetMCCECallObserver( const_cast( &aObserver )); + + if (iCCEDurationTimer) + { + iCCEDurationTimer->SetObserver( iObserver ); + } + } + +// --------------------------------------------------------------------------- +// SetConvergedCall( MCCPCall* aCall ) +// --------------------------------------------------------------------------- +// +void CCCECall::SetConvergedCallL( MCCPCall* aCall, + TUid aImplementationUid, + TBool aTransferred ) + { + CCELOGSTRING2("id:%d CCCECall::SetConvergedCall():IN", iCallId); + + iCall = aCall; + iImplementationUid = aImplementationUid; + + delete iCallParameters; + iCallParameters = NULL; + iCallParameters = aCall->Parameters().CloneL(); + + + // This object is now in use + + CCELOGSTRING3("id:%d CCCECall::SetConvergedCall: CallId = %d", iCallId, iCallId); + // Reserve call id for this call + // If this is transferred call then call id has been already reserved + if( !aTransferred ) + { + iCallContainer.ReserveCallInfoCallId( iCallId ); + } + + CCELOGSTRING2("id:%d CCCECall::SetConvergedCall: CallId reserved", iCallId); + + // Set call direction + if( aCall->IsMobileOriginated() ) + { + CCELOGSTRING2("id:%d CCCECall::SetConvergedCall:Mobile originated call", iCallId); + iCallDirection = CCPCall::EMobileOriginated; + } + else + { + CCELOGSTRING2("id:%d CCCECall::SetConvergedCall():Mobile terminated call", iCallId); + + if ( !aTransferred ) + { + iCallState = CCPCall::EStateRinging; + } + iCallDirection = CCPCall::EMobileTerminated; + aCall->AddObserverL(*this); + } + + TRAP_IGNORE( iTransferProvider = iCall->TransferProviderL(*this) ); + + TRAP_IGNORE( iForwardProvider = iCall->ForwardProviderL(*this) ); + + CCELOGSTRING2("id:%d CCCECall::SetConvergedCall():OUT", iCallId); + } + +// --------------------------------------------------------------------------- +// Returns implementationuid +// --------------------------------------------------------------------------- +// +const TUid CCCECall::ImplementationUid() const + { + return iImplementationUid; + } + +// --------------------------------------------------------------------------- +// From base class MCCECallInfo +// Returns direction of the call +// --------------------------------------------------------------------------- +// +CCPCall::TCallDirection CCCECall::Direction() const + { + return iCallDirection; + } + +// --------------------------------------------------------------------------- +// From base class MCCECallInfo +// Returns the type of the call +// --------------------------------------------------------------------------- +// +CCPCall::TCallType CCCECall::CallType() const + { + if ( iCallParameters ) + { + return iCallParameters->CallType(); + } + return CCPCall::ECallTypeCSVoice; + } + +// --------------------------------------------------------------------------- +// From base class MCCECallInfo, MCCECall +// Returns the index of the call +// --------------------------------------------------------------------------- +// +TInt CCCECall::CallIndex() const + { + return iCallIndex; + } + +// --------------------------------------------------------------------------- +// ServiceId +// --------------------------------------------------------------------------- +// +TUint32 CCCECall::ServiceId() const + { + if( iCall ) + { + return iCall->Parameters().ServiceId(); + } + return 0; + } + +// --------------------------------------------------------------------------- +// Return ETrue if this call object is in use +// --------------------------------------------------------------------------- +// +TBool CCCECall::IsInUse() const + { + CCELOGSTRING3("id:%d CCCECall::IsInUse() %d", iCallId, ( iCall != NULL ) ); + return ( iCall != NULL ); + } + +// --------------------------------------------------------------------------- +// Return ETrue if this calls secure status can be specified +// --------------------------------------------------------------------------- +// +TBool CCCECall::SecureSpecified() const + { + return iCall->SecureSpecified(); + } + +// --------------------------------------------------------------------------- +// Return ETrue if this call object is secured +// --------------------------------------------------------------------------- +// +TBool CCCECall::IsSecured() const + { + return iCall->IsSecured(); + } + +// --------------------------------------------------------------------------- +// Return if call is an emergency call or not. +// --------------------------------------------------------------------------- +// +TBool CCCECall::IsEmergency() const + { + return EFalse; + } + +// --------------------------------------------------------------------------- +// CCCECall::RemoteParty +// --------------------------------------------------------------------------- +// +const TDesC& CCCECall::RemoteParty() const + { + if( iCall ) + { + return iCall->RemoteParty(); + } + + return KNullDesC; + } + +// --------------------------------------------------------------------------- +// CCCECall::RemotePartyName +// --------------------------------------------------------------------------- +// +const TDesC& CCCECall::RemotePartyName() const + { + if( iCall ) + { + return iCall->RemotePartyName(); + } + + return KNullDesC; + } + +// --------------------------------------------------------------------------- +// CCCECall::DialledParty +// --------------------------------------------------------------------------- +// +const TDesC& CCCECall::DialledParty() const + { + if( iCall ) + { + return iCall->DialledParty(); + } + + return KNullDesC; + } + +// --------------------------------------------------------------------------- +// Return current active request +// --------------------------------------------------------------------------- +// +CCCECall::TCallRequest CCCECall::Request() const + { + return iActiveRequest; + } + +// --------------------------------------------------------------------------- +// Returns reference to converged call provider call object +// --------------------------------------------------------------------------- +// +MCCPCall& CCCECall::GetCCPCall() const + { + return *iCall; + } + +// --------------------------------------------------------------------------- +// CallId() +// Returns ID of the call +// --------------------------------------------------------------------------- +// +TInt CCCECall::CallId() const + { + return iCallId; + } + +// --------------------------------------------------------------------------- +// From class MCCECall. +// Hold() +// --------------------------------------------------------------------------- +// +TInt CCCECall::Hold() + { + CCELOGSTRING2( "id:%d CCCECall::Hold() ", iCallId); + TInt error = KErrNone; + + if( iCallState != CCPCall::EStateConnected ) + { + if( iCallState == CCPCall::EStateHold ) + { + error = KErrAlreadyExists; + } + else + { + error = KErrNotReady; + } + } + else + { + iActiveRequest = ECCEHold; + error = iCall->Hold(); + } + + return error; + } + +// --------------------------------------------------------------------------- +// From class MCCECall. +// Resume() +// --------------------------------------------------------------------------- +// +TInt CCCECall::Resume() + { + CCELOGSTRING2( "id:%d CCCECall::Resume()", iCallId ); + TInt error = KErrNone; + + if( iCallState != CCPCall::EStateHold ) + { + if( iCallState == CCPCall::EStateConnected ) + { + error = KErrAlreadyExists; + } + else + { + error = KErrNotReady; + } + } + else + { + iActiveRequest = ECCEResume; + error = iCall->Resume(); + } + + return error; + } + +// --------------------------------------------------------------------------- +// From class MCCECall. +// HangUp() +// --------------------------------------------------------------------------- +// +TInt CCCECall::HangUp() + { + CCELOGSTRING3("id:%d CCCECall::HangUp() callstate = %d", iCallId, iCallState); + + TInt error = KErrNone; + + // Inform that currently ongoing request is canceled + if( iActiveRequest != ECCENone && + iActiveRequest != ECCEReleaseActive && + iActiveRequest != ECCEReleaseHeld && + iActiveRequest != ECCEReleaseOutgoing && + iActiveRequest != ECCETerminateDisconnected ) + { + RequestComplete( ECCPErrorCancel ); + } + + switch(iCallState) + { + case CCPCall::EStateDialling: + CCELOGSTRING2("id:%d CCCECall::HangUp(): DialCancel: Cancel", iCallId); + iActiveRequest = ECCEReleaseOutgoing; + + error = iCall->Cancel(); + + RequestComplete( ECCPErrorNone ); + CallStateChanged( MCCPCallObserver::ECCPStateIdle, EFalse ); + break; + + case CCPCall::EStateConnecting: + CCELOGSTRING2("id:%d CCCECall::HangUp(): DialCancel: HangUp", iCallId); + iActiveRequest = ECCEReleaseOutgoing; + NotifyCallStatusChange( + CCPCall::EStateDisconnecting, ETrue, CCECallEnums::ENoNotify ); + error = iCall->HangUp(); + break; + + case CCPCall::EStateAnswering: + case CCPCall::EStateRinging: + case CCPCall::EStateQueued: + CCELOGSTRING2("id:%d CCCECall::HangUpL: Reject", iCallId); + iActiveRequest = ECCERejectIncoming; + // Set exitcode to rejected to avoid + // missed call notification + iExitCode = ECCPErrorRejected; + NotifyCallStatusChange( + CCPCall::EStateDisconnecting, ETrue, CCECallEnums::ENoNotify ); + error = iCall->Reject(); + break; + + case CCPCall::EStateDisconnecting: + if( ECCETerminateDisconnected != iActiveRequest && + ECCEReleaseOutgoing != iActiveRequest ) + { + RequestComplete( ECCPErrorNone ); + iActiveRequest = ECCETerminateDisconnected; + error = iCall->HangUp(); + } + else + { + error = KErrGeneral; + } + break; + + case CCPCall::EStateIdle: + error = KErrAlreadyExists; + break; + + case CCPCall::EStateHold: + iActiveRequest = ECCEReleaseHeld; + iCCEDurationTimer->Stop(); + NotifyCallStatusChange( + CCPCall::EStateDisconnecting, ETrue, CCECallEnums::ENoNotify ); + error = iCall->HangUp(); + break; + + case CCPCall::EStateConnected: + iActiveRequest = ECCEReleaseActive; + iCCEDurationTimer->Stop(); + NotifyCallStatusChange( + CCPCall::EStateDisconnecting, ETrue, CCECallEnums::ENoNotify ); + error = iCall->HangUp(); + break; + + default: + CCCEUtility::Panic( ECCEPanicInvalidState ); + break; + } + + + + // If hangup was completed successfully, change + // call status to disconnecting. This must be done + // because if hangup was caused by replace -command + // and in that case AnswerIncomingCall is called right + // after hangup. If call is not changed to disconnecting + // state, ResumeAutomaticallyHeldCall would try to + // resume this call and it causes error. + return error; + } + +// --------------------------------------------------------------------------- +// Swap() +// --------------------------------------------------------------------------- +// +TInt CCCECall::Swap() + { + CCELOGSTRING2( "id:%d CCCECall::Swap()", iCallId ); + + TInt error = KErrNone; + + // if there is other CSProvider call use swap instead of Hold + if ( ( iImplementationUid == KCSProviderUid || + iImplementationUid == KVCCProviderUid ) && + ( IsCsPlugin() ) && + 1 < iCallContainer.CountCsCalls( iImplementationUid ) ) + { + error = iCall->Swap(); + } + else if( iCallState == CCPCall::EStateConnected ) + { + // Swapping starts - 1.phase + error = HoldNoNotify(); + } + else + { + error = KErrNotReady; + + iActiveRequest = ECCENone; + } + + if( !error ) + { + // Everything went ok + iActiveRequest = ECCESwap; + } + + return error; + } + +// --------------------------------------------------------------------------- +// NotifyRequestComplete( TInt aRequest, TCCPError aError ) +// --------------------------------------------------------------------------- +// +void CCCECall::NotifyRequestComplete( TInt aRequest, TCCPError aError ) + { + CCELOGSTRING4("id:%d CCCECall::NotifyRequestComplete: aRequest = %d, aError = %d", + iCallId, aRequest, aError ); + + // Notify observer, if NoNotify is NOT set + if ( aRequest == iDoNotReportRequest ) + { + iDoNotReportRequest = KErrNotFound; + } + else + { + if( iObserver ) + { + iObserver->ErrorOccurred( aError ); + } + else + { + CCELOGSTRING( "CCCECall::NotifyRequestComplete: observer was NOT set!" ); + } + } + } + +// --------------------------------------------------------------------------- +// GetMobileCallInfo( TDes8& aCallInfo ) const +// TODO: We should use our own packet instead of TMobileCallInfoV3Pckg +// --------------------------------------------------------------------------- +// +void CCCECall::GetMobileCallInfo( TDes8& aCallInfo ) const + { + CCELOGSTRING3("id:%d CCCECall::GetMobileCallInfo() Call = %d", iCallId, iCallId); + + RMobileCall::TMobileCallInfoV3Pckg& pckg = + reinterpret_cast( aCallInfo ); + + // Check for call object needed, due call info can be fetched + // also if dial fails. + if ( iCall ) + { + RMobileCall::TMobileCallStatus state = RMobileCall::EStatusUnknown; + + switch(iCallState) + { + case CCPCall::EStateIdle: + state = RMobileCall::EStatusIdle; + break; + case CCPCall::EStateRinging: + state = RMobileCall::EStatusRinging; + break; + case CCPCall::EStateConnecting: + state = RMobileCall::EStatusConnecting; + break; + case CCPCall::EStateConnected: + state = RMobileCall::EStatusConnected; + break; + case CCPCall::EStateDisconnecting: + state = RMobileCall::EStatusDisconnecting; + break; + case CCPCall::EStateHold: + state = RMobileCall::EStatusHold; + break; + case CCPCall::EStateTransferring: + state = RMobileCall::EStatusTransferring; + break; + case CCPCall::EStateForwarding: + state = RMobileCall::EStatusConnecting; + break; + case CCPCall::EStateQueued: + state = RMobileCall::EStatusRinging; + break; + case CCPCall::EStateAnswering: + state = RMobileCall::EStatusAnswering; + break; + case CCPCall::EStateDialling: + state = RMobileCall::EStatusDialling; + break; + default: + state = RMobileCall::EStatusUnknown; + break; + } + + if( IsCsPlugin() ) + { + TInt error = + static_cast(iCall)->GetMobileCallInfo(aCallInfo); + + pckg().iCallId = iCallId+1; + pckg().iStatus = state; + pckg().iDuration = iCCEDurationTimer->NumberOfBeats(); + return; + } + + TInt err = KErrNone; + switch( iExitCode ) + { + case ECCPErrorNone: + break; + /** + General: KErrNotFound + */ + case ECCPErrorNotFound: + err = KErrNotFound; + break; + /** + General: KErrGeneral + */ + case ECCPErrorGeneral: + err = KErrGeneral; + break; + + /** + General: KErrCancel + */ + case ECCPErrorCancel: + err = KErrCancel; + break; + + /** + General: KErrNoMemory */ + case ECCPErrorNoMemory: + err = KErrNoMemory; + break; + + /** + General: KErrNotSupported */ + case ECCPErrorNotSupported: + err = KErrNotSupported; + break; + + /** + General: KErrInUse + */ + case ECCPErrorAlreadyInUse: + err = KErrInUse; + break; + + /** + No corresponding cs/sip error identified yet. + */ + case ECCPErrorNotReady: + err = KErrNotReady; + break; + + /** + KErrGsmCCFacilityRejected + KErrGsmCallServerFail + KErrGsm0707NotFound + */ + case ECCPErrorRejected: + case ECCPErrorCCFacilityRejected: + err = KErrGsmCCFacilityRejected; + break; + + /** + KErrGsmCCUnassignedNumber + SIP: 404 Not found + */ + case ECCPErrorNotReached: + err = KErrGsmCCUnassignedNumber; + break; + + /** KErrGsmCCNumberChanged + SIP: 301 Moved permanently/410 Gone + */ + case ECCPErrorMovedPermanently: + err = KErrGsmCCNumberChanged; + break; + /** + KErrGsmCCInvalidNumberFormat + SIP: BadUri + */ + case ECCPErrorInvalidURI: + err = KErrGsmCCInvalidNumberFormat; + break; + + /** + KErrGsmCCNetworkOutOfOrder + SIP: 502 Bad gateway + (redial logic needs) + */ + case ECCPErrorNetworkOutOfOrder: + err = KErrGsmCCNetworkOutOfOrder; + break; + + /** + KErrGsmCCUserBusy + SIP: 486 Busy here + */ + case ECCPErrorBusy: + err = KErrGsmCCUserBusy; + break; + + /** + KErrGsmCCUserNotResponding + SIP: 480 Temporarily unavailable + */ + case ECCPErrorNotResponding: + case ECCPErrorCCUserNotResponding: + err = KErrGsmCCUserNotResponding; + break; + + /** + KErrGsmCCTemporaryFailure + SIP: 500 Internal server error + KErrGsmCCSwitchingEquipmentCongestion + SIP: 503 Service unavailable + KErrGsmCCRequestedChannelNotAvailable + */ + case ECCPErrorNetworkBusy: + err = KErrGsmCCTemporaryFailure; + break; + + /** + KErrGsmCCNoRouteToDestination + SIP: 404 Not Found + SIP: 404 Not found / Timeout + SIP: 503 Service unavailable + */ + case ECCPErrorConnectionErrorRedial: + case ECCPErrorCCNoRouteToDestination: + err = KErrGsmCCNoRouteToDestination; + break; + + /** + KErrArgument + */ + case ECCPErrorInvalidPhoneNumber: + err = KErrArgument; + break; + + /** + KErrGsmNoService + */ + case ECCPErrorNoService: + err = KErrGsmNoService; + break; + + /** + KErrGsmNoNumber + */ + case ECCPErrorInvalidPhoneNumberCancelRedial: + err = KErrGsmNoNumber; + break; + + /** + KErrGsmReleaseByUser + */ + case ECCPErrorReleaseByUserForCancelRedial: + err = KErrGsmReleaseByUser; + break; + + /** + KErrGsmCCRequestedFacilityNotImplemented + */ + case ECCPErrorServiceSettingError: + err = KErrGsmCCRequestedFacilityNotImplemented; + break; + + /** + KErrGsm0707SimNotInserted + KErrGsm0707SIMPuk1Required + KErrGsm0707SimPin1Required + KErrGsm0707SimPin2Required + KErrGsm0707SimFailure + KErrGsm0707PhoneToSimLockRequired + KErrGsm0707SimWrong + */ + case ECCPErrorAuthenticationFailed: + err = KErrGsm0707SimNotInserted; + break; + + /** + KErrGsmOfflineOpNotAllowed + */ + case ECCPErrorNotAllowedInOfflineMode: + err = KErrGsmOfflineOpNotAllowed; + break; + + /** + KErrMMEtelCallForbidden + KErrGsmCallInProgress + KErrGsmNumberBarred + KErrGsmNotAllowed + KErrEtelCallNotActive + KErrEtelCallAlreadyActive + SIP: 403 Forbidden + */ + case ECCPErrorNotAllowed: + err = KErrGsmNotAllowed; + break; + + /** + KErrTimedOut + */ + case ECCPErrorTimedOut: + err = KErrTimedOut; + break; + + /** + KErrGsmInvalidFdn + */ + case ECCPErrorInvalidFDN: + err = KErrGsmInvalidFdn; + break; + + /** + KErrGsmCCChannelUnacceptable + */ + case ECCPErrorUnacceptableChannel: + err = KErrGsmCCChannelUnacceptable; + break; + + /** + KErrGsmCCAccessInformationDiscarded + */ + case ECCPErrorAccessInformationDiscarded: + err = KErrGsmCCAccessInformationDiscarded; + break; + + /** + KErrGsmCCQualityOfServiceNotAvailable + */ + case ECCPErrorQualityOfServiceNotAvailable: + err = KErrGsmCCQualityOfServiceNotAvailable; + break; + + /** + KErrGsmCCInvalidCallReferenceValue + */ + case ECCPErrorInvalidCallReferenceValue: + err = KErrGsmCCInvalidCallReferenceValue; + break; + + /** + KErrGsmCCInvalidTransitNetworkSelection + KErrGsmCCSemanticallyIncorrectMessage + KErrGsmCCConditionalIEError + SIP: 400 Bad request + KErrGsmCCUnspecifiedProtocolError + SIP: 400 Bad request + SIP: 400 Bad request + */ + case ECCPErrorConnectionError: + case ECCPErrorCCInvalidTransitNetworkSelection: + err = KErrGsmCCInvalidTransitNetworkSelection; + break; + + /** + KErrGsmCCIncompatibleDestination + SIP: 400 Bad request + */ + case ECCPErrorBadRequest: + case ECCPErrorCCIncompatibleDestination: + err = KErrGsmCCIncompatibleDestination; + break; + + /** + KErrGsmCCOperatorDeterminedBarring + SIP: 403 Forbidden + */ + case ECCPErrorNumberBarred: + err = KErrGsmCCOperatorDeterminedBarring; + break; + + /** + KErrGsmCCNormalUnspecified + 400 Bad request + */ + case ECCPErrorNoAnswerForVideo: + err = KErrGsmCCNormalUnspecified; + break; + + /** + KErrPhoneEngineNoWcdmaNetwork + */ + case ECCPErrorVideoCallNotSupportedByNetwork: + // err = KErrPhoneEngineNoWcdmaNetwork; + break; + + /** + KErrPhoneEngineVideoCallNotAllowedDuringRestore + */ + case ECCPErrorVideoCallNotAllowedDuringRestore: + // err = KErrPhoneEngineVideoCallNotAllowedDuringRestore; + break; + + /** + KErrPhoneEngineVideoCallSetupFailed + */ + case ECCPErrorVideoCallSetupFailed: + // err = KErrPhoneEngineVideoCallSetupFailed; + break; + + /** + KErrDiagnosticInfoBarredWithCUG + */ + case ECCPErrorCUGOutgoingCallsBarred: + // err = KErrDiagnosticInfoBarredWithCUG; + break; + + /** + KErrDiagnosticInfoBarredNoCUG + */ + case ECCPErrorCUGNotSelected: + // err = KErrDiagnosticInfoBarredNoCUG; + break; + + /** + KErrDiagnosticInfoBarredUnknownCUG + */ + case ECCPErrorCUGIndexUnknown: + // err = KErrDiagnosticInfoBarredUnknownCUG; + break; + + /** + KErrDiagnosticInfoBarredIncompatibleCUG + */ + case ECCPErrorCUGIndexIncompatible: + // err = KErrDiagnosticInfoBarredIncompatibleCUG; + break; + + /** + KErrDiagnosticInfoBarredFailureCUG + */ + case ECCPErrorCUGCallsFailure: + // err = KErrDiagnosticInfoBarredFailureCUG; + break; + + /** + KErrDiagnosticInfoBarredClirNotSubscribed + */ + case ECCPErrorCLIRNotSubscribed: + // err = KErrDiagnosticInfoBarredClirNotSubscribed; + break; + + /** + KErrDiagnosticInfoBarredCCBSPossible + */ + case ECCPErrorCCBSPossible: + // err = KErrDiagnosticInfoBarredCCBSPossible; + break; + + /** + KErrDiagnosticInfoBarredCCBSNotPossible + */ + case ECCPErrorCCBSNotPossible: + // err = KErrDiagnosticInfoBarredCCBSNotPossible; + break; + + /** + Secure call failed. + */ + case ECCPSecureCallFailed: + err = KErrGsmCCChannelUnacceptable; + break; + + /** + Emergency call failed. + */ + case ECCPEmergencyFailed: + err = KErrGsmCCAcmGreaterThanAcmMax; + break; + + /** + Transfer failed. + */ + case ECCPTransferFailed: + /** + Local hold failed. + */ + case ECCPLocalHoldFail: + /** + Local resume failed. + */ + case ECCPLocalResumeFail: + err = KErrGsmCCNormalUnspecified; + break; + + /** + When none of other errors map and received a 3XX response. + */ + case ECCPRedirection: + err = KErrGsmCCUnassignedNumber; + break; + + /** + When none of other errors map and received a 4XX response. + */ + case ECCPRequestFailure: + err = KErrGsmCCUnassignedNumber; + break; + + /** + When none of other errors map and received a 5XX response. + + */ + case ECCPServerFailure: + err = KErrGsmCallServerFail; + break; + + /** + When none of other errors map and received a 6XX response. + */ + case ECCPGlobalFailure: + err = KErrGsmCCUnspecifiedProtocolError; + break; + + /** Rtp detection media error. */ + case ECCPErrorMedia: + err = KErrGsmCCUnspecifiedProtocolError; // TODO + break; + + /** + KErrGsmCCServiceNotImplemented + SIP 488 Not Acceptable Here + SIP 606 Not Acceptable + */ + case ECCPErrorNotAcceptable: + case ECCPErrorCCServiceNotImplemented: + err = KErrGsmCCServiceNotImplemented; + break; + + /* Access denied error */ + case ECCPErrorAccessDenied: + err = KErrAccessDenied; + break; + + + /** + KErrGsmCCDestinationOutOfOrder + */ + case ECCPErrorCCDestinationOutOfOrder: + err = KErrGsmCCDestinationOutOfOrder; + break; + + /** + KErrGsmCCResourceNotAvailable + */ + case ECCPErrorCCResourceNotAvailable: + err = KErrGsmCCResourceNotAvailable; + break; + + /** + KErrGsmCCIncompatibleMessageInCallState; + */ + case ECCPErrorCCIncompatibleMessageInCallState: + err = KErrGsmCCIncompatibleMessageInCallState; + break; + + /** + KErrGsmCCIncompatibleMessageInProtocolState; + */ + case ECCPErrorCCIncompatibleMessageInProtocolState: + err = KErrGsmCCIncompatibleMessageInProtocolState; + break; + + + /** + KErrGsmCCNormalCallClearing; + */ + case ECCPErrorCCNormalCallClearing: + err = KErrGsmCCNormalCallClearing; + break; + + + /** + KErrGsmCCUserAlertingNoAnswer; + */ + case ECCPErrorCCUserAlertingNoAnswer: + err = KErrGsmCCUserAlertingNoAnswer; + break; + + /** + KErrGsmCCCallRejected; + */ + case ECCPErrorCCCallRejected: + err = KErrGsmCCCallRejected; + break; + + + /** + KErrGsmCCPreemption; + */ + case ECCPErrorCCPreemption: + err = KErrGsmCCPreemption; + break; + + /** + KErrGsmCCResponseToStatusEnquiry; + */ + case ECCPErrorCCResponseToStatusEnquiry: + err = KErrGsmCCResponseToStatusEnquiry; + break; + + + /** + KErrGsmCCInvalidMandatoryInformation; + */ + case ECCPErrorCCInvalidMandatoryInformation: + err = KErrGsmCCInvalidMandatoryInformation; + break; + + + /** + KErrGsmCCNonExistentMessageType; + */ + case ECCPErrorCCNonExistentMessageType: + err = KErrGsmCCNonExistentMessageType; + break; + + + /** + KErrGsmCCNonExistentInformationElement; + */ + case ECCPErrorCCNonExistentInformationElement: + err = KErrGsmCCNonExistentInformationElement; + break; + + + /** + KErrGsmCCNoChannelAvailable; + */ + case ECCPErrorCCNoChannelAvailable: + err = KErrGsmCCNoChannelAvailable; + break; + + + /** + KErrGsmCCRequestedFacilityNotSubscribed; + */ + case ECCPErrorCCRequestedFacilityNotSubscribed: + err = KErrGsmCCRequestedFacilityNotSubscribed; + break; + + + /** + KErrGsmCCIncomingCallsBarredInCug; + */ + case ECCPErrorCCIncomingCallsBarredInCug: + err = KErrGsmCCIncomingCallsBarredInCug; + break; + + + /** + KErrGsmCCBearerCapabilityNotAuthorised; + */ + case ECCPErrorCCBearerCapabilityNotAuthorised: + err = KErrGsmCCBearerCapabilityNotAuthorised; + break; + + + /** + KErrGsmCCBearerCapabilityNotCurrentlyAvailable; + */ + case ECCPErrorCCBearerCapabilityNotCurrentlyAvailable: + err = KErrGsmCCBearerCapabilityNotCurrentlyAvailable; + break; + + + /** + KErrGsmCCServiceNotAvailable; + */ + case ECCPErrorCCServiceNotAvailable: + err = KErrGsmCCServiceNotAvailable; + break; + + + /** + KErrGsmCCBearerServiceNotImplemented; + */ + case ECCPErrorCCBearerServiceNotImplemented: + err = KErrGsmCCBearerServiceNotImplemented; + break; + + + /** + KErrGsmCCOnlyRestrictedDigitalInformationBCAvailable; + */ + case ECCPErrorCCOnlyRestrictedDigitalInformationBCAvailable: + err = KErrGsmCCOnlyRestrictedDigitalInformationBCAvailable; + break; + + /** + KErrGsmCCUnspecifiedInterworkingError; + */ + case ECCPErrorCCUnspecifiedInterworkingError: + err = KErrGsmCCUnspecifiedInterworkingError; + break; + + + /** User not in Gug */ + case ECCPErrorUserNotInCug: // TODO + default: + CCELOGSTRING3("id:%d CCCECall::GetMobileCallInfo() Unhandled iExitCode %d", + iCallId, iExitCode); + break; + } + + pckg().iValid = RMobileCall::KCallDuration + | RMobileCall::KCallId + | RMobileCall::KCallRemoteParty + | RMobileCall::KCallDialledParty + | RMobileCall::KCallExitCode + | RMobileCall::KCallEmergency + | RMobileCall::KCallSecurity; + + pckg().iService = RMobilePhone::EVoiceService; + pckg().iStatus = state; + pckg().iCallId = iCallId+1; + pckg().iExitCode = err; + pckg().iEmergency = EFalse; + pckg().iForwarded = iCall->IsCallForwarded(); + pckg().iDuration = iCCEDurationTimer->NumberOfBeats(); + pckg().iStartTime = iCCEDurationTimer->StartTime(); + + pckg().iRemoteParty.iDirection = + (RMobileCall::TMobileCallDirection)iCallDirection; + pckg().iRemoteParty.iRemoteNumber.iTelNumber = + iCall->RemoteParty().Left( RMobilePhone::KMaxMobileTelNumberSize ); + + const TDesC& remoteParty = pckg().iRemoteParty.iRemoteNumber.iTelNumber; + + if ( CCPCall::EMobileTerminated == iCallDirection ) + { + if ( remoteParty == KNullDesC ) + { + pckg().iRemoteParty.iRemoteIdStatus = + RMobileCall::ERemoteIdentitySuppressed; + } + else + { + pckg().iRemoteParty.iRemoteIdStatus = + RMobileCall::ERemoteIdentityAvailable; + } + + pckg().iForwarded = EFalse; + + pckg().iValid |= RMobileCall::KCallForwarded; + } + else + { + pckg().iRemoteParty.iRemoteIdStatus = + RMobileCall::ERemoteIdentityUnknown; + } + + pckg().iDialledParty.iTelNumber = remoteParty; + pckg().iCallName = KNullDesC; + + // InfoV3 + if ( iCallState == CCPCall::EStateConnected ) + { + if ( iCall->IsSecured()) + { + // Because ETel does not support VoIP, GSM ciphering is reported + pckg().iSecurity = RMobilePhone::ECipheringGSM; + } + } + else + { + pckg().iSecurity = RMobilePhone::ECipheringOff; + } + } + else + { + CCELOGSTRING2("id:%d CCCECall::GetMobileCallInfo: Not found", iCallId); + } + } + +// --------------------------------------------------------------------------- +// From class MCCECall. +// +// --------------------------------------------------------------------------- +// +CCPCall::TCallState CCCECall::State() const + { + CCELOGSTRING3( "id:%d CCCECall::State() = %d", iCallId, iCallState ); + return iCallState; + } + +// --------------------------------------------------------------------------- +// TCCPTone Tone() const +// +// --------------------------------------------------------------------------- +// +TCCPTone CCCECall::Tone() const + { + TCCPTone tone = iCall->Tone(); + CCELOGSTRING3( "id:%d CCCECall::Tone() = %d", iCallId, (TInt)tone ); + return tone; + + } +// --------------------------------------------------------------------------- +// CallDuration() const +// --------------------------------------------------------------------------- +// +TTimeIntervalSeconds CCCECall::CallDuration() const + { + return iCCEDurationTimer->NumberOfBeats(); + } + + +// --------------------------------------------------------------------------- +// StartTime() const +// --------------------------------------------------------------------------- +// +TDateTime CCCECall::StartTime() const + { + return iCCEDurationTimer->StartTime(); + } + +// --------------------------------------------------------------------------- +// Caps() const +// --------------------------------------------------------------------------- +// +MCCECallObserver::TCCECallControlCaps CCCECall::Caps() const + { + CCELOGSTRING3( "id:%d CCCECall::Caps(): caps = %d", iCallId, iCall->Caps() ); + + return (MCCECallObserver::TCCECallControlCaps)iCall->Caps(); + } + +// --------------------------------------------------------------------------- +// SetParameters() +// --------------------------------------------------------------------------- +// +void CCCECall::SetParameters( const CCCECallParameters& aNewParams ) + { + delete iCallParameters; + iCallParameters = NULL; + TRAP_IGNORE(iCallParameters = aNewParams.CloneL()); + } + +// --------------------------------------------------------------------------- +// Parameters() const +// --------------------------------------------------------------------------- +// +const CCCPCallParameters& CCCECall::Parameters() const + { + if ( FeatureManager::FeatureSupported( KFeatureIdFfVoiceCallContinuity ) ) + { + return iCall->Parameters(); + } + return *iCallParameters; + } + +// --------------------------------------------------------------------------- +// Get transfer target +// --------------------------------------------------------------------------- +// +const TDesC& CCCECall::TransferTarget() const + { + // nothing here yet + return KNullDesC; + } + +// --------------------------------------------------------------------------- +// AttendedTransfer() +// --------------------------------------------------------------------------- +// +TInt CCCECall::AttendedTransfer( const TDesC& /*aTransferTarget*/ ) + { + CCELOGSTRING2( "id:%d CCCECall::AttendedTransfer()", iCallId ); + TInt error = KErrNone; + + if ( iTransferProvider ) + { + CCCECall* toCall = iCallContainer.GetCall( + CCPCall::EStateConnected, this ); + + // On cs world it is possible to transfer call to connecting + // call + if( !toCall ) + { + toCall = iCallContainer.GetCall( + CCPCall::EStateConnecting, this ); + + TBool condition( EFalse ); + + if ( FeatureManager::FeatureSupported( + KFeatureIdFfVoiceCallContinuity ) ) + { + if ( toCall && + toCall->Parameters().CallType() != + CCPCall::ECallTypeCSVoice ) + { + condition = ETrue; + } + } + else + { + if ( toCall && toCall->ImplementationUid() != KCSProviderUid ) + { + condition = ETrue; + } + } + if ( condition ) + + { + toCall = NULL; + } + } + + if( toCall ) + { + error = iTransferProvider->AttendedTransfer( toCall->GetCCPCall() ); + + if ( error == KErrNone ) + { + iActiveRequest = ECCETransfer; + } + } + else + { + error = KErrNotReady; + } + } + else + { + error = KErrNotSupported; + } + + return error; + } + +// --------------------------------------------------------------------------- +// UnattendedTransfer( const TDesC& /*aTarget*/ ) +// --------------------------------------------------------------------------- +// +TInt CCCECall::UnattendedTransfer( const TDesC& aTarget ) + { + CCELOGSTRING2("id:%d CCCECall::UnattendedTransfer():IN", iCallId); + TInt error = KErrNone; + + if( iTransferProvider ) + { + error = iTransferProvider->UnattendedTransfer( aTarget ); + + if ( error == KErrNone ) + { + iActiveRequest = ECCEUnattendedTransfer; + } + } + else + { + error = KErrNotSupported; + } + + CCELOGSTRING2("id:%d CCCECall::UnattendedTransfer():OUT", iCallId); + return error; + } + +// --------------------------------------------------------------------------- +// AcceptTransfer( TBool /*aAccept*/ ) +// --------------------------------------------------------------------------- +// +TInt CCCECall::AcceptTransfer( const TBool aAccept ) + { + CCELOGSTRING3("id:%d CCCECall::AcceptTransfer():IN aAccept=%d", iCallId,aAccept); + TInt error = KErrNone; + + if( iTransferController && + iTransferProvider ) + { + if( CCPCall::EStateConnected == iCallState || + CCPCall::EStateHold == iCallState ) + { + iTransferProvider->AcceptTransfer( aAccept ); + if( aAccept ) + { + iTransferController->SetTransferAccepted( aAccept ); + } + else + { + iTransferController->ReleaseTransferCall(); + } + } + else + { + iTransferController->ReleaseTransferCall(); + } + } + else + { + error = KErrNotSupported; + } + CCELOGSTRING2("id:%d CCCECall::AcceptTransfer():OUT", iCallId); + return error; + } + +// --------------------------------------------------------------------------- +// ForwardCallToAddressChoices() +// --------------------------------------------------------------------------- +// +const CDesC8Array& CCCECall::GetForwardAddressChoicesL() + { + CCELOGSTRING2("id:%d CCCECall::GetForwardAddressChoicesL()", iCallId); + const CDesC8Array* array = NULL; + + if( iForwardProvider ) + { + array = &iForwardProvider->GetForwardAddressChoicesL(); + } + else + { + User::Leave( KErrNotSupported ); + } + + return *array; + } + +// --------------------------------------------------------------------------- +// ForwardCallToAddress( TInt /*aIndex*/ ) +// --------------------------------------------------------------------------- +// +void CCCECall::ForwardToAddressL( TInt aIndex ) + { + CCELOGSTRING2("id:%d CCCECall::ForwardCallToAddress()", iCallId); + if( iForwardProvider ) + { + iForwardProvider->ForwardToAddressL( aIndex ); + } + else + { + User::Leave( KErrNotSupported ); + } + } + +// --------------------------------------------------------------------------- +// From class MCCECall. +// Check if other call needs to placed on hold +// If no, continue call +// --------------------------------------------------------------------------- +// +TInt CCCECall::Dial( const TDesC8& aCallParams ) + { + CCELOGSTRING2( "id:%d CCCECall::Dial()", iCallId ); + TInt error = KErrNone; + + if( iCallState != CCPCall::EStateIdle ) + { + return KErrNotReady; + } + + iCallParams = &aCallParams; + iActiveRequest = ECCEDial; + + // If this is unattended transfer dial + if( iTransferController && + iCall == iTransferController->TransferCall() ) + { + CCELOGSTRING2( "id:%d CCCECall::Dial(): TransferDial", iCallId); + // Must wait that original call is disconnected before transfer + // dial can be done + if( MCCPCallObserver::ECCPStateDisconnecting == + iTransferController->OriginatorCall()->State() ) + { + error = DoPendingRequest(); + } + else + { + iTransferController->SetTransferDialPending( ETrue ); + } + } + else + { + + CCCECall* call = iCallContainer.GetCall( + CCPCall::EStateConnected, this); + + if(call) + { + if( 0 == iCallContainer.ConferenceCall().EnumerateCalls() ) + { + if( (iCallContainer.GetCall( + CCPCall::EStateHold, this)) && (ECCENone != iActiveRequest)) + { + CCELOGSTRING2( "id:%d CCCECall::Dial() failed. Too many calls. ", iCallId); + error = KErrInUse; + } + else + { + error = call->HoldNoNotify(); + } + } + else + { + error = iCallContainer.ConferenceCall().Swap(); + } + } + else + { + // Continue dial if no other connected calls exist + error = DoPendingRequest(); + } + } + return error; + } + +// --------------------------------------------------------------------------- +// From class MCCECSCall. +// NoFDNCheck() +// --------------------------------------------------------------------------- +// +void CCCECall::NoFDNCheck() + { + if ( IsCsPlugin() ) + { + static_cast(iCall)->NoFDNCheck(); + } + } + +// --------------------------------------------------------------------------- +// From class MCCECall. +// Answer() +// --------------------------------------------------------------------------- +// +TInt CCCECall::Answer() + { + CCELOGSTRING2( "id:%d CCCECall::Answer()", iCallId ); + TInt error = KErrNone; + iActiveRequest = ECCEAnswer; + + CCCECall* call = iCallContainer.GetCall( + CCPCall::EStateConnected, this); + + if(call) + { + if( 0 == iCallContainer.ConferenceCall().EnumerateCalls() ) + { + if( (iCallContainer.GetCall( + CCPCall::EStateHold, this)) && (ECCENone != iActiveRequest)) + { + CCELOGSTRING2( "id:%d CCCECall::Answer() failed. Too many calls. " + , iCallId); + error = KErrInUse; + iActiveRequest = ECCENone; + } + else + { + error = call->HoldNoNotify(); + } + } + else + { + error = iCallContainer.ConferenceCall().Swap(); + } + } + else + { + // Continue answering if no other connected calls exist + error = DoPendingRequest(); + } + + return error; + } + +// --------------------------------------------------------------------------- +// DoPendingRequest() +// This does the pending request. It can be called from cccecallcontainer +// --------------------------------------------------------------------------- +// +TInt CCCECall::DoPendingRequest() + { + CCELOGSTRING2( "id:%d CCCECall::DoPendingRequest()", iCallId ); + TInt error = KErrNone; + + if( iActiveRequest == ECCEDial ) + { + CCELOGSTRING2("id:%d CCCECall::DoDial", iCallId); + + if ( IsCsPlugin() ) + { + error = static_cast(iCall)->Dial(*iCallParams); + } + else if( iCall ) + { + error = iCall->Dial(); + } + } + else if( iActiveRequest == ECCEAnswer || + iActiveRequest == ECCEReplaceActive ) + { + CCELOGSTRING2("id:%d CCCECall::DoAnswer", iCallId); + error = iCall->Answer(); + } + else + { + error = KErrNotFound; + } + + return error; + } + +// --------------------------------------------------------------------------- +// DialEmergencyCall( const TDesC16& /*aNumber*/ ) +// --------------------------------------------------------------------------- +// +void CCCECall::DialEmergencyCall( const TDesC16& /*aNumber*/ ) + { + CCELOGSTRING2("id:%d CCCECall::DialEmergencyCall()", iCallId); + } + +// --------------------------------------------------------------------------- +// From class MCCECall. +// Close call object +// --------------------------------------------------------------------------- +// +TInt CCCECall::Release() + { + CCELOGSTRING2( "id:%d CCCECall::Release()", iCallId ); + + if( CCPCall::EStateIdle != iCallState ) + { + iCallContainer.HandleCallStatusChange( + CCPCall::EStateIdle, + this, CCECallEnums::ENotifySynchronously ); + } + + // Stop duration timer if it is not yet stopped. + iCCEDurationTimer->Stop(); + // Reset timer observer + iCCEDurationTimer->SetObserver( NULL ); + + // Delete converged call + // Release call id + iCallContainer.ReleaseCallInfoCallId( iCallId ); + + if( iCall ) + { + iCallContainer.ReleaseCall(*iCall); + } + + Reset(); + + return KErrNone; + } + +// --------------------------------------------------------------------------- +// Request is to an ringing/waiting state call. +// Active call if found is hang-up +// When active call goes to idle incoming call is answered +// --------------------------------------------------------------------------- +// +TInt CCCECall::ReplaceActive() + { + CCELOGSTRING2( "id:%d CCCECall::ReplaceActive()", iCallId ); + TInt error = KErrNone; + iActiveRequest = ECCEReplaceActive; + CCCECall* callConnected = iCallContainer.GetCall( + CCPCall::EStateConnected, this); + + if ( callConnected ) + { + if ( !iCallContainer.ConferenceCall().IsPartOfConference( *callConnected ) ) + { + error = callConnected->GetCCPCall().HangUp(); + } + else if ( iCallContainer.ConferenceCall().State() == + MCCPConferenceCallObserver::ECCPConferenceActive ) + { + error = iCallContainer.ConferenceCall().HangUp(); + } + + if ( KErrNone != error ) + { + iActiveRequest = ECCENone; + } + } + else + { + // Continue answering if no other connected calls exist + error = DoPendingRequest(); + } + + return error; + } + +// --------------------------------------------------------------------------- +// Hold call but do not notify observer when completed +// --------------------------------------------------------------------------- +// +TInt CCCECall::HoldNoNotify() + { + CCELOGSTRING2( "id:%d CCCECall::HoldNoNotifyL()", iCallId ); + + return iCall->Hold(); + } + + +// --------------------------------------------------------------------------- +// Resume call but do not notify observer when completed +// --------------------------------------------------------------------------- +// +TInt CCCECall::ResumeNoNotify() + { + CCELOGSTRING2( "id:%d CCCECall::ResumeNoNotifyL()", iCallId ); + + return iCall->Resume(); + } + +// --------------------------------------------------------------------------- +// HandleTransfer() +// Notifies phoneengine about received transfer request from remote end +// --------------------------------------------------------------------------- +// +void CCCECall::HandleTransfer(const TBool aAttented, + CCCETransferController& aTransferController ) + { + iTransferController = &aTransferController; + if( iObserver ) + { + iObserver->HandleTransfer( aAttented, + iTransferProvider->TransferTarget() ); + } + else + { + CCELOGSTRING( "CCCECall::HandleTransfer: observer was NOT set!" ); + } + } + +// --------------------------------------------------------------------------- +// SetTransferController() +// +// --------------------------------------------------------------------------- +// +void CCCECall::SetTransferController( + CCCETransferController* aTransferController ) + { + iTransferController = aTransferController; + } + +// --------------------------------------------------------------------------- +// Sets call index +// --------------------------------------------------------------------------- +// +void CCCECall::SetNewCallIndex() + { + if ( iCallIndex == KInvalidCallIndex ) + { + TCCECallIndex callIndex( iCallContainer ); + iCallIndex = callIndex.CurrentCallIndex(); + } + } + +// --------------------------------------------------------------------------- +// Reset call object to initial state +// --------------------------------------------------------------------------- +// +void CCCECall::Reset() + { + CCELOGSTRING2( "id:%d CCCECall::Reset()", iCallId ); + + iActiveRequest = ECCENone; + + // only one observer at the moment. Clear it. + if (iObserver) + { + iObserver->SetMCCECallObserver(NULL); + } + + + // This object is no longer in use. + iExitCode = ECCPErrorNone; + + iCallDirection = CCPCall::EDirectionUnknown; + iCallState = CCPCall::EStateIdle; + + iImplementationUid.iUid = 0; + + iCall = NULL; + delete iCallParameters; + iCallParameters = NULL; + iCallParams = NULL; + + iDoNotReportRequest = KErrNotFound; + + iTransferProvider = NULL; + iTransferController = NULL; + + if( iCCEDurationTimer ) + { + iCCEDurationTimer->Reset(); + } + } + +// --------------------------------------------------------------------------- +// GetMobileDataCallCaps( TDes8& /*aCaps*/ ) const +// --------------------------------------------------------------------------- +// +TInt CCCECall::GetMobileDataCallCaps( TDes8& aCaps ) const + { + CCELOGSTRING2("id:%d CCCECall::GetMobileDataCallCaps()", iCallId); + + if ( IsCsPlugin() ) + { + return static_cast(iCall)->GetMobileDataCallCaps(aCaps); + } + else + return KErrNotSupported; + } + + +// --------------------------------------------------------------------------- +// LogDialedNumber() +// --------------------------------------------------------------------------- +// +TBool CCCECall::LogDialedNumber() const + { + // CS related + CCELOGSTRING2("id:%d CCCECall::LogDialedNumber()", iCallId); + + if ( IsCsPlugin() ) + { + return static_cast(iCall)->LogDialedNumber(); + } + // for other than CS always return true + return ETrue; + } + +// --------------------------------------------------------------------------- +// SwitchAlternatingCall() +// --------------------------------------------------------------------------- +// +TInt CCCECall::SwitchAlternatingCall() + { + CCELOGSTRING2("id:%d CCCECall::SwitchAlternatingCall()", iCallId); + if ( IsCsPlugin() ) + { + static_cast(iCall)->SwitchAlternatingCall(); + return KErrNone; + } + else + return KErrNotSupported; + } + +// --------------------------------------------------------------------------- +// ErrorOccured( TCCPCallError aError ) +// --------------------------------------------------------------------------- +// +void CCCECall::ErrorOccurred( TCCPError aError, MCCPCall* /*aCall*/ ) + { + if( !iCall ) + { + CCELOGSTRING2("id:%d CCCECall::ErrorOccurred()::Call not active", iCallId); + return; + } + + CCELOGSTRING3("id:%d CCCECall::ErrorOccurred: Error = %d", + iCallId, aError ); + + iExitCode = aError; + iCallContainer.ErrorOccurred( this, aError ); + + // Complete request to observer + if ( ECCENone != iActiveRequest ) + { + RequestComplete( aError ); + } + else + { + if( iObserver ) + { + iObserver->ErrorOccurred(aError); + } + else + { + CCELOGSTRING( "CCCECall::ErrorOccurred: observer was NOT set!" ); + } + } + + } + +// --------------------------------------------------------------------------- +// RequestComplete( TInt aError ) +// --------------------------------------------------------------------------- +// +void CCCECall::RequestComplete( TCCPError aError ) + { + CCELOGSTRING4("id:%d CCCECall::RequestComplete: Request = %d, Error = %d",iCallId + ,iActiveRequest, aError ); + + // Complete request to observer + if ( ECCENone != iActiveRequest ) + { + NotifyRequestComplete( iActiveRequest, aError ); + } + else + { + CCELOGSTRING2("id:%d CCCECall::RequestComplete: No active request.", iCallId); + } + + // Reset active request + iActiveRequest = ECCENone; + } + +// --------------------------------------------------------------------------- +// CallEventOccurred( TCCPCallEvent aEvent ) +// --------------------------------------------------------------------------- +// +void CCCECall::CallEventOccurred( TCCPCallEvent aEvent, MCCPCall* /*aCall*/ ) + { + if( !iCall ) + { + CCELOGSTRING2("id:%d CCCECall::CallEventOccurred()::Call not active", iCallId); + return; + } + + + if( !iObserver->GetMCCECallObserver() ) + { + CCELOGSTRING( "CCCECall::CallEventOccurred: observer was NOT set!" ); + return; + } + + + CCELOGSTRING4("id:%d CCCECall::CallEventOccurred() Event = %d CallId = %d", + iCallId, aEvent, iCallId ); + + switch ( aEvent ) + { + /** Call has been placed on hold as a result of a local action. */ + case ECCPLocalHold: + iObserver->CallEventOccurred( MCCECallObserver::ELocalHold ); + break; + /** Call has been placed on hold by the remote connected party. */ + case ECCPRemoteHold: + iObserver->CallEventOccurred( MCCECallObserver::ERemoteHold ); + break; + /** Call has been resumed as a result of a local action. */ + case ECCPLocalResume: + iObserver->CallEventOccurred( MCCECallObserver::ELocalResume ); + break; + /** Call has been resumed by the remote connected party. */ + case ECCPRemoteResume: + iObserver->CallEventOccurred( MCCECallObserver::ERemoteResume ); + break; + /** Outgoing call has been barred by the local party. */ + case ECCPLocalBarred: + iObserver->CallEventOccurred( MCCECallObserver::ELocalBarred ); + break; + /** Outgoing call has been barred by the remote party. */ + case ECCPRemoteBarred: + iObserver->CallEventOccurred( MCCECallObserver::ERemoteBarred ); + break; + /** Call is waiting at the remote end. */ + case ECCPRemoteWaiting: + iObserver->CallEventOccurred( MCCECallObserver::ERemoteWaiting ); + break; + /** Call has been terminated by the remote party. */ + case ECCPRemoteTerminated: + iObserver->CallEventOccurred( MCCECallObserver::ERemoteTerminated); + break; + /** Call is in queue */ + case ECCPQueued: + iObserver->CallEventOccurred( MCCECallObserver::ERemoteWaiting ); + break; + /** VoIP specific */ + case ECCCSPEarlyMediaStarted: + iObserver->CallEventOccurred( MCCECallObserver::EVoIPEventEarlyMediaStarted ); + break; + /** Call is secure */ + case ECCPSecureCall: + iObserver->CallEventOccurred( MCCECallObserver::ESecureSession ); + break; + /** Call is not secure */ + case ECCPNotSecureCall: + iObserver->CallEventOccurred( MCCECallObserver::ENotSecureSession ); + break; + /** Secure call signaling is not possible */ + case ECCPNotSecureSessionWithSips: + iObserver->CallEventOccurred( MCCECallObserver::EVoIPEventNotSecureSessionWithSips ); + break; + /** Call has been added to remote conference call at remote end */ + case ECCPRemoteConferenceCreate: + iObserver->CallEventOccurred( MCCECallObserver::ERemoteConferenceCreate ); + break; + /** CS call specific event */ + case ECCPCSDataPortLoaned: + iObserver->CallEventOccurred( MCCECallObserver::ECCECSDataPortLoaned ); + break; + /** CS call specific event */ + case ECCPCSDataPortRecovered: + iObserver->CallEventOccurred( MCCECallObserver::ECCECSDataPortRecovered ); + break; + /** Remote party info target meaning has changed */ + case ECCPNotifyRemotePartyInfoChange: + { + //Ho occurred, call type has changed + if ( FeatureManager::FeatureSupported( KFeatureIdFfVoiceCallContinuity ) ) + { + CCELOGSTRING( "CCCECall::CallEventOccurred: ECCPNotifyRemotePartyInfoChange!" ); + delete iCallParameters; + iCallParameters = NULL; + + TRAP_IGNORE( iCallParameters = iCall->Parameters().CloneL() ); + } + iCallContainer.AirTimeDurationSwap( + iCall->Parameters().CallType() ); + iObserver->CallEventOccurred( MCCECallObserver::ECCENotifyRemotePartyInfoChange ); + } + break; + /** Call secure status cannot be determined */ + case ECCPSecureNotSpecified: + iObserver->CallEventOccurred( MCCECallObserver::ECCESecureNotSpecified ); + break; + default: + CCELOGSTRING3("id:%d CCCECall::SessionEventOccurred: Unhandled event = %d", iCallId, + aEvent ); + break; + } + } + +// --------------------------------------------------------------------------- +// CallCapsChanged( TUint32 aCapsFlags ) +// --------------------------------------------------------------------------- +// +void CCCECall::CallCapsChanged( TUint32 aCapsFlags, MCCPCall* /*aCall*/ ) + { + CCELOGSTRING2("id:%d CCCECall::CallCapsChanged()", iCallId); + if( !iCall ) + { + CCELOGSTRING2("id:%d CCCECall::CallCapsChanged()::Call not active", iCallId); + return; + } + + if( iObserver ) + { + iObserver->CallCapsChanged( (MCCECallObserver::TCCECallControlCaps)aCapsFlags ); + } + else + { + CCELOGSTRING( "CCCECall::CallCapsChanged: observer was NOT set!" ); + } + } + +// --------------------------------------------------------------------------- +// TransferEventOccurred() +// --------------------------------------------------------------------------- +// +void CCCECall::TransferEventOccurred( TCCPTransferEvent aEvent ) + { + CCELOGSTRING2("id:%d CCCECall::TransferEventOccurred()", iCallId); + + if( !iObserver->GetMCCECallObserver() ) + { + CCELOGSTRING( "CCCECall::TransferEventOccurred: observer was NOT set!" ); + return; + } + + switch ( aEvent ) + { + /** Call has been transferred to another remote party as a result + of a local action. This is the result of transfer being succesfully + completed */ + case ECCPLocalTransfer: + iObserver->CallEventOccurred( MCCECallObserver::ELocalTransfer ); + break; + /** Outgoing call is transfering. The transfer request has now been + accepted by the current call recipient. */ + case ECCPRemoteTransferring: + iObserver->CallEventOccurred( MCCECallObserver::ERemoteTransferring ); + break; + /** Outgoing transfer call is alerting. Current call recipinet has sent + connection request to transfer target*/ + case ECCPRemoteTransferAlerting: + iObserver->CallEventOccurred( MCCECallObserver::ERemoteTransferAlerting ); + break; + + default: + CCELOGSTRING3("id:%d CCCECall::TransferEventOccurred: Unhandled event = %d", iCallId, + aEvent ); + break; + } + } + +// --------------------------------------------------------------------------- +// ForwardEventOccurred() +// --------------------------------------------------------------------------- +// +void CCCECall::ForwardEventOccurred( + const MCCPForwardObserver::TCCPForwardEvent aEvent ) + { + CCELOGSTRING2("id:%d CCCECall::ForwardEventOccurred()", iCallId); + + if( !iObserver->GetMCCECallObserver() ) + { + CCELOGSTRING( "CCCECall::ForwardEventOccurred: observer was NOT set!" ); + return; + } + + switch ( aEvent ) + { + /** Call is being forwarded by the remote party. */ + /** MovedTemporarily is handled as forwarding */ + case ECCPRemoteForwarding: + case ECCPMovedTemporarily: + iObserver->CallEventOccurred( MCCECallObserver::ERemoteForwarding ); + break; + /** Multiple call forward choices are available */ + case ECCPMultipleChoices: + iObserver->CallEventOccurred( MCCECallObserver::EVoIPEventMultipleChoices ); + break; + /** Call moved permanently */ + case ECCPMovedPermanentlyEvent: + iObserver->CallEventOccurred( MCCECallObserver::EVoIPEventMovedPermanently ); + break; + /** Call is forwarded */ + case ECCPForwarded: + default: + CCELOGSTRING3("id:%d CCCECall::ForwardEventOccurred: Unhandled event = %d", iCallId, + aEvent ); + break; + } + } + +// --------------------------------------------------------------------------- +// CallStateChanged( TCCPCallState aState ) +// --------------------------------------------------------------------------- +// +void CCCECall::CallStateChanged( TCCPCallState aState, MCCPCall* /*aCall*/ ) + { + CCELOGSTRING3("id:%d CCCECall::CallStateChanged() State = %d", + iCallId, aState ); + + CallStateChanged( aState, EFalse ); + } + +// --------------------------------------------------------------------------- +// CallStateChangedWithInband( TCCPCallState aState ) +// --------------------------------------------------------------------------- +// +void CCCECall::CallStateChangedWithInband( TCCPCallState aState, + MCCPCall* /*aCall*/ ) + { + CCELOGSTRING3("id:%d CCCECall::CallStateChangedWithInband() State = %d", + iCallId , aState ); + + CallStateChanged( aState, ETrue ); + } + +// --------------------------------------------------------------------------- +// CallStateChanged( TCCPCSCallState aState ) +// --------------------------------------------------------------------------- +// +void CCCECall::CallStateChanged( TCCPCallState aState, TBool aInband ) + { + if( !iCall ) + { + CCELOGSTRING2("id:%d CCCECall::CallStateChanged()::Call not active", iCallId); + return; + } + + TInt notify = EFalse; + CCPCall::TCallState state( CCPCall::EStateIdle); + + switch ( aState ) + { + case ECCPStateQueued: + CCELOGSTRING2("id:%d CCCECall::CallStateChanged: Queued", iCallId); + // Call index becomes available when call gets to dialling or ringing/queued state. + // Idle call does not have call index. + SetNewCallIndex(); + if ( iCallDirection == CCPCall::EMobileTerminated ) + { + state = CCPCall::EStateQueued; + notify = ETrue; + } + break; + + case ECCPStateDialling: + // Call index becomes available when call gets to dialling or ringing/queued state. + // Idle call does not have call index. + SetNewCallIndex(); + + CCELOGSTRING2("id:%d CCCECall::CallStateChanged: Dialling", iCallId); + state = CCPCall::EStateDialling; + notify = ETrue; + + break; + + case ECCPStateAnswering: + CCELOGSTRING2("id:%d CCCECall::CallStateChanged: Answering", iCallId); + state = CCPCall::EStateAnswering; + notify = ETrue; + + break; + + case ECCPStateConnecting: + case ECCPStateRinging: + CCELOGSTRING2("id:%d CCCECall::CallStateChanged: Connecting/Ringing", iCallId); + if ( iCallDirection == CCPCall::EMobileTerminated ) + { + state = CCPCall::EStateRinging; + // Call index becomes available when call gets to dialling or incoming state. + // Idle call does not have call index. + SetNewCallIndex(); + } + else + { + if ( ECCEDial == iActiveRequest ) + { + RequestComplete( ECCPErrorNone ); + } + + state = CCPCall::EStateConnecting; + } + notify = ETrue; + break; + + case ECCPStateConnected: + CCELOGSTRING2("id:%d CCCECall::CallStateChanged: Connected", iCallId); + // Start call duration timer + iCCEDurationTimer->Start(); + + // We are either dialling or answering + if ( ECCEAnswer == iActiveRequest || + ECCEResume == iActiveRequest || + ECCEDial == iActiveRequest || + ECCEReplaceActive == iActiveRequest ) + { + RequestComplete( ECCPErrorNone ); + } + + state = CCPCall::EStateConnected; + notify = ETrue; + break; + + case ECCPStateDisconnecting: + CCELOGSTRING2("id:%d CCCECall::CallStateChanged: Disconnecting", iCallId); + // Stop duration timer + iCCEDurationTimer->Stop(); + + if ( ECCETransfer == iActiveRequest ) + { + RequestComplete( ECCPErrorNone ); + } + + state = CCPCall::EStateDisconnecting; + notify = ETrue; + break; + + case ECCPStateIdle: + CCELOGSTRING2("id:%d CCCECall::CallStateChanged: Disconnected/Idle", iCallId); + // Stop duration timer + iCCEDurationTimer->Stop(); + + // Remove call from conference before it is notified elsewhere + if( iCallContainer.ConferenceCall().IsPartOfConference(*this) ) + { + MCCPConferenceCallObserver& confObserver = iCallContainer.ConferenceCall(); + confObserver.ConferenceCallEventOccurred( + MCCPConferenceCallObserver::ECCPConferenceCallRemoved, iCall ); + } + + if ( ECCENone != iActiveRequest ) + { + RequestComplete( ECCPErrorNone ); + } + + state = CCPCall::EStateIdle; + iCallIndex = KInvalidCallIndex; // Call index not valid anymore in idle state + notify = ETrue; + + if( !iObserver->GetMCCECallObserver() ) + { + notify = EFalse; + Release(); + + } + break; + + case ECCPStateHold: + CCELOGSTRING2("id:%d CCCECall::CallStateChanged: Hold", iCallId); + state = CCPCall::EStateHold; + if ( ECCEHold == iActiveRequest ) + { + RequestComplete( ECCPErrorNone ); + } + + notify = ETrue; + break; + + case ECCPStateForwarding: + CCELOGSTRING2("id:%d CCCECall::CallStateChanged: Forwarding", iCallId); + // Notify observer + // Forwarding state is notified to upstairs but is not set + // to calls internal state + if( iObserver ) + { + if (aInband) + { + iObserver->CallStateChangedWithInband(CCPCall::EStateForwarding); + } + else + { + iObserver->CallStateChanged(CCPCall::EStateForwarding); + } + + } + break; + + case ECCPStateTransferring: + CCELOGSTRING2("id:%d CCCECall::CallStateChanged: Transferring", iCallId); + // Notify observer + // Transferring state is notified to upstairs but is not set + // to calls internal state + if( iObserver ) + { + if (aInband) + { + iObserver->CallStateChangedWithInband(CCPCall::EStateTransferring) ; + } + else + { + iObserver->CallStateChanged(CCPCall::EStateTransferring); + } + + } + + break; + + default: + CCELOGSTRING3("id:%d CCCECall::CallStateChanged: Unhandled state = %d", iCallId, + aState ); + break; + } + + if( notify ) + { + NotifyCallStatusChange( state, aInband, CCECallEnums::ENotifyAsynchronously ); + } + } + +// --------------------------------------------------------------------------- +// Notify observers about call status change +// --------------------------------------------------------------------------- +// +void CCCECall::NotifyCallStatusChange( + CCPCall::TCallState aCallState, + TBool aInband, + CCECallEnums::TNotifyType aNotify ) + { + CCELOGSTRING3("id:%d CCCECall::NotifyCallStatusChange: Status = %d",iCallId, aCallState ); + + if( (iCallState == aCallState) && ( aCallState == MCCPCallObserver::ECCPStateIdle )) + { + CCELOGSTRING2("id:%d CCCECall::NotifyCallStatusChange: Same status, still Idle", iCallId ); + return; + } + + iCallState = aCallState; + + if( iTransferController ) + { + iTransferController->HandleCallStateChanged( this, aCallState ); + } + + // Notify observer + if( iObserver && (aNotify != CCECallEnums::ENoNotify)) + { + if( aInband ) + { + iObserver->CallStateChangedWithInband( aCallState ); + } + else + { + iObserver->CallStateChanged( aCallState ); + } + + } + else + { + CCELOGSTRING2("id:%d CCCECall::NotifyCallStatusChange:No observer", iCallId ); + } + + // Notify CallContainer + iCallContainer.HandleCallStatusChange( aCallState, this, aNotify ); + } + +// --------------------------------------------------------------------------- +// Tells if CS plugin is used +// --------------------------------------------------------------------------- +// +TBool CCCECall::IsCsPlugin() const + { + TBool isCsPlugin( EFalse ); + if ( FeatureManager::FeatureSupported( KFeatureIdFfVoiceCallContinuity ) ) + { + if ( iCall->Parameters().CallType() != + CCPCall::ECallTypePS ) + { + isCsPlugin = ETrue; + } + } + else + { + if( iImplementationUid == KCSProviderUid ) + { + isCsPlugin = ETrue; + } + } + return isCsPlugin; + } + +// End of file