|
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 } |