From d7fb9654d3c0859410dd60deee7f720e1ca8e0c8 Mon Sep 17 00:00:00 2001 From: Niel Nielsen Date: Mon, 14 Sep 2026 16:23:38 +0200 Subject: [PATCH] fix(hitag): only one reply_ng on reader/writer abort path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ReaderHitag() and WriterHitag() double-replied on the abort path: when a new command arrives mid-loop, data_available() sets checked = -1 and breaks, then the out: block calls reply_ng(PM3_ESOFT) *and* falls through to a second reply_ng(PM3_SUCCESS/EFAILED) — two NG responses for one command. USB tolerates the stray frame, but over the BLE/FPC bridge the extra unsolicited response desyncs the pipeline and the device appears to stop responding until reconnect (reproducible with `lf hitag dump --pwd` on empty air, then any following command over BLE). Gate the final reply_ng behind an else so each command yields exactly one response on every path: abort -> PM3_ESOFT, otherwise -> PM3_SUCCESS/EFAILED. Signed-off-by: Niel Nielsen --- armsrc/hitag2.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 73cd36860..fd98999ad 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -3636,16 +3636,21 @@ out: // release allocated memory from BigBuff. BigBuf_free(); + // Exactly one NG response per command. On the abort path (checked == -1, + // a new command arrived while the reader loop was still running) send only + // the abort reply - falling through to a second reply_ng left the transport + // with a stray unsolicited frame, which the higher-latency BLE/FPC bridge + // desyncs on (USB tolerates it). if (checked == -1) { reply_ng(CMD_LF_HITAG_READER, PM3_ESOFT, NULL, 0); + } else { + reply_ng(CMD_LF_HITAG_READER + , (bSuccessful) ? PM3_SUCCESS : PM3_EFAILED + , (uint8_t *)tag.sectors + , tag_size + ); } - reply_ng(CMD_LF_HITAG_READER - , (bSuccessful) ? PM3_SUCCESS : PM3_EFAILED - , (uint8_t *)tag.sectors - , tag_size - ); - } void WriterHitag(const lf_hitag_data_t *payload, bool ledcontrol) { @@ -3976,15 +3981,20 @@ out: // release allocated memory from BigBuff. BigBuf_free(); + // Exactly one NG response per command. On the abort path (checked == -1, + // a new command arrived while the reader loop was still running) send only + // the abort reply - falling through to a second reply_ng left the transport + // with a stray unsolicited frame, which the higher-latency BLE/FPC bridge + // desyncs on (USB tolerates it). if (checked == -1) { reply_ng(CMD_LF_HITAG2_WRITE, PM3_ESOFT, NULL, 0); + } else { + reply_ng(CMD_LF_HITAG2_WRITE + , (bSuccessful) ? PM3_SUCCESS : PM3_EFAILED + , (uint8_t *)tag.sectors + , tag_size + ); } - - reply_ng(CMD_LF_HITAG2_WRITE - , (bSuccessful) ? PM3_SUCCESS : PM3_EFAILED - , (uint8_t *)tag.sectors - , tag_size - ); }