feat: v0.3.8 — full access control stack, GRANTED working, NTAG424 ISO7816 read, PN532 driver

This commit is contained in:
2026-06-07 21:01:41 +02:00
parent 1467fc4886
commit 29300732c1
4 changed files with 167 additions and 82 deletions

View File

@@ -302,7 +302,7 @@ class PN532_I2C:
# 0. Poll for tag — activate it for InDataExchange
uid = self.read_passive_target(timeout=timeout)
if uid is None:
return None
return None, None, None
utime.sleep_ms(100)
# 1. Select NDEF Application (D2 76 00 00 85 01 01)
@@ -310,37 +310,37 @@ class PN532_I2C:
0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01, 0x00]
resp = self._apdu(sel_app)
if not resp:
return None
return None, None
sw1, sw2 = resp[0], resp[1]
if sw1 != 0x90:
print('[pn532] select app failed: %02x %02x' % (sw1, sw2))
return None
return None, None
# 2. Select NDEF file (E1 04)
sel_file = [0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x04]
resp = self._apdu(sel_file)
if not resp:
return None
return None, None
sw1, sw2 = resp[0], resp[1]
if sw1 != 0x90:
print('[pn532] select file failed: %02x %02x' % (sw1, sw2))
return None
return None, None
# 3. Read first 2 bytes to get NDEF length
read_len = [0x00, 0xB0, 0x00, 0x00, 0x02]
resp = self._apdu(read_len)
if not resp or len(resp) < 4:
return None
return None, None
# resp = [len_hi][len_lo][SW1][SW2]
if len(resp) < 4:
return None
return None, None
sw1, sw2 = resp[2], resp[3]
if sw1 != 0x90:
print('[pn532] read len failed: %02x %02x' % (sw1, sw2))
return None
return None, None
ndef_len = (resp[0] << 8) | resp[1]
if ndef_len == 0:
return None
return None, None
# 4. Read NDEF data (max 200 bytes per read)
ndef_data = bytearray()
@@ -367,12 +367,12 @@ class PN532_I2C:
remaining -= chunk
if not ndef_data:
return None
return None, None
# 5. Parse NDEF message
# ndef_data = clean NDEF bytes, no response code prefix
if len(ndef_data) < 3:
return None
return None, None
flags = ndef_data[0]
type_len = ndef_data[1]
@@ -395,19 +395,21 @@ class PN532_I2C:
idx += type_len # skip type bytes
if idx + payload_len > len(ndef_data):
return None
return None, None
payload = ndef_data[idx:idx+payload_len]
# TextRecord: byte 0 = status (lang_len), then lang, then text
if len(payload) < 1:
return None
return None, None
lang_len = payload[0] & 0x3F
text_start = 1 + lang_len
if text_start > len(payload):
return None
return None, None
try:
return bytes(payload[text_start:]).decode('utf-8')
import ubinascii as _ub
uid_hex = _ub.hexlify(uid).decode()
return uid_hex, bytes(payload[text_start:]).decode('utf-8')
except Exception:
return None
return None, None