diff -r 000000000000 -r 5a93021fdf25 connectionmonitoring/connmon/connectionmonitor/src/CCsdFax.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/connectionmonitoring/connmon/connectionmonitor/src/CCsdFax.cpp Thu Dec 17 08:55:21 2009 +0200 @@ -0,0 +1,815 @@ +/* +* Copyright (c) 2002-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: Provides information on CSD fax calls. +* +*/ + +#include +#include +#include "ConnMonServ.h" +#include "ConnMonIAP.h" +#include "CEventQueue.h" +#include "CCsdFax.h" +#include "log.h" + +// ----------------------------------------------------------------------------- +// CCsdFax::CCsdFax +// ----------------------------------------------------------------------------- +// +CCsdFax::CCsdFax( + CConnMonServer* aServer, + RTelServer* aTelServer, + RMobilePhone* aMobilePhone ) + : + iServer( aServer ), + iTelServer( aTelServer ), + iMobilePhone( aMobilePhone ) + { + } + +// ----------------------------------------------------------------------------- +// CCsdFax::ConstructL +// ----------------------------------------------------------------------------- +// +void CCsdFax::ConstructL() + { + //LOGENTRFN("CCsdFax::ConstructL()") + // Open "Data" line + TInt ret = iLine.Open( *iMobilePhone, KMmTsyDataLineName ); + + if ( ret != KErrNone ) + { + LOGIT("CCsdFax: Could not open data line.") + return; + } + else + { + iState = ELineOpen; + } + + // Start external connection Up notifier + if ( iConnUpNotifier == 0 ) + { + iConnUpNotifier = new( ELeave ) CCsdFaxUpNotifier( + this, + iServer, + iMobilePhone, + iLine); + iConnUpNotifier->Construct(); + iConnUpNotifier->Receive(); + } + + // Start external connection Up notifier + if ( iStatusNotifier == 0 ) + { + iStatusNotifier = new( ELeave ) CCsdStatusNotifier( + this, + iServer ); + iStatusNotifier->Construct(); + } + //LOGEXITFN("CCsdFax::ConstructL()") + } + +// Destructor +CCsdFax::~CCsdFax() + { + if ( iConnUpNotifier != 0 ) + { + iConnUpNotifier->Cancel(); + delete iConnUpNotifier; + iConnUpNotifier = 0; + } + + if ( iStatusNotifier != 0 ) + { + iStatusNotifier->Cancel(); + delete iStatusNotifier; + iStatusNotifier = 0; + } + + if ( iState == ECallOpen ) + { + CloseCall(); + } + + if ( iState > EModuleClosed ) + { + iLine.Close(); + } + } + +// ----------------------------------------------------------------------------- +// CCsdFax::OpenCall +// ----------------------------------------------------------------------------- +// +TInt CCsdFax::OpenCall( const TDes& aName ) + { + if ( iState == ECallOpen ) + { + CloseCall(); + } + + RTelServer::TPhoneInfo phoneInfo; + TInt err = iTelServer->GetPhoneInfo( 0, phoneInfo ); + + if ( err != KErrNone ) + { + return err; + } + + iCsdFaxCallName.Copy( phoneInfo.iName ); + iCsdFaxCallName.Append( KDoubleColon ); + iCsdFaxCallName.Append( KMmTsyDataLineName ); + iCsdFaxCallName.Append( KDoubleColon ); + iCsdFaxCallName.Append( aName ); + + err = iCall.OpenExistingCall( *iTelServer, iCsdFaxCallName ); + + if ( KErrNone == err ) + { + iState = ECallOpen; + + // Start status event watcher + if ( !iStatusNotifier->IsActive() ) + { + iStatusNotifier->Start( &iCall ); + } + } + + return err; + } + +// ----------------------------------------------------------------------------- +// CCsdFax::CloseCall +// ----------------------------------------------------------------------------- +// +void CCsdFax::CloseCall() + { + if ( iStatusNotifier != 0 ) + { + iStatusNotifier->Cancel(); + } + + iCall.Close(); + iState = ELineOpen; + + iCsdFaxCallName.FillZ(); + iCsdFaxCallName.Zero(); + } + +// ----------------------------------------------------------------------------- +// CCsdFax::IsValid +// ----------------------------------------------------------------------------- +// +TBool CCsdFax::IsValid() + { + if ( iState == ECallOpen ) + { + return ETrue; + } + else + { + return EFalse; + } + } + +// ----------------------------------------------------------------------------- +// CCsdFax::FindCall +// ----------------------------------------------------------------------------- +// +TInt CCsdFax::FindCall() + { + TInt ret( KErrNone ); + TInt countCalls( 0 ); + + if ( iState == ECallOpen ) + { + return KErrNone; + } + else if ( iState < ELineOpen ) + { + return KErrNotFound; + } + + // Enumerate calls on data line + ret = iLine.EnumerateCall( countCalls ); + + if ( ret != KErrNone ) + { + return ret; + } + else if ( countCalls == 0 ) + { + return KErrNotFound; + } + + RMmCustomAPI customApi; + RMmCustomAPI::TCallOrigin origin; + + ret = customApi.Open( *iMobilePhone ); + + if ( ret != KErrNone ) + { + return ret; + } + + // Get call info + for ( TInt j = 0; j < countCalls; j++ ) + { + RLine::TCallInfo callInfo; + + ret = iLine.GetCallInfo( j, callInfo ); + if ( ret != KErrNone ) + { + customApi.Close(); + return ret; + } + + customApi.CallOrigin( callInfo.iCallName, origin ); + + // TF + if ( origin == RMmCustomAPI::EOutsider ) + { + ret = KErrNone; + OpenCall( callInfo.iCallName ); + break; + } + else + { + ret = KErrNotFound; + } + } + + customApi.Close(); + return ret; + } + +// ----------------------------------------------------------------------------- +// CCsdFax::GetBearer +// ----------------------------------------------------------------------------- +// +TInt CCsdFax::GetBearer( TInt& aBearer, TBearerInfo& aBearerInfo ) const + { + TInt ret( KErrNone ); + RMobileCall::TMobileCallStatus mobileCallStatus; + + if ( iState < ECallOpen ) + { + return KErrNotFound; + } + + // Is network WCDMA + RMobilePhone::TMobilePhoneNetworkMode mode; + ret = iMobilePhone->GetCurrentMode( mode ); + + if ( ret != KErrNone ) + { + return ret; + } + if ( mode == RMobilePhone::ENetworkModeWcdma ) + { + aBearer = EBearerExternalWcdmaCSD; + aBearerInfo.iBearer = EBearerInfoWcdmaCSD; + aBearerInfo.iInternal = EFalse; + + return KErrNone; + } + + ret = iCall.GetMobileCallStatus( mobileCallStatus ); + + if ( ret != KErrNone ) + { + return ret; + } + + aBearer = EBearerExternalCSD; + aBearerInfo.iBearer = EBearerInfoCSD; + aBearerInfo.iInternal = EFalse; + + if ( mobileCallStatus != RMobileCall::EStatusIdle ) + { + RMobileCall::TMobileCallHscsdInfoV1 hscsdInfo; + RMobileCall::TMobileCallHscsdInfoV1Pckg hscsdInfoPckg( hscsdInfo ); + + for ( TInt a = 0; a < KBearerQueryCount; a++ ) + { + ret = iCall.GetCurrentHscsdInfo( hscsdInfoPckg ); + + if ( ret != KErrEtelCallNotActive ) + { + break; + } + + User::After( KBearerQueryTimeout ); + } + + if ( KErrNone == ret ) + { + if ( hscsdInfo.iAiur != RMobileCall::EAiurBpsUnspecified ) + { + aBearer = EBearerExternalHSCSD; + aBearerInfo.iBearer = EBearerInfoHSCSD; + } + } + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CCsdFax::GetStatus +// ----------------------------------------------------------------------------- +// +TInt CCsdFax::GetStatus( TInt& aStatus ) const + { + TInt ret( KErrNone ); + + if ( iState < ECallOpen ) + { + return KErrNotFound; + } + + RMobileCall::TMobileCallStatus mobileCallStatus; + ret = iCall.GetMobileCallStatus( mobileCallStatus ); + + if ( ret != KErrNone ) + { + return ret; + } + + aStatus = mobileCallStatus; + ret = MapStatus( aStatus ); + + return ret; + } + +// ----------------------------------------------------------------------------- +// CCsdFax::MapStatus +// ----------------------------------------------------------------------------- +// +TInt CCsdFax::MapStatus( TInt& aStatus ) const + { + switch( aStatus ) + { + case RMobileCall::EStatusUnknown: + return KErrUnknown; + + case RMobileCall::EStatusIdle: + aStatus = KConnectionUninitialised; + break; + + case RMobileCall::EStatusDialling: + aStatus = KCsdStartingDialling; + break; + + case RMobileCall::EStatusRinging: + return KErrUnknown; + + case RMobileCall::EStatusAnswering: + aStatus = KCsdStartingAnswer; + break; + + case RMobileCall::EStatusConnecting: + aStatus = KCsdStartingConnect; + break; + + case RMobileCall::EStatusConnected: + aStatus = KCsdConnectionOpen; + break; + + case RMobileCall::EStatusDisconnecting: + case RMobileCall::EStatusDisconnectingWithInband: + aStatus = KCsdStartingHangUp; + break; + + default: + return KErrUnknown; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CCsdFax::GetTelNumber +// ----------------------------------------------------------------------------- +// +TInt CCsdFax::GetTelNumber( TDes& aNumber ) const + { + LOGENTRFN("CCsdFax::GetTelNumber()") + TInt err( KErrNone ); + + if ( iState < ECallOpen ) + { + err = KErrNotFound; + } + else + { + RMobileCall::TMobileCallInfoV1 info; + RMobileCall::TMobileCallInfoV1Pckg infoPckg( info ); + err = iCall.GetMobileCallInfo( infoPckg ); + + if ( KErrNone == err ) + { + if ( infoPckg().iRemoteParty.iRemoteNumber.iTelNumber.Length() > 0 ) + { + aNumber = infoPckg().iRemoteParty.iRemoteNumber.iTelNumber; + } + else if ( infoPckg().iDialledParty.iTelNumber.Length() > 0 ) + { + aNumber = infoPckg().iDialledParty.iTelNumber; + } + } + } + + LOGEXITFN1("CCsdFax::GetTelNumber()", err) + return err; + } + +// ----------------------------------------------------------------------------- +// CCsdFax::GetStartTime +// ----------------------------------------------------------------------------- +// +TInt CCsdFax::GetStartTime( TTime& aTime ) const + { + TInt ret( KErrNone ); + + if ( iState < ECallOpen ) + { + return KErrNotFound; + } + + TTimeIntervalSeconds duration; + ret = iCall.GetCallDuration( duration ); + + if ( KErrNone == ret ) + { + TTime current; + current.UniversalTime(); + aTime = current - duration; + } + return ret; + } + +// ----------------------------------------------------------------------------- +// CCsdFax::Stop +// ----------------------------------------------------------------------------- +// +TInt CCsdFax::Stop() + { + TInt err( KErrNone ); + + if ( iState != ECallOpen ) + { + return KErrNotFound; + } + + err = iCall.HangUp(); + + // Remove from server tables if + // status notifier is not active. + if ( !iStatusNotifier->IsActive() ) + { + RemoveFromServer(); + } + + return err; + } + +// ----------------------------------------------------------------------------- +// CCsdFax::RemoveFromServer +// ----------------------------------------------------------------------------- +// +void CCsdFax::RemoveFromServer() + { + // Remove the connection from internal table + TInt bearer( 0 ); + TBearerInfo bearerInfo( EBearerInfoCSD, ETrue); + + TConnInfo connInfo( 0, 0, 0, EBearerExternalCSD, bearerInfo ); + + TInt err = GetBearer( bearer, bearerInfo ); + + if ( KErrNone == err ) + { + connInfo.iBearer = bearer; + connInfo.iBearerInfo.iBearer = bearerInfo.iBearer; + connInfo.iBearerInfo.iInternal = bearerInfo.iInternal; + } + + iServer->Iap()->RemoveConnection( connInfo ); + } + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CCsdFaxUpNotifier::CCsdFaxUpNotifier +// ----------------------------------------------------------------------------- +// +CCsdFaxUpNotifier::CCsdFaxUpNotifier( + CCsdFax* aFaxModule, + CConnMonServer* aServer, + RMobilePhone* aMobilePhone, + RLine& aLine) + : + CActive( EConnMonPriorityNormal ), + iFaxModule( aFaxModule ), + iServer( aServer ), + iMobilePhone( aMobilePhone ), + iLine( aLine ) + { + } + +// ----------------------------------------------------------------------------- +// CCsdFaxUpNotifier::Construct +// ----------------------------------------------------------------------------- +// +void CCsdFaxUpNotifier::Construct() + { + CActiveScheduler::Add( this ); + } + +// Destructor +CCsdFaxUpNotifier::~CCsdFaxUpNotifier() + { + Cancel(); + } + +// ----------------------------------------------------------------------------- +// CCsdFaxUpNotifier::Receive +// Requests a new event (connection up/down) from RConnection +// ----------------------------------------------------------------------------- +// +void CCsdFaxUpNotifier::Receive() + { + if ( IsActive() ) + { + Cancel(); + } + + iName.FillZ(); + + iLine.NotifyCallAdded( iStatus, iName ); + SetActive(); + } + +// ----------------------------------------------------------------------------- +// CCsdFaxUpNotifier::DoCancel +// Cancels the request from RConnection. +// ----------------------------------------------------------------------------- +// +void CCsdFaxUpNotifier::DoCancel() + { + if ( IsActive() ) + { + iLine.NotifyCallAddedCancel(); + } + } + +// ----------------------------------------------------------------------------- +// CCsdFaxUpNotifier::RunL +// Handles the event that has arrived from RConnection +// ----------------------------------------------------------------------------- +// +void CCsdFaxUpNotifier::RunL() + { + // All RunL():s outside CServer-derived main class MUST NOT LEAVE. + // Use TRAPD when needed. + + if ( iStatus.Int() != KErrNone ) + { + LOGIT1("External Csd up event FAILED <%d>", iStatus.Int() ) + } + else + { + RMmCustomAPI customApi; + RMmCustomAPI::TCallOrigin origin( RMmCustomAPI::EUnknown ); + + TInt ret = customApi.Open( *iMobilePhone ); + + if ( KErrNone == ret ) + { + customApi.CallOrigin( iName, origin ); + customApi.Close(); + } + + if ( origin == RMmCustomAPI::EOutsider ) + { + TInt bearer( 0 ); + TBearerInfo bearerInfo; + TInt err( KErrNone ); + + LOGIT("SERVER: EVENT -> new EXTERNAL CSD connection") + + if ( iFaxModule->IsValid() ) + { + // Sometimes when data call is rejected by the other end, a new + // data call is started before the old one has been notified to + // be closed. In this case send the EConnMonDeleteConnection to + // all clients that are listening. + iEventInfo.Reset(); + iEventInfo.iEventType = EConnMonDeleteConnection; + iEventInfo.iConnectionId = iFaxModule->ConnectionId(); + + iServer->EventQueue()->Add( iEventInfo ); + + // Remove from server tables + iFaxModule->RemoveFromServer(); + + // Close the call + iFaxModule->CloseCall(); + + LOGIT("SERVER: Closed the unfinished EXTERNAL CSD connection") + } + + err = iFaxModule->OpenCall( iName ); + + if ( KErrNone == err ) + { + err = iFaxModule->GetBearer( bearer, bearerInfo ); + } + + if ( KErrNone == err ) + { + // Send event to clients + TConnInfo connInfo( 0, 0, 0, bearer, bearerInfo ); + + iEventInfo.Reset(); + + iEventInfo.iEventType = EConnMonCreateConnection; + + // Add to the connection table and fill in the new connectioId to connInfo + TRAP( ret, ( err = iServer->Iap()->AddConnectionL( connInfo ) ) ); + + if ( ret ) + { + LOGIT("AddConnectionL failed.") + return; // Can't leave + } + + // Set connection id + iEventInfo.iConnectionId = connInfo.iConnectionId; + iFaxModule->SetConnectionId( connInfo.iConnectionId ); + + // Send event to all clients that are listening + iServer->EventQueue()->Add( iEventInfo ); + } + else + { + LOGIT("Could not get the external call info!") + } + } + + // New request + Receive(); + } + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CCsdStatusNotifier::CCsdStatusNotifier +// ----------------------------------------------------------------------------- +// +CCsdStatusNotifier::CCsdStatusNotifier( + CCsdFax* aFaxModule, + CConnMonServer* aServer ) + : + CActive( EConnMonPriorityNormal ), + iFaxModule( aFaxModule ), + iServer( aServer ) + { + } + +// ----------------------------------------------------------------------------- +// CCsdStatusNotifier::Construct +// ----------------------------------------------------------------------------- +// +void CCsdStatusNotifier::Construct() + { + CActiveScheduler::Add( this ); + } + +// Destructor +CCsdStatusNotifier::~CCsdStatusNotifier() + { + Cancel(); + } + +// ----------------------------------------------------------------------------- +// CCsdStatusNotifier::Start +// Requests a new event (connection up/down) from RConnection +// ----------------------------------------------------------------------------- +// +void CCsdStatusNotifier::Start( RMobileCall* aCall ) + { + // Cancel must be called before assigning a new aCall handle + if ( IsActive() ) + { + Cancel(); + } + + iCall = aCall; + Receive(); + } + +// ----------------------------------------------------------------------------- +// CCsdStatusNotifier::Receive +// Requests a new event (connection up/down) from RConnection +// ----------------------------------------------------------------------------- +// +void CCsdStatusNotifier::Receive() + { + if ( IsActive() ) + { + Cancel(); + } + + iCall->NotifyMobileCallStatusChange( iStatus, iMobileCallStatus ); + SetActive(); + } + +// ----------------------------------------------------------------------------- +// CCsdStatusNotifier::DoCancel +// Cancels the request from RConnection. +// ----------------------------------------------------------------------------- +// +void CCsdStatusNotifier::DoCancel() + { + if ( IsActive() ) + { + iCall->CancelAsyncRequest( EMobileCallNotifyMobileCallStatusChange ); + } + } + +// ----------------------------------------------------------------------------- +// CCsdStatusNotifier::RunL +// Handles the event that has arrived from RConnection +// ----------------------------------------------------------------------------- +// +void CCsdStatusNotifier::RunL() + { + // All RunL():s outside CServer-derived main class MUST NOT LEAVE. + // Use TRAPD when needed. + + if ( iStatus.Int() != KErrNone ) + { + LOGIT1("External Csd status FAILED <%d>", iStatus.Int() ) + } + else + { + // Send event to clients + LOGIT1("SERVER: EVENT -> EXTERNAL CSD status changed <%d>", iMobileCallStatus ) + + iEventInfo.Reset(); + iEventInfo.iEventType = EConnMonConnectionStatusChange; + + iEventInfo.iConnectionId = iFaxModule->ConnectionId(); + + TInt status = iMobileCallStatus; + TInt err = iFaxModule->MapStatus( status ); + iEventInfo.iData = status; + + if ( ( iServer->NumberOfListeners() > 0 ) && ( err == KErrNone ) ) + { + // Send event to all clients that are listening + iServer->EventQueue()->Add( iEventInfo ); + } + + if ( ( iMobileCallStatus == ( TInt )RMobileCall::EStatusDisconnecting ) + || + ( iMobileCallStatus == ( TInt )RMobileCall::EStatusDisconnectingWithInband ) ) + { + // Send connection closed event to all clients that are listening + iEventInfo.Reset(); + iEventInfo.iEventType = EConnMonDeleteConnection; + iEventInfo.iConnectionId = iFaxModule->ConnectionId(); + + iServer->EventQueue()->Add( iEventInfo ); + + // Remove from server tables + iFaxModule->RemoveFromServer(); + + // Close the call + iFaxModule->CloseCall(); + + // Stop listening + return; + } + + // New request + Receive(); + } + } + +// End-of-file