/*
* 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 ( RMobileCall::EOriginatorSIM == aCallInfo.iCallParamOrigin )
{
iParams->SetOrigin(CCCECallParameters::ECCECallOriginSAT);
iParams->SetAlphaId(aCallInfo.iAlphaId);
}
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