Skip to content

Fix config parser silently dropping NFC/flash when touch/buzzer present#6

Open
balloob wants to merge 1 commit into
OpenDisplay:mainfrom
balloob:fix/config-parser-skip-unknown-packets
Open

Fix config parser silently dropping NFC/flash when touch/buzzer present#6
balloob wants to merge 1 commit into
OpenDisplay:mainfrom
balloob:fix/config-parser-skip-unknown-packets

Conversation

@balloob

@balloob balloob commented Jul 5, 2026

Copy link
Copy Markdown

Problem

The TLV config parser advances by a fixed size per packet and, on any unrecognized packet ID, its default case does offset = configLen - 2 (jump straight to the CRC) and stops — silently dropping every packet that follows the first unknown one.

Silabs implements cases for 0x01, 0x02, 0x04, 0x20, 0x21, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2A (NFC), 0x2B (flash), but has no case for 0x28 (touch_controller), 0x29 (passive_buzzer), or 0x2C (data_extended).

The Python client emits touch/buzzer before flash (0x2B) and NFC (0x2A). So a config that contains a touch or buzzer packet makes Silabs hit default at the touch packet, jump to the CRC, and never parse the flash or NFC packets — silently disabling NFC and external-flash feature init on the device.

Fix

Add handling for 0x28, 0x29, and 0x2C so the parser skips past them by their exact wire size (matching the existing 0x26 WiFi skip-by-size pattern), instead of falling into the default abort. Silabs does not consume touch/buzzer (handled by the main MCU) or data_extended (host-only strings), so skip-by-exact-size is the minimal fix that lets the packets after them (flash 0x2B, NFC 0x2A) parse. The default case is kept as the last-resort fallback for genuinely unknown IDs.

Packet sizes (cross-checked)

ID Packet Size (bytes) Source
0x28 touch_controller 32 Arduino struct TouchController (structs.h); Python serialize_touch_controller ("to 32 bytes")
0x29 passive_buzzer 32 Arduino struct PassiveBuzzerConfig (5×u8 + reserved[27]); Python serialize_passive_buzzer ("to 32 bytes")
0x2C data_extended 288 Arduino struct DataExtended (9×32-byte strings); Python serialize_data_extended ("to 288 bytes")

All three sizes match what the client actually serializes onto the wire.

Testing

  • gcc -fsyntax-only passes on the modified parser (local headers are self-contained). The full SLC / arm-none-eabi-gcc firmware build was not available in this environment, so it was not run here.
  • Verified the offset arithmetic with a standalone reproduction of the parse loop: a config containing touch (0x28) → flash (0x2B) → NFC (0x2A) now walks all three packets and reaches the CRC exactly, with the default abort never triggered.

Related

nRF firmware has the same gap and gets a companion PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_012g2e8mr132vcizx92WsgiR


Companion PR: OpenDisplay/Firmware_NRF#1 (same MJ-8 fix, nRF side — adds 0x2A/0x2B too). Sizes cross-validated: both derived 0x28=32, 0x29=32, 0x2C=288 independently.

The TLV config parser's default case jumps to the CRC (offset = configLen
- 2) on any unrecognized packet ID, silently dropping every packet that
follows. Silabs had no cases for 0x28 (touch_controller), 0x29
(passive_buzzer), or 0x2C (data_extended). The client emits touch/buzzer
before flash (0x2B) and NFC (0x2A), so a config containing a touch or
buzzer packet made Silabs abort mid-parse and never initialize its NFC +
external-flash features.

Add skip-by-size handling for these three packet IDs so later packets
still parse. Silabs does not consume touch/buzzer (handled by the main
MCU) or data_extended (host-only), so skip-by-exact-size is the minimum
fix. Sizes cross-checked against Arduino structs.h, the Python
config_serializer, and match the client wire format.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012g2e8mr132vcizx92WsgiR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant