mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2026-10-23 12:52:23 +00:00
* 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>
29 lines
618 B
Python
29 lines
618 B
Python
Import("env")
|
|
|
|
env.Append(
|
|
LINT_SOURCES=[
|
|
Dir("."),
|
|
],
|
|
CPPPATH=[
|
|
"#/lib/lfrfid",
|
|
],
|
|
SDK_HEADERS=[
|
|
File("lfrfid_worker.h"),
|
|
File("lfrfid_raw_worker.h"),
|
|
File("lfrfid_raw_file.h"),
|
|
File("lfrfid_dict_file.h"),
|
|
File("lfrfid_settings.h"),
|
|
File("lfrfid_write_targets.h"),
|
|
File("protocols/lfrfid_protocols.h"),
|
|
],
|
|
)
|
|
|
|
libenv = env.Clone(FW_LIB_NAME="lfrfid")
|
|
libenv.ApplyLibFlags()
|
|
|
|
sources = libenv.GlobRecursive("*.c*")
|
|
|
|
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
|
|
libenv.Install("${LIB_DIST_DIR}", lib)
|
|
Return("lib")
|