diff options
author | Henryk Plötz <henryk@ploetzli.ch> | 2010-02-25 19:50:25 +0100 |
---|---|---|
committer | Henryk Plötz <henryk@ploetzli.ch> | 2010-02-26 02:27:26 +0100 |
commit | e960c92fbd19181661c6a315aa8666599bbda252 (patch) | |
tree | 8b547cdd647dde7a96bdba11790976c139077179 | |
parent | 8f5ec36f7afbdd2e170d03bff5e42658b076e813 (diff) |
Initial and very minimal support for ISO 14443-4 over PN532 over ISO 7816-3 T=0 on the ACR122 firmware 1.x
-rw-r--r-- | cards/pn532_card.py | 9 | ||||
-rw-r--r-- | readers.py | 77 |
2 files changed, 82 insertions, 4 deletions
diff --git a/cards/pn532_card.py b/cards/pn532_card.py index 6c34324..464ee42 100644 --- a/cards/pn532_card.py +++ b/cards/pn532_card.py @@ -25,9 +25,12 @@ class PN532_Virtual_Card(Card): self.cmd_pn532("d4 4a 01 00") def pn532_transceive(self, cmd): - apdu = C_APDU(self.APDU_TRANSCEIVE_PN532, lc=len(cmd), data=cmd) - response = self.send_apdu(apdu) - return response + if hasattr(self.reader, "pn532_transceive_raw"): + return R_APDU(self.reader.pn532_transceive_raw(cmd)) + else: + apdu = C_APDU(self.APDU_TRANSCEIVE_PN532, lc=len(cmd), data=cmd) + response = self.send_apdu(apdu) + return response def pn532_parse(self, response): result = [] @@ -8,9 +8,10 @@ pycsc you'll need to downgrade to SVN revision 246. """ raise class Smartcard_Reader(object): - def list_readers(): + def list_readers(cls): "Return a list of tuples: (reader name, implementing object)" return [] + list_readers = classmethod(list_readers) def connect(self): "Create a connection to this reader" @@ -93,10 +94,84 @@ class PCSC_Reader(Smartcard_Reader): self._cardservice.connection.disconnect() del self._cardservice self._cardservice = None + +class ACR122_Reader(Smartcard_Reader): + """This class implements ISO 14443-4 access through the + PN532 in an ACR122 reader with firmware version 1.x""" + def list_readers(cls): + pcsc_readers = PCSC_Reader.list_readers() + readers = [] + for name, obj in pcsc_readers: + if name.startswith("ACS ACR 38U-CCID"): + reader = cls(obj) + readers.append( (reader.name, reader) ) + return readers + list_readers = classmethod(list_readers) + + name = property(lambda self: self._name, None, None, "The human readable name of the reader") + + def __init__(self, parent): + self._parent = parent + self._name = self._parent.name+"-RFID" + + def pn532_transceive_raw(self, command): + c_apdu = "\xff\x00\x00\x00" + chr(len(command)) + command + r_apdu = self._parent.transceive(c_apdu) + + if len(r_apdu) == 2 and r_apdu[0] == "\x61": + c_apdu = "\xff\xc0\x00\x00" + r_apdu[1] + r_apdu = self._parent.transceive(c_apdu) + + return r_apdu + + def pn532_transceive(self, command): + response = self.pn532_transceive_raw(command) + + if len(response) < 2 or response[-2:] != ["\x90", "\x00"]: + raise IOError, "Couldn't communicate with PN532" + + if not (response[0] == "\xd5" and ord(response[1]) == ord(command[1])+1 ): + raise IOError, "Wrong response from PN532" + + return "".join(response[:-2]) + + def pn532_acquire_card(self): + response = self.pn532_transceive("\xd4\x04") + if ord(response[4]) > 0: + return True + else: + response = self.pn532_transceive("\xd4\x4a\x01\x00") + if ord(response[2]) > 0: + return True + else: + response = self.pn532_transceive("\xd4\x4a\x01\x03") + if ord(response[2]) > 0: + return True + + def connect(self): + # FIXME Add loop or something similar to PCSC_Reader.connect + self._parent.connect() + self.pn532_acquire_card() + + def get_ATR(self): + # FIXME Properly implement for PC/SC version 2 + return "\x3b\x80\x80\x01\x01" + + def transceive(self, data): + # FIXME Properly determine target number + response = self.pn532_transceive("\xd4\x40\x01" + data) + if response[2] != "\x00": + # FIXME Proper error processing + raise IOError, "Error while transceiving" + return response[3:] + + def disconnect(self): + self._parent.disconnect() def list_readers(): "Collect readers from all known drivers" readers = PCSC_Reader.list_readers() + readers.extend( ACR122_Reader.list_readers() ) return readers def connect_to(reader): |