wlan_bearer/wlanengine/wlan_symbian/wlanengine_symbian_3.1/src/wlantimerservices.cpp
changeset 0 c40eb8fe8501
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanengine/wlan_symbian/wlanengine_symbian_3.1/src/wlantimerservices.cpp	Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,480 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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:  This class implements timer service with callback functionality.
+*
+*/
+
+/*
+* %version: 2 %
+*/
+
+#include <e32std.h>
+#include <e32base.h>
+#include "wlantimerservices.h"
+#include "am_debug.h"
+
+const TInt KMaxTimerTimeout            = 0x7FFFFFFF;
+const TInt KFirstItemIndex             = 0;
+const TInt KNoRequests                 = -1;
+const TInt KEntriesAreEqual            = 0;
+const TInt KFirstEntryIsBigger         = 1;
+const TInt KFirstEntryIsSmaller        = -1;
+
+#ifdef _DEBUG
+/**
+ * Formatting of date time debug string.
+ */
+_LIT( KWlanTimerServicesDateTimeFormat, "%F %*E %*N %D %H:%T:%S" );
+
+/**
+ * Maximun length for date time debug string.
+ */
+const TInt KWlanTimerServicesMaxDateTimeStrLen = 50;
+#endif
+
+// ================= MEMBER FUNCTIONS =======================
+
+// C++ default constructor can NOT contain any code, that
+// might leave.
+//
+CWlanTimerServices::CWlanTimerServices() :
+    CActive( CActive::EPriorityStandard ),
+    iRequestId( 0 )
+    {
+    DEBUG( "CWlanTimerServices::CWlanTimerServices()" );
+    }
+
+// Static constructor.
+CWlanTimerServices* CWlanTimerServices::NewL()
+    {
+    DEBUG( "CWlanTimerServices::NewL()" );
+    CWlanTimerServices* self =
+        new (ELeave) CWlanTimerServices();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// Symbian 2nd phase constructor can leave.
+void CWlanTimerServices::ConstructL()
+    {
+    DEBUG( "CWlanTimerServices::ConstructL()" );
+
+    CActiveScheduler::Add( this );
+    User::LeaveIfError( iTimer.CreateLocal() );
+    
+    DEBUG( "CWlanTimerServices::ConstructL() - done" );
+    }
+
+// Destructor
+CWlanTimerServices::~CWlanTimerServices()
+    {
+    DEBUG( "CWlanTimerServices::~CWlanTimerServices()" );
+
+    Cancel();
+    iTimer.Close();
+    iRequests.Close();
+    }
+
+// ---------------------------------------------------------
+// CWlanTimerServices::DoCancel
+// Is called by CActive::Cancel()
+// ---------------------------------------------------------
+//
+void CWlanTimerServices::DoCancel()
+    {
+    DEBUG( "CWlanTimerServices::DoCancel()" );
+    iTimer.Cancel();
+    }
+
+// ---------------------------------------------------------
+// CWlanTimerServices::CompareTimeouts
+// ---------------------------------------------------------
+//
+TInt CWlanTimerServices::CompareTimeouts( const CTimeoutRequestEntry& aFirst,
+                                          const CTimeoutRequestEntry& aSecond )
+    {
+    DEBUG( "CWlanTimerServices::CompareTimeouts()" );
+
+    TInt ret( 0 );
+    
+    if( aFirst.At() == aSecond.At() )
+        {
+        ret = KEntriesAreEqual;
+        }
+    else if( aFirst.At() > aSecond.At() )
+        {
+        ret = KFirstEntryIsBigger;
+        }
+    else
+        {
+        ret = KFirstEntryIsSmaller;
+        }
+    
+    DEBUG1( "CWlanTimerServices::CompareTimeouts() - returning %d", ret );
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CWlanTimerServices::CalculateInterval
+// ---------------------------------------------------------
+//
+TInt CWlanTimerServices::CalculateInterval( TTimeIntervalMicroSeconds32& aInterval, TTime& aAt, TBool& aDoSeveralRounds ) const
+    {
+    TTime currentTime;
+    currentTime.HomeTime();
+    
+#ifdef _DEBUG
+    TBuf<KWlanTimerServicesMaxDateTimeStrLen> dbgString, timeoutDbgStr;
+    TRAP_IGNORE( aAt.FormatL( timeoutDbgStr, KWlanTimerServicesDateTimeFormat ) );
+    DEBUG1( "CWlanTimerServices::CalculateInterval() - timeout:  %S", &timeoutDbgStr );
+    TRAP_IGNORE( currentTime.FormatL( dbgString, KWlanTimerServicesDateTimeFormat ) );
+    DEBUG1( "CWlanTimerServices::CalculateInterval() - time now: %S", &dbgString );
+#endif
+    
+    if( aAt < currentTime )
+        {
+        DEBUG( "CWlanTimerServices::CalculateInterval() - timeout happens in past, returning KErrArgument" );
+        return KErrArgument;
+        }
+    
+    TTimeIntervalDays days( aAt.DaysFrom( currentTime ) );
+    DEBUG1( "CWlanTimerServices::CalculateInterval() - difference %d day(s)", days.Int() );
+    if( days.Int() != 0 )
+        {
+        DEBUG( "CWlanTimerServices::CalculateInterval() - difference day or more, adjusting timeout to same day" );
+        TDateTime timeout = aAt.DateTime();
+        TDateTime now = currentTime.DateTime();
+        timeout.SetYear( now.Year() );
+        timeout.SetMonth( now.Month() );
+        timeout.SetDay( now.Day() );
+        aAt = TTime( timeout );
+        if( aAt < currentTime )
+            {
+            DEBUG1( "CWlanTimerServices::CalculateInterval() - timeout would happen in past, adding %d day(s) to it", days.Int() );
+            aAt += days;
+            }
+        
+#ifdef _DEBUG
+        TBuf<KWlanTimerServicesMaxDateTimeStrLen> newTimeoutDbgStr;
+        TRAP_IGNORE( aAt.FormatL( newTimeoutDbgStr, KWlanTimerServicesDateTimeFormat ) );
+        DEBUG1( "CWlanTimerServices::CalculateInterval() - timeout:  %S", &newTimeoutDbgStr );
+#endif
+        }
+    
+    TTimeIntervalMicroSeconds difference = aAt.MicroSecondsFrom( currentTime );
+    
+    TTimeIntervalMicroSeconds32 newInterval_32bit( KMaxTimerTimeout );
+    
+    TTimeIntervalMicroSeconds interval_64bit( newInterval_32bit.Int() );
+    
+    if ( difference < interval_64bit )
+        {
+        newInterval_32bit = static_cast<TTimeIntervalMicroSeconds32>( difference.Int64() );
+        aDoSeveralRounds = EFalse;
+        }
+    else
+        {
+        DEBUG( "CWlanTimerServices::CalculateInterval() - requested timeout so big it requires several timer rounds" );
+        aDoSeveralRounds = ETrue;
+        }
+
+    aInterval = newInterval_32bit;
+    
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// CWlanTimerServices::StartTimer
+// ---------------------------------------------------------
+//
+TInt CWlanTimerServices::StartTimer( TUint& aRequestId, TTime& aAt, MWlanTimerServiceCallback& aCb )
+    {
+    TTimeIntervalMicroSeconds32 newInterval( 0 );
+    TBool doSeveralRounds( EFalse );
+    
+    TInt err = CalculateInterval( newInterval, aAt, doSeveralRounds );
+    
+    if( err != KErrNone ) 
+        {
+        DEBUG1( "CWlanTimerServices::StartTimer() - CalculateInterval() returned %d", err );
+        return err;
+        }
+        
+    CTimeoutRequestEntry entry( aAt, aCb, ++iRequestId, doSeveralRounds );
+    
+    TInt requestIdOfOriginallyFirstEntry( RequestIdOfFirstEntry() );
+    
+    TLinearOrder<CTimeoutRequestEntry> order( CWlanTimerServices::CompareTimeouts );
+    err = iRequests.InsertInOrder( entry, order );
+    
+    if( err != KErrNone )
+        {
+        DEBUG1( "CWlanTimerServices::StartTimer() - InsertInOrder() returned %d", err );
+        return err;
+        }
+
+    DEBUG1( "CWlanTimerServices::StartTimer() - new entry added to queue, request id %d", entry.RequestId() );
+    
+#ifdef _DEBUG
+    for( TInt i = 0; i < iRequests.Count(); i++ )
+        {
+        DEBUG3( "CWlanTimerServices::StartTimer() - entry[%d]: request id %u, located @ 0x%08X",
+                i,
+                iRequests[i].RequestId(),
+                &iRequests[i] );
+        }
+#endif
+    
+    if( requestIdOfOriginallyFirstEntry != iRequests[0].RequestId() )
+        {
+        // first request has changed, restart timer
+        ActivateTimer( newInterval );
+        }
+    
+    aRequestId = iRequestId;
+    
+    DEBUG( "CWlanTimerServices::StartTimer() - done" );
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// CWlanTimerServices::RequestIdOfFirstEntry   
+// ---------------------------------------------------------
+//
+TInt CWlanTimerServices::RequestIdOfFirstEntry()
+    {
+    TInt idOfFirstEntry = KNoRequests;
+    if( iRequests.Count() > 0 )
+        {
+        idOfFirstEntry = iRequests[KFirstItemIndex].RequestId();
+        }
+    DEBUG1( "CWlanTimerServices::RequestIdOfFirstEntry() - returning %d", idOfFirstEntry );
+    return idOfFirstEntry;
+    }    
+
+// ---------------------------------------------------------
+// CWlanTimerServices::RemoveRequest   
+// ---------------------------------------------------------
+//
+void CWlanTimerServices::RemoveRequest( const TUint& aRequestId )
+    {
+    DEBUG1( "CWlanTimerServices::RemoveRequest( aRequestId: %u )", aRequestId );
+    
+    TInt numOfRequests( iRequests.Count() );
+    DEBUG1( "CWlanTimerServices::RemoveRequest() - numOfRequests: %d", numOfRequests );
+    
+    for( TInt index( 0 ); index < numOfRequests; index++ )
+        {
+        DEBUG2( "CWlanTimerServices::RemoveRequest() - checking iRequests[%d].RequestId: %d", index, iRequests[index].RequestId() );
+        if( iRequests[index].RequestId() == aRequestId )
+            {
+            DEBUG1( "CWlanTimerServices::RemoveRequest() - matching request id found, removing index: %d", index );
+            iRequests.Remove( index );
+            break;
+            }
+        }
+    
+    DEBUG( "CWlanTimerServices::RemoveRequest() - done" );
+    }
+
+// ---------------------------------------------------------
+// CWlanTimerServices::StopTimer   
+// ---------------------------------------------------------
+//
+void CWlanTimerServices::StopTimer( const TUint& aRequestId )
+    {
+    DEBUG1( "CWlanTimerServices::StopTimer( aRequestId: %u )", aRequestId );
+    
+    TInt numOfRequests( iRequests.Count() );
+    DEBUG1( "CWlanTimerServices::StopTimer() - numOfRequests: %d", numOfRequests );
+
+    TInt requestIdOfOriginallyFirstEntry( RequestIdOfFirstEntry() );
+    
+    DEBUG( "CWlanTimerServices::StopTimer() - calling RemoveRequest()" );
+    RemoveRequest( aRequestId );
+    DEBUG( "CWlanTimerServices::StopTimer() - RemoveRequest() returned" );
+
+    if( iRequests.Count() > 0 )
+        {
+        if( requestIdOfOriginallyFirstEntry != iRequests[0].RequestId() )
+            {
+            DEBUG( "CWlanTimerServices::StopTimer() - first request changed, updating timer" );
+            
+            TTimeIntervalMicroSeconds32 newInterval( GetIntervalForNextRequest() );
+                        
+            ActivateTimer( newInterval );
+            }
+#ifdef _DEBUG
+        else
+            {
+            DEBUG( "CWlanTimerServices::StopTimer() - first request hasn't changed" );
+            }
+#endif
+        }
+    else
+        {
+        DEBUG( "CWlanTimerServices::StopTimer() - request count is zero, cancelling timer" );
+        Cancel();
+        iTimer.Cancel();
+        }
+    DEBUG( "CWlanTimerServices::StopTimer() - done" );
+    }    
+
+// ---------------------------------------------------------
+// CWlanTimerServices::GetIntervalForNextRequest
+// ---------------------------------------------------------
+//
+TTimeIntervalMicroSeconds32 CWlanTimerServices::GetIntervalForNextRequest()
+    {
+    DEBUG( "CWlanTimerServices::GetIntervalForNextRequest()" );
+    
+    TTimeIntervalMicroSeconds32 interval( 0 );
+    
+    while( iRequests.Count() > 0  && 
+            KErrArgument == CalculateInterval( interval,
+                        iRequests[KFirstItemIndex].GetAt(),
+                        iRequests[KFirstItemIndex].GetDoSeveralRounds() ))
+        {
+        DEBUG1( "CWlanTimerServices::GetIntervalForNextRequest() - request %u happens in past, time out and remove it", iRequests[KFirstItemIndex].RequestId() );
+        TUint requestToBeRemoved = iRequests[KFirstItemIndex].RequestId();
+        iRequests[KFirstItemIndex].Timeout();
+        RemoveRequest( requestToBeRemoved );
+        }
+    
+    DEBUG( "CWlanTimerServices::GetIntervalForNextRequest() - done" );
+    return interval;
+    }
+
+// ---------------------------------------------------------
+// CWlanTimerServices::RunL
+// Timer has expired. 
+// ---------------------------------------------------------
+//
+void CWlanTimerServices::RunL()
+    {
+
+    DEBUG1( "CWlanTimerServices::RunL() - iStatus: %d", iStatus.Int() );
+    switch( iStatus.Int() )
+        {
+        case KErrCancel:
+            {
+            DEBUG( "CWlanTimerServices::RunL() - iStatus == KErrCancel -> timer cancelled" );
+            break;
+            }
+        case KErrNone:
+            {
+            DEBUG( "CWlanTimerServices::RunL() - iStatus == KErrNone -> timeout occurred" );
+            HandleTimeout();
+            break;
+            }
+        default:
+            {
+            DEBUG( "CWlanTimerServices::RunL() - unexpected iStatus!" );
+            ASSERT( 0 );
+            }
+        }
+    DEBUG( "CWlanTimerServices::RunL() - done" );
+    }
+
+// ---------------------------------------------------------
+// CWlanTimerServices::HandleTimeout
+// ---------------------------------------------------------
+//
+void CWlanTimerServices::HandleTimeout()
+    {
+    DEBUG( "CWlanTimerServices::HandleTimeout()" );
+
+    Cancel();
+    iTimer.Cancel();
+    
+    // if requests exist...
+    if( iRequests.Count() )
+        {
+        // if there's no need to do several rounds...
+        if( !IsTimeInFuture( iRequests[KFirstItemIndex].At() ) )
+        //if( iRequests[KFirstItemIndex].GetDoSeveralRounds() == EFalse )
+            {
+            // store id of the request to be timed out
+            TUint requestIdToTimeout = iRequests[KFirstItemIndex].RequestId();
+            DEBUG1( "CWlanTimerServices::HandleTimeout() - timeout request %u", requestIdToTimeout );
+            iRequests[KFirstItemIndex].Timeout();
+            DEBUG( "CWlanTimerServices::HandleTimeout() - make sure timed out request is removed" );
+            RemoveRequest( requestIdToTimeout );
+            }
+        
+        TTimeIntervalMicroSeconds32 newInterval( GetIntervalForNextRequest() );
+
+        ActivateTimer( newInterval );
+
+        }
+#ifdef _DEBUG
+    else
+        {
+        DEBUG( "CWlanTimerServices::HandleTimeout() - no requests" );
+        }
+#endif
+    DEBUG( "CWlanTimerServices::HandleTimeout() - done" );
+    }
+
+// ---------------------------------------------------------
+// CWlanTimerServices::HandleTimeout
+// ---------------------------------------------------------
+//
+TBool CWlanTimerServices::IsTimeInFuture( const TTime& aAt ) const
+    {
+    DEBUG( "CWlanTimerServices::IsTimeInFuture()" );
+
+    TBool ret( ETrue );
+    
+    TTime currentTime;
+    currentTime.HomeTime();
+    
+#ifdef _DEBUG
+    TBuf<KWlanTimerServicesMaxDateTimeStrLen> dbgString, timeoutDbgStr;
+    TRAP_IGNORE( aAt.FormatL( timeoutDbgStr, KWlanTimerServicesDateTimeFormat ) );
+    DEBUG1( "CWlanTimerServices::IsTimeInFuture() - time to check: %S", &timeoutDbgStr );
+    TRAP_IGNORE( currentTime.FormatL( dbgString, KWlanTimerServicesDateTimeFormat ) );
+    DEBUG1( "CWlanTimerServices::IsTimeInFuture() - time now:      %S", &dbgString );
+#endif
+    
+    if( aAt <= currentTime )
+        {
+        DEBUG( "CWlanTimerServices::IsTimeInFuture() - time is not in the future" );
+        ret = EFalse;
+        }
+    
+    DEBUG1( "CWlanTimerServices::IsTimeInFuture() - returning %d", ret );
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CWlanTimerServices::ActivateTimer
+// ---------------------------------------------------------
+//
+void CWlanTimerServices::ActivateTimer( const TTimeIntervalMicroSeconds32& aInterval )
+    {
+    DEBUG( "CWlanTimerServices::ActivateTimer()" );
+
+    if( aInterval.Int() )
+        {
+        Cancel();
+        iTimer.Cancel();
+        iTimer.After( iStatus, aInterval );
+        SetActive();
+        DEBUG( "CWlanTimerServices::ActivateTimer() - timer active" );
+        }   
+    }
+