This is part of the series: "
OS X El Capitan and smart cards: known bugs".
SCardGetStatusChange() and number of card events
SCardGetStatusChange() does not return the number of card events in the upper word of
dwEventState
.
This is not a bug since I don't think this feature was every present in the PC/SC from Apple. It is a feature request and not a bug report.
From the Doxygen documentation of
pcsc-lite:
dwEventState
also contains a number of events in the upper 16 bits (dwEventState
& 0xFFFF0000). This number of events is incremented for each card insertion or removal in the specified reader. This can be used to detect a card removal/insertion between two calls to SCardGetStatusChange()
.
This behaviour is also present in PC/SC on Windows.
It is the only way to know that the card has been removed from a reader and inserted again while no call to
SCardGetStatusChange()
was running. Potentially the inserted card is not the same as the removed card so the PC/SC application may have to build a new applicative context for the new card.
See also
Apple bug report #23937633 "PC/SC SCardGetStatusChange() and number of card events"
Sample code
Using the Python PC/SC wrapper
PySCard to have a shorter code.
#! /usr/bin/env python
from smartcard.scard import *
from smartcard.pcsc.PCSCExceptions import *
def parseEventState(eventstate):
stateList = list()
states = {SCARD_STATE_IGNORE: "Ignore",
SCARD_STATE_CHANGED: "Changed",
SCARD_STATE_UNKNOWN: "Unknown",
SCARD_STATE_UNAVAILABLE: "Unavailable",
SCARD_STATE_EMPTY: "Empty",
SCARD_STATE_PRESENT: "Present",
SCARD_STATE_ATRMATCH: "ATR match",
SCARD_STATE_EXCLUSIVE: "Exclusive",
SCARD_STATE_INUSE: "In use",
SCARD_STATE_MUTE: "Mute"}
for state in states:
if eventstate & state:
stateList.append(states[state])
return stateList
hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
if hresult != SCARD_S_SUCCESS:
raise EstablishContextException(hresult)
hresult, readers = SCardListReaders(hcontext, [])
if hresult != SCARD_S_SUCCESS:
raise ListReadersException(hresult)
print 'PC/SC Readers:', readers
readerstates = {}
for reader in readers:
readerstates[reader] = (reader, SCARD_STATE_UNAWARE)
hresult, newstates = SCardGetStatusChange(hcontext, 0, readerstates.values())
if hresult != SCARD_S_SUCCESS:
raise BaseSCardException(hresult)
print newstates
for readerState in newstates:
readername, eventstate, atr = readerState
readerstates[readername] = (readername, eventstate)
print "Move the smart card"
ok = True
while ok:
try:
hresult, newstates = SCardGetStatusChange(hcontext, INFINITE, newstates)
if hresult != SCARD_S_SUCCESS and hresult != SCARD_E_TIMEOUT:
raise BaseSCardException(hresult)
except KeyboardInterrupt:
ok = False
for readerState in newstates:
readername, eventstate, atr = readerState
states = parseEventState(eventstate)
print states, hex(eventstate)
hresult = SCardReleaseContext(hcontext)
print "SCardReleaseContext()", SCardGetErrorMessage(hresult)
if hresult != SCARD_S_SUCCESS:
raise ReleaseContextException(hresult)
Result (on El Capitan)
$ ./SCardGetStatusChange.py
PC/SC Readers: ['Gemalto PC Twin Reader']
[('Gemalto PC Twin Reader', 18, [])]
Move the smart card
['Changed', 'Present'] 0x22
['Empty', 'Changed'] 0x12
['Changed', 'Present'] 0x22
['Empty', 'Changed'] 0x12
^C['Empty', 'Changed'] 0x12
SCardReleaseContext() Command successful.
For the tests I insert and remove the card 2 times.
Then press Control-C and insert the card to quit the program.
Expected result (on Debian)
$ ./SCardGetStatusChange.py
PC/SC Readers: ['Gemalto PC Twin Reader 00 00']
[('Gemalto PC Twin Reader 00 00', 18, [])]
Move the smart card
['Changed', 'Present'] 0x10022
['Empty', 'Changed'] 0x20012
['Changed', 'Present'] 0x30022
['Empty', 'Changed'] 0x40012
^C['Empty', 'Changed'] 0x40012
SCardReleaseContext() Command successful.
The change is the value
eventstate
displayed (in hexadecimal).
On Debian the high word (upper 16 bits) takes the values 1, 2, 3 and 4.
If the value change from 0x10022 to 0x30022, the reader state is the same (
SCARD_STATE_CHANGED
and
SCARD_STATE_PRESENT
) but you know that the card has been removed and inserted.
Known workaround
None known.
[Update 2022-08-31, after 7 years]
Apple just answered to my bug report, now called feedback. The bug report #23937633 is now known as FB7531166. Apple answer is (I have it in French in my Feedback Assistant application. Surprising!):
"Thank you for your review and patience. We apologize for the late response. We do not intend to treat this report as an enhancement.
Indeed, adding new features to the existing PC/SC interface is not on the agenda. However, we will consider this suggestion in case our plans change."
Apple is reviewing (old) PC/SC issues. Nice to know.
But do not plan to add new features.