--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phoneplugins/csplugin/src/cspcall.cpp Fri Mar 19 09:28:42 2010 +0200
@@ -0,0 +1,1910 @@
+/*
+* 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 )
+ {
+ 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");
+ {
+ if ( iAudioHandler && iParams->CallType() == CCPCall:: ECallTypeCSVoice )
+ {
+ 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 );
+ 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::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& aRemoteParty)
+ {
+ CSPLOGSTRING(CSPREQIN, "CSPCall::NotifyRemotePartyInfoChanged");
+ iRemotePartyName = aRemoteParty;
+ 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
+