vtengines/videoteleng/Src/Base/CVtEngInitializer.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 23 Nov 2009 14:47:47 +0200
changeset 0 ed9695c8bcbe
permissions -rw-r--r--
Revision: 200948

/*
* Copyright (c) 2004 - 2008 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:    Implementation class for initializing the engine gradually.
*                Active object initializes one "subsystem" on each
*                round. In case of failure timer is started and
*                retrial is done after time-out. Uninitialization
*                is done is one shot.




*
*/


// INCLUDE FILES
#include    "CVtEngInitializer.h"
#include    "CVtEngStateManager.h"
#include    "CVtEngEventManager.h"
#include    "VtEngUtils.h"
#include    "CVtEngHandlerContainer.h"
#include    "CVtEngOperation.h"
#include    "VtEngPanic.h"
#include    "VtEngConstants.h"
#include    "VtEngDefs.hrh"
#include    <cvtlogger.h>
#include    <mvtprotocolhandler.h>
#include    <telcommsinfopskeys.h>
#include    <videotelephonyvariant.hrh>
#include    "VtEngUtils.h"
#include    "CVtEngSettings.h"

// CONSTANTS
const TInt KVtEngInitializerPriority = CActive::EPriorityStandard;
const TInt KVtEngInitializerRetrials = 3;
const TInt KVtEngInitializerRetrialTimeout = 500000; // 0.5 seconds
const TInt KVtEngInitializerTimerPriority = CActive::EPriorityUserInput;

_LIT( KVtEngCommDiagPortName, "PVDIAGPORT" );
_LIT( KVtEngCommTestPortName, "COMM::0" );

// ============================ MEMBER FUNCTIONS ===============================

CVtEngInitializer* CVtEngInitializer::NewL( CVtEngHandlerContainer& aHandlers )
    {
    __VTPRINTENTER( "Intlzr.NewL" )
    CVtEngInitializer* self = new ( ELeave ) CVtEngInitializer( aHandlers );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
    __VTPRINTEXIT( "Intlzr.NewL" )
    return self;
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::CVtEngInitializer
// C++ constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CVtEngInitializer::CVtEngInitializer(
            CVtEngHandlerContainer& aHandlers ) :
            CActive( KVtEngInitializerPriority ),
            iHandlers( aHandlers ),
            iStep( EInitNone ),
            iDataportHandled( 0 ),
			iOwnershipInMH( EFalse )
    {
    CActiveScheduler::Add( this );
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::ConstructL
// Second phase constructor.
//
// -----------------------------------------------------------------------------
//
void CVtEngInitializer::ConstructL()
    {
    iTimer = CPeriodic::NewL( KVtEngInitializerTimerPriority );
    
    }

// Destructor
CVtEngInitializer::~CVtEngInitializer()
    {
    __VTPRINTENTER( "Intlzr.~" )
    delete iTimer;
    Cancel();
    
    if ( iSessionCommand && !iOwnershipInMH )
        {
        VTProtocolFactory::DeleteSessionCommand( iSessionCommand );
        iSessionCommand = NULL;
        }
    __VTPRINTEXIT( "Intlzr.~" )
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::InitializeL
// Start initialization process.
//
// -----------------------------------------------------------------------------
//
void CVtEngInitializer::InitializeL( CVtEngOperation& aCallback )
    {
    __VTPRINTENTER( "Intlzr.InitializeL" )
    __VTPRINT( DEBUG_GEN, "Intlzr.Init")
    __ASSERT_ALWAYS( iStep != EInitComplete,
        Panic( EVtEngPanicInvalidInitializationEntry ) );
    iCallback = &aCallback;
    if ( iStep == EInitComplete )
        {
        __VTPRINTEXIT( "Intlzr.InitializeL" )
        return;
        }
    ContinueOrRetry( EContinue );
    __VTPRINTEXIT( "Intlzr.InitializeL" )
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::CancelInit
// Cancels already started ini.
//
// -----------------------------------------------------------------------------
//
TBool CVtEngInitializer::CancelInit()
    {
    __VTPRINTENTER( "Intlzr.CancelInit" )
    TBool cancelSignalled = EFalse;
    __VTPRINT2( DEBUG_GEN, "Intlzr.CancelInit %d", iStep )
    if ( IsActive() )
        {
        switch ( iStep )
            {
            case EInitMedia: // media->InitializeL pending
            case EInitProto: // media->InitializeProviderL pending
                {
                if ( ! ( iDataportHandled & EDataportReceived )  )
                    {
                    __VTPRINT( DEBUG_GEN, "Intlzr.CancelInit complete" )
                    if ( iStatus == KRequestPending )
	                    {
                        // Actual protocol init is not done yet.
                        TRequestStatus* status = &iStatus;
                        __VTPRINT( DEBUG_GEN, "Intlzr.CancelInit complete1" )
                        User::RequestComplete( status, KErrNone );
                        __VTPRINT( DEBUG_GEN, "Intlzr.CancelInit complete2" )
                        }
                    iDataportHandled |= EDataportReceived;
                    __VTPRINT( DEBUG_GEN, "Intlzr.CancelInit complete" )
                    }
                __VTPRINT( DEBUG_GEN, "Intlzr.CancelInit MH cancel" )
                CVtEngMediaHandler* media =
                    static_cast<CVtEngMediaHandler*>( &iHandlers.Media() );
                media->CancelInitialize();
                iStep = EResetMediaPhase2;
                }
                break;
            case EResetMedia:
                break;
            default:
                cancelSignalled = ETrue;
                Cancel();
            }
        }
    __VTPRINTEXITR( "Intlzr.CancelInit %d", cancelSignalled )
    return cancelSignalled;
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::Uninitialize
// Start un-initialization process.
//
// -----------------------------------------------------------------------------
//
void CVtEngInitializer::Uninitialize( CVtEngOperation& aCallback )
    {
    __VTPRINTENTER( "Intlzr.Uninitialize" )
    iCallback = &aCallback;
    ContinueOrRetry( EReset );
    __VTPRINTEXIT( "Intlzr.Uninitialize" )
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::GetSessionCommand
// Transfer ownership of Protocol and continue initialization.
//
// -----------------------------------------------------------------------------
//
MVtSessionCommand* CVtEngInitializer::GetSessionCommand()
    {
    __VTPRINTENTER( "Intlzr.GetSessionCommand" )
	 __VTPRINT2( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.GetSessionCommand iSessionCommand: $%x", reinterpret_cast< TUint >( iSessionCommand ) )
    MVtSessionCommand* sessionCommand = iSessionCommand;

	// Set ownership to media handler since media handler is requesting so.
	iOwnershipInMH = ETrue;
	if( iStep >= EInitDataportCompleted )
		{
		// Ownership can be totally given to MH after dataport is loaned.
		__VTPRINT( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.GetSessionCommand iSessionCommand ownership to MH GetSessionCommand")
		
		iSessionCommand = NULL;
		iStep = EInitComplete;
		ContinueOrRetry( EContinue );		
		}
    if ( iStep != EResetMedia )
        {
        __VTPRINT( DEBUG_GEN, "Intlzr.GetSessionCommand=>ContinueOrRetry( EContinue )")
        ContinueOrRetry( EContinue );
        }
    else
        {
        // Reset requested. ContinueOrRetry with EReset was called
        // while protocol Init was ongoing. Now continue
        __VTPRINT( DEBUG_GEN, "Intlzr.GetSessionCommand=>ContinueOrRetry( EReset )")
        ContinueOrRetry( EReset );
        }
    __VTPRINTEXIT( "Intlzr.GetSessionCommand" )
    return sessionCommand;
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::Initialized
// Returns if engine is initialized.
//
// -----------------------------------------------------------------------------
//
TBool CVtEngInitializer::Initialized() const
    {
    return ( iStep == EInitComplete );
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::RunL
// Perform initialization step
//
// -----------------------------------------------------------------------------
//
void CVtEngInitializer::RunL()
    {
    __VTPRINTENTER( "Intlzr.RunL" )
    __VTPRINT3( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.Run step=%d err=%d",
        iStep, iStatus.Int() )
    if ( iStatus != KErrNone )
        {
        Notify( iStatus.Int() );
        __VTPRINTEXIT( "Intlzr.RunL" )
        return;
        }
    CVtEngMediaHandler* media =
        static_cast<CVtEngMediaHandler*>( &iHandlers.Media() );

    switch ( iStep )
        {
        case EInitNone:
            return;
        case EInitMedia:
            // Initialize video source
            iStatus = KRequestPending;
            media->InitializeL( iStatus );
            SetActive();
            iStep++; // EInitProto
            __VTPRINTEXIT( "Intlzr.RunL" )
            return;
        case EInitProto:
            // Initialize Protocol => create terminal only once.
            __VTPRINT( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.Run create Protocol")
            if ( !iSessionCommand )
                {
                __VTPRINT( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.Run DOCREATE Protocol" )
                TVt3G324MSupported protocolSupported;
                iSessionCommand = VTProtocolFactory::CreateSessionCommandL(
                    media, ETrue, protocolSupported );
                    
                if (protocolSupported == EVt3G324MMissing)
                    {
                    __VTPRINT( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.Run init 3G324M stack is missing")    
                    Notify(KErrNotReady);
                    return;   
                    }

				// Initialize Protocol immediately after it is created.
				if( iSessionCommand )
					{
					__VTPRINT( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.Run InitL protocol")
					iSessionCommand->InitProtocolL( media->SdkInitInfo() );
					}
                }
            if ( iSessionCommand )
                {
                const TDesC* dataportName = NULL;
                __VTPRINT( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.Run init protocol")
                if(iCallback->Command() == KVtEngInitializeEngineTest )
                    {
                    __VTPRINT( DEBUG_GEN | DEBUG_DETAIL,
                        "Intlzr.Run init with COMM::0")
                    CVtEngUtility::Settings().SetConnectReady();    
                    iComms = VTProtocolFactory::CreateCommServerL(
                        KVtEngCommTestPortName );
                    }
                else if( iCallback->Command() == KVtEngInitializeEngineDiag )
                    {
                    __VTPRINT( DEBUG_GEN | DEBUG_DETAIL,
                        "Intlzr.Run init with PVDIAGPORT")
                    CVtEngUtility::Settings().SetConnectReady();    
                    iComms = VTProtocolFactory::CreateCommServerL(
                    KVtEngCommDiagPortName  );
                    }
                else
                    { // [MediatorChange]: 
                    __VTPRINT( DEBUG_GEN | DEBUG_DETAIL,
                        "Intlzr.Run init with DATAPORT" )
                    dataportName = 
                        CVtEngUtility::Settings().DataportInfo();
                    if ( !dataportName ) 
                        {
                        // not available yet, start waiting,
                        // HandleSettingChangedL is called when dataport
                        // becomes available
                        __VTPRINT( DEBUG_GEN | DEBUG_DETAIL,
                                                "Intlzr.Run DATAPORT is not ready yet" )
                        
                        CVtEngUtility::Settings().NotifyChangeL( 
                        CVtEngSettings::EDataportInfo, *this );
                        iStatus = KRequestPending;
                        SetActive();                        
                        __VTPRINTEXIT( "Intlzr.RunL" )
                        return;
                        }
                    else
                        {
                        //RDebug::Print( _L("DataportName is:%S"), dataportName );
                        TBool bitReversed( BitReversalUsed() );
                                        
                        iComms = VTProtocolFactory::CreateCommServerL(
                           *dataportName, bitReversed );
                        // not interested of DP info any more
                        CVtEngUtility::Settings().CancelNotifyChange( 
                            CVtEngSettings::EDataportInfo, *this );
                        }
                    }
                    
                // Initialization is now completed
					iStep = EInitDataportCompleted;

					// Dataport is now loaned
					CVtEngUtility::Settings().SetDataportLoaned( ETrue );

					// Update states since dataport is now loaned
					CVtEngStateManager* states = CVtEngUtility::StateManager();
					states->Update();

					// No need for ownership anymore, media handler owns the pointer and is 
					// responsible of deletion.
					if( iOwnershipInMH )
						{
						__VTPRINT( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.Run iSessionCommand ownership to MH")						
						iSessionCommand = NULL; 
						iStep = EInitComplete;
						ContinueOrRetry( EContinue );						
						}
                    
                    __VTPRINT( DEBUG_GEN | DEBUG_DETAIL,
                        "Intlzr.Run init protocol port operation completed")
                // Media handler calls GetSessionCommand when InitL
                // is complete and initialization continues.
                __VTPRINTEXIT( "Intlzr.RunL" )
                return;
                }
            break;
        case EInitSession:
            {
            CVtEngSessionHandler* session =
                static_cast<CVtEngSessionHandler*>( &iHandlers.Session() );
            session->InitializeL();
            __VTPRINT( DEBUG_GEN | DEBUG_DETAIL,
                    "Intlzr.RunL StartMediatorListenerL" )
            CVtEngUtility::EngineUtils()->StartMediatorListenerL();
            }
            break;
        case EResetMedia:
            iHandlers.Uninitialize();
            iStatus = KRequestPending;
            media->Uninitialize( iStatus );
            SetActive();
            iStep++; // EResetMediaPhase2
            __VTPRINT( DEBUG_GEN | DEBUG_DETAIL,
                "Intlzr.RunL step reset media started" )
            __VTPRINTEXIT( "Intlzr.RunL" )
            return;
        case EResetMediaPhase2:
            if ( iComms )
                {
                __VTPRINT( DEBUG_GEN | DEBUG_DETAIL,
                    "Intlzr.RunL VTENgine deletes COMM server" )
                CVtEngMediaHandler* media =
                static_cast<CVtEngMediaHandler*>( &iHandlers.Media() );
                if ( media->ProtoInitialized() )
                    {
                    TRAPD( err, VTProtocolFactory::DeleteCommServerL( iComms ) );
                    __VTPRINT2( DEBUG_GEN | DEBUG_DETAIL,
                        "Intlzr.RunL VTENgine deletes COMM server err=%d", err )
                    __ASSERT_ALWAYS( err == KErrNone,
                        Panic( EVtEngPanicCommsDestructOnInvalidState ) );
                    iComms = NULL;
                    }
                else if ( !media->ProtoInitialized() && iSessionCommand )
                    {
                    __VTPRINTEXIT( "Intlzr.RunL" )
                    return;
                    }
                }
            break;
        case EInitComplete:
            break;
        default:
            Panic( EVtEngPanicInvalidInitializationState );
            break;
        }
    ContinueOrRetry( EContinue );
    __VTPRINTEXIT( "Intlzr.RunL" )
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::DoCancel
// Cancels initialization
//
// -----------------------------------------------------------------------------
//
void CVtEngInitializer::DoCancel()
    {
    __VTPRINTENTER( "Intlzr.DoCancel" )    
    if ( iStatus == KRequestPending )
        {
        __VTPRINT2( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.DoCancel step=%d", iStep )
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, KErrCancel );
        }
    iStep = EInitNone;
    iCallback = NULL;
    __VTPRINTEXIT( "Intlzr.DoCancel" )
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::RunError
// Handler error on initialization.
//
// -----------------------------------------------------------------------------
//
TInt CVtEngInitializer::RunError( TInt aError )
    {
    __VTPRINTENTER( "Intlzr.RunError" )
    __VTPRINT2( DEBUG_GEN, "Intlzr.RunError %d", aError )
    if ( iRetrials )
        {
        __VTPRINT2( DEBUG_GEN | DEBUG_DETAIL, "Intlzr.retrials %d", iRetrials )
        TCallBack callback( CVtEngInitializer::HandleTimer, this );
        iTimer->Start(
            KVtEngInitializerRetrialTimeout,
            KVtEngInitializerRetrialTimeout,
            callback );
        }
    else
        {
        Notify( aError );
        }
    __VTPRINTEXIT( "Intlzr.RunError" )
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::HandleTimer
// Handler for retrial timer.
//
// -----------------------------------------------------------------------------
//
TInt CVtEngInitializer::HandleTimer( TAny* aAny )
    {
    CVtEngInitializer* handler =
        reinterpret_cast<CVtEngInitializer*>( aAny );
    handler->DoHandleTimer();
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::DoHandleTimer
// Handler for retrial timer.
//
// -----------------------------------------------------------------------------
//
void CVtEngInitializer::DoHandleTimer()
    {
    iTimer->Cancel();
    ContinueOrRetry( ERetry );
    }

TBool CVtEngInitializer::ActivateAndSignal( TInt aSignalValue )
    {
    __VTPRINTENTER( "Intlzr.ActivateAndSignal" )
    TRequestStatus* status = &iStatus;
    TBool signaled = EFalse;
    if ( iStatus.Int() != KRequestPending && !IsActive() )
        {
        iStatus = KRequestPending;
        SetActive();
        User::RequestComplete( status, aSignalValue );
        signaled = ETrue;
        }                
    __VTPRINTEXITR( "Intlzr.ActivateAndSignal signaled=%d", signaled )
    return signaled;
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::CreateDtmfHandlerL
// Creates handler for DTMF sending.
//
// -----------------------------------------------------------------------------
//
void CVtEngInitializer::CreateDtmfHandlerL( MVtH324ConfigCommand* aH324Config )
    {
    iHandlers.CreateDtmfHandlerL( aH324Config );
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::ContinueOrRetry
// Proceed to next step, retry on failure or notify observer.
//
// -----------------------------------------------------------------------------
//
void CVtEngInitializer::ContinueOrRetry( const TProcess aOperation )
    {
      __VTPRINTENTER( "Intlzr.ContinueOrRetry" )
    __VTPRINT2( DEBUG_GEN, "Intlzr.CoR op=%d", aOperation )
    if ( aOperation == EContinue )
        {
        const TBool resetComplete( iStep == EResetMediaPhase2 );
        // check if last step complete and notify observer
        if ( iStep == EInitComplete || resetComplete )
            {
            if ( resetComplete && 
                // resetComplete is true also when clearing state is entered
                // while waiting for dataport. In that case Final Uninit must
                // not be done because MediaHandler's state is not ready for
                // it => need to wait for KVtEngResetEngine from UI
                iCallback->Command() == KVtEngResetEngine )
                {
                CVtEngMediaHandler* media =
                    static_cast<CVtEngMediaHandler*>( &iHandlers.Media() );
                media->FinalizeUninitialization();
                iStep = EInitNone;
                }
            Notify( KErrNone );
            __VTPRINT2( DEBUG_GEN, "Intlzr.CoR op=EContinue, branch=%d", 1 )
            return;
            }
		else if( iStep == EInitProto )
			{
			__VTPRINT2( DEBUG_GEN, "Intlzr.CoR op=EContinue, branch=%d", 2 )
			return;
			}
        __VTPRINT2( DEBUG_GEN, "Intlzr.CoR op=EContinue, branch=%d", 3 )
        iStep++;
        iRetrials = KVtEngInitializerRetrials;
        }
    else if ( aOperation == EReset )
        {
        __VTPRINT( DEBUG_GEN, "Intlzr.CoR op=EReset")
        iRetrials = KVtEngInitializerRetrials;
        const TInt step( iStep );
        if ( step != EInitComplete && IsActive() )
            {
            // Reset requested while init ongoing but
            // Protocol InitL not yet issued
            if ( CancelInit() == EFalse )
                { // AO still active, must return here because end of this method 
                __VTPRINT( DEBUG_GEN, " Initializer CoR 2")
                __VTPRINTEXIT( "Intlzr.ContinueOrRetry" )
                return;
                }
            }
        iStep = EResetMedia;
        if ( ( step == EInitProto ||
               step == EInitSession ) && !IsActive() )
            {
            // Protocol InitL is pending. Wait until it completes.
            // GetSessionCommand is called and there we this is
            // again called.
            __VTPRINT( DEBUG_GEN, " Initializer reset while InitL")
            __VTPRINTEXIT( "Intlzr.ContinueOrRetry" )
            return;
            }
        }
    else
        {
        iRetrials--;
        }
    ActivateAndSignal( KErrNone );    
    __VTPRINTEXIT( "Intlzr.ContinueOrRetry" )
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::Notify
// Notifies observer on completion or error.
//
// -----------------------------------------------------------------------------
//
void CVtEngInitializer::Notify( const TInt aResult )
    {
    __VTPRINTENTER( "Intlzr.Notify" )
    if ( iStep == EInitComplete )
        {
        CVtEngStateManager* states = CVtEngUtility::StateManager();
        states->Update();
        }

    if ( iCallback )
        {
        if ( aResult != KErrCancel )
            { // UI is not interested on cancel completion
            iCallback->HandleOpComplete( aResult );
            }
        iCallback = NULL;
        __VTPRINT2( DEBUG_GEN, "Intlzr.Notify res=%d", aResult )
        }
    __VTPRINTEXIT( "Intlzr.Notify" )
    }


// -----------------------------------------------------------------------------
// CVtEngInitializer::BitReversalUsed
// Checks if bit reversal should be used from locally variated information.
// -----------------------------------------------------------------------------
//
TBool CVtEngInitializer::BitReversalUsed()
    {
    __VTPRINT( DEBUG_GEN, "Intlzr.BitReversalUsed" )
    return CVtEngUtility::Settings().CheckBits(
        KVTLVFlagEnableBitReversal );
    }

// -----------------------------------------------------------------------------
// CVtEngInitializer::HandleSettingChangedL
// Notification of received dataport name.
// -----------------------------------------------------------------------------
//
void CVtEngInitializer::HandleSettingChangedL( 
    CVtEngSettings::TSettingId aId, 
    const TDesC& /*aValue*/ )
    {
    __VTPRINTENTER( "Intlzr.HandleSettingChangedL" )
    if ( !( iDataportHandled & EDataportReceived ) && 
            aId == CVtEngSettings::EDataportInfo && 
            iStatus == KRequestPending )
     
        {        
        iDataportHandled |= EDataportReceived;
        //dataport will be fetched in runl, otherwise, cancelinit can not work
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, KErrNone );
        }    
    __VTPRINTEXIT( "Intlzr.HandleSettingChangedL" )
    }      

// -----------------------------------------------------------------------------
// CVtEngInitializer::GetVtComms
// Return pointer to communication port.
// -----------------------------------------------------------------------------
//
MCommServer* CVtEngInitializer::GetVtComms()
	{
	return iComms;
	}

//  End of File