fix(hitag): only one reply_ng on reader/writer abort path

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 <nieldk@gmail.com>
This commit is contained in:
Niel Nielsen authored and GitHub committed 2026-09-14 16:23:38 +02:00
1 parent 5f641c6f75
commit d7fb9654d3
1 file changed
+22 -12
+22 -12
View File
@@ -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
);
}