예제 #1
0
        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);
            });
        }
예제 #2
0
        protected void SpawnOnCardRemovedEvent(PCSCReader reader)
        {
            if (reader.ActiveCard == null)
            {
                return;
            }

            ThreadPool.QueueUserWorkItem(delegate
            {
                this.RaiseOnCardRemoved(reader.Name);
            });
        }
예제 #3
0
        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
        }