protected void SpawnOnCardInsertedEvent(PCSCReader reader) { // Create the card instance for our reader reader.ActiveCard = new PCSCCard(reader.Name); ThreadPool.QueueUserWorkItem(delegate { this.RaiseOnCardInserted(reader.Name, reader.ActiveCard); }); }
protected void SpawnOnCardRemovedEvent(PCSCReader reader) { if (reader.ActiveCard == null) { return; } ThreadPool.QueueUserWorkItem(delegate { this.RaiseOnCardRemoved(reader.Name); }); }
private void PollingProcedure() { PCSCResult result; SCardState pnpState = SCardState.Unaware; // Set all existing readers to the 'Unaware' state to force a re-detection foreach (var reader in myReaders.Values) { reader.State = SCardState.Unaware; } // Reader detection loop while (true) { // List readers string[] readers = ListReaders(); // Check for added readers foreach (string r in readers) { if (!myReaders.ContainsKey(r)) { lock (myReaders) { myReaders.Add(r, new PCSCReader(r)); } SpawnOnReaderInsertedEvent(r); } } // Check for removed readers List <string> removed = new List <string>(); foreach (string r in myReaders.Keys) { if (!readers.Contains(r)) { removed.Add(r); } } foreach (string r in removed) { SpawnOnReaderRemovedEvent(r); lock (myReaders) { myReaders.Remove(r); } } // Create our reader states, including 1 for the PnP notification reader SCARD_READERSTATE[] readerStates = new SCARD_READERSTATE[myReaders.Count + 1]; readerStates[0].szReader = PnPDetectorReader; readerStates[0].dwCurrentState = pnpState; for (int i = 0; i < myReaders.Count; i++) { PCSCReader r = myReaders.ElementAt(i).Value; readerStates[i + 1].szReader = r.Name; readerStates[i + 1].dwCurrentState = r.State; } // Reader state detection loop while (true) { // Call the suspend wait event. If it is cleared, we will hold here mySuspendEvent.WaitOne(); // First, check for a thread abort request if (myThreadAbortRequested == true) { return; } // Wait for a status change result = NativeMethods.SCardGetStatusChange(myContext, PollingInterval, readerStates, readerStates.Length); // Was it a timeout? If so, just continue to the next iteration of the loop if (PCSCResult.Timeout == result) { continue; } // Was an abort requested? If so return if (PCSCResult.Canceled == result) { return; } // Was there another error? If so restart the loop if (PCSCResult.None != result) { Debug.WriteLine($"PCSC> Error: {result}"); continue; } ; // Loop through each reader (skipping the PnP) for (int i = 1; i < readerStates.Length; i++) { // Mask off any changes SCardState changes = (readerStates[i].dwEventState ^ readerStates[i].dwCurrentState); // Was a card inserted? if ((SCardState.Present & changes & readerStates[i].dwEventState) != 0x00) { // Ignore cards with the MUTE flag set if ((readerStates[i].dwEventState & SCardState.Mute) == 0) { lock (myReaders) { myReaders[readerStates[i].szReader].State |= SCardState.Present; } SpawnOnCardInsertedEvent(myReaders[readerStates[i].szReader]); } } // Was a card removed? if ((SCardState.Present & changes & ~readerStates[i].dwEventState) != 0x00) { lock (myReaders) { myReaders[readerStates[i].szReader].State &= ~SCardState.Present; } SpawnOnCardRemovedEvent(myReaders[readerStates[i].szReader]); } // Reset our reader polling state readerStates[i].dwCurrentState = readerStates[i].dwEventState; } // Has a reader been inserted or removed? If so, break to the reader detection loop pnpState = readerStates[0].dwEventState; if ((readerStates[0].dwEventState & SCardState.Changed) != 0x00) { break; } readerStates[0].dwCurrentState = readerStates[0].dwEventState; // This is where we notify the Start() method that we have run at least once myRunOnceEvent.Set(); } } // reader detection while }