wlan_bearer/wlanldd/wlan_symbian/osa_symbian/src/osatimer.cpp
changeset 0 c40eb8fe8501
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanldd/wlan_symbian/osa_symbian/src/osatimer.cpp	Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,302 @@
+/*
+* Copyright (c) 2006-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:   WlanTimer implementation
+*
+*/
+
+/*
+* %version: 10 %
+*/
+
+#include "osa_includeme.h"
+
+#include <wlantimerclient.h>
+
+#include "osatimer.h"
+#include "osa.h"
+
+// mask value to check is timer periodic or not
+const TUint KPeriodicTimerMask( 1 << 1 );
+// mask value to check if timer is running
+const TUint KTimerRunningMask( 1 << 2 );
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+WlanTimer::WlanTimer( WlanOsa& aOsa, void* aDfcQueue )
+  : iTimerDfc( WlanTimer::TimerTrigger, this, 0 ),
+    iOsa( aOsa ),
+    iNTimer( ),
+    iTimerClient( NULL ),
+    iTimeoutInMicroSeconds( 0 ),
+    iCtx( 0 ),
+    iFlags( 0 ),
+    iRefCnt( 1 )
+    {
+    TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() ctor +"));
+
+    MWlanOsa::Assert( 
+        reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
+        aDfcQueue != NULL );
+
+    iTimerDfc.SetDfcQ( reinterpret_cast<TDfcQue*>(aDfcQueue) );
+    Validate();
+
+    TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() ctor -"));
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+WlanTimer::~WlanTimer()
+    {
+    TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() dtor +"));
+
+    if ( iRefCnt != 0 )
+        {
+        TraceDump(CRIT_LEVEL, (("[WLAN] error: Timer destroyed while "
+                                "active - delete used directly?")));
+        MWlanOsa::Assert(
+            reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
+        }
+
+    TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() dtor -"));
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTimer::TimerTrigger( TAny* aPtr )
+    {
+    WlanTimer* timer = reinterpret_cast< WlanTimer* >( aPtr );
+    timer->TimerTrigger();
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTimer::TimerTrigger()
+    {
+    WlanOsa &osa = iOsa;
+
+    TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer::TimerTrigger +"));
+
+    // get hold of the global mutex
+    iOsa.MutexAcquire();
+
+    if (iFlags & KTimerRunningMask)
+        {
+        if ( iFlags & KPeriodicTimerMask )
+            {
+            // a periodic timer was requested - re-arm the timer for the next
+            // run now.
+            const TInt ticks(
+                NKern::TimerTicks( iTimeoutInMicroSeconds / 1000 ));
+            TraceDump(TIMER_LEVEL, (("[WLAN] timer ticks: %d"), ticks));
+
+            // on arming the timer, add a reference to it - the reference
+            // shall be cleared upon the completion callback execution.
+            RefAdd();
+            const TInt ret (iNTimer.Again( ticks ));
+
+            if ( ret != KErrNone )
+                {
+                TraceDump(CRIT_LEVEL, (("[WLAN] error: ret %d"), ret));
+                MWlanOsa::Assert(
+                    reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
+                RefDel();
+                }
+            }
+        else
+            {
+            // clear the timer running mask
+            iFlags &= (~KTimerRunningMask);
+            }
+
+        TraceDump(TIMER_LEVEL,
+            (("[WLAN] current system time: %d"), Kern::SystemTime()));
+        TraceDump(TIMER_LEVEL,
+            (("[WLAN] timer client address: 0x%08x"), iTimerClient));
+        TraceDump(TIMER_LEVEL,
+            (("[WLAN] call timer callback with context: %d"), iCtx));
+
+        // execute the timer client call back function
+        iTimerClient->OnTimeout( iCtx );
+        }
+
+    // a reference was added for this timer instance upon arming of the
+    // timer - here, we must remove that reference - and possibly delete
+    // the object instance if we were last to hold reference to it.
+    // NOTE! here the reference count may become zero (if the
+    // TimerDestroy OSA method was called for the instance prior to this
+    // handler executing) and hence the instance may be deleted upon this
+    // call. do not touch instance data after this call.
+    RefDel();
+
+    // release the global mutex - do not use the "iOsa" as the instance
+    // may now have been deleted, instead use a local reference.
+    osa.MutexRelease();
+
+    TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer::TimerTrigger -"));
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTimer::Enqueue(
+    MWlanTimerClient& aTimerClient,
+    TInt aCtx,
+    TInt aTimeoutInMicroSeconds,
+    TBool aPeriodic )
+    {
+
+    if ( iFlags & KTimerRunningMask )
+        {
+        // ignore the call if the timer is already running
+        TraceDump(INFO_LEVEL | TIMER_LEVEL,
+            (("[WLAN] WlanTimer::Enqueue: + addr: 0x%08x: "
+              "Timer already enqueued, no effect."), this));
+        }
+    else
+        {
+        TraceDump(INFO_LEVEL | TIMER_LEVEL,
+            (("[WLAN] WlanTimer::Enqueue: + addr: 0x%08x"), this));
+        TraceDump(TIMER_LEVEL,
+            (("[WLAN] timeout in microseconds: %d"), aTimeoutInMicroSeconds));
+        TraceDump(TIMER_LEVEL, (("[WLAN] periodic: %d"), aPeriodic));
+
+        // store timer parameters
+        iFlags = KTimerRunningMask;
+        iTimerClient = &aTimerClient;
+        iCtx = aCtx;
+
+        if ( aPeriodic )
+            {
+            iFlags |= KPeriodicTimerMask;
+            }
+
+        const TInt KMinTimeout = 1000;
+
+        // the timeout minimum is 1000 us
+        if (aTimeoutInMicroSeconds < KMinTimeout)
+            {
+              iTimeoutInMicroSeconds = KMinTimeout;
+            }
+        else
+            {
+            // adding 999 here will allow the us timeout to be rounded
+            // up to the next full ms, guaranteeing at least the timeout
+            // requested, no less.
+            iTimeoutInMicroSeconds = aTimeoutInMicroSeconds + 999;
+            }
+
+        // arm the timer (using ms instead of us for the unit)
+        const TInt ticks( NKern::TimerTicks( iTimeoutInMicroSeconds / 1000 ));
+
+        TraceDump(TIMER_LEVEL, (("[WLAN] timeout in ticks: %d"), ticks));
+        TraceDump(TIMER_LEVEL,
+            (("[WLAN] current system time: %d"), Kern::SystemTime()));
+
+        // add reference to the timer instance - this reference will be
+        // removed once the timeout event has been handled
+        RefAdd();
+        const TInt ret( iNTimer.OneShot( ticks, iTimerDfc ));
+
+        if ( ret != KErrNone )
+            {
+            TraceDump(CRIT_LEVEL, (("[WLAN] error: ret %d"), ret));
+            MWlanOsa::Assert(
+                reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
+            RefDel();
+            }
+        }
+
+    TraceDump(INFO_LEVEL | TIMER_LEVEL,
+        (("[WLAN] WlanTimer::Enqueue: - addr: 0x%08x: "), this));
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTimer::Dequeue()
+    {
+    TraceDump(INFO_LEVEL | TIMER_LEVEL,
+        (("[WLAN] WlanTimer::Dequeue: + addr: 0x%08x"), this));
+
+    if ( iFlags & KTimerRunningMask )
+        {
+        iFlags = 0;
+
+        if ( iNTimer.Cancel())
+            {
+            // if cancellation of the timer succeeds, remove a reference from
+            // the timer instance - as this will not be done in the timeout
+            // handler now. NOTE! that here the reference count should never
+            // reach zero (instance exists + the timer is running == 2)
+            RefDel();
+
+            }
+        // if the cancellation of the timer failed above, the DFC is most
+        // likely already executing - attempting to cancel it here would
+        // be wasting of clock cycles.
+        //
+        // the most common scenario is that the timer cancel succeeds. for
+        // the rare cases of a failure, we just let the DFC execute, and
+        // do nothing (the flags are cleared.)
+        }
+    else
+        {
+        TraceDump(INFO_LEVEL | TIMER_LEVEL,
+             (("[WLAN] WlanTimer::Dequeue: Timer is not running.")));
+        }
+
+    TraceDump(INFO_LEVEL | TIMER_LEVEL,
+        (("[WLAN] WlanTimer::Dequeue: - addr: 0x%08x"), this));
+    }
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTimer::RefDel(void)
+    {
+    // decrement the reference counter
+    iRefCnt --;
+
+    if (iRefCnt == 0)
+        {
+        // referees have reached zero, the object is abandoned, and
+        // shall be deleted
+        WlanTimer *timer = this;
+        delete timer;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTimer::RefAdd(void)
+    {
+    // increment the reference counter
+    iRefCnt ++;
+    }