--- /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 <mmtsy_names.h>
+#include <rmmcustomapi.h>
+#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