New CLI command `lf cotag sim` with COTAG tag simulation implementation.
Detects COTAG reader activation sequence and emulates a COTAG tag.
Signed-off-by: andrej@towelbyte.net
It is a build product of `make pm5`, like the .bin next to it, and the
build recreates it, so the copy in the tree only went stale and made
every build touch it again.
Co-Authored-By: Claude Code <noreply@anthropic.com>
save_graphbuffer() and save_buffer8() calloc a copy, and the restore_*()
helpers only copy out of it, so every owner leaked its save state.
check_chiptype() lost 4 * g_GraphTraceLen bytes plus the packed demod
buffer on each online `lf search` (~2 MB after the COTAG probe), and the
Visa2000 demod leaked on every `lf search`, online or offline.
Add free_buffer_savestate() and call it after the last restore in
check_chiptype(), demodTI(), demodVisa2k(), demodzx(),
try_detect_modulation() and t55xx_psk_untrim_head(), including the
early-return and success paths that never restored.
Reported with the check_chiptype() diagnosis and fix by @BeheSQ.
Fixes#3675
Co-Authored-By: Grok Bot <noreply@users.noreply.github.com>
RF over CEP works now that the FPGA bitstream step is done - it was
never actually CEP-blocked. Note CMD_CEP_STATUS (Hardware Status
dashboard) and the real open bug (Read Hitag2 over CEP fails with
stale cached data, firmware-side). SPI bit-order/phase is confirmed,
not pending.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
For the Flipper Zero FAP's status page: hw status/CMD_STATUS replies
entirely via free-text Dbprintf packets the FAP's frame layer discards,
with nothing structured on the terminating ack. CMD_CEP_STATUS follows
the CMD_CAPABILITIES precedent instead - one binary cep_status_t reply
covering CEP handshake state, BWM battery telemetry, and a firmware
version string.
Always replies PM3_SUCCESS; fields for a feature this build lacks
(no WITH_CEP, no WITH_BWM_STATUS) read as zero rather than failing the
command, so any client can call it unconditionally. cep_attached isn't
included yet - its getter (cep_is_attached()) only exists on the
not-yet-merged WFI-skip responsiveness branch (#3687); can be appended
later following capabilities_t's own append-only convention.
Stacked on the pm5-bwm-battery-telemetry branch (CMD_PM5_BWM_GET_BATTERY),
which this command's battery field reuses via bwm_read_battery_info().
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The Flipper master only clocks the bus in bursts roughly every ~120ms
(its own idle poll cadence). CEP_SPI_BYTE_TIMEOUT (~3-10ms real time)
is ~20x shorter than that gap, so cep_spi_write_sync()'s first reply
byte - the one racing against the master's next poll - was giving up
long before the master actually showed up. Measured CEP reply success
at ~22% before this fix, ~100% after, across repeated LA-captured test
runs.
Fix: a separate, ~20x longer timeout (CEP_SPI_HEADER_BYTE_TIMEOUT) used
only for the first two length-header bytes of a reply - the ones that
can land in the gap. Every byte after that stays on the short timeout,
since once the master starts clocking it stays mid-CS and keeps going.
Also makes cep_spi_data_available() call cep_spi_resync() on its two
existing desync-evidence paths (sync-preamble discard overflow, an
implausible length header) instead of just returning false - those are
exactly the AT32 errata ES0003 corruption cep_spi_resync() already
exists to recover from; silently returning false left SPI1 in that bad
state until a later CRC/length check happened to catch it.
Stacked on fix-cep-spi-reliability (#3686, open) - this builds directly
on cep_spi_resync()/cep_spi_wait_tdbe()'s bounded-wait rewrite from that
PR and can't be tested standalone without it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>