7 Commits
Author SHA1 Message Date
22ce1d9ae5 RFID: choose which chip types a write may try (#1146)
* LFRFID: let a caller restrict which chips a write may target

The write loop tried every writable chip in turn - T5577, EM4305, then each
Hitag micro password variant - and verified after each one. A verify read
costs up to 2 s, so a pass that does not find the chip in front of you can
take 10 s before it starts over, most of it spent on chips the user knows are
not there.

Adds LFRFIDWriteTarget, which names a chip rather than an encoding: the Hitag
micro variants share one write type but differ by password, so each is its own
target. lfrfid_worker_set_write_targets() takes a mask of them, defaulting to
all, so a caller that never sets one behaves exactly as before.

lfrfid_settings holds that mask on the SD card next to the saved keys, so the
app, the CLI and any app writing through LFRFIDWorker agree on it without one
having to hand it to another.

The loop now intersects the mask with what the protocol can actually encode
for, once, before writing anything. That replaces the per-pass skip counter
(which re-fired "cannot be written" on every pass) and flattens the nested
variant loop into the single pass over targets.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* LFRFID: add a Settings menu with a Write Chips page

Settings sits at the bottom of the app menu and holds one page for now, where
each writable chip - T5577, EM4305 and the three Hitag micro / ID82xx variants
- can be switched on or off. Everything starts enabled, so a user who never
opens it sees no change.

The page itself lives in a plugin, loaded when the scene opens and unloaded
when it closes, since it is only reachable from one menu entry. The plugin
resolves against the firmware API alone - it needs no app-private symbols, so
there is no composite resolver or app symbol table here - and it is handed a
three-field context rather than LfRfid, which keeps the app's own layout out
of the plugin ABI.

The app keeps the VariableItemList: removing a view while it is the one on
screen latches the event loop stop, and the scene manager runs on_exit before
the previous scene's on_enter, so a plugin-owned view would be removed at
exactly the wrong moment. The list is reset before the plugin is freed, since
its change callbacks point into plugin code.

A missing or stale .fal costs only the ability to edit the setting: writes
read the mask from the settings file, not from the plugin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* LFRFID: say why a write cannot start instead of spinning

With every chip enabled the write screen always had something to try, so the
only failure it reported was the protocol being unwritable, and only after a
full pass. Now that chips can be switched off, two more ways to have nothing
to do exist, and they are worth telling apart: nothing enabled at all, and
nothing enabled that this protocol can be written to (HID, for instance, only
encodes for a T5577).

The check runs before the worker starts, so the error is immediate rather than
10 s of "Writing" first. Probing re-encodes the key, hence the snapshot before
it and the restore after.

The worker is only stopped on exit if it was actually started - stopping a
thread that never ran is not allowed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* LFRFID: honour the write chip setting in the CLI

rfid write drives the same worker as the app, so leaving it on the default
would have it quietly write to a chip the user switched off on the device.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* CHANGELOG: RFID write chip settings

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* LFRFID: rework the write chip settings after review

A 5-agent review and a 4-agent cleanup pass over the previous commits. The
feature is unchanged; what it costs and how it fails are not.

Settings file layout is no longer SDK ABI. saved_struct_load() copies as many
bytes as the *firmware* thinks the struct is, so exporting LFRFIDSettings meant
adding a field later would overflow the stack object of any .fap built against
the older header - and only the major API version gates loading, which this
would not have bumped. The struct, path, magic and version are now private to
lfrfid_settings.c and the SDK gets two scalar accessors.

A chip the user switched off is now its own outcome. The worker reported
LFRFIDWorkerWriteProtocolCannotBeWritten for both "this protocol has no
writable chip" and "every chip that could write it is disabled", so the CLI
told users their protocol was unwritable when the real fix was a setting. It
now reports LFRFIDWorkerWriteNoEnabledTarget for the second, which also lets
the write screen drop its own pre-flight probe: the scene ran the same
lfrfid_write_targets_supported() sweep the worker was about to run, purely to
pick the message, and paid a data snapshot/restore and a started-the-worker
flag for the privilege.

The settings page no longer leaves anything behind. variable_item_list_reset()
does not clear the enter callback - it lives outside the model and
set_enter_callback() rejects NULL - so a pointer into the unloaded plugin stayed
parked in app-owned state; the app now installs its own. The cached VariableItem
pointers are gone: they were justified by a deadlock that cannot happen (the
view model mutex is recursive, and subghz already calls
variable_item_list_get() from a change callback) and would have dangled once
the list outgrew M*LIB's initial capacity of 16.

A failed save is no longer silent. It reported nothing, and re-entering the page
showed the old values as though the user had chosen them. Saving moved to the
Back event, where the screen still belongs to this scene, and a failure goes
through dialog_message_show_storage_error() like the app's other storage errors.

The VariableItemList is allocated on first use. variable_item_list_alloc()
starts a periodic 333 ms timer it never stops, so allocating it at startup
capped tickless idle for the whole RFID session over a screen most users never
open.

Also: the static assert forbade the append the header told you to make, so
appending a target broke the build with a message about Hitag; the two ordering
asserts and the variant subtraction are replaced by a table whose rows state
their own variant. lfrfid_write_target_type() lost its default label, so
-Wswitch now forces a new target to be classified at compile time. The plugin
ABI lost its context struct - a page gets the list and the scene owns the view
switch, matching subghz. Four helpers with no caller outside the firmware are
marked "-" rather than exported for good. The plugin load shows the loading
animation and names the loader error, which separates a missing .fal from a
stale one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* LFRFID: second review pass over the write chip settings

Nine more agents over the reworked code. Four real defects, the rest comment
and shape corrections.

The lazily allocated VariableItemList was allocated before the plugin load, so
a failed load still started the periodic 333 ms timer the laziness exists to
avoid - for the rest of the session, on a screen the user could not use. It now
happens only once the page is known to be there.

lfrfid_settings_get_write_targets() stat'ed the file after trying to load it,
purely to pick a log level, so the missing-file case still went through
saved_struct_load()'s E log. It checks first and skips the load, which makes
the default path - every device whose owner never opened the screen - silent
again on every write.

The plugin-error popup was one character too long for the buffer and rendered
as "(error 1", because lfrfid_text_store_set() passed LFRFID_TEXT_STORE_SIZE
against a buffer that carries the extra byte for the terminator. Fixed at the
helper, so every caller gets its last character back.

The CLI never handled LFRFIDWorkerWriteTooLongToWrite, so a non-writable card
left it printing nothing while the app said "Still Trying to Write" on screen.
Both write callbacks now log an unhandled result instead of sending custom
event 0, which is not a LfRfidCustomEvent and would be dropped in silence.

Shape: the write scene's file static moved into the scene manager's own
per-scene state, lfrfid_settings_load() folded into its only caller, the write
loop's "done" flag stopped standing in for "never started", and the write type
switch lost its default so -Wswitch covers it like the target switch (a probe
build confirms an unclassified enumerator is now a build error). The <= 32
assert became < 32: at exactly 32 targets LFRFID_WRITE_TARGET_MASK_ALL shifts
by the full width of its type.

Comments: five said things that were not true - that the error code tells a
missing .fal from a stale one (plugin_manager collapses both into one value),
that a failed settings read had no other trace (saved_struct logs all four
causes), that the loading view swallows input (leaving it resets the input
queue), that opening the settings page writes a file, and that a scene's screen
belongs to the next scene by the time on_exit runs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* CHANGELOG: annotate the RFID write chip entry with its issue and PR

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: MX <10697207+xMasterX@users.noreply.github.com>
2026-09-14 08:40:22 +03:00
dd988ba449 bit_lib and nfc_util refactor (#3383)
* nfc_util functions for processing bytes moved into bit_lib
* bitlib test update
* bit_lib moved from lfrfid to standalone lib
* Added bit functions for any supported data types
* Error fix and api add
* Added test for 64
* Added doc
* Testcase for 64 rewrited
* Realization error fix
* API version bump
* sync api version, fix after-merge old libs usage
* fix build errors
* build fix
* fbt format

Co-authored-by: assasinfil <nfa57643@gmail.com>
Co-authored-by: gornekich <n.gorbadey@gmail.com>
Co-authored-by: あく <alleteam@gmail.com>
2024-02-14 11:41:42 +07:00
hedgerandあく f9730bcafe fbt: lint fixes (#2008)
* lint: exclude "lib" subfolder from naming checks; fbt: moved LINT_SOURCES from literal strings to Dir() nodes
* lint: also exclude hidden directories

Co-authored-by: あく <alleteam@gmail.com>
2022-11-12 19:03:22 +09:00
hedgerandあく ebc2b66372 fbt fixes for mfbt pt2 (#1951)
* fbt: split sdk management code
* scripts: fixed import handling
* fbt: sdk: reformatted paths
* scrips: dist: bundling libs as a build artifact
* fbt: sdk: better path management
* typo fix
* fbt: sdk: minor path handling fixes
* toolchain: fixed windows toolchain download
* fbt: minor refactorin
* fbt: moved sdk management code to extapps.scons
* fbt: fixed sdk symbols header path; disabled -fstack-usage
* fbt: changed pathing for .py scripts
* fbt: changed SDK_HEADERS pathing; added libusb to SDK; added icon_i.h to SDK; added hw target to SDK meta
* fbt: added libusb headers to SDK
* picopass: include cleanup; api: added subghz/registry.h; api: added mbedtls to exported headers
* picopass: fixed formatting
* fbt: fixed COPRO_ASSETS_SCRIPT
* sdk: added basic infrared apis
* toolchain: added ufbt to list of legal fbtenv callers; updated error messages
* fbt: changed manifest collection & icon processing code
* fbt: simpler srcdir lookup
* toolchain: path management fixes; fbt: fixes for fap private libs paths
* scripts: toolchain: reworked download on Windows
* toolchain: v17
* scripts: added colorlog for logging
* Github: fix unit tests

Co-authored-by: あく <alleteam@gmail.com>
2022-11-03 00:15:40 +09:00
hedgerandあく 8b7a52b97b fbt: fixed linter paths (#1930)
* fbt: fixed linter paths
* lint: changed file permissions

Co-authored-by: あく <alleteam@gmail.com>
2022-10-27 05:25:31 +09:00
hedgerandあく ed385594a3 faploader: more subsystem headers in API table (#1742)
* faploader: more subsystem headers in API table; not counting header entries for SDK version change
* subghz: removed dead function
* Adjusted API version
* hal: removed furi_hal_power_get_system_voltage
* lib: mbedtls: additional flags for .fap linkage
* fbt: rebuilding assets when git commit id changes
* fbt: removed assets rebuild on git commit id change; added explicit dependency for SDK source on compiled assets parts; removed unneeded sdk regeneration runs
* fbt: changed stock plugins to EXTERNAL apps; restored building app as a PLUGIN as a part of main fw as well as a .fap; readme fixes
* fbt: restored certain apps to PLUGIN type
* fbt: app manifests: renamed version->fap_version, added extra fields
* fbt: fixed version processing after rename

Co-authored-by: あく <alleteam@gmail.com>
2022-09-19 21:39:00 +09:00
9bfb641d3e [FL-2529][FL-1628] New LF-RFID subsystem (#1601)
* Makefile: unit tests pack
* RFID: pulse joiner and its unit test
* Move pulse protocol helpers to appropriate place
* Drop pulse_joiner tests
* Generic protocol, protocols dictionary, unit test
* Protocol dict unit test
* iButton: protocols dictionary
* Lib: varint
* Lib: profiler
* Unit test: varint
* rfid: worker mockup
* LFRFID: em4100 unit test
* Storage: file_exist function
* rfid: fsk osc
* rfid: generic fsk demodulator
* rfid: protocol em4100
* rfid: protocol h10301
* rfid: protocol io prox xsf
* Unit test: rfid protocols
* rfid: new hal
* rfid: raw worker
* Unit test: fix error output
* rfid: worker
* rfid: plain c cli
* fw: migrate to scons
* lfrfid: full io prox support
* unit test: io prox protocol
* SubGHZ: move bit defines to source
* FSK oscillator: level duration compability
* libs: bit manipulation library
* lfrfid: ioprox protocol, use bit library and new level duration method of FSK ocillator
* bit lib: unit tests
* Bit lib: parity tests, remove every nth bit, copy bits
* Lfrfid: awid protocol
* bit lib: uint16 and uint32 getters, unit tests
* lfrfid: FDX-B read, draft version
* Minunit: better memeq assert
* bit lib: reverse, print, print regions
* Protocol dict: get protocol features, get protocol validate count
* lfrfid worker: improved read
* lfrfid raw worker: psk support
* Cli: rfid plain C cli
* protocol AWID: render
* protocol em4100: render
* protocol h10301: render
* protocol indala26: support every indala 26 scramble
* Protocol IO Prox: render
* Protocol FDX-B: advanced read
* lfrfid: remove unused test function
* lfrfid: fix os primitives
* bit lib: crc16 and unit tests
* FDX-B: save data
* lfrfid worker: increase stream size. Alloc raw worker only when needed.
* lfrfid: indala26 emulation
* lfrfid: prepare to write
* lfrfid: fdx-b emulation
* lfrfid: awid, ioprox write
* lfrfid: write t55xx w\o validation
* lfrfid: better t55xx block0 handling
* lfrfid: use new t5577 functions in worker
* lfrfid: improve protocol description
* lfrfid: write and verify
* lfrfid: delete cpp cli
* lfrfid: improve worker usage
* lfrfid-app: step to new worker
* lfrfid: old indala (I40134) load fallback
* lfrfid: indala26, recover wrong synced data
* lfrfid: remove old worker
* lfrfid app: dummy read screen
* lfrfid app: less dummy read screen
* lfrfid: generic 96-bit HID protocol (covers up to HID 37-bit)
* rename
* lfrfid: improve indala26 read
* lfrfid: generic 192-bit HID protocol (covers all HID extended)
* lfrfid: TODO about HID render
* lfrfid: new protocol FDX-A
* lfrfid-app: correct worker stop on exit
* misc fixes
* lfrfid: FDX-A and HID distinguishability has been fixed.
* lfrfid: decode HID size header and render it (#1612)
* lfrfid: rename HID96 and HID192 to HIDProx and HIDExt
* lfrfid: extra actions scene
* lfrfid: decode generic HID Proximity size lazily (#1618)
* lib: stream of data buffers concept
* lfrfid: raw file helper
* lfrfid: changed raw worker api
* lfrfid: packed varint pair
* lfrfid: read stream speedup
* lfrfid app: show read mode
* Documentation
* lfrfid app: raw read gui
* lfrfid app: storage check for raw read
* memleak fix
* review fixes
* lfrfid app: read blink color
* lfrfid app: reset key name after read
* review fixes
* lfrfid app: fix copypasted text
* review fixes
* lfrfid: disable debug gpio
* lfrfid: card detection events
* lfrfid: change validation color from magenta to green
* Update core_defines.
* lfrfid: prefix fdx-b id by zeroes
* lfrfid: parse up to 43-bit HID Proximity keys (#1640)
* Fbt: downgrade toolchain and fix PS1
* lfrfid: fix unit tests
* lfrfid app: remove printf
* lfrfid: indala26, use bit 55 as data
* lfrfid: indala26, better brief format
* lfrfid: indala26, loading fallback
* lfrfid: read timing tuning

Co-authored-by: James Ide <ide@users.noreply.github.com>
Co-authored-by: あく <alleteam@gmail.com>
2022-08-24 00:57:39 +09:00