diff -r 7d48bed6ce0c -r 987c9837762f convergedcallengine/csplugin/src/cspcall.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include + +#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( 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 +