Skip to content

CI check: ESP32-S3 USB bridge backend - #1

Draft
cheetahdotcat wants to merge 7 commits into
masterfrom
esp32-bridge-pr
Draft

cheetahdotcat wants to merge 7 commits into
masterfrom
esp32-bridge-pr

Conversation

@cheetahdotcat

Copy link
Copy Markdown
Owner

Fork-internal draft to run CI before the upstream pull request.

Add BackendKind::esp32_bridge. An ESP32-S3 running the bridge firmware
enumerates as a composite USB device: a CDC-ACM control port plus two
slots that hold an XInput pad, a HID pad (DualSense, DualShock 4, Switch
Pro), or a shared keyboard and mouse. The host binds its inbox drivers.

- Wire protocol (esp32_bridge_protocol.h) shared with the firmware:
  COBS frames with CRC-16, layout transactions, input and output reports,
  keepalive. The bridge re-enumerates on every layout change; the client
  reopens the port, restores the desired layout after resets, and replays
  the latest gamepad report.
- platform_default switches to an attached bridge (USB serial LVHB-*),
  LVH_ESP32_PORT, or LVH_BACKEND=esp32_bridge unless
  Esp32BridgeOptions::autodetect is false; gamepads fall back to the
  platform backend when an implicitly selected bridge does not answer.
- Pairing: the bridge accepts layout and input frames only from hosts
  that answer an HMAC-SHA256 challenge with a secret it issued after a
  press of its BOOT button. Secrets are stored per bridge in a file only
  its owner (and SYSTEM/Administrators on Windows) can read. POSIX ports
  are opened with TIOCEXCL.
- lvh::find_esp32_bridge_ports() and lvh::esp32_bridge_status() report
  attached bridges and the connection and pairing state without opening
  a port.
- Build lizardbyte-common's env helper on every platform.
Use small structs for the key usage tables instead of std::pair built
from int literals (MSVC C4244), and a string_view for the auth context
instead of pointer arithmetic on a literal (-Wstring-plus-int).
Build the fixed-size auth message and AUTH payload as arrays and the
keyboard/mouse descriptor with a sized vector instead of repeated
vector::insert calls.
@cheetahdotcat

Copy link
Copy Markdown
Owner Author

Superseded by LizardByte#201.

- Replace the C protocol header with a C++ one (constexpr constants,
  std::span, std::optional frame decoding); the firmware keeps a C copy.
- Group BridgeClient state into per-mutex structs and move the frame
  handlers onto the connection state.
- Split frame accumulation out of the reader loop.
- Use std::byte for bit manipulation, std::format for messages, and
  std::array instead of C arrays.
- Split the fake firmware's frame handler in the tests and create test
  directories below the working directory.
@cheetahdotcat cheetahdotcat reopened this Oct 22, 2026
A layout change waited for a session that reported the new generation. If
the bridge reset again before the waiting thread woke up, the wait ran
into the re-enumeration timeout while holding the layout lock, which also
delayed restoring the layout after the reset. Record the last generation
a usable session reported and wait for that instead.
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