diff -r 000000000000 -r 164170e6151a wim/Scard/src/ScardChannelManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wim/Scard/src/ScardChannelManager.cpp Tue Jan 26 15:20:08 2010 +0200 @@ -0,0 +1,513 @@ +/* +* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: Handles individual channels on a singular SC (which equals one +* Smart Card reader handler). Can be queried for information +* about channels, controls traffic etc. +* +*/ + + + +// INCLUDE FILES +#include "ScardAccessControl.h" +#include "ScardBase.h" +#include "ScardChannelManager.h" +#include "ScardMessageStack.h" +#include "WimTrace.h" + + +// MACROS +// Assert that a session is on a channel +#define __ASSERT_SESSION( a, b ) if ( !SessionIsOnChannel( (a), (b) ) )\ + User::Leave( KScServerErrIllegalChannel ); +// Assert that the channel number is legal, or leave +#define __ASSERT_CHANNEL_LEAVE( a ) if ( (a) < 0 || (a) > KMaxChannels - 1 )\ + User::Leave( KScServerErrIllegalChannel ) + +// Assert that the channel number is legal, or return false +#define __ASSERT_CHANNEL_FALSE( a ) if ( (a) < 0 || (a) > KMaxChannels - 1 )\ + return EFalse + +// LOCAL FUNCTION PROTOTYPES +TUint8 pow2( const TInt aPower ); + + +// ============================= LOCAL FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// pow2 +// Returns: 2 powered to given value +// ----------------------------------------------------------------------------- +// + +TUint8 pow2( const TInt aPower ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::pow2|Begin")); + TUint8 result = 1; + for ( TInt i = 0; i < aPower; i++ ) + { + result *= 2; + } + return result; + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CScardChannelManager::CScardChannelManager +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CScardChannelManager::CScardChannelManager() + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::CScardChannelManager|Begin")); + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CScardChannelManager::ConstructL() + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ConstructL|Begin")); + iChannels = new( ELeave ) CArrayPtrFlat >( 1 ); + + // Channel 0 is always open + CArrayFixFlat* zeroChannel = new( ELeave ) CArrayFixFlat( 1 ); + CleanupStack::PushL( zeroChannel ); + iChannels->AppendL( zeroChannel ); + + // others are opened as the need arises + iChannels->AppendL( static_cast< CArrayFixFlat* >( NULL ) ); + iChannels->AppendL( static_cast< CArrayFixFlat* >( NULL ) ); + iChannels->AppendL( static_cast< CArrayFixFlat* >( NULL ) ); + + iMessageStack = CScardMessageStack::NewL(); + CleanupStack::Pop( zeroChannel ); + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CScardChannelManager* CScardChannelManager::NewL() + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::NewL|Begin")); + CScardChannelManager* self = new( ELeave ) CScardChannelManager; + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + + +// Destructor +CScardChannelManager::~CScardChannelManager() + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::~CScardChannelManager|Begin")); + if ( iChannels ) + { + iChannels->ResetAndDestroy(); + } + delete iChannels; + delete iMessageStack; + } + + +// ----------------------------------------------------------------------------- +// CScardChannelManager::ChannelStatus +// Give available channels +// Returns two-byte parameter telling: +// b0 - Channel 0 open (should always be set) +// b1 - Channel 0 reserved +// b2 - Channel 1 open +// b3 - Channel 1 reserved +// ... +// b7 - Channel 3 open +// b8 - Channel 3 reserved +// +// b9-b15 Maximum number of channels available (at the moment always 4) +// +// ----------------------------------------------------------------------------- +// +TUint16 CScardChannelManager::ChannelStatus() + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ChannelStatus|Begin")); + TUint16 free( 0 ); + free = static_cast< TUint16 >( 0x04 << 8 ); // 4 channels available + + // Get the status for each individual channel, and set the according bits + for ( TInt i = 0; i < KMaxChannels; i++ ) + { + if ( iChannels->At( i ) ) + { + free |= pow2( 2 * i ); + } + if ( iReserverID[i] ) + { + free |= pow2( 2 * i + 1 ); + } + } + return free; + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::SessionIsOnChannel +// Does the session have permission to the channel. +// ----------------------------------------------------------------------------- +// +TBool CScardChannelManager::SessionIsOnChannel( + const TInt8 aChannel, + const TInt aSessionID ) const + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::SessionIsOnChannel|Begin")); + __ASSERT_CHANNEL_FALSE( aChannel ); + if ( iChannels->At( aChannel ) ) + { + TInt count = iChannels->At( aChannel )->Count(); + for ( TInt j( 0 ); j < count; j++ ) + { + if ( iChannels->At( aChannel )->At( j ) == aSessionID ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::SessionIsOnChannel|Permission granted")); + return ETrue; + } + } + } + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::SessionIsOnChannel|Permission denied")); + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::AddSessionToChannelL +// Give the session the right to use the channel +// ----------------------------------------------------------------------------- +// +TBool CScardChannelManager::AddSessionToChannelL( + const TInt8 aChannel, + const TInt aSessionID ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::AddSessionToChannelL|Begin")); + __ASSERT_CHANNEL_FALSE( aChannel ); + if ( !SessionIsOnChannel( aChannel, aSessionID ) ) + { + // if the channel is not yet opened... + if ( !iChannels->At( aChannel ) ) + { + CArrayFixFlat* channel = NULL; + channel = new( ELeave ) CArrayFixFlat( 1 ); + iChannels->At( aChannel ) = channel; + } + iChannels->At( aChannel )->AppendL( aSessionID ); + } + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::RemoveSessionL +// Remove session entries from the channel. +// ----------------------------------------------------------------------------- +// +TBool CScardChannelManager::RemoveSessionL( + const TInt8 aChannel, + const TInt aSessionID ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::RemoveSessionL|Begin")); + __ASSERT_CHANNEL_LEAVE( aChannel ); + if ( SessionIsOnChannel( aChannel, aSessionID ) ) + { + for ( TInt i( 0 ); i < iChannels->At( aChannel )->Count(); i++ ) + { + // remove the indivídual from the channel + if ( iChannels->At( aChannel )->At( i ) == aSessionID ) + { + iChannels->At( aChannel )->Delete( i ); + i = iChannels->At( aChannel )->Count(); // Stop loop + } + } + // if the channel is empty (except channel 0), delete it + if ( aChannel != 0 && !iChannels->At( aChannel )->Count() ) + { + delete iChannels->At( aChannel ); + iChannels->At( aChannel ) = NULL; + return EFalse; + } + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::PushMessageToBottomL +// Push message to bottom of message stack +// ----------------------------------------------------------------------------- +// +void CScardChannelManager::PushMessageToBottomL( + const TMessageHandle& aMessage ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::PushMessageToBottomL|Begin")); + __ASSERT_CHANNEL_LEAVE( aMessage.iChannel ); + __ASSERT_SESSION( aMessage.iChannel, aMessage.iSessionID ); + __ASSERT_MEMORY( iMessageStack->PushToBottom( aMessage ) ); + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::PushMessageToTopL +// Push message to top of message stack +// ----------------------------------------------------------------------------- +// +void CScardChannelManager::PushMessageToTopL( + const TMessageHandle& aMessage ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::PushMessageToTopL|Begin")); + __ASSERT_CHANNEL_LEAVE( aMessage.iChannel ); + __ASSERT_SESSION( aMessage.iChannel, aMessage.iSessionID ); + __ASSERT_MEMORY( iMessageStack->PushToTop( aMessage ) ); + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::NextMessageL +// Get the next available message from the stack (preserving +// the order of other messages) +// ----------------------------------------------------------------------------- +// +const TMessageHandle CScardChannelManager::NextMessageL() + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::NextMessage|Begin")); + TInt count = iMessageStack->Count(); + TInt index( 0 ); + while ( index < count ) + { + TMessageHandle tmp = iMessageStack->FromPositionL( index ); + + // If the channel is reserved (for someone else), + // put message back to wait + if ( iReserverID[tmp.iChannel] && iReserverID[tmp.iChannel] != + tmp.iSessionID ) + { + iMessageStack->PushToPositionL( index, tmp ); + index++; + } + else + { + return tmp; + } + } + TMessageHandle noMessage; + return noMessage; + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::MessageFromTop +// Get message from top of message stack +// ----------------------------------------------------------------------------- +// +const TMessageHandle CScardChannelManager::MessageFromTop() + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::MessageFromTop|Begin")); + return iMessageStack->FromTop(); + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::CancelAll +// Cancel all messages from the stack that match the criteria +// ----------------------------------------------------------------------------- +// +void CScardChannelManager::CancelAll( const TInt aSessionID ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::CancelAll|Begin")); + if ( aSessionID == EAccessMasterID ) + { + iMessageStack->CancelAll( KScErrCancelled ); + } + else + { + iMessageStack->CancelAll( aSessionID, KScErrCancelled ); + } + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::ChannelReservedL +// Return reserver session of the channel +// ----------------------------------------------------------------------------- +// +TInt CScardChannelManager::ChannelReservedL( + const TInt8 aChannel ) const + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ChannelReservedL|Begin")); + __ASSERT_CHANNEL_LEAVE( aChannel ); + return iReserverID[aChannel]; + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::FreeChannelL +// Free channel +// ----------------------------------------------------------------------------- +// +void CScardChannelManager::FreeChannelL( + const TInt8 aChannel, + const TInt aSessionID ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::FreeChannelL|Begin")); + __ASSERT_CHANNEL_LEAVE( aChannel ); + if ( iReserverID[aChannel] == aSessionID ) + { + iReserverID[aChannel] = ENoSession; + } + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::FreeChannels +// Free all channels this session has reserved +// ----------------------------------------------------------------------------- +// +void CScardChannelManager::FreeChannels( const TInt aSessionID ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::FreeChannels|Begin")); + for ( TInt i( 0 ); i < KMaxChannels; i++ ) + { + if ( iReserverID[i] == aSessionID ) + { + iReserverID[i] = 0; + } + } + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::ChannelOpenedYet +// Return ETrue if channel is allready opened, otherwise return EFalse +// ----------------------------------------------------------------------------- +// +TBool CScardChannelManager::ChannelOpenedYet( const TInt8 aChannel ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ChannelOpenedYet|Begin")); + __ASSERT_CHANNEL_LEAVE( aChannel ); + if ( iChannels->At( aChannel ) ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ChannelOpenedYet|True")); + return ETrue; + } + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ChannelOpenedYet|False")); + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::UnreservedLogicalChannel +// First channel w/o a reservation +// ----------------------------------------------------------------------------- +// +TInt8 CScardChannelManager::UnreservedLogicalChannel() const + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::UnreservedLogicalChannel|Begin")); + for ( TInt8 i( 0 ); i < KMaxChannels; i++ ) + { + if ( !iReserverID[i] ) + { + return i; + } + } + return -1; + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::NextMessageFromFree +// Return next message from free +// ----------------------------------------------------------------------------- +// +const TMessageHandle CScardChannelManager::NextMessageFromFree( + const TInt8 aChannel) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::NextMessageFromFree|Begin")); + TMessageHandle tmp = iMessageStack->NextReservation( aChannel ); + if ( tmp.iSessionID != ENoSession ) + { + return tmp; + } + + TMessageHandle nextMessage; + + TRAPD( err, nextMessage = NextMessageL() ); + + if ( err != KErrNone ) + { + TMessageHandle noMessage; + return noMessage; + } + else + { + return nextMessage; + } + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::ValidateChannelL +// Channel is legal & open for this session +// ----------------------------------------------------------------------------- +// +void CScardChannelManager::ValidateChannelL( + const TInt8 aChannel, + const TInt aSessionID ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::ValidateChannelL|Begin")); + __ASSERT_CHANNEL_LEAVE( aChannel ); + if ( iChannels->At( aChannel ) ) + { + for ( TInt j( 0 ); j < iChannels->At( aChannel )->Count(); j++ ) + { + if ( iChannels->At( aChannel )->At( j ) == aSessionID ) + { + return; + } + } + } + _WIMTRACE(_L("WIM|Scard|CScardSession::ValidateChannelL|Leave")); + User::Leave( KScErrNotFound ); + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::CardRemoved +// Card removed. Clear all card-spesific data & transmissions +// ----------------------------------------------------------------------------- +// +void CScardChannelManager::CardRemoved() + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::CardRemoved|Begin")); + // Cancel all card operations + iMessageStack->CancelCardOperations(); + + // remove all session entries from channel registers + for ( TInt i( 1 ); i < iChannels->Count(); i++ ) + { + delete iChannels->At( i ); + iChannels->At( i ) = static_cast< CArrayFixFlat* >( NULL ); + iReserverID[i] = ENoSession; + } + } + +// ----------------------------------------------------------------------------- +// CScardChannelManager::CancelByTimeOut +// Cancel messages by timeout +// ----------------------------------------------------------------------------- +// +void CScardChannelManager::CancelByTimeOut( CScardCommandTimer* aTimer ) + { + _WIMTRACE(_L("WIM|Scard|CScardChannelManager::CancelByTimeOut|Begin")); + iMessageStack->CancelByTimeOut( aTimer ); + } + +// End of File