aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenryk Plötz <henryk@ploetzli.ch>2010-02-25 16:54:29 +0100
committerHenryk Plötz <henryk@ploetzli.ch>2010-02-26 02:27:26 +0100
commit8f5ec36f7afbdd2e170d03bff5e42658b076e813 (patch)
treeb88f077f5c6299495b335546e7b6961cce8217a0
parent331bfc4d476e9ce215e2100b43c75d7be408ae6c (diff)
Move PN532 code to a separate class (I forgot how easy that is)
-rw-r--r--cards/acos6sam_card.py135
-rw-r--r--cards/pn532_card.py149
2 files changed, 149 insertions, 135 deletions
diff --git a/cards/acos6sam_card.py b/cards/acos6sam_card.py
index 42d362a..412398d 100644
--- a/cards/acos6sam_card.py
+++ b/cards/acos6sam_card.py
@@ -8,138 +8,3 @@ class ACOS6SAM_Card(ISO_7816_4_Card):
ATRS = [
("3bbe9600004103000000000000000000029000", None),
]
- STATUS_WORDS = dict(ISO_7816_4_Card.STATUS_WORDS)
- COMMANDS = dict(ISO_7816_4_Card.COMMANDS)
-
- # All of the following is for the PN532 and probably should go
- # in a separate class
- #################################################
- APDU_TRANSCEIVE_PN532 = C_APDU(cla=0xff, ins=0, p1=0, p2=0)
-
- def cmd_pn532(self, *cmd):
- "Transmit a command to the PN532 and receive the response"
- result = self.pn532_transceive(binascii.unhexlify("".join("".join(cmd).split())))
- print utils.hexdump(result.data)
-
- parsed = self.pn532_parse(result.data)
- if len(parsed) > 0:
- print "\n".join(parsed) + "\n"
-
- def cmd_pn532_poll(self):
- "Poll for cards in the field"
- 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
-
- def pn532_parse(self, response):
- result = []
- type = None
- cmd = None
-
- if len(response) == 0:
- pass
- elif response[0] == "\xd4":
- type="command"
- elif response[0] == "\xd5":
- type="response"
- else:
- result.append("Invalid PN532 direction header")
-
- if len(response) > 1: cmd = ord(response[1])
-
- if type is not None:
- desc = "PN532 %s (%s)" % (type,
- self.PN532_COMMANDS.get(cmd & 0xfe, "Unknown command") )
- result.append(desc)
-
- if len(response) > 1:
- s = "pn532_parse_%s_%02X" % (type, cmd)
- if hasattr(self, s):
- result.extend( getattr(self, s)(response[2:]) )
- elif len(response) > 2:
- result.append( "No detailed decoding available" )
-
- return result
-
- def pn532_parse_response_03(self, response):
- return [ "Version: PN5%02X, firmware %i.%i (cap: %02X)" % tuple(map(ord, response)) ]
-
- def pn532_parse_response_05(self, response):
- result = ["Last error: %02X" % ord(response[0]),
- "External field: %s" % ( response[1] == "\x01" and "present" or "not present" ),
- "Number of targets: %i" % ord(response[2])]
-
- for i in range( (len(response)-4)/4 ):
- t = "Target %i: %i kbps receive, %i kbps send, type: %s" % (
- ord(response[3+i*4]),
- self.PN532_BIT_RATES.get( ord(response[3+i*4+1]), "XXX" ),
- self.PN532_BIT_RATES.get( ord(response[3+i*4+2]), "XXX" ),
- self.PN532_TAG_TYPES.get( ord(response[3+i*4+3]), "unknown" ),
- )
- result.append(t)
-
- result.append( "SAM status: %02X" % ord(response[-1]) )
- return result
-
- STATUS_WORDS.update( {
- '\x63\x00': "Operation failed",
- '\x63\x01': "PN532 did not respond",
- '\x63\x27': "PN532 response checksum wrong",
- '\x63\x7f': "PN532 command wrong",
- } )
-
- COMMANDS.update( {
- "pn532": cmd_pn532,
- "pn532_poll": cmd_pn532_poll,
- } )
-
- PN532_COMMANDS = {
- 0x00: "Diagnose",
- 0x02: "GetFirmwareVersion",
- 0x04: "GetGeneralStatus",
- 0x06: "ReadRegister",
- 0x08: "WriteRegister",
- 0x0c: "ReadGPIO",
- 0x0e: "WriteGPIO",
- 0x10: "SetSerialBaudrate",
- 0x12: "SetParameters",
- 0x14: "SAMConfiguration",
- 0x16: "PowerDown",
- 0x32: "RFConfiguration",
- 0x58: "RFRegulationTest",
- 0x56: "InJumpForDEP",
- 0x46: "InJumpForPSL",
- 0x4A: "InListPassiveTarget",
- 0x50: "InATR",
- 0x4E: "InPSL",
- 0x40: "InDataExchange",
- 0x42: "InCommunicateThru",
- 0x44: "InDeselect",
- 0x52: "InRelease",
- 0x54: "InSelect",
- 0x60: "InPoll",
- 0x8C: "TgInitAsTarget",
- 0x92: "TgSetGeneralBytes",
- 0x86: "TgGetData",
- 0x8E: "TgSetData",
- 0x94: "TgSetMetaData",
- 0x88: "TgGetInitiatorCommand",
- 0x90: "TgResponseToInitiator",
- 0x8A: "TgGetTargetStatus",
- }
-
- PN532_BIT_RATES = {
- 0x0: 106,
- 0x1: 212,
- 0x2: 424,
- }
-
- PN532_TAG_TYPES = {
- 0x00: "Mifare, ISO 14443-3 A/B or ISO 18092 passive 106 kbps",
- 0x10: "FeliCa or ISO 18092 passive 212/424 kbps",
- 0x01: "ISO 18092 active",
- 0x02: "Innovision Jewel",
- }
diff --git a/cards/pn532_card.py b/cards/pn532_card.py
new file mode 100644
index 0000000..6c34324
--- /dev/null
+++ b/cards/pn532_card.py
@@ -0,0 +1,149 @@
+import utils, binascii
+from generic_card import *
+
+class PN532_Virtual_Card(Card):
+ # This is a virtual card that is enabled for the ACS ACR reader that
+ # contains a PN532 module
+ DRIVER_NAME = ["PN532"]
+
+ STATUS_WORDS = dict(Card.STATUS_WORDS)
+ COMMANDS = dict(Card.COMMANDS)
+
+ APDU_TRANSCEIVE_PN532 = C_APDU(cla=0xff, ins=0, p1=0, p2=0)
+
+ def cmd_pn532(self, *cmd):
+ "Transmit a command to the PN532 and receive the response"
+ result = self.pn532_transceive(binascii.unhexlify("".join("".join(cmd).split())))
+ print utils.hexdump(result.data)
+
+ parsed = self.pn532_parse(result.data)
+ if len(parsed) > 0:
+ print "\n".join(parsed) + "\n"
+
+ def cmd_pn532_poll(self):
+ "Poll for cards in the field"
+ 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
+
+ def pn532_parse(self, response):
+ result = []
+ type = None
+ cmd = None
+
+ if len(response) == 0:
+ pass
+ elif response[0] == "\xd4":
+ type="command"
+ elif response[0] == "\xd5":
+ type="response"
+ else:
+ result.append("Invalid PN532 direction header")
+
+ if len(response) > 1: cmd = ord(response[1])
+
+ if type is not None:
+ desc = "PN532 %s (%s)" % (type,
+ self.PN532_COMMANDS.get(cmd & 0xfe, "Unknown command") )
+ result.append(desc)
+
+ if len(response) > 1:
+ s = "pn532_parse_%s_%02X" % (type, cmd)
+ if hasattr(self, s):
+ result.extend( getattr(self, s)(response[2:]) )
+ elif len(response) > 2:
+ result.append( "No detailed decoding available" )
+
+ return result
+
+ def pn532_parse_response_03(self, response):
+ return [ "Version: PN5%02X, firmware %i.%i (cap: %02X)" % tuple(map(ord, response)) ]
+
+ def pn532_parse_response_05(self, response):
+ result = ["Last error: %02X" % ord(response[0]),
+ "External field: %s" % ( response[1] == "\x01" and "present" or "not present" ),
+ "Number of targets: %i" % ord(response[2])]
+
+ for i in range( (len(response)-4)/4 ):
+ t = "Target %i: %i kbps receive, %i kbps send, type: %s" % (
+ ord(response[3+i*4]),
+ self.PN532_BIT_RATES.get( ord(response[3+i*4+1]), "XXX" ),
+ self.PN532_BIT_RATES.get( ord(response[3+i*4+2]), "XXX" ),
+ self.PN532_TAG_TYPES.get( ord(response[3+i*4+3]), "unknown" ),
+ )
+ result.append(t)
+
+ result.append( "SAM status: %02X" % ord(response[-1]) )
+ return result
+
+ def can_handle(cls, reader):
+ """Determine whether this class can handle a given reader object."""
+ if reader.name.startswith("ACS ACR 38U-CCID"):
+ return True
+ return False
+
+ can_handle = classmethod(can_handle)
+
+
+ STATUS_WORDS.update( {
+ '\x63\x00': "Operation failed",
+ '\x63\x01': "PN532 did not respond",
+ '\x63\x27': "PN532 response checksum wrong",
+ '\x63\x7f': "PN532 command wrong",
+ } )
+
+ COMMANDS.update( {
+ "pn532": cmd_pn532,
+ "pn532_poll": cmd_pn532_poll,
+ } )
+
+ PN532_COMMANDS = {
+ 0x00: "Diagnose",
+ 0x02: "GetFirmwareVersion",
+ 0x04: "GetGeneralStatus",
+ 0x06: "ReadRegister",
+ 0x08: "WriteRegister",
+ 0x0c: "ReadGPIO",
+ 0x0e: "WriteGPIO",
+ 0x10: "SetSerialBaudrate",
+ 0x12: "SetParameters",
+ 0x14: "SAMConfiguration",
+ 0x16: "PowerDown",
+ 0x32: "RFConfiguration",
+ 0x58: "RFRegulationTest",
+ 0x56: "InJumpForDEP",
+ 0x46: "InJumpForPSL",
+ 0x4A: "InListPassiveTarget",
+ 0x50: "InATR",
+ 0x4E: "InPSL",
+ 0x40: "InDataExchange",
+ 0x42: "InCommunicateThru",
+ 0x44: "InDeselect",
+ 0x52: "InRelease",
+ 0x54: "InSelect",
+ 0x60: "InPoll",
+ 0x8C: "TgInitAsTarget",
+ 0x92: "TgSetGeneralBytes",
+ 0x86: "TgGetData",
+ 0x8E: "TgSetData",
+ 0x94: "TgSetMetaData",
+ 0x88: "TgGetInitiatorCommand",
+ 0x90: "TgResponseToInitiator",
+ 0x8A: "TgGetTargetStatus",
+ }
+
+ PN532_BIT_RATES = {
+ 0x0: 106,
+ 0x1: 212,
+ 0x2: 424,
+ }
+
+ PN532_TAG_TYPES = {
+ 0x00: "Mifare, ISO 14443-3 A/B or ISO 18092 passive 106 kbps",
+ 0x10: "FeliCa or ISO 18092 passive 212/424 kbps",
+ 0x01: "ISO 18092 active",
+ 0x02: "Innovision Jewel",
+ }