Move all PC/SC specific stuff to a separate class structure for readers (thus preparing the way for non-PC/SC-readers)
This commit should be known as "Holy excessive layering, batman!"henryk_github
parent
63d7c9d0a8
commit
331bfc4d47
@ -0,0 +1,130 @@ |
||||
try: |
||||
import smartcard, smartcard.CardRequest |
||||
except ImportError: |
||||
print >>sys.stderr, """Could not import smartcard module. Please install pyscard |
||||
from http://pyscard.sourceforge.net/ |
||||
If you can't install pyscard and want to continue using |
||||
pycsc you'll need to downgrade to SVN revision 246. |
||||
""" |
||||
raise |
||||
class Smartcard_Reader(object): |
||||
def list_readers(): |
||||
"Return a list of tuples: (reader name, implementing object)" |
||||
return [] |
||||
|
||||
def connect(self): |
||||
"Create a connection to this reader" |
||||
raise NotImplementedError, "Please implement in a sub-class" |
||||
|
||||
def get_ATR(self): |
||||
"Get the ATR of the inserted card as a binary string" |
||||
raise NotImplementedError, "Please implement in a sub-class" |
||||
|
||||
def transceive(self, data): |
||||
"Send a binary blob, receive a binary blob" |
||||
raise NotImplementedError, "Please implement in a sub-class" |
||||
|
||||
def disconnect(self): |
||||
"Disconnect from the card and release all resources" |
||||
raise NotImplementedError, "Please implement in a sub-class" |
||||
|
||||
class PCSC_Reader(Smartcard_Reader): |
||||
def __init__(self, reader): |
||||
self._reader = reader |
||||
self._name = str(reader) |
||||
self._cardservice = None |
||||
|
||||
name = property(lambda self: self._name, None, None, "The human readable name of the reader") |
||||
|
||||
def list_readers(cls): |
||||
return [ (str(r), cls(r)) for r in smartcard.System.readers() ] |
||||
list_readers = classmethod(list_readers) |
||||
|
||||
def connect(self): |
||||
unpatched = False |
||||
printed = False |
||||
while True: |
||||
try: |
||||
if not unpatched: |
||||
cardrequest = smartcard.CardRequest.CardRequest( readers=[self._reader], timeout=0.1 ) |
||||
else: |
||||
cardrequest = smartcard.CardRequest.CardRequest( readers=[self._reader], timeout=1 ) |
||||
|
||||
self._cardservice = cardrequest.waitforcard() |
||||
self._cardservice.connection.connect() |
||||
break |
||||
except TypeError: |
||||
unpatched = True |
||||
except (KeyboardInterrupt, SystemExit): |
||||
raise |
||||
except smartcard.Exceptions.CardRequestException: |
||||
if sys.exc_info()[1].message.endswith("Command timeout."): |
||||
if not printed: |
||||
print "Please insert card ..." |
||||
printed = True |
||||
else: |
||||
raise |
||||
except smartcard.Exceptions.CardRequestTimeoutException: |
||||
if not printed: |
||||
print "Please insert card ..." |
||||
printed = True |
||||
except smartcard.Exceptions.NoCardException: |
||||
print "Card is mute or absent. Please retry." |
||||
|
||||
def get_ATR(self): |
||||
return smartcard.util.toASCIIString(self._cardservice.connection.getATR()) |
||||
|
||||
def get_protocol(self): |
||||
hresult, reader, state, protocol, atr = smartcard.scard.SCardStatus( self._cardservice.connection.component.hcard ) |
||||
return ((protocol == smartcard.scard.SCARD_PROTOCOL_T0) and (0,) or (1,))[0] |
||||
|
||||
PROTOMAP = { |
||||
0: smartcard.scard.SCARD_PCI_T0, |
||||
1: smartcard.scard.SCARD_PCI_T1, |
||||
} |
||||
|
||||
def transceive(self, data): |
||||
data_bytes = map(lambda x: ord(x), data) |
||||
data, sw1, sw2 = self._cardservice.connection.transmit(data_bytes, protocol=self.PROTOMAP[self.get_protocol()]) |
||||
result_binary = map(lambda x: chr(x), data + [sw1,sw2]) |
||||
return result_binary |
||||
|
||||
def disconnect(self): |
||||
self._cardservice.connection.disconnect() |
||||
del self._cardservice |
||||
self._cardservice = None |
||||
|
||||
def list_readers(): |
||||
"Collect readers from all known drivers" |
||||
readers = PCSC_Reader.list_readers() |
||||
return readers |
||||
|
||||
def connect_to(reader): |
||||
"Open the connection to a reader" |
||||
|
||||
readerObject = None |
||||
readers = list_readers() |
||||
|
||||
if isinstance(reader, int) or reader.isdigit(): |
||||
reader = int(reader) |
||||
readerObject = readers[reader][1] |
||||
else: |
||||
for i, name, obj in readers: |
||||
if str(name).startswith(reader): |
||||
readerObject = obj |
||||
|
||||
if readerObject is None: |
||||
readerObject = readers[0][1] |
||||
|
||||
print "Using reader: %s" % readerObject.name |
||||
|
||||
readerObject.connect() |
||||
|
||||
from utils import hexdump |
||||
|
||||
print "ATR: %s" % hexdump(readerObject.get_ATR(), short = True) |
||||
return readerObject |
||||
|
||||
if __name__ == "__main__": |
||||
list_readers() |
||||
|
Loading…
Reference in new issue