convergedcallengine/csplugin/src/cspcall.cpp
branchRCL_3
changeset 20 987c9837762f
child 21 0a6dd2dc9970
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/convergedcallengine/csplugin/src/cspcall.cpp	Wed Sep 01 12:15:03 2010 +0100
@@ -0,0 +1,1971 @@
+/*
+* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Implements class CSPCall which provides call functionality
+*
+*/
+
+
+#include <etelmm.h>
+#include <etel.h>
+#include <centralrepository.h>
+#include <settingsinternalcrkeys.h>
+#include <ccpdefs.h>
+#include <gsmerror.h>
+#include <etelsat.h>
+#include <cccpcallparameters.h>
+
+#include "cspcall.h"
+#include "cspetelcallrequester.h"
+#include "cspetelcalleventmonitor.h"
+#include "cspcallinfomonitor.h"
+#include "cspetelcallstatusmonitor.h"
+#include "cspetelcallcapsmonitor.h"
+#include "csptransferprovider.h"
+#include "cspforwardprovider.h"
+#include "csplogger.h"
+#include "csppanic.pan"
+#include "cspconsts.h"
+#include "cspaudiohandler.h"
+#include "mcspcommoninfo.h"
+#include "mcspsecuritysettingobserver.h"
+#include "tcspskypeidparser.h"
+#include "cspuuimonitor.h"
+#include "cspuuimessagesender.h"
+
+const TInt KTimesToSplitValue = 16;
+
+
+// ---------------------------------------------------------------------------
+// CSPCall::~CSPCall
+// ---------------------------------------------------------------------------
+//
+CSPCall::~CSPCall()
+    {
+    CSPLOGSTRING(CSPOBJECT, "CSPCall::~CSPCall <");
+
+    delete iParams;
+    iCommonInfo.IndicateHangupComplete( *this );
+    
+    if ( iAudioHandler 
+         && iAudioStatus == ECSPCallAudioStatusActive )
+        {
+        iAudioStatus = ECSPCallAudioStatusInactive;
+        iAudioHandler->Stop();
+        }
+    
+    delete iUserToUserInformation;    
+    delete iRequester;    
+    delete iCallEventMonitor;
+    delete iCallStatusMonitor;
+    delete iCallCapsMonitor; 
+    delete iCallInfoMonitor;
+    delete iForwardProvider;
+    delete iTransferProvider;
+    delete iUUIMonitor;
+    delete iUUIMessageSender;
+    delete iSkypeId;
+
+    iObservers.Close();        
+    if ( iCall.SubSessionHandle() )
+        {
+        iCall.Close();
+        }
+    
+    CSPLOGSTRING(CSPOBJECT, "CSPCall::~CSPCall >");
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::SetAudioHandler
+// ---------------------------------------------------------------------------
+//
+void CSPCall::SetAudioHandler( CSPAudioHandler* aHandler )
+    {
+    CSPLOGSTRING2(CSPINT, "CSPCall::SetAudioHandler handler: %x", aHandler);
+    iAudioHandler = aHandler;
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::SecuritySettingChanged
+// ---------------------------------------------------------------------------
+//
+void CSPCall::SecuritySettingChanged( TInt aValue )
+    {
+    switch ( aValue )
+        {
+        case MCSPSecuritySettingObserver::ESecureCall:         
+            {
+            CSPLOGSTRING(CSPINT, 
+                    "CSPCall::SecuritySettingChanged Sending 'secure call' event");
+            NotifyCallEventOccurred( MCCPCallObserver::ECCPSecureCall );
+            break; 
+            }            
+        case MCSPSecuritySettingObserver::ENotSecureCall:                     
+            {
+            CSPLOGSTRING(CSPINT, 
+                    "CSPCall::SecuritySettingChanged Sending 'not secure call' event");
+            NotifyCallEventOccurred( MCCPCallObserver::ECCPNotSecureCall );
+            break;  
+            }
+        case MCSPSecuritySettingObserver::ESecureNotSpecified:                     
+            {
+            CSPLOGSTRING(CSPINT, 
+                    "CSPCall::SecuritySettingChanged Sending SecureNotSpecified");
+            NotifyCallEventOccurred( MCCPCallObserver::ECCPSecureNotSpecified );
+            break;  
+            }
+
+        default: 
+            {
+            CSPLOGSTRING(CSPERROR, "CSPCall::SecuritySettingChanged, \
+                unknown event");            
+            break;  
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::RemoteAlertingToneStatusChanged
+// Sends EarlyMediaStarted event to observer if network has started to 
+// play remote alerting tone. There is only one known use case: Network
+// starts playing alerting tone during connecting state. 
+//
+// This RemoteAlertingToneStatusChanged is called for every call, 
+// so it is calls responsibility to determine if the 
+// observer should be notified.
+// ---------------------------------------------------------------------------
+//
+void CSPCall::RemoteAlertingToneStatusChanged(
+    RMmCustomAPI::TRemoteAlertingToneStatus aNewStatus )
+    {
+    CSPLOGSTRING2(CSPINT, 
+        "CSPCall::RemoteAlertingToneStatusChanged new status: %d", aNewStatus );
+    
+    if ( aNewStatus == RMmCustomAPI::EUiStopTone ||
+         aNewStatus == RMmCustomAPI::EUiNoTone ) // NW tells us to stop playing 
+        {
+        // Connecting is only state where network starts playing the tone.
+        if ( iCallState == MCCPCallObserver::ECCPStateConnecting )
+            {
+            NotifyCallEventOccurred( 
+                MCCPCallObserver::ECCCSPEarlyMediaStarted );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::NotifyCallStateChangedETel
+// Notifies observers about state changes
+// ---------------------------------------------------------------------------
+//
+void CSPCall::NotifyCallStateChangedETel( RMobileCall::TMobileCallStatus aState ) 
+    {
+    CSPLOGSTRING3(CSPINT, 
+                  "CSPCall::NotifyCallStateChangedETel < state: %d this: %x", 
+                  aState, this );
+    switch ( aState )
+        {
+        /*
+        Cannot receive any mapping call statuses from ETel to following
+        optional states:
+        
+        ECCPStateForwarding   MO call is being forwarded at receiver end
+        ECCPStateQueued       Call is queued locally.
+        
+        The commented observer calls are for CS specific call states.
+        */
+        
+        // Indicates that the call is idle or unknown.
+        case RMobileCall::EStatusIdle:
+        case RMobileCall::EStatusUnknown:
+            {
+            CSPLOGSTRING(CSPINT, "CSPCall::NotifyCallStateChangedETel Idle");
+
+            // If audio still active
+            if ( iAudioStatus == ECSPCallAudioStatusActive 
+                 && iAudioHandler
+                 && ( iParams->CallType() == CCPCall::ECallTypeCSVoice 
+                    || iParams->CallType() == CCPCall::ECallTypeVideo ) )
+                {
+                iAudioStatus = ECSPCallAudioStatusInactive;
+                iAudioHandler->Stop();
+                }
+                
+            // Notify error in case not going through disconnecting
+            if ( iCallState != MCCPCallObserver::ECCPStateDisconnecting 
+                     && !iTerminationErrorNotified )
+                {
+                CheckAndNotifyTerminationError();
+                }
+            
+            NotifyCallStateChanged( MCCPCallObserver::ECCPStateIdle );
+            iCommonInfo.IndicateHangupComplete( *this );
+            break;
+            }
+        // The call is dialling.
+        case RMobileCall::EStatusDialling:
+            CSPLOGSTRING(CSPINT, "CSPCall callstate Dialling");
+            {
+			// Start streams also for MO video call to prevent audio routing problems
+			// with other applications.
+            if ( iAudioHandler 
+                 && ( iParams->CallType() == CCPCall::ECallTypeCSVoice 
+                    || iParams->CallType() == CCPCall::ECallTypeVideo ) )
+                {
+                iAudioStatus = ECSPCallAudioStatusActive;
+                iAudioHandler->Start();
+                }
+                
+            iDontReportTerm = EFalse;
+            NotifyCallStateChanged( MCCPCallObserver::ECCPStateDialling );
+            break;
+            }            
+        //Indicates that the MT call is ringing but not answered yet by 
+        // the local user
+        case RMobileCall::EStatusRinging:
+            {
+            CSPLOGSTRING(CSPINT, "CSPCall::NotifyCallStateChangedETel Ringing");
+            NotifyCallStateChanged( MCCPCallObserver::ECCPStateRinging );
+            break;
+            }
+        // Indicates that the local user has answered the MT call but
+        // the network has not acknowledged the call connection yet. 
+        case RMobileCall::EStatusAnswering:
+            {
+            CSPLOGSTRING(CSPINT, "CSPCall::NotifyCallStateChangedETel Answering");
+
+            if ( !iMobileOriginated
+                && iAudioHandler 
+                && iAudioStatus == ECSPCallAudioStatusInactive
+                && iParams->CallType() == CCPCall::ECallTypeCSVoice )
+                {
+                iAudioStatus = ECSPCallAudioStatusActive;
+                iAudioHandler->Start();
+                }
+
+            NotifyCallStateChanged( MCCPCallObserver::ECCPStateAnswering );
+            break;
+            }
+        // MO Call: the network notifies to the MS that the remote party
+        // is now ringing. 
+        case RMobileCall::EStatusConnecting:
+            {
+            CSPLOGSTRING(CSPINT, "CSPCall::NotifyCallStateChangedETelConnecting");
+            RMmCustomAPI::TRemoteAlertingToneStatus tone = 
+                iCommonInfo.GetRemoteAlertingToneStatus();
+            if ( tone == RMmCustomAPI::EUiNoTone ||
+                 tone == RMmCustomAPI::EUiStopTone )
+                {
+                NotifyCallStateChangedWithInband( MCCPCallObserver::ECCPStateConnecting );
+                }
+            else
+                {
+                NotifyCallStateChanged( MCCPCallObserver::ECCPStateConnecting );
+                }
+            break;
+            }
+        // Indicates that call is connected and active.
+        case RMobileCall::EStatusConnected:
+            {
+            CSPLOGSTRING(CSPINT, "CSPCall::NotifyCallStateChangedETel Connected");
+
+            iDontReportTerm = ETrue;
+            NotifyCallStateChanged( MCCPCallObserver::ECCPStateConnected );
+            
+            // Agreement with TSY is that the
+            // COLP number is available in connected state.
+            NotifyRemotePartyNumberChanged();            
+            
+            // Stop streams for MO video call so that Video Telephony can 
+            // receive RemCon commands instead of Phone.
+            if ( iMobileOriginated
+                && iAudioHandler 
+                && iAudioStatus == ECSPCallAudioStatusActive
+                && iParams->CallType() == CCPCall::ECallTypeVideo )
+                {
+                iAudioStatus = ECSPCallAudioStatusInactive;
+                iAudioHandler->Stop();
+                }
+            break;
+            }
+        // Indicates that call is disconnecting. (Same as RCall::HangingUp)
+        case RMobileCall::EStatusDisconnecting:
+            {
+            CSPLOGSTRING(CSPINT, "CSPCall::NotifyCallStateChangedETel Disconnecting");
+
+            if ( !iTerminationErrorNotified )
+                {
+                CheckAndNotifyTerminationError();
+                }
+            
+            NotifyCallStateChanged( MCCPCallObserver::ECCPStateDisconnecting );                
+            break;
+            }
+        // Indicates that the call is disconnecting with inband data
+        // (to enable the network to send an audio tone), signifying
+        // that the call is not to be released until user terminates call
+        case RMobileCall::EStatusDisconnectingWithInband:
+            {
+            CSPLOGSTRING(CSPINT, 
+                "CSPCall::NotifyCallStateChangedETel DisconnectingWithInband");
+
+            if ( !iTerminationErrorNotified )
+                {
+                CheckAndNotifyTerminationError();
+                }
+            
+            NotifyCallStateChangedWithInband( 
+                                MCCPCallObserver::ECCPStateDisconnecting );
+            break;
+            }
+        // Indicates that the call is connected but on hold.  
+        case RMobileCall::EStatusHold:
+            {
+            CSPLOGSTRING(CSPINT, "CSPCall::NotifyCallStateChangedETel Hold");
+            NotifyCallStateChanged( MCCPCallObserver::ECCPStateHold );
+            break;
+            }
+        case RMobileCall::EStatusTransferring:
+            {
+            CSPLOGSTRING(CSPINT, "CSPCall::NotifyCallStateChangedETel Transferring");
+            NotifyCallStateChanged( MCCPCallObserver::ECCPStateTransferring );
+            break;
+            }
+            
+        // Indicates that call is undergoing temporary channel loss
+        // and it may or may not be reconnected.  
+        case RMobileCall::EStatusReconnectPending: // fall through 
+        //Indicates that the call is the non-active half of an alternating
+        // call. This call is waiting for its active half or the remote
+        // end to switch alternating call mode.
+        case RMobileCall::EStatusWaitingAlternatingCallSwitch: // fall through
+        case RMobileCall::EStatusTransferAlerting:
+            {
+            CSPLOGSTRING2(CSPINT, 
+                    "CSPCall::NotifyCallStateChangedETel no special handling for state %d",
+                    aState);            
+            break;
+            }
+
+        default:
+            {
+            CSPLOGSTRING(CSPERROR, 
+                    "CSPCall::NotifyCallStateChangedETel callstate UNKNOWN");
+            break;
+            }
+        }
+    CSPLOGSTRING(CSPREQIN, "CSPCall::NotifyCallStateChangedETel >");
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::NotifyCallEventOccurred
+// Notifies observers about call events
+// ---------------------------------------------------------------------------
+//
+void CSPCall::NotifyCallEventOccurred( 
+    MCCPCallObserver::TCCPCallEvent aEvent )
+    {
+    CSPLOGSTRING2(CSPINT, 
+            "CSPCall::NotifyCallEventOccurred < event: %d", aEvent);
+    
+    TInt obsCount = iObservers.Count();
+    for ( TInt i = 0; i < obsCount; i++ )
+        {
+        CSPLOGSTRING2(CSPINT, "CSPCall::NotifyCallEventOccurred obs=%d",i);
+        MCCPCallObserver *obs = iObservers[i];
+        if ( obs )
+            {
+            obs->CallEventOccurred( aEvent, this );
+            }
+            
+        CSPLOGSTRING2(CSPINT, "CSPCall::NotifyCallEventOccurred ok obs=%d",i);
+        }
+        
+    CSPLOGSTRING2(CSPINT, "CSPCall::NotifyCallEventOccurred > event: %d", aEvent);
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::NotifyTransferCallEventOccurred
+// Forward notification of transfer event to it's provider
+// ---------------------------------------------------------------------------
+//
+void CSPCall::NotifyTransferCallEventOccurred( 
+    MCCPTransferObserver::TCCPTransferEvent aEvent ) 
+    {
+    CSPLOGSTRING2(CSPINT, "CSPCall::NotifyTransferCallEventOccurred %d", aEvent);
+    // forward the method call to CSPTransferProvider object
+    iTransferProvider->TransferEventOccurred( aEvent );
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::NotifyForwardEventOccurred
+// Notifies observers about call events
+// ---------------------------------------------------------------------------
+//
+void CSPCall::NotifyForwardEventOccurred( 
+    MCCPForwardObserver::TCCPForwardEvent aEvent )
+    {
+    CSPLOGSTRING2(CSPINT, "CSPCall::NotifyForwardEventOccurred %d", aEvent);
+    iForwardProvider->NotifyForwardEventOccurred( aEvent );    
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::CallName
+// Get call name
+// ---------------------------------------------------------------------------
+//
+void CSPCall::CallName( TName& aCallName )
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::CallName");
+    aCallName.Zero();
+    aCallName.Append( iCallName );
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::DialRequestFailed
+// Handles situations when dial fails
+// ---------------------------------------------------------------------------
+//
+void CSPCall::DialRequestFailed( TInt aErrorCode )
+    {
+    CSPLOGSTRING(CSPERROR, "CSPCall::DialRequestFailed");
+    iDialCompletionCode = aErrorCode;
+    
+    // If state has not changed 
+    // ( e.g. in case of dial could not be initiated by network problem)
+    if ( iCallStatusMonitor->State() == 
+                   RMobileCall::RMobileCall::EStatusUnknown )
+        {
+	    NotifyErrorOccurred( iRequester->MapError( aErrorCode ) );	        	
+        
+        // Force release since otherwise call remains unreleased
+        CSPLOGSTRING(CSPERROR, "CSPCall::DialRequestFailed() Force Idle");
+        NotifyCallStateChanged( MCCPCallObserver::ECCPStateIdle );
+        }
+    
+    // If dial request has completed after notifying disconnecting state
+    else if ( iCallState == MCCPCallObserver::ECCPStateDisconnecting
+             && !iTerminationErrorNotified )
+        {
+        CheckAndNotifyTerminationError();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::EmergencyDialRequestFailed
+// Handles situations when emergency dial fails
+// ---------------------------------------------------------------------------
+//
+void CSPCall::EmergencyDialRequestFailed( TInt /*aErrorCode*/ )
+    {
+    CSPLOGSTRING(CSPERROR, "CSPCall::EmergencyDialRequestFailed");
+    
+    // Always same error code for CCE
+    NotifyErrorOccurred( ECCPEmergencyFailed );
+    
+    // Mark that exit code will not be used
+    iTerminationErrorNotified = ETrue;
+    }
+    
+// ---------------------------------------------------------------------------
+// CSPCall::NotifyErrorOccurred
+// Notifies observers about errors
+// ---------------------------------------------------------------------------
+//
+void CSPCall::NotifyErrorOccurred( TCCPError aError )
+    {
+    CSPLOGSTRING2(CSPERROR, "CSPCall::NotifyErrorOccurred err %d", aError );
+
+    TInt obsCount = iObservers.Count();
+    for ( TInt i = 0; i < obsCount; i++ )
+        {
+        MCCPCallObserver *obs = iObservers[i];
+        if ( obs )
+            {
+            obs->ErrorOccurred( aError, this );
+            }
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// CSPCall::CallCapsChanged
+// Notifies observers about new capabilities.
+// ---------------------------------------------------------------------------
+//
+void CSPCall::CallCapsChanged( const TUint32 aCapsFlags )
+    {
+    CSPLOGSTRING2(CSPERROR, "CSPCall::CallCapsChanged %b", aCapsFlags );
+    iCapsFlags = aCapsFlags;
+    TInt obsCount = iObservers.Count();
+    for ( TInt i = 0; i < obsCount; i++ )
+        {
+        MCCPCallObserver *obs = iObservers[i];
+        if ( obs )
+            {
+            obs->CallCapsChanged( aCapsFlags, this );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCSCall
+// CSPCall::GetMobileCallInfo
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::GetMobileCallInfo( TDes8& aCallInfo ) const
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::GetMobileCallInfo");
+    return iCall.GetMobileCallInfo( aCallInfo );
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCSCall
+// CSPCall::GetMobileDataCallCaps
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::GetMobileDataCallCaps( TDes8& /*aCaps*/ ) const
+    {
+    CSPLOGSTRING(CSPERROR, 
+            "CSPCall::GetMobileDataCallCaps ERROR, Not supported");
+    return KErrNotSupported;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Dial
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::Dial()
+    {
+    CSPLOGSTRING( CSPREQIN, "CSPCall::Dial" );
+    // Parameters not given, must create empty descriptor.
+    TBuf8<1> params;
+    return Dial(params);
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::RemoteParty
+// ---------------------------------------------------------------------------
+//
+const TDesC& CSPCall::RemoteParty() const
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::RemoteParty");
+    return iRemotePartyNumber;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::RemotePartyName
+// ---------------------------------------------------------------------------
+//
+const TDesC& CSPCall::RemotePartyName()
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::RemotePartyName");
+    return iRemotePartyName;
+    }
+  
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::DialledParty
+// ---------------------------------------------------------------------------
+//  
+const TDesC& CSPCall::DialledParty() const 
+    {
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::DialledParty %S", &iRemotePartyNumber);
+    return iRemotePartyNumber;
+    }
+    
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Answer
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::Answer()
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::Answer <");
+    TInt ret( KErrNone );
+    
+    if ( iCallState == MCCPCallObserver::ECCPStateRinging 
+         || iCallState == MCCPCallObserver::ECCPStateQueued )
+        {    
+        if( iMobileOriginated )
+            {
+            ret = KErrGeneral;
+            }
+        else if( iCallState != MCCPCallObserver::ECCPStateRinging && 
+            iCallState != MCCPCallObserver::ECCPStateQueued )
+            {
+            ret = KErrAccessDenied;
+            }
+        else
+            {
+            ret = iCommonInfo.IndicateAnswerRequest( *this );
+            }
+        }
+    else
+        {
+        // Not correct state for answer
+        ret = KErrNotReady;
+        }
+    
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::Answer > ret %d", ret);
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCallCommandHandling
+// CSPCall::PerformAnswerRequest
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::PerformAnswerRequest()
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::PerformAnswerRequest");
+    
+    TInt ret = iRequester->MakeRequest( CSPEtelCallRequester::ERequestTypeAnswer );
+    CSPLOGSTRING3(CSPINT, 
+            "CSPCall::Answer request performed, call state %d ret: %d", iCallState, ret);
+
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Reject
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::Reject()
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::Reject <");
+    TInt ret;
+    if ( iCallState == MCCPCallObserver::ECCPStateRinging
+         || iCallState == MCCPCallObserver::ECCPStateQueued
+         || iCallState == MCCPCallObserver::ECCPStateAnswering )
+        {        
+        CSPLOGSTRING( CSPREQIN, "CSPCall::Reject 2" );
+        ret = HangUp();
+        }
+    else
+        {
+        ret = KErrNotReady;
+        }
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::Reject > ret: %d", ret );
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Queue
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::Queue()
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::Queue");
+    TBool callWaitingState;
+    iDontReportTerm = ETrue;
+    
+    TRAPD( res, iCommonInfo.GetCallWaitingL( *iParams, callWaitingState ) );
+    if( res == KErrNone )
+        {
+        if ( callWaitingState )
+            {
+            CSPLOGSTRING(CSPREQIN, "CSPCall::Queue Call Waiting On");
+            iCallState = MCCPCallObserver::ECCPStateQueued;
+            
+            // Notify Queued state
+            TInt obsCount = iObservers.Count ( );
+            for (TInt i = 0; i < obsCount; i++ )
+                {
+                MCCPCallObserver *obs = iObservers[i];
+                if ( obs )
+                    {
+                    obs->CallStateChanged ( iCallState, this );
+                    }
+                }
+            CSPLOGSTRING(CSPOBJECT, "CSPCall::Queue ok");
+
+            return KErrNone;
+            }
+        else
+            {
+            CSPLOGSTRING(CSPREQIN, "CSPCall::Queue Call Waiting Off");
+            }
+        }
+    else
+        {
+        CSPLOGSTRING2(CSPERROR, 
+                      "CSPCall::Queue Error %d with CR. Call Waiting Off", 
+                      res);
+        }
+    
+    return KErrNotSupported;
+    }
+    
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Ringing
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::Ringing()
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::Ringing");
+    iDontReportTerm = ETrue;
+    
+    // Ringing state is accepted because MT-call goes to ringing
+    // state in the beginning based on ETel state maching.
+    if ( iCallState == MCCPCallObserver::ECCPStateIdle ||
+         iCallState == MCCPCallObserver::ECCPStateRinging ) 
+        {
+        NotifyRingingState();
+        return KErrNone;
+        }
+    else if ( iCallState == MCCPCallObserver::ECCPStateAnswering )
+        {
+        // Do nothing if already in Answering state (autoanswer).   
+        return KErrNone; 
+        }
+        
+    return KErrNotReady;
+    }
+    
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::HangUp
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::HangUp()
+    {
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::HangUp this: %x", this);
+    TInt ret( KErrNone );
+    
+    CSPEtelCallRequester::TRequestType req = iRequester->Request();
+    if ( req == CSPEtelCallRequester::ERequestTypeDial || 
+         ( req == CSPEtelCallRequester::ERequestTypeDialEmergency ) )
+        {
+        CSPLOGSTRING(CSPREQIN, "CSPCall::HangUp 1: Cancel ongoing dial");
+        ret = iRequester->DialCancel();
+        CSPLOGSTRING(CSPREQIN, "CSPCall::HangUp Canceled");
+        }
+    else if ( req == CSPEtelCallRequester::ERequestTypeHangup )
+        {
+        CSPLOGSTRING(CSPREQIN, "CSPCall::HangUp 2");
+        ret = KErrAlreadyExists;
+        }
+    else if ( req == CSPEtelCallRequester::ERequestTypeNone 
+              && iCallState != MCCPCallObserver::ECCPStateIdle )
+        {
+        CSPLOGSTRING(CSPREQIN, "CSPCall::HangUp 3");
+        ret = iRequester->MakeRequest( CSPEtelCallRequester::ERequestTypeHangup );
+        iCommonInfo.IndicateActiveHangup( *this );
+        }
+    else if ( req == CSPEtelCallRequester::ERequestTypeNone )
+        {
+        CSPLOGSTRING(CSPREQIN, "CSPCall::HangUp 4");
+        ret = KErrAlreadyExists;
+        }
+    else
+        {
+        CSPLOGSTRING(CSPREQIN, "CSPCall::HangUp 5");
+        // Request pending, must be canceled
+        iRequester->Cancel();
+        ret = iRequester->MakeRequest( CSPEtelCallRequester::ERequestTypeHangup );
+        iCommonInfo.IndicateActiveHangup( *this );
+        }
+        
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Cancel
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::Cancel()
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::Cancel");
+    return HangUp();
+    }
+        
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Hold
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::Hold()
+    {
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::Hold this: %x", this);
+    TInt ret;
+        
+    if ( iCallState == MCCPCallObserver::ECCPStateConnected )
+        {
+        CSPLOGSTRING(CSPREQOUT, "CSPCall::Hold make request");
+
+        // Set call on hold
+        ret = iRequester->MakeRequest( 
+                    CSPEtelCallRequester::ERequestTypeHold );
+        if ( ret != KErrNone )
+            {
+            CSPLOGSTRING2(CSPERROR, 
+                "CSPCall::Hold ERROR: %d", ret);
+            }
+        }
+    else if ( iCallState == MCCPCallObserver::ECCPStateHold )
+        {
+        CSPLOGSTRING(CSPERROR, "CSPCall::Hold : already held");
+        ret = KErrAlreadyExists;
+        }
+    else
+        {
+        CSPLOGSTRING(CSPERROR, "CSPCall::Hold not allowed");
+        ret = KErrNotReady;
+        }
+
+    return ret;
+    } 
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Resume
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::Resume()
+    {
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::Resume this: %x", this);
+    TInt ret;
+        
+    if ( iCallState == MCCPCallObserver::ECCPStateHold )
+        {
+        CSPLOGSTRING(CSPREQOUT, "CSPCall::Resume request");
+        
+        ret = iRequester->MakeRequest( 
+            CSPEtelCallRequester::ERequestTypeResume );
+        if ( KErrNone != ret )
+            {
+            CSPLOGSTRING2(CSPERROR, "CSPCall::Resume ERROR %d", ret);
+            }
+        }
+    else if ( iCallState == MCCPCallObserver::ECCPStateConnected )
+        {
+        CSPLOGSTRING(CSPERROR, "CSPCall::Resume already connected" );
+        ret = KErrAlreadyExists;
+        }
+    else
+        {
+        CSPLOGSTRING(CSPERROR, "CSPCall::Resume not held state" );
+        ret = KErrNotReady;
+        }
+    
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Swap
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::Swap()
+    {
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::Swap this: %x", this);
+    TInt ret;
+    if ( iCallState == MCCPCallObserver::ECCPStateConnected
+         || iCallState == MCCPCallObserver::ECCPStateHold )
+        {    
+        ret = iRequester->MakeRequest( CSPEtelCallRequester::ERequestTypeSwap );
+        if ( ret )
+            {
+            CSPLOGSTRING2( CSPERROR, "CSPCall::Swap Error %d", ret );
+            }
+        }
+    else
+        {
+        ret = KErrNotReady;
+        }
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::IsMobileOriginated
+// ---------------------------------------------------------------------------
+//
+TBool CSPCall::IsMobileOriginated() const
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::IsMobileOriginated");
+    return iMobileOriginated;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::State
+// ---------------------------------------------------------------------------
+//
+MCCPCallObserver::TCCPCallState CSPCall::State() const
+    {
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::State %d", iCallState);
+    return iCallState;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Uid
+// ---------------------------------------------------------------------------
+//
+TUid CSPCall::Uid() const
+    {
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::Uid %d", KCSPImplementationUid);
+    return KCSPImplementationUid;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Caps
+// ---------------------------------------------------------------------------
+//
+MCCPCallObserver::TCCPCallControlCaps CSPCall::Caps( ) const
+    {
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::Caps %b", iCapsFlags );
+    return (MCCPCallObserver::TCCPCallControlCaps) iCapsFlags;
+    }
+ 
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::SetParameters
+// ---------------------------------------------------------------------------
+//
+void CSPCall::SetParameters( const CCCPCallParameters& /*aNewParams*/ )
+    {
+    CSPLOGSTRING(CSPOBJECT, "CSPCall::SetParameters ERROR Can't set params");
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Parameters
+// ---------------------------------------------------------------------------
+//
+const CCCPCallParameters& CSPCall::Parameters() const
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::Parameters");
+    return *iParams;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::TransferProvider
+// ---------------------------------------------------------------------------
+//
+MCCPTransferProvider* CSPCall::TransferProviderL(const MCCPTransferObserver& 
+                                                            aObserver )
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::TransferProvider");
+    iTransferProvider->AddObserverL( aObserver );
+    return iTransferProvider;
+    }
+    
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::ForwardProvider
+// ---------------------------------------------------------------------------
+//
+MCCPForwardProvider* CSPCall::ForwardProviderL( 
+        const MCCPForwardObserver& aObserver )
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::ForwardProvider");
+    iForwardProvider->AddObserverL( aObserver );
+    return iForwardProvider;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::AddObserverL
+// ---------------------------------------------------------------------------
+//
+void CSPCall::AddObserverL( const MCCPCallObserver& aObserver )
+    {
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::AddObserverL %x", &aObserver);
+    if ( iObservers.Find( &aObserver ) == KErrNotFound )
+        {
+        iObservers.AppendL( &aObserver );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// Removes observer.
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::RemoveObserver( const MCCPCallObserver& aObserver )
+    {
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::RemoveObserver %x", &aObserver);
+    
+    TInt found = iObservers.Find( &aObserver );
+    if ( found != KErrNotFound )
+        {
+        iObservers.Remove( found );
+        return KErrNone;
+        }
+        
+    return found;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::IsCallForwarded
+// ---------------------------------------------------------------------------
+//
+TBool CSPCall::IsCallForwarded( ) const
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::IsCallForwarded <");
+    TBool ret( EFalse );
+    TInt err( KErrNone );
+    RMobileCall::TMobileCallInfoV3 callInfo;
+    RMobileCall::TMobileCallInfoV3Pckg pck( callInfo );
+    err = iCall.GetMobileCallInfo( pck );
+    if (err == KErrNone )
+        {
+        ret = callInfo.iForwarded;
+        }
+    
+    CSPLOGSTRING2(CSPREQIN, 
+            "CSPCall::IsCallForwarded > forwarder: %d", ret );
+    
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::IsSecured
+// ---------------------------------------------------------------------------
+//
+TBool CSPCall::IsSecured( ) const
+    {    
+    CSPLOGSTRING(CSPREQIN, "CSPCall::IsSecured");
+    return iCommonInfo.NetworkSecurityStatus();
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::SecureSpecified
+// ---------------------------------------------------------------------------
+//
+TBool CSPCall::SecureSpecified( ) const
+    {    
+    CSPLOGSTRING(CSPREQIN, "CSPCall::SecureSpecified");
+    return iCommonInfo.SecureSpecified();
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCall
+// CSPCall::Tone
+// ---------------------------------------------------------------------------
+//
+TCCPTone CSPCall::Tone() const
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::Tone <");
+    TCCPTone tone( ECCPNoSoundSequence );
+
+    if ( iCallState == MCCPCallObserver::ECCPStateConnecting )
+        {
+        RMmCustomAPI::TRemoteAlertingToneStatus ts = iCommonInfo.GetRemoteAlertingToneStatus();
+        
+        if (ts == RMmCustomAPI::EUiRbtTone )
+            {
+            tone = ECCPRemoteAlerting;
+            }
+        else if ( ts == RMmCustomAPI::EUiStopTone )
+            {
+            tone = ECCPNoSoundSequence;
+            }
+        else            
+            {
+            // No tone
+            tone = ECCPNoSoundSequence;
+            }
+        }
+    else
+        {
+        // Handle disconnecting tones      
+        TInt callDisconnectingError = ExitCodeError();
+        CSPLOGSTRING2(CSPINT, "CSPCall::Tone exit code err: %d", callDisconnectingError);
+
+        switch( callDisconnectingError )
+            {
+            case KErrNone:
+                // GSM: DIAL TONE (optional) - not used in Nokia phones 
+                CSPLOGSTRING(CSPERROR, "CSPCall::Tone: No sound");
+                break;
+            case KErrGsmCCUserBusy:
+                // GSM: SUBSCRIBER BUSY
+                tone = ECCPToneUserBusy;
+                CSPLOGSTRING(CSPINT, "CSPCall::Tone: Subscriber Busy");
+                break;
+                // Fall through
+            case KErrGsmCCNumberChanged:
+            case KErrGsmCCResponseToStatusEnquiry:
+            case KErrGsmCCNormalUnspecified:
+                // GSM: NONE, Nokia phones: radio path not available
+                tone = ECCPToneRadioPathNotAvailable;
+                CSPLOGSTRING(CSPINT, "CSPCall::Tone: RadioPathNotAvailable");
+                break;      
+            case KErrGsmCCNoChannelAvailable:
+            case KErrGsmCCTemporaryFailure:
+            case KErrGsmCCSwitchingEquipmentCongestion:
+            case KErrGsmCCRequestedChannelNotAvailable:
+            case KErrGsmCCQualityOfServiceNotAvailable:
+            case KErrGsmCCBearerCapabilityNotCurrentlyAvailable:
+                // GSM: CONGESTION
+                tone = ECCPToneCongestion;
+                CSPLOGSTRING(CSPINT, "CSPCall::Tone: Congestion");
+                break;
+            case KErrGsmCCUnassignedNumber:
+            case KErrGsmCCNoRouteToDestination:
+            case KErrGsmCCChannelUnacceptable:
+            case KErrGsmCCOperatorDeterminedBarring:
+            case KErrGsmCCUserNotResponding:
+            case KErrGsmCCUserAlertingNoAnswer:
+            case KErrGsmCCCallRejected:
+            case KErrGsmCCNonSelectedUserClearing:
+            case KErrGsmCCDestinationOutOfOrder:
+            case KErrGsmCCInvalidNumberFormat:
+            case KErrGsmCCFacilityRejected:
+            case KErrGsmCCNetworkOutOfOrder:
+            case KErrGsmCCAccessInformationDiscarded:
+            case KErrGsmCCResourceNotAvailable:
+            case KErrGsmCCRequestedFacilityNotSubscribed:
+            case KErrGsmCCIncomingCallsBarredInCug:
+            case KErrGsmCCBearerCapabilityNotAuthorised:
+            case KErrGsmCCServiceNotAvailable:
+            case KErrGsmCCBearerServiceNotImplemented:
+            case KErrGsmCCChannelTypeNotImplemented:
+            case KErrGsmCCAcmGreaterThanAcmMax:
+            case KErrGsmCCRequestedFacilityNotImplemented:
+            case KErrGsmCCOnlyRestrictedDigitalInformationBCAvailable:
+            case KErrGsmCCServiceNotImplemented:
+            case KErrGsmCCInvalidCallReferenceValue:
+            case KErrGsmCCChannelDoesNotExist:
+            case KErrGsmCCSuspendedCallExistsButCallIdentityDoesNotWork:
+            case KErrGsmCCCallIdentityInUse:
+            case KErrGsmCCNoCallSuspended:
+            case KErrGsmCCRequestedCallIdentityAlreadyCleared:
+            case KErrGsmCCUserNotInCug:
+            case KErrGsmCCIncompatibleDestination:
+            case KErrGsmCCInvalidTransitNetworkSelection:
+            case KErrGsmCCIncompatibleSegmentedMessage:
+            case KErrGsmCCSemanticallyIncorrectMessage:
+            case KErrGsmCCInvalidMandatoryInformation:
+            case KErrGsmCCNonExistentMessageType:
+            case KErrGsmCCIncompatibleMessageInProtocolState:
+            case KErrGsmCCNonExistentInformationElement:
+            case KErrGsmCCConditionalIEError:
+            case KErrGsmCCIncompatibleMessageInCallState:
+            case KErrGsmCCRecoveryOnTimerExpiry:
+            case KErrGsmCCUnspecifiedProtocolError:
+            case KErrGsmCCUnspecifiedInterworkingError:
+                // GSM: SPECIAL INFORMATION
+                tone = ECCPToneSpecialInformation;
+                CSPLOGSTRING(CSPINT, "CSPCall::Tone: Special Information");
+                break;
+            default:
+                CSPLOGSTRING(CSPERROR, "CSPCall::Tone: ERROR not found");
+                break;
+            }
+         }
+    
+    CSPLOGSTRING2(CSPREQIN, "CSPCall::Tone > tone: %d", tone);
+    return tone;
+    }
+    
+// ---------------------------------------------------------------------------
+// From class MCCPCSCall
+// CSPCall::NoFdnCheck
+// ---------------------------------------------------------------------------
+//
+void CSPCall::NoFDNCheck( )
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::NoFDNCheck");
+    iFdnCheck = EFalse;
+    }
+    
+// ---------------------------------------------------------------------------
+// CSPCall::LogDialedNumber
+// ---------------------------------------------------------------------------
+//
+TBool CSPCall::LogDialedNumber() const
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::LogDialedNumber true");
+    return ETrue;
+    }
+    
+// ---------------------------------------------------------------------------
+// From class MCCPCSCall
+// CSPCall::Dial
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::Dial( const TDesC8& /*aCallParams*/ )
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::Dial");
+    return iCommonInfo.IndicateDialRequest( *this );
+    }
+
+// ---------------------------------------------------------------------------
+// From class MCCPCallCommandHandling
+// CSPCall::PerformDialRequest
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::PerformDialRequest()
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::PerformDialRequest");
+    iDialCompletionCode = KErrNone;
+    iTerminationErrorNotified = EFalse;
+    
+    // Send the User to User Information.
+    if( iUserToUserInformation->Length() )
+        {
+        iUUIMessageSender->SendUUIMessage( *iUserToUserInformation );
+        }
+    
+    return DialFdnCond( iFdnCheck );
+    }
+    
+// ---------------------------------------------------------------------------
+// CSPCall::CSPCall
+// ---------------------------------------------------------------------------
+//
+CSPCall::CSPCall( RMobileLine& aLine, 
+                  TBool aMobileOriginated,
+                  const TDesC& aName,
+                  MCSPCommonInfo& aCommonInfo,
+                  TBool aIsEmergencyCall ) : 
+                    iLine( aLine ),
+                    iMobileOriginated( aMobileOriginated ),
+                    iName( aName ), 
+                    iCommonInfo( aCommonInfo ),
+                    iTerminationErrorNotified( EFalse ),
+                    iIsEmergencyCall( aIsEmergencyCall),
+                    iFdnCheck(ETrue),
+                    iAudioStatus( ECSPCallAudioStatusInactive ) 
+                    
+    {
+    CSPLOGSTRING(CSPOBJECT, "CSPCall::CSPCall");
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::ConstructL
+// Constructing CSPCall in 2nd phase
+// ---------------------------------------------------------------------------
+//    
+void CSPCall::ConstructL( const CCCECallParameters& aParams )
+    {
+    CSPLOGSTRING(CSPOBJECT, "CSPCall::ConstructL <");
+
+    // Create cloned copy of call parameters 
+    iParams = static_cast<CCCECallParameters*>( aParams.CloneL() );
+    
+    // Open call handle  
+    OpenCallHandleL(); 
+
+    // Update call info 
+    UpdateCallInfo(); 
+    
+    // Update call state from ETel 
+    UpdateCallState(); 
+    
+    // Create call handlers for call related requests 
+    // and for monitoring call related events 
+    CreateCallHandlersL(); 
+        
+    CSPLOGSTRING(CSPOBJECT, "CSPCall::ConstructL >");
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::OpenCallHandleL
+// Open call handle, calls either OpenNewCallL or OpenExistingCallL depending 
+// of the call direction and if the call is a client call       
+// ---------------------------------------------------------------------------
+//    
+void CSPCall::OpenCallHandleL()
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::OpenCallHandleL <");
+    
+    if ( iMobileOriginated )
+        {
+        // There is no existing call on line, open new call 
+        OpenNewCall();
+        }
+    else
+        {
+        // Mobile terminated call on line, open existing call 
+        OpenExistingCallL( iName ); 
+        }
+
+    CSPLOGSTRING(CSPINT, "CSPCall::OpenCallHandleL >");
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::UpdateCallInfoL
+// Update call info including remote party name and number data  
+// ---------------------------------------------------------------------------
+//    
+void CSPCall::UpdateCallInfo()
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::UpdateCallInfo <");
+    RMobileCall::TMobileCallInfoV7 callInfo;
+    RMobileCall::TMobileCallInfoV7Pckg pck( callInfo );
+    TInt err = iCall.GetMobileCallInfo( pck );
+    
+    UpdateCallInfoImpl( callInfo );
+
+    CSPLOGSTRING(CSPINT, "CSPCall::UpdateCallInfo >");
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::UpdateCallInfoImpl
+// Implementation for UpdateCallInfo().
+// ---------------------------------------------------------------------------
+//    
+void CSPCall::UpdateCallInfoImpl( RMobileCall::TMobileCallInfoV7 aCallInfo )
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::UpdateCallInfoImpl <");
+
+    if ( iMobileOriginated )
+        {
+        // Call wasn't added by ETel monitor, update info accordingly
+        UpdateCallNameNumberInfo( aCallInfo, EFalse ); 
+        }
+    else
+        {
+        // Call was added by ETel monitor, update info accordingly
+        UpdateCallNameNumberInfo( aCallInfo, ETrue );
+        }
+    
+
+    CSPLOGSTRING(CSPINT, "CSPCall::UpdateCallInfoImpl >");
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::UpdateCallOrigin
+// Set call origin to CCCECallParameters.
+// ---------------------------------------------------------------------------
+//    
+void CSPCall::UpdateCallOrigin( RMobileCall::TMobileCallInfoV7 aCallInfo )
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::UpdateCallOrigin <");
+   
+    if ( iMobileOriginated )
+        {
+        if ( RMobileCall::EOriginatorSIM == aCallInfo.iCallParamOrigin )
+            {
+            iParams->SetOrigin(CCCECallParameters::ECCECallOriginSAT);
+            }
+        }
+    CSPLOGSTRING(CSPINT, "CSPCall::UpdateCallOrigin >");
+    }
+
+
+
+// ---------------------------------------------------------------------------
+// CSPCall::UpdateCallStateL
+//   
+// ---------------------------------------------------------------------------
+//    
+int CSPCall::UpdateCallState()
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::UpdateCallState <");
+    TInt err( KErrNone ); 
+    
+    // Update call state from ETel
+    RMobileCall::TMobileCallStatus etelState;
+    err = iCall.GetMobileCallStatus( etelState );
+    if ( KErrNone == err )
+        {
+        iCallState = CCPStateFromETelState( etelState );
+        }
+    CSPLOGSTRING2(CSPINT, "CSPCall::UpdateCallState > res %d", err);
+    
+    return err; 
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::NotifyRemotePartyNumberChanged
+//   
+// ---------------------------------------------------------------------------
+//
+void CSPCall::NotifyRemotePartyNumberChanged()
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::NotifyRemotePartyNumberChanged <");
+    
+    // If COLP number is different from original dialled number
+    // it is available in connected state of a MO call.
+    // TSY does not send notification so number must be fetched.
+    if ( IsMobileOriginated() )
+        {
+        RMobileCall::TMobileCallInfoV3 callInfo;
+        RMobileCall::TMobileCallInfoV3Pckg callInfoPckg( callInfo );
+    
+        GetMobileCallInfo( callInfoPckg );    
+        callInfo = callInfoPckg();
+    
+        
+        if ( callInfo.iRemoteParty.iRemoteNumber.iTelNumber.Length() )
+            {        
+            NotifyRemotePartyInfoChanged( KNullDesC(),
+                callInfo.iRemoteParty.iRemoteNumber.iTelNumber);        
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CSPCall::CreateCallHandlersL
+// Create call handlers for call related requests and call monitoring  
+// ---------------------------------------------------------------------------
+//    
+void CSPCall::CreateCallHandlersL()
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::CreateCallHandlersL <");
+
+    iRequester = CSPEtelCallRequester::NewL( *this, iCall );
+
+    iCallEventMonitor = CSPEtelCallEventMonitor::NewL( *this, iCall );
+    iCallEventMonitor->StartMonitoring();
+    iCallStatusMonitor = CSPEtelCallStatusMonitor::NewL( *this, iCall );
+    iCallStatusMonitor->StartMonitoring();
+    
+    iCallCapsMonitor = CSPEtelCallCapsMonitor::NewL( *this, iCall );
+    iCallCapsMonitor->StartMonitoring();
+    iCapsFlags = iCallCapsMonitor->FetchCallControlCapsL();
+    
+    iCallInfoMonitor = CSPCallInfoMonitor::NewL( *this, iCall );
+    iCallInfoMonitor->StartMonitoring();
+    
+    // Start UUI monitor and create message sender 
+    iSkypeId = TCSPSkypeIdParser::CreateSkypeIdBufferL();
+    iUUIMonitor = CSPUUIMonitor::NewL( iCall,*this );
+    iUUIMonitor->StartMonitor();
+    iUUIMessageSender = CSPUUIMessageSender::NewL( iCall );
+    iUserToUserInformation = iParams->UUSId().AllocL();
+    
+    // Transfer provider
+    iTransferProvider = CSPTransferProvider::NewL( iCall, *this, iCommonInfo );
+
+    // Forward provider
+    iForwardProvider = CSPForwardProvider::NewL();
+    
+    CSPLOGSTRING(CSPINT, "CSPCall::CreateCallHandlersL >");
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::NotifyRingingState
+// Gets to ringing state
+// ---------------------------------------------------------------------------
+//     
+void CSPCall::NotifyRingingState( )
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::NotifyRingingState");
+    iCallState = MCCPCallObserver::ECCPStateRinging;
+
+    TInt obsCount = iObservers.Count ( );
+    for (TInt i = 0; i < obsCount; i++ )
+        {
+        MCCPCallObserver *obs = iObservers[i];
+        if ( obs )
+            {
+            obs->CallStateChanged ( iCallState, this );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::CCPStateFromETelState
+// Simple mapping between state enumerations.
+// ---------------------------------------------------------------------------
+//     
+MCCPCallObserver::TCCPCallState CSPCall::CCPStateFromETelState( 
+    RMobileCall::TMobileCallStatus aEtelState ) 
+    {
+    MCCPCallObserver::TCCPCallState ret = MCCPCallObserver::ECCPStateIdle;
+    switch ( aEtelState )
+        {
+        case RMobileCall::EStatusUnknown:
+            {
+            CSPLOGSTRING( CSPREQIN, 
+                "CSPCall::State > RMobileCall::Unknown" );
+            ret = MCCPCallObserver::ECCPStateIdle;
+            break;
+            }
+        case RMobileCall::EStatusIdle:
+            {
+            CSPLOGSTRING( CSPREQIN, 
+                "CSPCall::State > RMobileCall::EStatusIdle" );
+            ret = MCCPCallObserver::ECCPStateIdle;
+            break;
+            }
+        case RMobileCall::EStatusRinging:
+            {
+            CSPLOGSTRING( CSPREQIN, 
+                "CSPCall::State > RMobileCall::EStatusRinging" );
+            ret = MCCPCallObserver::ECCPStateRinging;
+            break;
+            }
+        // Map the following to connecting status
+        case RMobileCall::EStatusDialling:                
+            {
+            CSPLOGSTRING( CSPREQIN, "CSPCall::State > \
+                RMobileCall::EStatusDialling" );
+            ret = MCCPCallObserver::ECCPStateDialling;
+            break;
+            }
+        case RMobileCall::EStatusConnecting:
+            {
+            CSPLOGSTRING( CSPREQIN, "CSPCall::State > \
+                RMobileCall::Connecting" );
+            ret = MCCPCallObserver::ECCPStateConnecting;
+            break;
+            }
+        case RMobileCall::EStatusAnswering:
+            {
+            CSPLOGSTRING( CSPREQIN, "CSPCall::State > \
+                RMobileCall::Answering" );
+            ret = MCCPCallObserver::ECCPStateAnswering;
+            break;                
+            }
+        // Call is connected and active.
+        case RMobileCall::EStatusConnected:
+            {
+            CSPLOGSTRING( CSPREQIN, 
+            "CSPCall::State > RMobileCall::EStatusConnected" );
+            ret = MCCPCallObserver::ECCPStateConnected;
+            break;
+            }
+        case RMobileCall::EStatusDisconnectingWithInband:
+        case RMobileCall::EStatusDisconnecting:
+            {
+            CSPLOGSTRING( CSPREQIN, 
+                 "CSPCall::State > RMobileCall::EStatusDisconnecting/Inband?");
+            ret = MCCPCallObserver::ECCPStateDisconnecting;
+            break;
+            }
+        case RMobileCall::EStatusReconnectPending:
+            {
+            CSPLOGSTRING( CSPREQIN, 
+            "CSPCall::State > RMobileCall::EStatusHangingUp" );
+            ret = MCCPCallObserver::ECCPStateDisconnecting;
+            break;
+            }
+        case RMobileCall::EStatusHold:
+            {
+            CSPLOGSTRING( CSPREQIN, 
+            "CSPCall::State > RMobileCall::EStatusHold" );
+            ret = MCCPCallObserver::ECCPStateHold;
+            break;
+            }
+        case RMobileCall::EStatusWaitingAlternatingCallSwitch: 
+            {
+            // This state is not used in real life.
+            CSPLOGSTRING( CSPREQIN, 
+            "CSPCall::State > RMobileCall::EStatusWaitingAlternatingCallSwitch" );
+            ret = MCCPCallObserver::ECCPStateConnected;
+            break;
+            }
+        case RMobileCall::EStatusTransferring: 
+            {
+            CSPLOGSTRING( CSPREQIN, 
+            "CSPCall::State > RMobileCall::EStatusHold" );
+            ret = MCCPCallObserver::ECCPStateTransferring;
+            break;
+            }
+        case RMobileCall::EStatusTransferAlerting: 
+            {
+            CSPLOGSTRING( CSPREQIN, 
+            "CSPCall::State > RMobileCall::EStatusHold" );
+            ret = MCCPCallObserver::ECCPStateTransferring;
+            break;
+            }            
+        default:
+            {
+            CSPLOGSTRING( CSPREQIN, 
+                "CSPCall::CCPStateFromETelState unhandled state ");
+            }
+        }
+
+    CSPLOGSTRING3(CSPINT, 
+        "CSPCall::CCPStateFromETelState ETel: %d CCP: %d", aEtelState, ret);
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::NotifyCallStateChanged
+// Notifies observers about state changes
+// ---------------------------------------------------------------------------
+//
+void CSPCall::NotifyCallStateChanged( MCCPCallObserver::TCCPCallState aState ) 
+    {
+    CSPLOGSTRING3(CSPINT, 
+            "CSPCall::NotifyCallStateChanged < state: %d this: %x", 
+            aState, this );
+                           
+    iCallState = aState;    
+    TBool notifyObservers( ETrue ); 
+
+    if ( !iMobileOriginated && MCCPCallObserver::ECCPStateRinging == aState )
+        {
+        CSPLOGSTRING2(CSPINT, "CSPCall::No notify on ringing MT", aState);        
+        notifyObservers = EFalse; 
+        }
+    
+    if ( notifyObservers )
+        {
+        TInt obsCount = iObservers.Count();
+        for ( TInt i = 0; i < obsCount; i++ )
+            {
+            MCCPCallObserver *obs = iObservers[i];
+            if ( obs )
+                {            
+                obs->CallStateChanged( aState, this );
+                }
+            }
+        }
+        
+    CSPLOGSTRING3(CSPINT, 
+            "CSPCall::NotifyCallStateChanged > state: %d this: %x", 
+            aState, this );
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::NotifyCallStateChangedWithInband
+// Notifies observers about state changes
+// ---------------------------------------------------------------------------
+//
+void CSPCall::NotifyCallStateChangedWithInband( 
+        MCCPCallObserver::TCCPCallState aState ) 
+    {
+    CSPLOGSTRING3(CSPINT, 
+        "CSPCall::NotifyCallStateChangedWithInBand < state: %d this: %x", 
+        aState, this );
+    
+    iCallState = aState;
+   
+    if ( !iMobileOriginated && MCCPCallObserver::ECCPStateRinging == aState )
+        {
+        CSPLOGSTRING2(CSPINT, "CSPCall::No notify on ringing MT", aState);
+        }
+    else
+        {        
+        TInt obsCount = iObservers.Count();
+        for ( TInt i = 0; i < obsCount; i++ )
+            {            
+            MCCPCallObserver *obs = iObservers[i];
+            if ( obs )
+                {
+                obs->CallStateChangedWithInband( aState, this );
+                }
+            }
+        }
+    CSPLOGSTRING3(CSPINT, 
+            "CSPCall::NotifyCallStateChangedWithInband > state: %d this: %x", 
+            aState, this);
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::ReadRepositoryL
+// Reads the given information from Central Repository.
+// ---------------------------------------------------------------------------
+//
+void CSPCall::ReadRepositoryL( TUid aUid, TUint aKey, TInt& aVal)
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::ReadRepositoryL");
+    
+    CRepository* cr = CRepository::NewL( aUid );
+    TInt err = cr->Get( aKey, aVal );
+    delete cr;
+    User::LeaveIfError( err );
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::CheckAndNotifyTerminationError
+// Reads error code from ETel.
+// ---------------------------------------------------------------------------
+//
+void CSPCall::CheckAndNotifyTerminationError()
+    {
+    CSPLOGSTRING2(CSPINT, 
+        "CSPCall::CheckAndNotifyTerminationError dial completion code: %d", 
+        iDialCompletionCode);
+    
+    // Emergency error handling is separated into CSPEtelCallRequester
+    if ( !iIsEmergencyCall )
+        {
+        TInt termErr = ExitCodeError();
+        CSPLOGSTRING2(CSPINT, 
+                "CSPCall::CheckAndNotifyTerminationError exit code error: %d", 
+                termErr);
+        
+        if ( termErr == KErrNone )
+            {
+            // Handle KErrGsmCCUnassignedNumber correctly
+            // because the value is not stored in exit code.
+            termErr = iDialCompletionCode;
+            CSPLOGSTRING(CSPINT, 
+                    "CSPCall::CheckAndNotifyTerminationError use dial completion code");
+            }
+            
+        if ( termErr == KErrGsmRRPreEmptiveRelease )
+            {
+            // Error KErrGsmRRPreEmptiveRelease occurs when there is active call 
+            // and user make emergency call, can be ignored.
+            CSPLOGSTRING3( 
+                CSPERROR, 
+                "CSPCall::CheckAndNotifyTerminationError preemptive release, ignore: %d",
+                termErr,
+                this );
+            }
+        else if ( iDontReportTerm 
+                && (  termErr == KErrGsmCCNormalUnspecified 
+                   || termErr == KErrGsmCCCallRejected ) )
+            {
+            // Not an error, since this happens on normal 
+            // call termination situation after connected call.
+            CSPLOGSTRING3(CSPERROR, 
+                    "CSPCall::CheckAndNotifyTerminationError DISCARD this: %x err: %d", 
+                    this, 
+                    termErr);    
+            }        
+        else if ( termErr )
+            {
+            TCCPError ccpErr(ECCPErrorNone);
+
+            // Only a couple of error codes can have diagnostic information. 
+            // aDiagnostic ought to be undefined in other situatios,
+            // but at least in this way we can really guarantee it.
+            if ( termErr == KErrGsmCCFacilityRejected ||
+                 termErr == KErrGsmCCRequestedFacilityNotSubscribed ||
+                 termErr == KErrGsmCCIncomingCallsBarredInCug ||
+                 termErr == KErrGsmCCRequestedFacilityNotImplemented ||
+                 termErr == KErrGsmCCUserNotInCug )
+                {
+                TName name;
+                CallName( name );        
+                TInt diagErr = iCommonInfo.GetDiagnosticError( name );
+                ccpErr = iRequester->MapError( diagErr );
+    
+                // Finally use exit code if diagnostic did not contain
+                // any useful information.
+                if ( ccpErr == ECCPRequestFailure )
+                    {
+                    ccpErr = iRequester->MapError( termErr );
+                    }
+                }
+            else
+                {
+                ccpErr = iRequester->MapError( termErr );
+                }
+            
+            NotifyErrorOccurred( ccpErr );
+            iTerminationErrorNotified = ETrue;
+            }
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::ExitCodeError
+// Reads error code from ETel call info's iExitCode.
+// ---------------------------------------------------------------------------
+//
+TInt CSPCall::ExitCodeError() const
+    {
+    CSPLOGSTRING2(CSPINT, "CSPCall::ExitCodeError < this: %x", 
+                    this );
+    TInt callError;
+    RMobileCall::TMobileCallInfoV3 callInfo;
+    RMobileCall::TMobileCallInfoV3Pckg pck( callInfo );
+    TInt getErr = iCall.GetMobileCallInfo( pck );
+    // Is there value in higher 16 bits
+    if ( KErrNone == getErr && (callInfo.iExitCode & 0xFFFF0000) ) 
+        {
+        CSPLOGSTRING2(CSPINT, "CSPCall::ExitCodeError callInfo.iExitCode %d", 
+            callInfo.iExitCode );
+        callError = ( callInfo.iExitCode >> KTimesToSplitValue ); 
+        
+        if ( callError > KErrEtelGsmBase ) 
+            // Not in valid exteded range
+            {
+            // Ignore invalid extented code
+            if ( ( callInfo.iExitCode & 0x0000FFFF ) == KErrNone ) 
+                // core error is zero
+                {
+                callError = KErrNone;
+                }
+            else
+                {
+                callError = ( ( callInfo.iExitCode & 0x0000FFFF ) 
+                    | 0xFFFF0000 ); 
+                }
+            }
+        }
+    // Higher and lower 16 bits are zero
+    else if ( !( callInfo.iExitCode & 0xFFFFFFFF ) ) 
+        {
+        callError = KErrNone;
+        }
+    else 
+        {
+        // No extended error, expand value to full range
+        callError = ( callInfo.iExitCode | 0xFFFF0000 );
+        }
+        
+    CSPLOGSTRING2(CSPINT, "CSPCall::ExitCodeError > err: %d", callError);
+        
+    return callError;
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::UUSMessageReceived
+// ---------------------------------------------------------------------------
+//
+ void CSPCall::UUSMessageReceived( TDesC& aMessage )
+    {      
+    CSPLOGSTRING(CSPREQIN, "CSPCall::UUSMessageReceived");
+    TCSPSkypeIdParser parser;
+           
+    TPtr ptr = iSkypeId->Des();
+    ptr.Zero();
+    const TInt error( parser.Parse( aMessage, ptr ) );
+    
+    if ( !error ) 
+        {
+        iRemotePartyName = ptr;
+        NotifyCallEventOccurred( MCCPCallObserver::ECCPNotifyRemotePartyInfoChange );            
+        }
+    CSPLOGSTRING2(CSPINT, "CSPCall::UUSMessageReceived  err: %d",  error );        
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::NotifyRemotePartyInfoChanged
+// ---------------------------------------------------------------------------
+//
+void CSPCall::NotifyRemotePartyInfoChanged( const TDesC& aRemotePartyName,
+                                            const TDesC& aRemotePartyNumber )
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::NotifyRemotePartyInfoChanged");
+    
+    if ( aRemotePartyName.Length() )    
+        {
+        iRemotePartyName = aRemotePartyName;
+        }
+    
+    if ( aRemotePartyNumber.Length() )    
+        {
+        iRemotePartyNumber = aRemotePartyNumber;
+        }
+    
+    NotifyCallEventOccurred( MCCPCallObserver::ECCPNotifyRemotePartyInfoChange );
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::DontReportTerminationError
+// ---------------------------------------------------------------------------
+//
+void CSPCall::DontReportTerminationError() 
+    {
+    CSPLOGSTRING(CSPREQIN, "CSPCall::DontReportTerminationError");
+    iDontReportTerm = ETrue;
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::UpdateCallNameNumberInfo
+// Update call info including remote party name and number data  
+// ---------------------------------------------------------------------------
+//    
+void CSPCall::UpdateCallNameNumberInfo(
+        RMobileCall::TMobileCallInfoV3& aCallInfo, 
+        TBool aCallAddedByMonitor )
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::UpdateCallNameNumberInfo <");
+
+    iCallName.Zero();
+    iRemotePartyNumber.Zero();
+    iRemotePartyName.Zero();
+    
+    if ( aCallAddedByMonitor )        
+        {
+        CSPLOGSTRING(CSPINT, 
+                "CSPCall::UpdateCallNameNumberInfo call added by monitor");
+
+        // If call was created by ETel line status or incoming call monitor
+        // the call name is already known, only remote party info is fetched from 
+        // call info 
+        iCallName.Append( iName );
+        iRemotePartyName.Append( aCallInfo.iRemoteParty.iCallingName );
+        iRemotePartyNumber.Append( aCallInfo.iRemoteParty.iRemoteNumber.iTelNumber );
+        }
+    else 
+        {
+        CSPLOGSTRING(CSPINT, 
+                "CSPCall::UpdateCallNameNumberInfo call added by plugin owner");
+        
+        // The call was not created by monitor and the remote number is already known, 
+        // fetch only call name from call info  
+        iCallName.Append( aCallInfo.iCallName );
+        iRemotePartyNumber.Append( iName ); 
+        }
+    
+    CSPLOGSTRING2(CSPINT, 
+            "CSPCall::UpdateCallNameNumberInfo iCallName: %S", &iCallName );
+    CSPLOGSTRING2(CSPINT, 
+            "CSPCall::UpdateCallNameNumberInfo iRemotePartyNumber: %S", &iRemotePartyNumber );
+    CSPLOGSTRING2(CSPINT, 
+            "CSPCall::UpdateCallNameNumberInfo iRemotePartyName: %S", &iRemotePartyName );
+
+    CSPLOGSTRING(CSPINT, "CSPCall::UpdateCallNameNumberInfo >");
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::OpenNewCall
+// Open new call 
+// ---------------------------------------------------------------------------
+//    
+void CSPCall::OpenNewCall()
+    {
+    CSPLOGSTRING(CSPINT, "CSPCall::OpenNewCall <");
+
+    // Open new call 
+    __ASSERT_ALWAYS( iCall.OpenNewCall( iLine ) == KErrNone, 
+            Panic( ECSPPanicNoEtel ) );
+
+    CSPLOGSTRING(CSPINT, "CSPCall::OpenNewCall >");
+    }
+
+// ---------------------------------------------------------------------------
+// CSPCall::OpenExistingCallL
+// Open existing call  
+// ---------------------------------------------------------------------------
+//    
+void CSPCall::OpenExistingCallL( const TDesC& aName )
+    {
+    CSPLOGSTRING2(CSPINT, 
+            "CSPCall::OpenExistingCallL < aName: %S", &aName);
+    
+    // Open existing call with given name from current line 
+    TInt err = iCall.OpenExistingCall( iLine, aName ); 
+    
+    if ( KErrNone != err  )
+        {
+        CSPLOGSTRING2(CSPERROR,
+            "CSPCall::OpenCallHandleL OpenExistingCall error: %d, leaving", err);    
+        User::Leave( err );
+        }
+
+    CSPLOGSTRING(CSPINT, "CSPCall::OpenExistingCallL >");
+    }
+
+// End of File
+