|
1 /* |
|
2 * Copyright (c) 2003 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: Handles individual channels on a singular SC (which equals one |
|
15 * Smart Card reader handler). Can be queried for information |
|
16 * about channels, controls traffic etc. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 // INCLUDE FILES |
|
23 #include "ScardAccessControl.h" |
|
24 #include "ScardBase.h" |
|
25 #include "ScardChannelManager.h" |
|
26 #include "ScardMessageStack.h" |
|
27 #include "WimTrace.h" |
|
28 |
|
29 |
|
30 // MACROS |
|
31 // Assert that a session is on a channel |
|
32 #define __ASSERT_SESSION( a, b ) if ( !SessionIsOnChannel( (a), (b) ) )\ |
|
33 User::Leave( KScServerErrIllegalChannel ); |
|
34 // Assert that the channel number is legal, or leave |
|
35 #define __ASSERT_CHANNEL_LEAVE( a ) if ( (a) < 0 || (a) > KMaxChannels - 1 )\ |
|
36 User::Leave( KScServerErrIllegalChannel ) |
|
37 |
|
38 // Assert that the channel number is legal, or return false |
|
39 #define __ASSERT_CHANNEL_FALSE( a ) if ( (a) < 0 || (a) > KMaxChannels - 1 )\ |
|
40 return EFalse |
|
41 |
|
42 // LOCAL FUNCTION PROTOTYPES |
|
43 TUint8 pow2( const TInt aPower ); |
|
44 |
|
45 |
|
46 // ============================= LOCAL FUNCTIONS =============================== |
|
47 |
|
48 // ----------------------------------------------------------------------------- |
|
49 // pow2 |
|
50 // Returns: 2 powered to given value |
|
51 // ----------------------------------------------------------------------------- |
|
52 // |
|
53 |
|
54 TUint8 pow2( const TInt aPower ) |
|
55 { |
|
56 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::pow2|Begin")); |
|
57 TUint8 result = 1; |
|
58 for ( TInt i = 0; i < aPower; i++ ) |
|
59 { |
|
60 result *= 2; |
|
61 } |
|
62 return result; |
|
63 } |
|
64 |
|
65 // ============================ MEMBER FUNCTIONS =============================== |
|
66 |
|
67 // ----------------------------------------------------------------------------- |
|
68 // CScardChannelManager::CScardChannelManager |
|
69 // C++ default constructor can NOT contain any code, that |
|
70 // might leave. |
|
71 // ----------------------------------------------------------------------------- |
|
72 // |
|
73 CScardChannelManager::CScardChannelManager() |
|
74 { |
|
75 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::CScardChannelManager|Begin")); |
|
76 } |
|
77 |
|
78 // ----------------------------------------------------------------------------- |
|
79 // CScardChannelManager::ConstructL |
|
80 // Symbian 2nd phase constructor can leave. |
|
81 // ----------------------------------------------------------------------------- |
|
82 // |
|
83 void CScardChannelManager::ConstructL() |
|
84 { |
|
85 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ConstructL|Begin")); |
|
86 iChannels = new( ELeave ) CArrayPtrFlat<CArrayFixFlat<TInt> >( 1 ); |
|
87 |
|
88 // Channel 0 is always open |
|
89 CArrayFixFlat<TInt>* zeroChannel = new( ELeave ) CArrayFixFlat<TInt>( 1 ); |
|
90 CleanupStack::PushL( zeroChannel ); |
|
91 iChannels->AppendL( zeroChannel ); |
|
92 |
|
93 // others are opened as the need arises |
|
94 iChannels->AppendL( static_cast< CArrayFixFlat<TInt>* >( NULL ) ); |
|
95 iChannels->AppendL( static_cast< CArrayFixFlat<TInt>* >( NULL ) ); |
|
96 iChannels->AppendL( static_cast< CArrayFixFlat<TInt>* >( NULL ) ); |
|
97 |
|
98 iMessageStack = CScardMessageStack::NewL(); |
|
99 CleanupStack::Pop( zeroChannel ); |
|
100 } |
|
101 |
|
102 // ----------------------------------------------------------------------------- |
|
103 // CScardChannelManager::NewL |
|
104 // Two-phased constructor. |
|
105 // ----------------------------------------------------------------------------- |
|
106 // |
|
107 CScardChannelManager* CScardChannelManager::NewL() |
|
108 { |
|
109 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::NewL|Begin")); |
|
110 CScardChannelManager* self = new( ELeave ) CScardChannelManager; |
|
111 |
|
112 CleanupStack::PushL( self ); |
|
113 self->ConstructL(); |
|
114 CleanupStack::Pop( self ); |
|
115 |
|
116 return self; |
|
117 } |
|
118 |
|
119 |
|
120 // Destructor |
|
121 CScardChannelManager::~CScardChannelManager() |
|
122 { |
|
123 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::~CScardChannelManager|Begin")); |
|
124 if ( iChannels ) |
|
125 { |
|
126 iChannels->ResetAndDestroy(); |
|
127 } |
|
128 delete iChannels; |
|
129 delete iMessageStack; |
|
130 } |
|
131 |
|
132 |
|
133 // ----------------------------------------------------------------------------- |
|
134 // CScardChannelManager::ChannelStatus |
|
135 // Give available channels |
|
136 // Returns two-byte parameter telling: |
|
137 // b0 - Channel 0 open (should always be set) |
|
138 // b1 - Channel 0 reserved |
|
139 // b2 - Channel 1 open |
|
140 // b3 - Channel 1 reserved |
|
141 // ... |
|
142 // b7 - Channel 3 open |
|
143 // b8 - Channel 3 reserved |
|
144 // |
|
145 // b9-b15 Maximum number of channels available (at the moment always 4) |
|
146 // |
|
147 // ----------------------------------------------------------------------------- |
|
148 // |
|
149 TUint16 CScardChannelManager::ChannelStatus() |
|
150 { |
|
151 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ChannelStatus|Begin")); |
|
152 TUint16 free( 0 ); |
|
153 free = static_cast< TUint16 >( 0x04 << 8 ); // 4 channels available |
|
154 |
|
155 // Get the status for each individual channel, and set the according bits |
|
156 for ( TInt i = 0; i < KMaxChannels; i++ ) |
|
157 { |
|
158 if ( iChannels->At( i ) ) |
|
159 { |
|
160 free |= pow2( 2 * i ); |
|
161 } |
|
162 if ( iReserverID[i] ) |
|
163 { |
|
164 free |= pow2( 2 * i + 1 ); |
|
165 } |
|
166 } |
|
167 return free; |
|
168 } |
|
169 |
|
170 // ----------------------------------------------------------------------------- |
|
171 // CScardChannelManager::SessionIsOnChannel |
|
172 // Does the session have permission to the channel. |
|
173 // ----------------------------------------------------------------------------- |
|
174 // |
|
175 TBool CScardChannelManager::SessionIsOnChannel( |
|
176 const TInt8 aChannel, |
|
177 const TInt aSessionID ) const |
|
178 { |
|
179 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::SessionIsOnChannel|Begin")); |
|
180 __ASSERT_CHANNEL_FALSE( aChannel ); |
|
181 if ( iChannels->At( aChannel ) ) |
|
182 { |
|
183 TInt count = iChannels->At( aChannel )->Count(); |
|
184 for ( TInt j( 0 ); j < count; j++ ) |
|
185 { |
|
186 if ( iChannels->At( aChannel )->At( j ) == aSessionID ) |
|
187 { |
|
188 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::SessionIsOnChannel|Permission granted")); |
|
189 return ETrue; |
|
190 } |
|
191 } |
|
192 } |
|
193 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::SessionIsOnChannel|Permission denied")); |
|
194 return EFalse; |
|
195 } |
|
196 |
|
197 // ----------------------------------------------------------------------------- |
|
198 // CScardChannelManager::AddSessionToChannelL |
|
199 // Give the session the right to use the channel |
|
200 // ----------------------------------------------------------------------------- |
|
201 // |
|
202 TBool CScardChannelManager::AddSessionToChannelL( |
|
203 const TInt8 aChannel, |
|
204 const TInt aSessionID ) |
|
205 { |
|
206 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::AddSessionToChannelL|Begin")); |
|
207 __ASSERT_CHANNEL_FALSE( aChannel ); |
|
208 if ( !SessionIsOnChannel( aChannel, aSessionID ) ) |
|
209 { |
|
210 // if the channel is not yet opened... |
|
211 if ( !iChannels->At( aChannel ) ) |
|
212 { |
|
213 CArrayFixFlat<TInt>* channel = NULL; |
|
214 channel = new( ELeave ) CArrayFixFlat<TInt>( 1 ); |
|
215 iChannels->At( aChannel ) = channel; |
|
216 } |
|
217 iChannels->At( aChannel )->AppendL( aSessionID ); |
|
218 } |
|
219 return ETrue; |
|
220 } |
|
221 |
|
222 // ----------------------------------------------------------------------------- |
|
223 // CScardChannelManager::RemoveSessionL |
|
224 // Remove session entries from the channel. |
|
225 // ----------------------------------------------------------------------------- |
|
226 // |
|
227 TBool CScardChannelManager::RemoveSessionL( |
|
228 const TInt8 aChannel, |
|
229 const TInt aSessionID ) |
|
230 { |
|
231 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::RemoveSessionL|Begin")); |
|
232 __ASSERT_CHANNEL_LEAVE( aChannel ); |
|
233 if ( SessionIsOnChannel( aChannel, aSessionID ) ) |
|
234 { |
|
235 for ( TInt i( 0 ); i < iChannels->At( aChannel )->Count(); i++ ) |
|
236 { |
|
237 // remove the indivídual from the channel |
|
238 if ( iChannels->At( aChannel )->At( i ) == aSessionID ) |
|
239 { |
|
240 iChannels->At( aChannel )->Delete( i ); |
|
241 i = iChannels->At( aChannel )->Count(); // Stop loop |
|
242 } |
|
243 } |
|
244 // if the channel is empty (except channel 0), delete it |
|
245 if ( aChannel != 0 && !iChannels->At( aChannel )->Count() ) |
|
246 { |
|
247 delete iChannels->At( aChannel ); |
|
248 iChannels->At( aChannel ) = NULL; |
|
249 return EFalse; |
|
250 } |
|
251 } |
|
252 return EFalse; |
|
253 } |
|
254 |
|
255 // ----------------------------------------------------------------------------- |
|
256 // CScardChannelManager::PushMessageToBottomL |
|
257 // Push message to bottom of message stack |
|
258 // ----------------------------------------------------------------------------- |
|
259 // |
|
260 void CScardChannelManager::PushMessageToBottomL( |
|
261 const TMessageHandle& aMessage ) |
|
262 { |
|
263 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::PushMessageToBottomL|Begin")); |
|
264 __ASSERT_CHANNEL_LEAVE( aMessage.iChannel ); |
|
265 __ASSERT_SESSION( aMessage.iChannel, aMessage.iSessionID ); |
|
266 __ASSERT_MEMORY( iMessageStack->PushToBottom( aMessage ) ); |
|
267 } |
|
268 |
|
269 // ----------------------------------------------------------------------------- |
|
270 // CScardChannelManager::PushMessageToTopL |
|
271 // Push message to top of message stack |
|
272 // ----------------------------------------------------------------------------- |
|
273 // |
|
274 void CScardChannelManager::PushMessageToTopL( |
|
275 const TMessageHandle& aMessage ) |
|
276 { |
|
277 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::PushMessageToTopL|Begin")); |
|
278 __ASSERT_CHANNEL_LEAVE( aMessage.iChannel ); |
|
279 __ASSERT_SESSION( aMessage.iChannel, aMessage.iSessionID ); |
|
280 __ASSERT_MEMORY( iMessageStack->PushToTop( aMessage ) ); |
|
281 } |
|
282 |
|
283 // ----------------------------------------------------------------------------- |
|
284 // CScardChannelManager::NextMessageL |
|
285 // Get the next available message from the stack (preserving |
|
286 // the order of other messages) |
|
287 // ----------------------------------------------------------------------------- |
|
288 // |
|
289 const TMessageHandle CScardChannelManager::NextMessageL() |
|
290 { |
|
291 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::NextMessage|Begin")); |
|
292 TInt count = iMessageStack->Count(); |
|
293 TInt index( 0 ); |
|
294 while ( index < count ) |
|
295 { |
|
296 TMessageHandle tmp = iMessageStack->FromPositionL( index ); |
|
297 |
|
298 // If the channel is reserved (for someone else), |
|
299 // put message back to wait |
|
300 if ( iReserverID[tmp.iChannel] && iReserverID[tmp.iChannel] != |
|
301 tmp.iSessionID ) |
|
302 { |
|
303 iMessageStack->PushToPositionL( index, tmp ); |
|
304 index++; |
|
305 } |
|
306 else |
|
307 { |
|
308 return tmp; |
|
309 } |
|
310 } |
|
311 TMessageHandle noMessage; |
|
312 return noMessage; |
|
313 } |
|
314 |
|
315 // ----------------------------------------------------------------------------- |
|
316 // CScardChannelManager::MessageFromTop |
|
317 // Get message from top of message stack |
|
318 // ----------------------------------------------------------------------------- |
|
319 // |
|
320 const TMessageHandle CScardChannelManager::MessageFromTop() |
|
321 { |
|
322 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::MessageFromTop|Begin")); |
|
323 return iMessageStack->FromTop(); |
|
324 } |
|
325 |
|
326 // ----------------------------------------------------------------------------- |
|
327 // CScardChannelManager::CancelAll |
|
328 // Cancel all messages from the stack that match the criteria |
|
329 // ----------------------------------------------------------------------------- |
|
330 // |
|
331 void CScardChannelManager::CancelAll( const TInt aSessionID ) |
|
332 { |
|
333 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::CancelAll|Begin")); |
|
334 if ( aSessionID == EAccessMasterID ) |
|
335 { |
|
336 iMessageStack->CancelAll( KScErrCancelled ); |
|
337 } |
|
338 else |
|
339 { |
|
340 iMessageStack->CancelAll( aSessionID, KScErrCancelled ); |
|
341 } |
|
342 } |
|
343 |
|
344 // ----------------------------------------------------------------------------- |
|
345 // CScardChannelManager::ChannelReservedL |
|
346 // Return reserver session of the channel |
|
347 // ----------------------------------------------------------------------------- |
|
348 // |
|
349 TInt CScardChannelManager::ChannelReservedL( |
|
350 const TInt8 aChannel ) const |
|
351 { |
|
352 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ChannelReservedL|Begin")); |
|
353 __ASSERT_CHANNEL_LEAVE( aChannel ); |
|
354 return iReserverID[aChannel]; |
|
355 } |
|
356 |
|
357 // ----------------------------------------------------------------------------- |
|
358 // CScardChannelManager::FreeChannelL |
|
359 // Free channel |
|
360 // ----------------------------------------------------------------------------- |
|
361 // |
|
362 void CScardChannelManager::FreeChannelL( |
|
363 const TInt8 aChannel, |
|
364 const TInt aSessionID ) |
|
365 { |
|
366 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::FreeChannelL|Begin")); |
|
367 __ASSERT_CHANNEL_LEAVE( aChannel ); |
|
368 if ( iReserverID[aChannel] == aSessionID ) |
|
369 { |
|
370 iReserverID[aChannel] = ENoSession; |
|
371 } |
|
372 } |
|
373 |
|
374 // ----------------------------------------------------------------------------- |
|
375 // CScardChannelManager::FreeChannels |
|
376 // Free all channels this session has reserved |
|
377 // ----------------------------------------------------------------------------- |
|
378 // |
|
379 void CScardChannelManager::FreeChannels( const TInt aSessionID ) |
|
380 { |
|
381 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::FreeChannels|Begin")); |
|
382 for ( TInt i( 0 ); i < KMaxChannels; i++ ) |
|
383 { |
|
384 if ( iReserverID[i] == aSessionID ) |
|
385 { |
|
386 iReserverID[i] = 0; |
|
387 } |
|
388 } |
|
389 } |
|
390 |
|
391 // ----------------------------------------------------------------------------- |
|
392 // CScardChannelManager::ChannelOpenedYet |
|
393 // Return ETrue if channel is allready opened, otherwise return EFalse |
|
394 // ----------------------------------------------------------------------------- |
|
395 // |
|
396 TBool CScardChannelManager::ChannelOpenedYet( const TInt8 aChannel ) |
|
397 { |
|
398 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ChannelOpenedYet|Begin")); |
|
399 __ASSERT_CHANNEL_LEAVE( aChannel ); |
|
400 if ( iChannels->At( aChannel ) ) |
|
401 { |
|
402 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ChannelOpenedYet|True")); |
|
403 return ETrue; |
|
404 } |
|
405 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ChannelOpenedYet|False")); |
|
406 return EFalse; |
|
407 } |
|
408 |
|
409 // ----------------------------------------------------------------------------- |
|
410 // CScardChannelManager::UnreservedLogicalChannel |
|
411 // First channel w/o a reservation |
|
412 // ----------------------------------------------------------------------------- |
|
413 // |
|
414 TInt8 CScardChannelManager::UnreservedLogicalChannel() const |
|
415 { |
|
416 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::UnreservedLogicalChannel|Begin")); |
|
417 for ( TInt8 i( 0 ); i < KMaxChannels; i++ ) |
|
418 { |
|
419 if ( !iReserverID[i] ) |
|
420 { |
|
421 return i; |
|
422 } |
|
423 } |
|
424 return -1; |
|
425 } |
|
426 |
|
427 // ----------------------------------------------------------------------------- |
|
428 // CScardChannelManager::NextMessageFromFree |
|
429 // Return next message from free |
|
430 // ----------------------------------------------------------------------------- |
|
431 // |
|
432 const TMessageHandle CScardChannelManager::NextMessageFromFree( |
|
433 const TInt8 aChannel) |
|
434 { |
|
435 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::NextMessageFromFree|Begin")); |
|
436 TMessageHandle tmp = iMessageStack->NextReservation( aChannel ); |
|
437 if ( tmp.iSessionID != ENoSession ) |
|
438 { |
|
439 return tmp; |
|
440 } |
|
441 |
|
442 TMessageHandle nextMessage; |
|
443 |
|
444 TRAPD( err, nextMessage = NextMessageL() ); |
|
445 |
|
446 if ( err != KErrNone ) |
|
447 { |
|
448 TMessageHandle noMessage; |
|
449 return noMessage; |
|
450 } |
|
451 else |
|
452 { |
|
453 return nextMessage; |
|
454 } |
|
455 } |
|
456 |
|
457 // ----------------------------------------------------------------------------- |
|
458 // CScardChannelManager::ValidateChannelL |
|
459 // Channel is legal & open for this session |
|
460 // ----------------------------------------------------------------------------- |
|
461 // |
|
462 void CScardChannelManager::ValidateChannelL( |
|
463 const TInt8 aChannel, |
|
464 const TInt aSessionID ) |
|
465 { |
|
466 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ValidateChannelL|Begin")); |
|
467 __ASSERT_CHANNEL_LEAVE( aChannel ); |
|
468 if ( iChannels->At( aChannel ) ) |
|
469 { |
|
470 for ( TInt j( 0 ); j < iChannels->At( aChannel )->Count(); j++ ) |
|
471 { |
|
472 if ( iChannels->At( aChannel )->At( j ) == aSessionID ) |
|
473 { |
|
474 return; |
|
475 } |
|
476 } |
|
477 } |
|
478 _WIMTRACE(_L("WIM|Scard|CScardSession::ValidateChannelL|Leave")); |
|
479 User::Leave( KScErrNotFound ); |
|
480 } |
|
481 |
|
482 // ----------------------------------------------------------------------------- |
|
483 // CScardChannelManager::CardRemoved |
|
484 // Card removed. Clear all card-spesific data & transmissions |
|
485 // ----------------------------------------------------------------------------- |
|
486 // |
|
487 void CScardChannelManager::CardRemoved() |
|
488 { |
|
489 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::CardRemoved|Begin")); |
|
490 // Cancel all card operations |
|
491 iMessageStack->CancelCardOperations(); |
|
492 |
|
493 // remove all session entries from channel registers |
|
494 for ( TInt i( 1 ); i < iChannels->Count(); i++ ) |
|
495 { |
|
496 delete iChannels->At( i ); |
|
497 iChannels->At( i ) = static_cast< CArrayFixFlat<TInt>* >( NULL ); |
|
498 iReserverID[i] = ENoSession; |
|
499 } |
|
500 } |
|
501 |
|
502 // ----------------------------------------------------------------------------- |
|
503 // CScardChannelManager::CancelByTimeOut |
|
504 // Cancel messages by timeout |
|
505 // ----------------------------------------------------------------------------- |
|
506 // |
|
507 void CScardChannelManager::CancelByTimeOut( CScardCommandTimer* aTimer ) |
|
508 { |
|
509 _WIMTRACE(_L("WIM|Scard|CScardChannelManager::CancelByTimeOut|Begin")); |
|
510 iMessageStack->CancelByTimeOut( aTimer ); |
|
511 } |
|
512 |
|
513 // End of File |