wlan_bearer/wlanldd/wlan_symbian/osa_symbian/src/osatimer.cpp
changeset 0 c40eb8fe8501
equal deleted inserted replaced
-1:000000000000 0:c40eb8fe8501
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   WlanTimer implementation
       
    15 *
       
    16 */
       
    17 
       
    18 /*
       
    19 * %version: 10 %
       
    20 */
       
    21 
       
    22 #include "osa_includeme.h"
       
    23 
       
    24 #include <wlantimerclient.h>
       
    25 
       
    26 #include "osatimer.h"
       
    27 #include "osa.h"
       
    28 
       
    29 // mask value to check is timer periodic or not
       
    30 const TUint KPeriodicTimerMask( 1 << 1 );
       
    31 // mask value to check if timer is running
       
    32 const TUint KTimerRunningMask( 1 << 2 );
       
    33 
       
    34 
       
    35 // ---------------------------------------------------------------------------
       
    36 //
       
    37 // ---------------------------------------------------------------------------
       
    38 //
       
    39 WlanTimer::WlanTimer( WlanOsa& aOsa, void* aDfcQueue )
       
    40   : iTimerDfc( WlanTimer::TimerTrigger, this, 0 ),
       
    41     iOsa( aOsa ),
       
    42     iNTimer( ),
       
    43     iTimerClient( NULL ),
       
    44     iTimeoutInMicroSeconds( 0 ),
       
    45     iCtx( 0 ),
       
    46     iFlags( 0 ),
       
    47     iRefCnt( 1 )
       
    48     {
       
    49     TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() ctor +"));
       
    50 
       
    51     MWlanOsa::Assert( 
       
    52         reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
       
    53         aDfcQueue != NULL );
       
    54 
       
    55     iTimerDfc.SetDfcQ( reinterpret_cast<TDfcQue*>(aDfcQueue) );
       
    56     Validate();
       
    57 
       
    58     TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() ctor -"));
       
    59     }
       
    60 
       
    61 // ---------------------------------------------------------------------------
       
    62 //
       
    63 // ---------------------------------------------------------------------------
       
    64 //
       
    65 WlanTimer::~WlanTimer()
       
    66     {
       
    67     TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() dtor +"));
       
    68 
       
    69     if ( iRefCnt != 0 )
       
    70         {
       
    71         TraceDump(CRIT_LEVEL, (("[WLAN] error: Timer destroyed while "
       
    72                                 "active - delete used directly?")));
       
    73         MWlanOsa::Assert(
       
    74             reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
       
    75         }
       
    76 
       
    77     TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() dtor -"));
       
    78     }
       
    79 
       
    80 // ---------------------------------------------------------------------------
       
    81 //
       
    82 // ---------------------------------------------------------------------------
       
    83 //
       
    84 void WlanTimer::TimerTrigger( TAny* aPtr )
       
    85     {
       
    86     WlanTimer* timer = reinterpret_cast< WlanTimer* >( aPtr );
       
    87     timer->TimerTrigger();
       
    88     }
       
    89 
       
    90 // ---------------------------------------------------------------------------
       
    91 //
       
    92 // ---------------------------------------------------------------------------
       
    93 //
       
    94 void WlanTimer::TimerTrigger()
       
    95     {
       
    96     WlanOsa &osa = iOsa;
       
    97 
       
    98     TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer::TimerTrigger +"));
       
    99 
       
   100     // get hold of the global mutex
       
   101     iOsa.MutexAcquire();
       
   102 
       
   103     if (iFlags & KTimerRunningMask)
       
   104         {
       
   105         if ( iFlags & KPeriodicTimerMask )
       
   106             {
       
   107             // a periodic timer was requested - re-arm the timer for the next
       
   108             // run now.
       
   109             const TInt ticks(
       
   110                 NKern::TimerTicks( iTimeoutInMicroSeconds / 1000 ));
       
   111             TraceDump(TIMER_LEVEL, (("[WLAN] timer ticks: %d"), ticks));
       
   112 
       
   113             // on arming the timer, add a reference to it - the reference
       
   114             // shall be cleared upon the completion callback execution.
       
   115             RefAdd();
       
   116             const TInt ret (iNTimer.Again( ticks ));
       
   117 
       
   118             if ( ret != KErrNone )
       
   119                 {
       
   120                 TraceDump(CRIT_LEVEL, (("[WLAN] error: ret %d"), ret));
       
   121                 MWlanOsa::Assert(
       
   122                     reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
       
   123                 RefDel();
       
   124                 }
       
   125             }
       
   126         else
       
   127             {
       
   128             // clear the timer running mask
       
   129             iFlags &= (~KTimerRunningMask);
       
   130             }
       
   131 
       
   132         TraceDump(TIMER_LEVEL,
       
   133             (("[WLAN] current system time: %d"), Kern::SystemTime()));
       
   134         TraceDump(TIMER_LEVEL,
       
   135             (("[WLAN] timer client address: 0x%08x"), iTimerClient));
       
   136         TraceDump(TIMER_LEVEL,
       
   137             (("[WLAN] call timer callback with context: %d"), iCtx));
       
   138 
       
   139         // execute the timer client call back function
       
   140         iTimerClient->OnTimeout( iCtx );
       
   141         }
       
   142 
       
   143     // a reference was added for this timer instance upon arming of the
       
   144     // timer - here, we must remove that reference - and possibly delete
       
   145     // the object instance if we were last to hold reference to it.
       
   146     // NOTE! here the reference count may become zero (if the
       
   147     // TimerDestroy OSA method was called for the instance prior to this
       
   148     // handler executing) and hence the instance may be deleted upon this
       
   149     // call. do not touch instance data after this call.
       
   150     RefDel();
       
   151 
       
   152     // release the global mutex - do not use the "iOsa" as the instance
       
   153     // may now have been deleted, instead use a local reference.
       
   154     osa.MutexRelease();
       
   155 
       
   156     TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer::TimerTrigger -"));
       
   157     }
       
   158 
       
   159 // ---------------------------------------------------------------------------
       
   160 //
       
   161 // ---------------------------------------------------------------------------
       
   162 //
       
   163 void WlanTimer::Enqueue(
       
   164     MWlanTimerClient& aTimerClient,
       
   165     TInt aCtx,
       
   166     TInt aTimeoutInMicroSeconds,
       
   167     TBool aPeriodic )
       
   168     {
       
   169 
       
   170     if ( iFlags & KTimerRunningMask )
       
   171         {
       
   172         // ignore the call if the timer is already running
       
   173         TraceDump(INFO_LEVEL | TIMER_LEVEL,
       
   174             (("[WLAN] WlanTimer::Enqueue: + addr: 0x%08x: "
       
   175               "Timer already enqueued, no effect."), this));
       
   176         }
       
   177     else
       
   178         {
       
   179         TraceDump(INFO_LEVEL | TIMER_LEVEL,
       
   180             (("[WLAN] WlanTimer::Enqueue: + addr: 0x%08x"), this));
       
   181         TraceDump(TIMER_LEVEL,
       
   182             (("[WLAN] timeout in microseconds: %d"), aTimeoutInMicroSeconds));
       
   183         TraceDump(TIMER_LEVEL, (("[WLAN] periodic: %d"), aPeriodic));
       
   184 
       
   185         // store timer parameters
       
   186         iFlags = KTimerRunningMask;
       
   187         iTimerClient = &aTimerClient;
       
   188         iCtx = aCtx;
       
   189 
       
   190         if ( aPeriodic )
       
   191             {
       
   192             iFlags |= KPeriodicTimerMask;
       
   193             }
       
   194 
       
   195         const TInt KMinTimeout = 1000;
       
   196 
       
   197         // the timeout minimum is 1000 us
       
   198         if (aTimeoutInMicroSeconds < KMinTimeout)
       
   199             {
       
   200               iTimeoutInMicroSeconds = KMinTimeout;
       
   201             }
       
   202         else
       
   203             {
       
   204             // adding 999 here will allow the us timeout to be rounded
       
   205             // up to the next full ms, guaranteeing at least the timeout
       
   206             // requested, no less.
       
   207             iTimeoutInMicroSeconds = aTimeoutInMicroSeconds + 999;
       
   208             }
       
   209 
       
   210         // arm the timer (using ms instead of us for the unit)
       
   211         const TInt ticks( NKern::TimerTicks( iTimeoutInMicroSeconds / 1000 ));
       
   212 
       
   213         TraceDump(TIMER_LEVEL, (("[WLAN] timeout in ticks: %d"), ticks));
       
   214         TraceDump(TIMER_LEVEL,
       
   215             (("[WLAN] current system time: %d"), Kern::SystemTime()));
       
   216 
       
   217         // add reference to the timer instance - this reference will be
       
   218         // removed once the timeout event has been handled
       
   219         RefAdd();
       
   220         const TInt ret( iNTimer.OneShot( ticks, iTimerDfc ));
       
   221 
       
   222         if ( ret != KErrNone )
       
   223             {
       
   224             TraceDump(CRIT_LEVEL, (("[WLAN] error: ret %d"), ret));
       
   225             MWlanOsa::Assert(
       
   226                 reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
       
   227             RefDel();
       
   228             }
       
   229         }
       
   230 
       
   231     TraceDump(INFO_LEVEL | TIMER_LEVEL,
       
   232         (("[WLAN] WlanTimer::Enqueue: - addr: 0x%08x: "), this));
       
   233     }
       
   234 
       
   235 // ---------------------------------------------------------------------------
       
   236 //
       
   237 // ---------------------------------------------------------------------------
       
   238 //
       
   239 void WlanTimer::Dequeue()
       
   240     {
       
   241     TraceDump(INFO_LEVEL | TIMER_LEVEL,
       
   242         (("[WLAN] WlanTimer::Dequeue: + addr: 0x%08x"), this));
       
   243 
       
   244     if ( iFlags & KTimerRunningMask )
       
   245         {
       
   246         iFlags = 0;
       
   247 
       
   248         if ( iNTimer.Cancel())
       
   249             {
       
   250             // if cancellation of the timer succeeds, remove a reference from
       
   251             // the timer instance - as this will not be done in the timeout
       
   252             // handler now. NOTE! that here the reference count should never
       
   253             // reach zero (instance exists + the timer is running == 2)
       
   254             RefDel();
       
   255 
       
   256             }
       
   257         // if the cancellation of the timer failed above, the DFC is most
       
   258         // likely already executing - attempting to cancel it here would
       
   259         // be wasting of clock cycles.
       
   260         //
       
   261         // the most common scenario is that the timer cancel succeeds. for
       
   262         // the rare cases of a failure, we just let the DFC execute, and
       
   263         // do nothing (the flags are cleared.)
       
   264         }
       
   265     else
       
   266         {
       
   267         TraceDump(INFO_LEVEL | TIMER_LEVEL,
       
   268              (("[WLAN] WlanTimer::Dequeue: Timer is not running.")));
       
   269         }
       
   270 
       
   271     TraceDump(INFO_LEVEL | TIMER_LEVEL,
       
   272         (("[WLAN] WlanTimer::Dequeue: - addr: 0x%08x"), this));
       
   273     }
       
   274 
       
   275 
       
   276 // ---------------------------------------------------------------------------
       
   277 //
       
   278 // ---------------------------------------------------------------------------
       
   279 //
       
   280 void WlanTimer::RefDel(void)
       
   281     {
       
   282     // decrement the reference counter
       
   283     iRefCnt --;
       
   284 
       
   285     if (iRefCnt == 0)
       
   286         {
       
   287         // referees have reached zero, the object is abandoned, and
       
   288         // shall be deleted
       
   289         WlanTimer *timer = this;
       
   290         delete timer;
       
   291         }
       
   292     }
       
   293 
       
   294 // ---------------------------------------------------------------------------
       
   295 //
       
   296 // ---------------------------------------------------------------------------
       
   297 //
       
   298 void WlanTimer::RefAdd(void)
       
   299     {
       
   300     // increment the reference counter
       
   301     iRefCnt ++;
       
   302     }