Implement InListPassiveTargets response parsing for ISO 14443 B
Implement PC/SC ATR generation for ISO 14443 B
This commit is contained in:
parent
30828a01e8
commit
7bc2017424
|
@ -120,6 +120,15 @@ class PN532_Virtual_Card(Card):
|
||||||
len(target.ats), " ".join(map(lambda a: "%02X" % a, target.ats)))
|
len(target.ats), " ".join(map(lambda a: "%02X" % a, target.ats)))
|
||||||
|
|
||||||
result.append(s)
|
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
|
return result
|
||||||
|
|
||||||
|
|
50
readers.py
50
readers.py
|
@ -139,7 +139,8 @@ class ACR122_Reader(Smartcard_Reader):
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
self._parent = parent
|
self._parent = parent
|
||||||
self._name = self._parent.name+"-RFID"
|
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):
|
def pn532_transceive_raw(self, command):
|
||||||
c_apdu = "\xff\x00\x00\x00" + chr(len(command)) + 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 = utils.PN532_Frame(response)
|
||||||
r.parse_result(0)
|
r.parse_result(0)
|
||||||
if len(r.targets) > 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
|
return True
|
||||||
else:
|
else:
|
||||||
response = self.pn532_transceive("\xd4\x4a\x01\x03\x00")
|
response = self.pn532_transceive("\xd4\x4a\x01\x03\x00")
|
||||||
r = utils.PN532_Frame(response)
|
r = utils.PN532_Frame(response)
|
||||||
r.parse_result(3)
|
r.parse_result(3)
|
||||||
if len(r.targets) > 0:
|
if len(r.targets) > 0:
|
||||||
|
self._current_target_number, self._current_target = r.targets.items()[0]
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _internal_connect(self):
|
def _internal_connect(self):
|
||||||
|
@ -194,21 +196,37 @@ class ACR122_Reader(Smartcard_Reader):
|
||||||
|
|
||||||
def get_ATR(self):
|
def get_ATR(self):
|
||||||
# FIXME Properly implement for PC/SC version 2
|
# FIXME Properly implement for PC/SC version 2
|
||||||
if len(self._last_ats) == 0:
|
if self._current_target is None: return ""
|
||||||
return "\x3b\x80\x80\x01\x01"
|
|
||||||
|
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:
|
else:
|
||||||
# Quick and dirty: Extract historical bytes from ATS
|
return ""
|
||||||
hist_bytes = []
|
|
||||||
if self._last_ats[0] > 1:
|
# The ISO 14443-4 A or -3 B code paths should have filled the hist_bytes list
|
||||||
interface_bytes = 0
|
atr = [0x3b, 0x80 + len(hist_bytes), 0x80, 0x01] + hist_bytes
|
||||||
if self._last_ats[1] & 0x40: interface_bytes = interface_bytes + 1
|
atr.append( reduce(lambda a,b: a ^ b, atr) ^ 0x3b )
|
||||||
if self._last_ats[1] & 0x20: interface_bytes = interface_bytes + 1
|
return "".join(map(chr, atr))
|
||||||
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))
|
|
||||||
|
|
||||||
def transceive(self, data):
|
def transceive(self, data):
|
||||||
# FIXME Properly determine target number
|
# FIXME Properly determine target number
|
||||||
|
|
15
utils.py
15
utils.py
|
@ -531,6 +531,7 @@ class PN532_Response(PN532_Frame):
|
||||||
|
|
||||||
class PN532_Target(object):
|
class PN532_Target(object):
|
||||||
TYPE_ISO14443A = "ISO 14443-A"
|
TYPE_ISO14443A = "ISO 14443-A"
|
||||||
|
TYPE_ISO14443B = "ISO 14443-B"
|
||||||
def __init__(self, type):
|
def __init__(self, type):
|
||||||
self.type = type
|
self.type = type
|
||||||
|
|
||||||
|
@ -567,6 +568,20 @@ class PN532_Response_InListPassiveTarget(PN532_Response):
|
||||||
target.ats = []
|
target.ats = []
|
||||||
# ATS length does count length byte
|
# 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:
|
if last_pos == pos:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue