Files
Mykhailo ShevchukandClaude Opus 5 3433331e31 Infrared: fix ir universal rebooting the device, and the universal record lookup behind it (#1211)
The dictionary lookup in infrared_brute_force_calculate_messages was guarded by
furi_assert(record), which is compiled out whenever FURI_DEBUG is undefined. On every
release build, a database name the caller had not registered dereferenced NULL.

`ir universal <remote> <signal>` registers exactly one name and then walks the whole
database, so the first name that is not the one asked for crashed the device. Every
shipped database holds several distinct names, so the command rebooted the Flipper every
time it ran and could never have worked. The same crash was reachable from the Universal
screens with any user-supplied .ir database holding a button the screen does not use; the
six shipped ones are safe only because each scene happens to register a list that matches
its asset exactly.

A miss is skipped now, which is also the semantics the CLI wants - collect the records it
asked for, ignore the rest - so the command sends instead of crashing.

Three more things in the same code:

- calculate_messages reported success when a signal failed validation: error stayed
  InfraredErrorCodeNone, the loop broke, and the function returned clean. So a database
  holding an invalid signal validated clean.
- set_raw_signal ignores a signal with no timings and returns without touching the
  destination, so a raw entry with an empty data: left the previously read signal in
  place. Read as the entry after a parsed one, it passed infrared_signal_is_valid against
  that stale message, and its file position went into the dictionary to be transmitted
  later as whatever the signal object happened to hold. Reported at the read now, where
  every caller sees it - and it is the concrete asset that reaches the validation exit
  above.
- infrared_brute_force_reset did not clear db_filename, so a caller that forgot
  set_db_filename silently re-read the previous database. The CLI also stopped the
  instance a second time if the database disappeared between calculate_messages and
  start, since start stops itself on a failed open; dead code until the lookup fix made
  the path reachable.

The four universal database tests no longer register any names. Their assertion is that
every signal in the shipped asset parses and is valid, and the name lists were four
hand-maintained copies of the ones the app scenes keep - the drift that produced the test
bug fixed in #1199. fans.ir and leds.ir are covered now, so all six shipped databases are
tested instead of four, and one new test covers the dictionary hit, which nothing
exercised once the lists went.

Verified on an f7. Before, `ir universal tv Power` dropped USB and reset uptime from
137h3m52s to 12s. After, it reports "Sending 295 signal(s)..." and transmits; all six
remotes send (tv 295, audio 131, fans 116, leds 51, projectors 44, ac 31), the Universal
screens load and send unchanged, and uptime ran unbroken across the whole session. All
seven infrared unit tests pass on device.

Fixes #1201

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-11-10 14:35:04 +02:00
..
2024-07-15 20:02:45 +03:00