From 042f49a9ec32ea5435794ed01d653dc0d573653f Mon Sep 17 00:00:00 2001 From: michael Date: Tue, 7 Jul 2026 10:04:44 -0700 Subject: [PATCH] fix(sim): bound 14a sim abort latency + detect teardown host-side Bump firmware pin to 3b6201d97, which bounds the 14a sim button / host-stop latency under continuous reader traffic (was multi-second, now ~10ms). SimSession now treats an HF_MIFARE_SIMULATE (0x0610) reply as end-of-sim for 14a: the sim starts with HF_ISO14443A_SIMULATE but the firmware tears down with HF_MIFARE_SIMULATE, so _trace_reader and _relay_loop watch for it and flip _active off on a button-driven stop (previously the host never noticed). Co-Authored-By: Claude Opus 4.8 --- firmware | 2 +- pm3py/_firmware.py | 2 +- pm3py/sim/sim_session.py | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/firmware b/firmware index 303bd58..3b6201d 160000 --- a/firmware +++ b/firmware @@ -1 +1 @@ -Subproject commit 303bd5873cac455d238968bf67c4b437090eb88b +Subproject commit 3b6201d972be07a08ca4f68910ecdabc40d6a9d9 diff --git a/pm3py/_firmware.py b/pm3py/_firmware.py index e7994f6..8dd7a4f 100644 --- a/pm3py/_firmware.py +++ b/pm3py/_firmware.py @@ -21,7 +21,7 @@ class FirmwarePin: # The firmware/ submodule commit this pm3py build was developed and tested against. -FIRMWARE_PIN = FirmwarePin(sha="303bd5873") +FIRMWARE_PIN = FirmwarePin(sha="3b6201d97") def matches(version_string: str, pin: FirmwarePin = FIRMWARE_PIN) -> bool: diff --git a/pm3py/sim/sim_session.py b/pm3py/sim/sim_session.py index 3c1eee3..29b65f4 100644 --- a/pm3py/sim/sim_session.py +++ b/pm3py/sim/sim_session.py @@ -388,6 +388,15 @@ class SimSession: resp = decode_response_frame(bytes(buf[:frame_len])) buf = buf[frame_len:] + if resp["cmd"] == Cmd.HF_MIFARE_SIMULATE: + # 14a sim tore down (button press, host stop, or + # exit_after). The firmware starts the sim with + # HF_ISO14443A_SIMULATE (0x0384) but its teardown reply + # is HF_MIFARE_SIMULATE (0x0610) — watch for the latter. + self._active = False + print(f"[SimSession] 14a sim ended, status={resp['status']}") + return + if resp["cmd"] in _TRACE_CMDS: protocol = _TRACE_CMDS[resp["cmd"]] data = resp["data"] @@ -442,8 +451,9 @@ class SimSession: if resp is None: continue - elif resp.cmd == Cmd.HF_ISO15693_SIMULATE: - # Sim ended (firmware sent final reply) + elif resp.cmd in (Cmd.HF_ISO15693_SIMULATE, Cmd.HF_MIFARE_SIMULATE): + # Sim ended (firmware sent final reply). 15693 replies with + # HF_ISO15693_SIMULATE; 14a tears down with HF_MIFARE_SIMULATE. print(f"[SimSession] Sim ended, status={resp.status}") self._active = False break