convergedcallengine/cce/src/cccecall.cpp
changeset 0 ff3b6d0fd310
child 19 7d48bed6ce0c
--- /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