--- /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<CArrayFixFlat<TInt> >( 1 );
+
+ // Channel 0 is always open
+ CArrayFixFlat<TInt>* zeroChannel = new( ELeave ) CArrayFixFlat<TInt>( 1 );
+ CleanupStack::PushL( zeroChannel );
+ iChannels->AppendL( zeroChannel );
+
+ // others are opened as the need arises
+ iChannels->AppendL( static_cast< CArrayFixFlat<TInt>* >( NULL ) );
+ iChannels->AppendL( static_cast< CArrayFixFlat<TInt>* >( NULL ) );
+ iChannels->AppendL( static_cast< CArrayFixFlat<TInt>* >( 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<TInt>* channel = NULL;
+ channel = new( ELeave ) CArrayFixFlat<TInt>( 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<TInt>* >( 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