def __init__(self, newcardonly=False, readers=None, cardType=None, cardServiceClass=None, timeout=1): """Construct new PCSCCardRequest. @param newcardonly: if True, request a new card default is False, i.e. accepts cards already inserted @param readers: the list of readers to consider for requesting a card default is to consider all readers @param cardTypeClass: the CardType class to wait for; default is AnyCardType, i.e. the request will returns with new or already inserted cards @param cardServiceClass: the specific card service class to create and bind to the card default is to create and bind a PassThruCardService @param timeout: the time in seconds we are ready to wait for connecting to the requested card. default is to wait one second to wait forever, set timeout to None """ AbstractCardRequest.__init__(self, newcardonly, readers, cardType, cardServiceClass, timeout) # polling interval in s for SCardGetStatusChange self.pollinginterval = 0.1 # if timeout is None, translate to scard.INFINITE if None == self.timeout: self.timeout = INFINITE # otherwise, from seconds to milliseconds else: self.timeout = int(self.timeout) self.hcontext = PCSCContext().getContext()
def __init__(self, newcardonly=False, readers=None, cardType=None, cardServiceClass=None, timeout=1, msr_active=None): """Construct new PCSCCardRequest. @param newcardonly: if True, request a new card default is False, i.e. accepts cards already inserted @param readers: the list of readers to consider for requesting a card default is to consider all readers @param cardType: the CardType class to wait for; default is AnyCardType, i.e. the request will returns with new or already inserted cards @param cardServiceClass: the specific card service class to create and bind to the card default is to create and bind a PassThruCardService @param timeout: the time in seconds we are ready to wait for connecting to the requested card. default is to wait one second to wait forever, set timeout to None """ AbstractCardRequest.__init__( self, newcardonly, readers, cardType, cardServiceClass, timeout) self.msr_active = True if msr_active == True else False # polling interval in s for SCardGetStatusChange self.pollinginterval = 0.01 if self.msr_active else 0.005 # normal 0.1 # if timeout is None, translate to scard.INFINITE if None == self.timeout: self.timeout = INFINITE # otherwise, from seconds to milliseconds else: self.timeout = int(self.timeout) self.hcontext = PCSCContext().getContext()
def waitforcardevent(self): """Wait for card insertion or removal.""" AbstractCardRequest.waitforcardevent(self) presentcards = [] evt = threading.Event() # for non infinite timeout, a timer will signal the end of the time-out if INFINITE == self.timeout: timertimeout = 1 else: timertimeout = self.timeout timer = threading.Timer( timertimeout, signalEvent, [evt, INFINITE == self.timeout]) # get status change until time-out, e.g. evt is set readerstates = {} timerstarted = False while not evt.isSet(): if not timerstarted: timerstarted = True timer.start() time.sleep(self.pollinginterval) # reinitialize at each iteration just in case a new reader appeared readernames = self.getReaderNames() for reader in readernames: # create a dictionary entry for new readers if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # get status change if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = 0 newstates = [] # time-out if SCARD_E_TIMEOUT == hresult: if evt.isSet(): raise CardRequestTimeoutException() # the reader was unplugged during the loop elif SCARD_E_UNKNOWN_READER == hresult: pass # some error happened elif 0 != hresult: timer.cancel() raise CardRequestException( 'Failed to get status change ' + \ SCardGetErrorMessage(hresult)) # something changed! else: timer.cancel() for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... Clear the state changed bit if # the card was already inserted and is still inserted if oldstate & SCARD_STATE_PRESENT and \ eventstate & \ (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT): eventstate = eventstate & \ (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if eventstate & SCARD_STATE_PRESENT and \ eventstate & SCARD_STATE_CHANGED: presentcards.append(Card.Card(readername, atr)) return presentcards if evt.isSet(): raise CardRequestTimeoutException()
def waitforcard(self): """Wait for card insertion and returns a card service.""" AbstractCardRequest.waitforcard(self) cardfound = False # for non infinite timeout, a timer will signal # the end of the time-out by setting the evt event evt = threading.Event() if INFINITE == self.timeout: timertimeout = 1 else: timertimeout = self.timeout timer = threading.Timer( timertimeout, signalEvent, [evt, INFINITE == self.timeout]) # create a dictionary entry for new readers readerstates = {} readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # call SCardGetStatusChange only if we have some readers if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = 0 newstates = [] # we can expect normally time-outs or reader # disappearing just before the call # otherwise, raise execption on error if 0 != hresult and \ SCARD_E_TIMEOUT != hresult and \ SCARD_E_UNKNOWN_READER != hresult: raise CardRequestException( 'Failed to SCardGetStatusChange ' + \ SCardGetErrorMessage(hresult)) # in case of timeout or reader disappearing, # the content of the states is useless # in which case we clear the changed bit if SCARD_E_TIMEOUT == hresult or SCARD_E_UNKNOWN_READER == hresult: for state in newstates: state[1] = state[1] & (0xFFFFFFFF ^ SCARD_STATE_CHANGED) # update readerstate for state in newstates: readername, eventstate, atr = state readerstates[readername] = (readername, eventstate) # if a new card is not requested, just return the first available if not self.newcardonly: for state in newstates: readername, eventstate, atr = state if eventstate & SCARD_STATE_PRESENT: reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True return self.cardServiceClass( reader.createConnection()) timerstarted = False while not evt.isSet() and not cardfound: if not timerstarted: timerstarted = True timer.start() time.sleep(self.pollinginterval) # create a dictionary entry for new readers readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # wait for card insertion if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = SCARD_E_TIMEOUT newstates = [] # time-out if SCARD_E_TIMEOUT == hresult: if evt.isSet(): raise CardRequestTimeoutException() # reader vanished before or during the call elif SCARD_E_UNKNOWN_READER == hresult: pass # some error happened elif 0 != hresult: timer.cancel() raise CardRequestException( 'Failed to get status change ' + \ SCardGetErrorMessage(hresult)) # something changed! else: # check if we have to return a match, i.e. # if no new card in inserted and there is a card found # or if a new card is requested, and there is a change+present for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... # if a new card is requested, clear the state changed bit # if the card was already inserted and is still inserted if self.newcardonly: if oldstate & SCARD_STATE_PRESENT and \ eventstate & \ (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT): eventstate = eventstate & \ (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if (self.newcardonly and \ eventstate & SCARD_STATE_PRESENT and \ eventstate & SCARD_STATE_CHANGED) or \ (not self.newcardonly and \ eventstate & SCARD_STATE_PRESENT): reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True timer.cancel() return self.cardServiceClass( reader.createConnection()) # update state dictionary readerstates[readername] = (readername, eventstate) if evt.isSet(): raise CardRequestTimeoutException()
def waitforcardevent(self): """Wait for card insertion or removal.""" AbstractCardRequest.waitforcardevent(self) presentcards = [] evt = threading.Event() # for non infinite timeout, a timer will signal the end of the time-out if INFINITE == self.timeout: timertimeout = 1 else: timertimeout = self.timeout timer = threading.Timer(timertimeout, signalEvent, [evt, INFINITE == self.timeout]) # get status change until time-out, e.g. evt is set readerstates = {} timerstarted = False while not evt.isSet(): if not timerstarted: timerstarted = True timer.start() time.sleep(self.pollinginterval) # reinitialize at each iteration just in case a new reader appeared readernames = self.getReaderNames() for reader in readernames: # create a dictionary entry for new readers if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # get status change if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = 0 newstates = [] # time-out if SCARD_E_TIMEOUT == hresult: if evt.isSet(): raise CardRequestTimeoutException() # the reader was unplugged during the loop elif SCARD_E_UNKNOWN_READER == hresult: pass # some error happened elif 0 != hresult: timer.cancel() raise CardRequestException( 'Failed to get status change ' + \ SCardGetErrorMessage(hresult)) # something changed! else: timer.cancel() for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... Clear the state changed bit if # the card was already inserted and is still inserted if oldstate & SCARD_STATE_PRESENT and \ eventstate & \ (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT): eventstate = eventstate & \ (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if eventstate & SCARD_STATE_PRESENT and \ eventstate & SCARD_STATE_CHANGED: presentcards.append(Card.Card(readername, atr)) return presentcards if evt.isSet(): raise CardRequestTimeoutException()
def waitforcard(self): """Wait for card insertion and returns a card service.""" AbstractCardRequest.waitforcard(self) cardfound = False # for non infinite timeout, a timer will signal # the end of the time-out by setting the evt event evt = threading.Event() if INFINITE == self.timeout: timertimeout = 1 else: timertimeout = self.timeout timer = threading.Timer(timertimeout, signalEvent, [evt, INFINITE == self.timeout]) # create a dictionary entry for new readers readerstates = {} readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # call SCardGetStatusChange only if we have some readers if {} != readerstates: hresult, newstates = SCardGetStatusChange(self.hcontext, 0, readerstates.values()) else: hresult = 0 newstates = [] # we can expect normally time-outs or reader # disappearing just before the call # otherwise, raise execption on error if 0 != hresult and \ SCARD_E_TIMEOUT != hresult and \ SCARD_E_UNKNOWN_READER != hresult: raise CardRequestException( 'Failed to SCardGetStatusChange ' + \ SCardGetErrorMessage(hresult)) # in case of timeout or reader disappearing, # the content of the states is useless # in which case we clear the changed bit if SCARD_E_TIMEOUT == hresult or SCARD_E_UNKNOWN_READER == hresult: for state in newstates: state[1] = state[1] & (0xFFFFFFFF ^ SCARD_STATE_CHANGED) # update readerstate for state in newstates: readername, eventstate, atr = state readerstates[readername] = (readername, eventstate) # if a new card is not requested, just return the first available if not self.newcardonly: for state in newstates: readername, eventstate, atr = state if eventstate & SCARD_STATE_PRESENT: reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True return self.cardServiceClass( reader.createConnection()) timerstarted = False while not evt.isSet() and not cardfound: if not timerstarted: timerstarted = True timer.start() time.sleep(self.pollinginterval) # create a dictionary entry for new readers readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # wait for card insertion if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = SCARD_E_TIMEOUT newstates = [] # time-out if SCARD_E_TIMEOUT == hresult: if evt.isSet(): raise CardRequestTimeoutException() # reader vanished before or during the call elif SCARD_E_UNKNOWN_READER == hresult: pass # some error happened elif 0 != hresult: timer.cancel() raise CardRequestException( 'Failed to get status change ' + \ SCardGetErrorMessage(hresult)) # something changed! else: # check if we have to return a match, i.e. # if no new card in inserted and there is a card found # or if a new card is requested, and there is a change+present for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... # if a new card is requested, clear the state changed bit # if the card was already inserted and is still inserted if self.newcardonly: if oldstate & SCARD_STATE_PRESENT and \ eventstate & \ (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT): eventstate = eventstate & \ (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if (self.newcardonly and \ eventstate & SCARD_STATE_PRESENT and \ eventstate & SCARD_STATE_CHANGED) or \ (not self.newcardonly and \ eventstate & SCARD_STATE_PRESENT): reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True timer.cancel() return self.cardServiceClass( reader.createConnection()) # update state dictionary readerstates[readername] = (readername, eventstate) if evt.isSet(): raise CardRequestTimeoutException()
def readCard(self, dend, msr): """Wait for card insertion and returns a card service.""" AbstractCardRequest.waitforcard(self) cardfound = False data = [] swiped = False # for non infinite timeout, a timer will signal # the end of the time-out by setting the evt event evt = Event() if INFINITE == self.timeout: timertimeout = 1 else: timertimeout = self.timeout timer = Timer( timertimeout, signalEvent, [evt, INFINITE == self.timeout]) # create a dictionary entry for new readers readerstates = {} readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in list(readerstates.keys()): if oldreader not in readernames: del readerstates[oldreader] # call SCardGetStatusChange only if we have some readers if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, list(readerstates.values())) else: hresult = 0 newstates = [] # we can expect normally time-outs or reader # disappearing just before the call # otherwise, raise execption on error if 0 != hresult and \ SCARD_E_TIMEOUT != hresult and \ SCARD_E_UNKNOWN_READER != hresult: raise CardRequestException( 'Failed to SCardGetStatusChange ' + \ SCardGetErrorMessage(hresult)) # in case of timeout or reader disappearing, # the content of the states is useless # in which case we clear the changed bit if SCARD_E_TIMEOUT == hresult or SCARD_E_UNKNOWN_READER == hresult: for state in newstates: state[1] = state[1] & (0xFFFFFFFF ^ SCARD_STATE_CHANGED) # update readerstate for state in newstates: readername, eventstate, atr = state readerstates[readername] = (readername, eventstate) # if a new card is not requested, just return the first available if not self.newcardonly: for state in newstates: readername, eventstate, atr = state if eventstate & SCARD_STATE_PRESENT: reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True return self.cardservice(reader) while not evt.isSet() and not cardfound: sleep(self.pollinginterval) # PCSC refresh rate # create a dictionary entry for new readers readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in list(readerstates.keys()): if oldreader not in readernames: del readerstates[oldreader] # wait for card insertion if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, list(readerstates.values())) else: hresult = SCARD_E_TIMEOUT newstates = [] # msr-read card intermezzo if not self.msr_active: try: if swiped: return msr.process_data(data) data += msr.device.read(dend.bEndpointAddress, dend.wMaxPacketSize, 5) if len(data) >= 537: swiped = True except usb.core.USBError as e: if e.args == ('Operation timed out',): print('Invalid swipe, discarding %s bytes of data', len(data)) data = [] continue # time-out if SCARD_E_TIMEOUT == hresult: if evt.isSet(): raise CardRequestTimeoutException() # reader vanished before or during the call elif SCARD_E_UNKNOWN_READER == hresult: pass # some error happened elif 0 != hresult: timer.cancel() raise CardRequestException( 'Failed to get status change ' + \ SCardGetErrorMessage(hresult)) # something changed! else: # check if we have to return a match, i.e. # if no new card in inserted and there is a card found # or if a new card is requested, and there is a change+present for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... # if a new card is requested, clear the state changed bit # if the card was already inserted and is still inserted if self.newcardonly: if oldstate & SCARD_STATE_PRESENT and \ eventstate & \ (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT): eventstate = eventstate & \ (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if (self.newcardonly and \ eventstate & SCARD_STATE_PRESENT and \ eventstate & SCARD_STATE_CHANGED) or \ (not self.newcardonly and \ eventstate & SCARD_STATE_PRESENT): reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True # timer.cancel() return self.cardservice(reader) # update state dictionary readerstates[readername] = (readername, eventstate) if evt.isSet(): raise CardRequestTimeoutException()