1 /* |
|
2 * Copyright (c) 2010 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 "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: Implementation of CFlexTimerSession class. |
|
15 * |
|
16 */ |
|
17 /* |
|
18 * %version: 1 % |
|
19 */ |
|
20 |
|
21 // System include files |
|
22 #include <e32def.h> |
|
23 #include <e32cmn.h> |
|
24 #include <hal.h> |
|
25 |
|
26 // User include files go here: |
|
27 #include "flextimercommon.h" |
|
28 #include "flextimersession.h" |
|
29 #include "mflextimerservice.h" |
|
30 #include "OstTraceDefinitions.h" |
|
31 #ifdef OST_TRACE_COMPILER_IN_USE |
|
32 #include "flextimersessionTraces.h" |
|
33 #endif |
|
34 |
|
35 // Constants |
|
36 |
|
37 // ======== MEMBER FUNCTIONS ======== |
|
38 |
|
39 // -------------------------------------------------------------------------- |
|
40 // Constructor |
|
41 // -------------------------------------------------------------------------- |
|
42 // |
|
43 CFlexTimerSession::CFlexTimerSession( MFlexTimerService* aFlexTimerService ) |
|
44 : iService( aFlexTimerService ), |
|
45 iTimerWinSize( 0 ), |
|
46 iUseDefaultWin( ETrue ) |
|
47 { |
|
48 OstTrace1( TRACE_INTERNAL, |
|
49 CFLEXTIMERSESSION, |
|
50 "CFlexTimerSession::CFlexTimerSession; this=%x", |
|
51 ( TUint )this ); |
|
52 } |
|
53 |
|
54 // -------------------------------------------------------------------------- |
|
55 // Destructor |
|
56 // -------------------------------------------------------------------------- |
|
57 // |
|
58 CFlexTimerSession::~CFlexTimerSession() |
|
59 { |
|
60 OstTrace1( TRACE_INTERNAL, |
|
61 CFLEXTIMERSESSIOND, |
|
62 "CFlexTimerSession::~CFlexTimerSession; this=%x", |
|
63 ( TUint )this ); |
|
64 } |
|
65 |
|
66 // -------------------------------------------------------------------------- |
|
67 // Function called from CFlexTimerService::RunL for messages targeted to |
|
68 // this session |
|
69 // -------------------------------------------------------------------------- |
|
70 // |
|
71 void CFlexTimerSession::ServiceL( const RMessage2& aMessage ) |
|
72 { |
|
73 TInt msgType( aMessage.Function() ); |
|
74 |
|
75 OstTraceExt2( TRACE_INTERNAL, |
|
76 CFLEXTIMERSESSION_MSG, |
|
77 "CFlexTimerSession::ServiceL; this=%x; msgType=%d", |
|
78 ( TInt )this, |
|
79 msgType ); |
|
80 |
|
81 // Check message type and pass it to correct handler. Handler either |
|
82 // stores the message or completes it immediately. |
|
83 switch ( msgType ) |
|
84 { |
|
85 case EFlexTimerServCancelRequest: |
|
86 CancelTimer( aMessage ); |
|
87 break; |
|
88 case EFlexTimerServAtRequest: |
|
89 NewAtTimer( aMessage ); |
|
90 break; |
|
91 case EFlexTimerServAtUTCRequest: |
|
92 NewAtUtcTimer( aMessage ); |
|
93 break; |
|
94 case EFlexTimerServAfterRequest: |
|
95 NewAfterTimer( aMessage ); |
|
96 break; |
|
97 case EFlexTimerServAfterTicksRequest: |
|
98 NewAfterTicksTimer( aMessage ); |
|
99 break; |
|
100 case EFlexTimerServConfigureRequest: |
|
101 ConfigureParameters( aMessage ); |
|
102 break; |
|
103 default: |
|
104 OstTrace1( |
|
105 TRACE_INTERNAL, |
|
106 CFLEXTIMERSESSION_ERROR, |
|
107 "CFlexTimerSession::ServiceL: Unknown message; this=%x", |
|
108 ( TUint )this ); |
|
109 aMessage.Complete( KErrNotSupported ); |
|
110 } |
|
111 } |
|
112 |
|
113 // -------------------------------------------------------------------------- |
|
114 // Timeout handler for triggering timers |
|
115 // -------------------------------------------------------------------------- |
|
116 // |
|
117 void CFlexTimerSession::Timeout() const |
|
118 { |
|
119 // Check for the validity of pending timeout request |
|
120 if ( !iPendingTimeoutMsg.IsNull() ) |
|
121 { |
|
122 OstTraceExt2( TRACE_INTERNAL, |
|
123 CFLEXTIMERSESSION_TIMEOUT, |
|
124 "CFlexTimerSession::Timeout; this=%x; msg=%x", |
|
125 ( TUint )this, |
|
126 ( TUint )iPendingTimeoutMsg.Handle() ); |
|
127 // Complete message, this sets message pointer to NULL |
|
128 iPendingTimeoutMsg.Complete( KErrNone ); |
|
129 } |
|
130 else |
|
131 { |
|
132 // No valid message pointer, nothing we can do here |
|
133 OstTrace1( TRACE_INTERNAL, |
|
134 CFLEXTIMERSESSION_TIMEOUT_ERROR, |
|
135 "CFlexTimerSession::Timeout: No Pending message; this=%x", |
|
136 ( TUint )this ); |
|
137 } |
|
138 } |
|
139 |
|
140 // -------------------------------------------------------------------------- |
|
141 // Function for aborting At-timer |
|
142 // -------------------------------------------------------------------------- |
|
143 // |
|
144 void CFlexTimerSession::Abort( TInt aReason ) const |
|
145 { |
|
146 // Check for the validity of pending timeout request |
|
147 if ( !iPendingTimeoutMsg.IsNull() ) |
|
148 { |
|
149 OstTraceExt2( TRACE_INTERNAL, |
|
150 CFLEXTIMERSESSION_ABORT, |
|
151 "CFlexTimerSession::Abort; this=%x; msg=%x", |
|
152 ( TUint )this, |
|
153 ( TUint )iPendingTimeoutMsg.Handle() ); |
|
154 // Complete message, this sets message pointer to NULL |
|
155 iPendingTimeoutMsg.Complete( aReason ); |
|
156 } |
|
157 else |
|
158 { |
|
159 // No valid message pointer, nothing we can do here |
|
160 OstTrace1( |
|
161 TRACE_INTERNAL, |
|
162 CFLEXTIMERSESSION_ABORT_ERROR, |
|
163 "CFlexTimerSession::Abort: No Pending message; this=%x", |
|
164 ( TUint )this ); |
|
165 |
|
166 } |
|
167 } |
|
168 |
|
169 // -------------------------------------------------------------------------- |
|
170 // Handler function for starting At() -timer |
|
171 // -------------------------------------------------------------------------- |
|
172 // |
|
173 void CFlexTimerSession::NewAtTimer( const RMessage2& aMessage ) |
|
174 { |
|
175 |
|
176 // Check that we do not have a pending timer request |
|
177 if ( !iPendingTimeoutMsg.IsNull() ) |
|
178 { |
|
179 OstTraceExt2( TRACE_INTERNAL, |
|
180 CFLEXTIMERSESSION_ATPANIC, |
|
181 "CFlexTimerSession::NewAtTimer: Already pending; " |
|
182 "this=%x; msg=%x", |
|
183 ( TUint )this, |
|
184 ( TUint )iPendingTimeoutMsg.Handle() ); |
|
185 |
|
186 aMessage.Panic( KRFlexTimerPanicCat, |
|
187 EFlexTimerServerErrorPendingTimer ); |
|
188 return; |
|
189 } |
|
190 |
|
191 // Get interval from current time to the requested timestamp |
|
192 TTime refTime; |
|
193 refTime.HomeTime(); |
|
194 TTimeIntervalMicroSeconds interval; |
|
195 GetIntervalToMsgTime( aMessage, refTime, interval ); |
|
196 |
|
197 OstTraceExt2( TRACE_INTERNAL, |
|
198 CFLEXTIMERSESSION_ATTIMER, |
|
199 "CFlexTimerSession::NewAtTimer; this=%x; interval=%lld", |
|
200 ( TUint )this, |
|
201 interval.Int64() ); |
|
202 |
|
203 // Add the timer to engine |
|
204 DoAddTimer( aMessage, interval, ETrue ); |
|
205 |
|
206 } |
|
207 |
|
208 // -------------------------------------------------------------------------- |
|
209 // Handler function for starting AtUTC() -timer |
|
210 // -------------------------------------------------------------------------- |
|
211 // |
|
212 void CFlexTimerSession::NewAtUtcTimer( const RMessage2& aMessage ) |
|
213 { |
|
214 |
|
215 // Check that we do not have a pending timer request |
|
216 if ( !iPendingTimeoutMsg.IsNull() ) |
|
217 { |
|
218 OstTraceExt2( TRACE_INTERNAL, |
|
219 CFLEXTIMERSESSION_ATUTCPANIC, |
|
220 "CFlexTimerSession::NewAtUtcTimer: Already pending; " |
|
221 "this=%x; msg=%x", |
|
222 ( TUint )this, |
|
223 ( TUint )iPendingTimeoutMsg.Handle() ); |
|
224 |
|
225 aMessage.Panic( KRFlexTimerPanicCat, |
|
226 EFlexTimerServerErrorPendingTimer ); |
|
227 return; |
|
228 } |
|
229 |
|
230 TTime refTime; |
|
231 refTime.UniversalTime(); |
|
232 TTimeIntervalMicroSeconds interval; |
|
233 GetIntervalToMsgTime( aMessage, refTime, interval ); |
|
234 |
|
235 OstTraceExt2( |
|
236 TRACE_INTERNAL, |
|
237 CFLEXTIMERSESSION_ATUTCTIMER, |
|
238 "CFlexTimerSession::NewAtUtcTimer; this=%x; interval=%lld", |
|
239 ( TUint )this, |
|
240 interval.Int64() ); |
|
241 |
|
242 // Add the timer to engine |
|
243 DoAddTimer( aMessage, interval, ETrue ); |
|
244 |
|
245 } |
|
246 |
|
247 // -------------------------------------------------------------------------- |
|
248 // Handler function for starting After()-timer |
|
249 // -------------------------------------------------------------------------- |
|
250 // |
|
251 void CFlexTimerSession::NewAfterTimer( const RMessage2& aMessage ) |
|
252 { |
|
253 |
|
254 // Check that we do not have a pending timer request |
|
255 if ( !iPendingTimeoutMsg.IsNull() ) |
|
256 { |
|
257 OstTraceExt2( TRACE_INTERNAL, |
|
258 CFLEXTIMERSESSION_AFTERPANIC, |
|
259 "CFlexTimerSession::NewAfterTimer: Already pending; " |
|
260 "this=%x; msg=%x", |
|
261 ( TUint )this, |
|
262 ( TUint )iPendingTimeoutMsg.Handle() ); |
|
263 |
|
264 aMessage.Panic( KRFlexTimerPanicCat, |
|
265 EFlexTimerServerErrorPendingTimer ); |
|
266 return; |
|
267 } |
|
268 |
|
269 TInt64 timeStamp = MAKE_TINT64( aMessage.Int1(), aMessage.Int0() ); |
|
270 TTimeIntervalMicroSeconds interval( timeStamp ); |
|
271 |
|
272 OstTraceExt2( |
|
273 TRACE_INTERNAL, |
|
274 CFLEXTIMERSESSION_AFTERTIMER, |
|
275 "CFlexTimerSession::NewAfterTimer; this=%x; interval=%llu", |
|
276 ( TUint )this, |
|
277 interval.Int64() ); |
|
278 |
|
279 // Add the timer to engine, request cancellation if the secure time |
|
280 // is not available |
|
281 DoAddTimer( aMessage, interval, EFalse ); |
|
282 } |
|
283 |
|
284 // -------------------------------------------------------------------------- |
|
285 // Handler function for starting AfterTicks()-timer |
|
286 // -------------------------------------------------------------------------- |
|
287 // |
|
288 void CFlexTimerSession::NewAfterTicksTimer( const RMessage2& aMessage ) |
|
289 { |
|
290 |
|
291 // Check that we do not have a pending timer request |
|
292 if ( !iPendingTimeoutMsg.IsNull() ) |
|
293 { |
|
294 OstTraceExt2( |
|
295 TRACE_INTERNAL, |
|
296 CFLEXTIMERSESSION_AFTERTICKSPANIC, |
|
297 "CFlexTimerSession::NewAfterTicksTimer: Already pending; " |
|
298 "this=%x; msg=%x", |
|
299 ( TUint )this, |
|
300 ( TUint )iPendingTimeoutMsg.Handle() ); |
|
301 |
|
302 aMessage.Panic( KRFlexTimerPanicCat, |
|
303 EFlexTimerServerErrorPendingTimer ); |
|
304 return; |
|
305 } |
|
306 |
|
307 // Get the tick period from HAL and convert ticks to microseconds |
|
308 TInt tickUs; |
|
309 HAL::Get( HAL::ESystemTickPeriod, tickUs ); |
|
310 |
|
311 TTimeIntervalMicroSeconds interval = |
|
312 static_cast<TInt64> ( aMessage.Int0() ) * tickUs; |
|
313 |
|
314 OstTraceExt2( |
|
315 TRACE_INTERNAL, |
|
316 CFLEXTIMERSESSION_AFTERTICKSTIMER, |
|
317 "CFlexTimerSession::NewAfterTicksTimer; this=%x; interval=%llu", |
|
318 ( TUint )this, |
|
319 interval.Int64() ); |
|
320 |
|
321 // Add the timer to engine |
|
322 DoAddTimer( aMessage, interval, EFalse ); |
|
323 } |
|
324 |
|
325 // -------------------------------------------------------------------------- |
|
326 // Handler function for cancelling running timer |
|
327 // -------------------------------------------------------------------------- |
|
328 // |
|
329 void CFlexTimerSession::CancelTimer( const RMessage2& aMessage ) |
|
330 { |
|
331 TInt ret; |
|
332 // Check that we have a pending timer request |
|
333 if ( iPendingTimeoutMsg.IsNull() ) |
|
334 { |
|
335 OstTrace1( |
|
336 TRACE_INTERNAL, |
|
337 CFLEXTIMERSESSION_CANCELERROR, |
|
338 "CFlexTimerSession::CancelTimer: no pending msg; this=%x", |
|
339 ( TUint )this ); |
|
340 ret = KErrNotFound; |
|
341 } |
|
342 else |
|
343 { |
|
344 ret = iService->CancelTimer( this ); |
|
345 OstTraceExt2( TRACE_INTERNAL, |
|
346 CFLEXTIMERSESSION_CANCEL, |
|
347 "CFlexTimerSession::CancelTimer; this=%x; ret=%d", |
|
348 ( TUint )this, |
|
349 ret ); |
|
350 |
|
351 // Complete pending message, this sets message pointer to NULL |
|
352 iPendingTimeoutMsg.Complete( KErrCancel ); |
|
353 } |
|
354 |
|
355 // Complete cancel message |
|
356 aMessage.Complete( ret ); |
|
357 } |
|
358 |
|
359 // -------------------------------------------------------------------------- |
|
360 // Handler function for configuring timer parameters |
|
361 // -------------------------------------------------------------------------- |
|
362 // |
|
363 void CFlexTimerSession::ConfigureParameters( const RMessage2& aMessage ) |
|
364 { |
|
365 TInt ret( KErrNone ); |
|
366 |
|
367 // Configuration is not allowed when there is a pending message |
|
368 if ( !iPendingTimeoutMsg.IsNull() ) |
|
369 { |
|
370 OstTrace1( TRACE_INTERNAL, |
|
371 CFLEXTIMERSESSION_CONFIGERROR, |
|
372 "CFlexTimerSession::ConfigureParameters: Timer pending; " |
|
373 "this=%x", |
|
374 ( TUint )this ); |
|
375 ret = KErrInUse; |
|
376 } |
|
377 else |
|
378 { |
|
379 TInt paramType( aMessage.Int0() ); |
|
380 OstTraceExt2( TRACE_INTERNAL, |
|
381 CFLEXTIMERSESSION_CONFIG, |
|
382 "CFlexTimerSession::ConfigureParameters; this=%x; " |
|
383 "paramType=%d", |
|
384 ( TUint )this, |
|
385 paramType ); |
|
386 |
|
387 switch ( paramType ) |
|
388 { |
|
389 case EConfigureRequestWindowSize: |
|
390 { |
|
391 TInt winLo = aMessage.Int1(); |
|
392 TInt winHi = aMessage.Int2(); |
|
393 |
|
394 iTimerWinSize = MAKE_TINT64( winHi, winLo ); |
|
395 iUseDefaultWin = EFalse; |
|
396 |
|
397 OstTraceExt1( TRACE_INTERNAL, |
|
398 CFLEXTIMERSESSION_CONFIGWIN, |
|
399 "CFlexTimerSession::ConfigureParameters; " |
|
400 "iTimerWinSize=%lld", |
|
401 iTimerWinSize.Int64() ); |
|
402 |
|
403 if ( iTimerWinSize.Int64() < 0 || |
|
404 iTimerWinSize.Int64() > KFlexTimerMaxTimerLength ) |
|
405 { |
|
406 aMessage.Panic( KRFlexTimerPanicCat, |
|
407 EFlexTimerServerIllegalTimerValue ); |
|
408 // Return after panicing the client -- completing the |
|
409 // message afterwards panics the server with USER 70. |
|
410 return; |
|
411 } |
|
412 break; |
|
413 } |
|
414 default: |
|
415 OstTrace0( TRACE_INTERNAL, |
|
416 CFLEXTIMERSESSION_CONFIGUNKNOWN, |
|
417 "CFlexTimerSession::ConfigureParameters: " |
|
418 "ERROR - Invalid parameter type" ); |
|
419 ret = KErrNotSupported; |
|
420 break; |
|
421 } |
|
422 } |
|
423 aMessage.Complete( ret ); |
|
424 } |
|
425 |
|
426 // -------------------------------------------------------------------------- |
|
427 // Function for adding timer to engine and handling its return value |
|
428 // -------------------------------------------------------------------------- |
|
429 // |
|
430 void CFlexTimerSession::DoAddTimer( const RMessage2& aMessage, |
|
431 TTimeIntervalMicroSeconds& aWinEnd, |
|
432 TBool aRequestAbort ) |
|
433 { |
|
434 OstTraceExt4( TRACE_INTERNAL, |
|
435 CFLEXTIMERSESSION_ADDTIMER, |
|
436 "CFlexTimerSession::DoAddTimer; this=%x; msg=%x; aWinEnd=%llu;" |
|
437 " aRequestAbort=%d", |
|
438 ( TUint )this, |
|
439 ( TUint )aMessage.Handle(), |
|
440 aWinEnd.Int64(), |
|
441 aRequestAbort ); |
|
442 |
|
443 // Check that the timer has valid values. |
|
444 if ( aWinEnd.Int64() < 0 || aWinEnd.Int64() > KFlexTimerMaxTimerLength) |
|
445 { |
|
446 OstTraceExt4( TRACE_INTERNAL, |
|
447 CFLEXTIMERSESSION_DOADDTIMER, |
|
448 "CFlexTimerSession::DoAddTimer;Invalid parameters " |
|
449 "- panicing client;this=%x;aMessage=%x;aWinEnd=%llu;" |
|
450 "aRequestAbort=%d", |
|
451 ( TUint )this, |
|
452 ( TUint )aMessage.Handle(), |
|
453 aWinEnd.Int64(), |
|
454 aRequestAbort ); |
|
455 aMessage.Panic( KRFlexTimerPanicCat, |
|
456 EFlexTimerServerIllegalTimerValue ); |
|
457 return; |
|
458 } |
|
459 |
|
460 TTimeIntervalMicroSeconds winStart; |
|
461 TTimeIntervalMicroSeconds window = iTimerWinSize; |
|
462 |
|
463 if ( iUseDefaultWin ) |
|
464 { |
|
465 window = static_cast<TInt64> ( static_cast<TReal64> ( aWinEnd.Int64() ) |
|
466 * KDefaultWindowMultiplier ); |
|
467 } |
|
468 |
|
469 winStart = aWinEnd.Int64() - window.Int64(); |
|
470 |
|
471 // Store pending message. Not completed until timer expires. |
|
472 // Note that in case of zero or negative timer value, message can |
|
473 // be completed through Timeout() even before AddTimer returns. This |
|
474 // implementation saves some checks and timer stopping/starting in engine. |
|
475 iPendingTimeoutMsg = aMessage; |
|
476 |
|
477 // Add timer to engine |
|
478 TInt ret = iService->AddTimer( winStart, aWinEnd, aRequestAbort, this ); |
|
479 |
|
480 if ( KErrNone != ret ) |
|
481 { |
|
482 // Failed, pass error code to client side |
|
483 OstTraceExt2( TRACE_INTERNAL, |
|
484 CFLEXTIMERSESSION_ADDERROR, |
|
485 "CFlexTimerSession::DoAddTimer: Error; this=%x, ret=%d", |
|
486 ( TUint )this, |
|
487 ret ); |
|
488 // Complete pending message, this sets message pointer to NULL |
|
489 iPendingTimeoutMsg.Complete( ret ); |
|
490 } |
|
491 } |
|
492 |
|
493 // -------------------------------------------------------------------------- |
|
494 // From CSession2 |
|
495 // Function for handling unintentional termination of the client |
|
496 // -------------------------------------------------------------------------- |
|
497 // |
|
498 void CFlexTimerSession::Disconnect( const RMessage2 &aMessage ) |
|
499 { |
|
500 // The client of this session has died. |
|
501 |
|
502 // Remove timer from engine. |
|
503 iService->CancelTimer( this ); |
|
504 |
|
505 // Disconnect() must end with a call to the base class implementation, |
|
506 // which will delete the session object and complete the disconnect |
|
507 // message. |
|
508 CSession2::Disconnect( aMessage ); |
|
509 } |
|