/// <summary>
        /// Monitor a card reader device for card insertion and removal
        /// Use OnCardInserted+= and OnCardRemoved+= to establish the handlers
        /// </summary>
        /// <param name="reader">The reader name to monitor</param>
        protected override void RunCardDetection(String reader)
        {
            const long SCARD_S_SUCCESS = 0x00;  // for readability

            IntPtr hContext  = IntPtr.Zero;     // SCARDCONTEXT (ULONG_PTR)
            IntPtr phContext = IntPtr.Zero;     // *SCARDCONTEXT (*ULONG_PTR)

            try
            {
                phContext = Marshal.AllocHGlobal(Marshal.SizeOf(hContext));

                if (PCSC.SCardEstablishContext((uint)SCOPE.User, IntPtr.Zero, IntPtr.Zero, phContext) != SCARD_S_SUCCESS)
                    return;

                hContext = Marshal.ReadIntPtr(phContext);

                UInt32 nbReaders = 1;
                PCSC.SCard_ReaderState[] readerState = new PCSC.SCard_ReaderState[nbReaders];
                readerState[0].CurrentState = (UInt32)PCSC.CARD_STATE.UNAWARE;
                readerState[0].Reader = reader;

                while (true)
                {
                    if (PCSC.SCardGetStatusChange(hContext, WAIT_TIME, readerState, nbReaders) == SCARD_S_SUCCESS)
                    {
                        UInt32 currentState = readerState[0].CurrentState;      // the old state (as known by the application)
                        UInt32 eventState = readerState[0].EventState;          // the new state (as known by Windows)

                        // fatal status codes, stop monitoring for insertion/removal
                        if (((eventState & (uint)PCSC.CARD_STATE.UNKNOWN)     == (uint)PCSC.CARD_STATE.UNKNOWN) ||      // reader is unknown
                            ((eventState & (uint)PCSC.CARD_STATE.IGNORE)      == (uint)PCSC.CARD_STATE.IGNORE)  ||      // reader should be ignored
                            ((eventState & (uint)PCSC.CARD_STATE.UNAVAILABLE) == (uint)PCSC.CARD_STATE.UNAVAILABLE))    // reader is unavailable
                            m_bRunCardDetection = false;

                        // we can't determine card insertion/removal on first pass (CurrentState == UNAWARE)
                        if (readerState[0].CurrentState != (uint)PCSC.CARD_STATE.UNAWARE)
                        {
                            bool cardIsPresent  = ((eventState   & (uint)PCSC.CARD_STATE.PRESENT) == (uint)PCSC.CARD_STATE.PRESENT);
                            bool cardWasPresent = ((currentState & (uint)PCSC.CARD_STATE.PRESENT) == (uint)PCSC.CARD_STATE.PRESENT);

                            if (cardIsPresent && !cardWasPresent)
                                CardInserted(reader);

                            if (cardWasPresent && !cardIsPresent)
                                CardRemoved(reader);
                        }

                        // The current state is now the event state
                        readerState[0].CurrentState = eventState;
                    }

                    if (m_bRunCardDetection == false)
                        break;

                    Thread.Sleep(100);
                }
            }
            catch       // since this executes in a thread we must prevent
            { }         // exceptions from escaping or they will be unhandled
            finally
            {
                if (phContext != IntPtr.Zero)
                    Marshal.FreeHGlobal(phContext);

                if (hContext != IntPtr.Zero)
                    PCSC.SCardReleaseContext(hContext);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// This function must implement a card detection mechanism.
        /// 
        /// When card insertion is detected, it must call the method CardInserted()
        /// When card removal is detected, it must call the method CardRemoved()
        /// 
        /// </summary>
        protected override void RunCardDetection(string reader)
        {
            bool bFirstLoop = true;
            IntPtr hContext = IntPtr.Zero;    // Local context
            IntPtr phContext;

            phContext = Marshal.AllocHGlobal(Marshal.SizeOf(hContext));

            if (PCSC.SCardEstablishContext((uint)SCOPE.User, IntPtr.Zero, IntPtr.Zero, phContext) == 0)
            {
                hContext = Marshal.ReadIntPtr(phContext);
                Marshal.FreeHGlobal(phContext);

                UInt32 nbReaders = 1;
                PCSC.SCard_ReaderState[] readerState = new PCSC.SCard_ReaderState[nbReaders];

                readerState[0].CurrentState = (UInt32)PCSC.CARD_STATE.UNAWARE;
                readerState[0].Reader = reader;

                UInt32 eventState;
                UInt32 currentState = readerState[0].CurrentState;

                // Card detection loop
                do
                {
                    if (PCSC.SCardGetStatusChange(hContext, WAIT_TIME
                        , readerState, nbReaders) == 0)
                    {
                        eventState = readerState[0].EventState;
                        currentState = readerState[0].CurrentState;

                        if (bFirstLoop)
                        {
                            // Check if a card is already inserted
                            if ((eventState & (uint)PCSC.CARD_STATE.PRESENT) == (uint)PCSC.CARD_STATE.PRESENT)
                            {
                                CardInserted(reader);
                            }
                        }
                        else if (((eventState & (uint)PCSC.CARD_STATE.CHANGED) == (uint)PCSC.CARD_STATE.CHANGED) && !bFirstLoop)
                        {
                            // State has changed
                            if ((eventState & (uint)PCSC.CARD_STATE.EMPTY) == (uint)PCSC.CARD_STATE.EMPTY)
                            {
                                // There is no card, card has been removed -> Fire CardRemoved event
                                CardRemoved(reader);
                            }

                            if (((eventState & (uint)PCSC.CARD_STATE.PRESENT) == (uint)PCSC.CARD_STATE.PRESENT) &&
                                ((eventState & (uint)PCSC.CARD_STATE.PRESENT) != (currentState & (uint)PCSC.CARD_STATE.PRESENT)) &&
                                ((eventState & (uint)PCSC.CARD_STATE.MUTE) != (uint)PCSC.CARD_STATE.MUTE))
                            {
                                // There is a card in the reader -> Fire CardInserted event
                                CardInserted(reader);
                            }

                            if ((eventState & (uint)PCSC.CARD_STATE.ATRMATCH) == (uint)PCSC.CARD_STATE.ATRMATCH)
                            {
                                // There is a card in the reader and it matches the ATR we were expecting-> Fire CardInserted event
                                CardInserted(reader);
                            }
                        }

                        // The current state is now the event state
                        readerState[0].CurrentState = eventState;

                        bFirstLoop = false;
                    }

                    Thread.Sleep(100);

                    if (m_bRunCardDetection == false)
                        break;
                }
                while (true);    // Exit on request
            }
            else
            {
                Marshal.FreeHGlobal(phContext);
                throw new Exception("PC/SC error");
            }

            PCSC.SCardReleaseContext(hContext);
        }
        /// <summary>
        /// This function must implement a card detection mechanism.
        ///
        /// When card insertion is detected, it must call the method CardInserted()
        /// When card removal is detected, it must call the method CardRemoved()
        ///
        /// </summary>
        private void RunCardDetection(object Reader)
        {
            bool   bFirstLoop = true;
            IntPtr hContext   = IntPtr.Zero;  // Local context
            IntPtr phContext;

            phContext = Marshal.AllocHGlobal(Marshal.SizeOf(hContext));

            if (PCSC.SCardEstablishContext((uint)SCOPE.User, IntPtr.Zero, IntPtr.Zero, phContext) == 0)
            {
                hContext = Marshal.ReadIntPtr(phContext);
                Marshal.FreeHGlobal(phContext);

                UInt32 nbReaders = 1;
                PCSC.SCard_ReaderState[] readerState = new PCSC.SCard_ReaderState[nbReaders];

                readerState[0].CurrentState = (UInt32)PCSC.CARD_STATE.UNAWARE;
                readerState[0].Reader       = (string)Reader;

                UInt32 eventState;
                UInt32 currentState = readerState[0].CurrentState;

                // Card detection loop
                do
                {
                    if (PCSC.SCardGetStatusChange(hContext, WAIT_TIME, readerState, nbReaders) == 0)
                    {
                        eventState   = readerState[0].EventState;
                        currentState = readerState[0].CurrentState;

                        // Check state
                        if (((eventState & (uint)PCSC.CARD_STATE.CHANGED) == (uint)PCSC.CARD_STATE.CHANGED) && !bFirstLoop)
                        {
                            // State has changed
                            if ((eventState & (uint)PCSC.CARD_STATE.EMPTY) == (uint)PCSC.CARD_STATE.EMPTY)
                            {
                                // There is no card, card has been removed -> Fire CardRemoved event
                                RaiseCardRemoved((string)Reader);
                            }

                            if (((eventState & (uint)PCSC.CARD_STATE.PRESENT) == (uint)PCSC.CARD_STATE.PRESENT) &&
                                ((eventState & (uint)PCSC.CARD_STATE.PRESENT) != (currentState & (uint)PCSC.CARD_STATE.PRESENT)))
                            {
                                // There is a card in the reader -> Fire CardInserted event
                                RaiseCardInserted((string)Reader);
                            }

                            if ((eventState & (uint)PCSC.CARD_STATE.ATRMATCH) == (uint)PCSC.CARD_STATE.ATRMATCH)
                            {
                                // There is a card in the reader and it matches the ATR we were expecting-> Fire CardInserted event
                                RaiseCardInserted((string)Reader);
                            }
                        }

                        // The current stateis now the event state
                        readerState[0].CurrentState = eventState;

                        bFirstLoop = false;
                    }

                    Thread.Sleep(100);

                    if (runCardDetectionFlag == false)
                    {
                        break;
                    }
                }while (true);    // Exit on request
            }
            else
            {
                Marshal.FreeHGlobal(phContext);
                throw new Exception("PC/SC error");
            }

            PCSC.SCardReleaseContext(hContext);
        }