From cbfa03b7adee8f8f4463629fe9571d3bee8d04e5 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Fri, 7 Aug 2026 14:00:30 +0200 Subject: [PATCH] =?UTF-8?q?docs(host/pads):=20the=20SC2's=20bInterval=20is?= =?UTF-8?q?=20already=201=20kHz=20=E2=80=94=20don't=20"fix"=20it=20to=2025?= =?UTF-8?q?0=20Hz?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Working G14/G18 turned up two sweep findings that do not survive contact with the code. Neither is implemented; one is now guarded. The 2026-08-07 sweep read the Triton (Steam Controller 2) usbip endpoint's `bInterval: 1` as 125 µs — an 8 kHz duplicate storm — and the plan's G14 says to raise it to 4 "like the Deck". That reading assumes a high-speed device, where bInterval is the 2^(n-1) × 125 µs exponent. Both Triton devices declare `UsbSpeed::Full`, and on a full-speed device the field is a plain frame count in milliseconds: 1 means 1 ms, which is the 1 kHz the existing comment claims. Raising it to 4 would mean 4 ms — a 4× cut to the motion rate a passed-through SC2 delivers, in the name of fixing a problem it doesn't have. The endpoint now carries the reasoning so the next reader doesn't repeat it. G18's first bullet ("bound/rate-cap the host's rich-input channel; motion is unbounded") is stale rather than wrong — it was true of the tree the sweep read. Current main already routes rich input, motion included, through a 1024-deep `sync_channel` whose `offer()` helper `try_send`s and drops on full, ending the loop only on Disconnected. That is the same bounded-queue pattern the mic plane adopted for security-review S6. Nothing owed. G14's remaining bullet — DS/Deck neutral accel should read 1 g on the up axis instead of 0 g free-fall — is deliberately NOT done here. Which axis is up is precisely what G16's on-glass session measures: `switch_proto` documents the wire as z-up and its neutral ships +Z, but the Deck's kernel negates Z/RZ, so guessing would leave one backend confidently disagreeing with another. A wrong constant is worse than the current obviously-unset 0. Gate: fmt, build, clippy --all-targets -D warnings, and the test suites — green. --- crates/pf-inject/src/inject/linux/triton_usbip.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/pf-inject/src/inject/linux/triton_usbip.rs b/crates/pf-inject/src/inject/linux/triton_usbip.rs index 382f6644..0259d0fb 100644 --- a/crates/pf-inject/src/inject/linux/triton_usbip.rs +++ b/crates/pf-inject/src/inject/linux/triton_usbip.rs @@ -472,7 +472,13 @@ fn build_triton_device( address: addr, attributes: 0x03, // interrupt max_packet_size: 64, // wMaxPacketSize 0x0040 - interval: 1, // bInterval 1 — the real pad's 1 kHz + // bInterval 1 — the real pad's 1 kHz. ⚠ Do NOT "fix" this to 4: bInterval is only the + // 2^(n-1) × 125 µs exponent on a HIGH-speed device, and this one negotiates FULL speed + // (`dev.speed` below), where the field is a plain frame count in milliseconds. So 1 means + // 1 ms = 1 kHz, exactly as intended, and 4 would mean 4 ms = 250 Hz — a 4× cut to the + // motion rate a passed-through SC2 delivers. (A 2026-08-07 sweep read this as high-speed + // and called it an 8 kHz duplicate storm; it is neither.) + interval: 1, }; let mut dev = UsbDevice::new(0); dev.vendor_id = TRITON_VENDOR;