connectionmonitoring/connmon/connectionmonitor/src/CCsdFax.cpp
changeset 0 5a93021fdf25
--- /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