diff options
author | Henryk Plötz <henryk@ploetzli.ch> | 2010-03-03 04:23:25 +0100 |
---|---|---|
committer | Henryk Plötz <henryk@ploetzli.ch> | 2010-03-03 04:23:25 +0100 |
commit | 7bc2017424cebb7dd40aa091838dfccb1469e340 (patch) | |
tree | ccc86d377a8bedadb8aa6f9ab680ceee88ce3fa1 | |
parent | 30828a01e8b623342f479cf668027ec141189ac4 (diff) |
Implement InListPassiveTargets response parsing for ISO 14443 B
Implement PC/SC ATR generation for ISO 14443 B
-rw-r--r-- | cards/pn532_card.py | 9 | ||||
-rw-r--r-- | readers.py | 50 | ||||
-rw-r--r-- | utils.py | 15 |
3 files changed, 58 insertions, 16 deletions
diff --git a/cards/pn532_card.py b/cards/pn532_card.py index 6bff738..bc84002 100644 --- a/cards/pn532_card.py +++ b/cards/pn532_card.py @@ -120,6 +120,15 @@ class PN532_Virtual_Card(Card): len(target.ats), " ".join(map(lambda a: "%02X" % a, target.ats))) result.append(s) + elif target.type == utils.PN532_Target.TYPE_ISO14443B: + s = s + ", ATQB: %s" % ( + " ".join(map(lambda a: "%02X" % a, target.atqb)) ) + + if len(target.attrib_res) > 0: + s = s + ", ATTRIB_RES (%i bytes): %s" % ( + len(target.attrib_res), " ".join(map(lambda a: "%02X" % a, target.attrib_res))) + + result.append(s) return result @@ -139,7 +139,8 @@ class ACR122_Reader(Smartcard_Reader): def __init__(self, parent): self._parent = parent self._name = self._parent.name+"-RFID" - self._last_ats = None + self._current_target = None + self._current_target_number = 0 def pn532_transceive_raw(self, command): c_apdu = "\xff\x00\x00\x00" + chr(len(command)) + command @@ -173,13 +174,14 @@ class ACR122_Reader(Smartcard_Reader): r = utils.PN532_Frame(response) r.parse_result(0) if len(r.targets) > 0: - self._last_ats = r.targets.values()[0].ats + self._current_target_number, self._current_target = r.targets.items()[0] return True else: response = self.pn532_transceive("\xd4\x4a\x01\x03\x00") r = utils.PN532_Frame(response) r.parse_result(3) if len(r.targets) > 0: + self._current_target_number, self._current_target = r.targets.items()[0] return True def _internal_connect(self): @@ -194,21 +196,37 @@ class ACR122_Reader(Smartcard_Reader): def get_ATR(self): # FIXME Properly implement for PC/SC version 2 - if len(self._last_ats) == 0: - return "\x3b\x80\x80\x01\x01" + if self._current_target is None: return "" + + hist_bytes = [] + + if self._current_target.type == utils.PN532_Target.TYPE_ISO14443A: + if len(self._current_target.ats) > 0: + # Quick and dirty: Extract historical bytes from ATS + ats = self._current_target.ats + if ats[0] > 1: + interface_bytes = 0 + if ats[1] & 0x40: interface_bytes = interface_bytes + 1 + if ats[1] & 0x20: interface_bytes = interface_bytes + 1 + if ats[1] & 0x10: interface_bytes = interface_bytes + 1 + hist_bytes = ats[ (2+interface_bytes): ] + if len(hist_bytes) > 15: hist_bytes = hist_bytes[:15] + else: + return "\x3b\x80\x80\x01\x01" + elif self._current_target.type == utils.PN532_Target.TYPE_ISO14443B: + hist_bytes = self._current_target.atqb[5:9] + self._current_target.atqb[5:12] + if len(self._current_target.attrib_res) > 0: + hist_bytes.append(self._current_target.attrib_res[0] & 0xf0) + else: + hist_bytes.append(0) else: - # Quick and dirty: Extract historical bytes from ATS - hist_bytes = [] - if self._last_ats[0] > 1: - interface_bytes = 0 - if self._last_ats[1] & 0x40: interface_bytes = interface_bytes + 1 - if self._last_ats[1] & 0x20: interface_bytes = interface_bytes + 1 - if self._last_ats[1] & 0x10: interface_bytes = interface_bytes + 1 - hist_bytes = self._last_ats[ (2+interface_bytes): ] - if len(hist_bytes) > 15: hist_bytes = hist_bytes[:15] - atr = [0x3b, 0x80 + len(hist_bytes), 0x80, 0x01] + hist_bytes - atr.append( reduce(lambda a,b: a ^ b, atr) ^ 0x3b ) - return "".join(map(chr, atr)) + return "" + + # The ISO 14443-4 A or -3 B code paths should have filled the hist_bytes list + atr = [0x3b, 0x80 + len(hist_bytes), 0x80, 0x01] + hist_bytes + atr.append( reduce(lambda a,b: a ^ b, atr) ^ 0x3b ) + return "".join(map(chr, atr)) + def transceive(self, data): # FIXME Properly determine target number @@ -531,6 +531,7 @@ class PN532_Response(PN532_Frame): class PN532_Target(object): TYPE_ISO14443A = "ISO 14443-A" + TYPE_ISO14443B = "ISO 14443-B" def __init__(self, type): self.type = type @@ -567,6 +568,20 @@ class PN532_Response_InListPassiveTarget(PN532_Response): target.ats = [] # ATS length does count length byte + elif baudrate_polled == 3: + target = PN532_Target(PN532_Target.TYPE_ISO14443B) + self.targets[response[pos]] = target + + target.atqb = response[(pos+1):(pos+13)] + pos = pos + 13 + + if response[pos] > 0: + target.attrib_res = response[pos+1:(pos+1+response[pos])] + pos = pos + response[pos] + else: + target.attrib_res = [] + pos = pos + 1 # ATTRIB_RES length does not count the length byte + if last_pos == pos: return False |