--- /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 <exterror.h> // GSM error codes
+#include <gsmerror.h>
+#include <etelmm.h>
+#include <ccpdefs.h>
+
+#include <featmgr.h>
+
+#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<MCCECallObserver*>( &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<RMobileCall::TMobileCallInfoV3Pckg&>( 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<MCCPCSCall*>(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<MCCPCSCall*>(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<MCCPCSCall*>(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<MCCPCSCall*>(iCall)->GetMobileDataCallCaps(aCaps);
+ }
+ else
+ return KErrNotSupported;
+ }
+
+
+// ---------------------------------------------------------------------------
+// LogDialedNumber()
+// ---------------------------------------------------------------------------
+//
+TBool CCCECall::LogDialedNumber() const
+ {
+ // CS related
+ CCELOGSTRING2("id:%d CCCECall::LogDialedNumber()", iCallId);
+
+ if ( IsCsPlugin() )
+ {
+ return static_cast<MCCPCSCall*>(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<MCCPCSCall*>(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