Context
Hi! I'm a Windows dev building FFB tuning software that drives the RS50 / G PRO directly via the interface-2 stream (no Logitech SDK, no G HUB requirement) plus HID++ for settings. Your protocol docs (TRUEFORCE_PROTOCOL.md, PROTOCOL_SPECIFICATION.md) validated our implementation byte-for-byte — the 68-packet two-pass init, the type-0x01 pure-KF packet layout (bytes 6-9 cur, byte 10 = 0), the type-0x0e range patch (we replay the G HUB init with packet 50 rewritten to the wheel's own rotation, exactly your "90° on game launch" root cause), and the HID++ feature indices/SET fns (0x8138 fn2, 0x8137 fn2, 0x8139 fn3, 0x8133 fn1, 0x12 responses). Thank you for the reverse-engineering work — it's excellent.
Two questions from field experience on real RS50 hardware:
1. Idle whine at 0% force
With the stream active and 0% force commanded, users report an audible "bee"/dither from the TrueForce amplifier (one user described it as the motor vibrating/crunching; TF4ALL's README notes the same "wheel whines" when a TrueForce channel is held live). Your native libtrueforce runs a continuous 250 Hz stream — do you observe this whine at zero force on your hardware? Any mitigation beyond stopping the stream entirely?
Our current approach:
- The session stays in standby (connected, no init, no packets) until the app actually outputs force — so an idle app leaves the wheel completely untouched.
- At zero force while running, we write neutral once and then a keepalive every 250 ms (4 Hz), relying on the set-and-hold behavior and your documented ~1-minute session idle-revert.
Does a ~4 Hz keepalive cadence safely hold the session without stressing the amplifier, or is there a lower bound on the stream rate you'd recommend?
2. Session teardown semantics
We end a session by replaying init packets 67 (type 0x04 "stop/clear") + 68 (type 0x03 "start/play") followed by silence, which empirically releases the wheel back to its normal FFB path (game FFB works immediately after app close). Is the 67+68 replay the correct end-of-session handshake, or would a bare type-0x04 suffice? Understanding the exact teardown semantics matters for us because an abrupt close without it leaves the wheel in a stale session state that overrides all force paths until power-cycle (confirmed by your docs' set-and-hold + idle-revert behavior).
Context
Hi! I'm a Windows dev building FFB tuning software that drives the RS50 / G PRO directly via the interface-2 stream (no Logitech SDK, no G HUB requirement) plus HID++ for settings. Your protocol docs (
TRUEFORCE_PROTOCOL.md,PROTOCOL_SPECIFICATION.md) validated our implementation byte-for-byte — the 68-packet two-pass init, the type-0x01 pure-KF packet layout (bytes 6-9cur, byte 10 = 0), the type-0x0e range patch (we replay the G HUB init with packet 50 rewritten to the wheel's own rotation, exactly your "90° on game launch" root cause), and the HID++ feature indices/SET fns (0x8138 fn2, 0x8137 fn2, 0x8139 fn3, 0x8133 fn1, 0x12 responses). Thank you for the reverse-engineering work — it's excellent.Two questions from field experience on real RS50 hardware:
1. Idle whine at 0% force
With the stream active and 0% force commanded, users report an audible "bee"/dither from the TrueForce amplifier (one user described it as the motor vibrating/crunching; TF4ALL's README notes the same "wheel whines" when a TrueForce channel is held live). Your native
libtrueforceruns a continuous 250 Hz stream — do you observe this whine at zero force on your hardware? Any mitigation beyond stopping the stream entirely?Our current approach:
Does a ~4 Hz keepalive cadence safely hold the session without stressing the amplifier, or is there a lower bound on the stream rate you'd recommend?
2. Session teardown semantics
We end a session by replaying init packets 67 (type 0x04 "stop/clear") + 68 (type 0x03 "start/play") followed by silence, which empirically releases the wheel back to its normal FFB path (game FFB works immediately after app close). Is the 67+68 replay the correct end-of-session handshake, or would a bare type-0x04 suffice? Understanding the exact teardown semantics matters for us because an abrupt close without it leaves the wheel in a stale session state that overrides all force paths until power-cycle (confirmed by your docs' set-and-hold + idle-revert behavior).