/// <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); } }
/// <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); }