Skip to content

hid-tmff2: add T500RS passive effects (spring, damper, friction, inertia) - #223

Draft
cazzoo wants to merge 4 commits into
Kimplul:masterfrom
cazzoo:t500rs/passive-effects
Draft

hid-tmff2: add T500RS passive effects (spring, damper, friction, inertia)#223
cazzoo wants to merge 4 commits into
Kimplul:masterfrom
cazzoo:t500rs/passive-effects

Conversation

@cazzoo

@cazzoo cazzoo commented Sep 10, 2026

Copy link
Copy Markdown

Stacked on the periodic/ramp PR (T500RS stack, after #221).

Extends the T500RS driver with condition (passive) effects: spring, damper, friction, and inertia.

Condition effects are the only family that occupy their own hardware slots: effect n gets slot n+1 with subtype channels derived from its logical id (param_sub = 0x0e + 0x1cn, env_sub = 0x1c + 0x1cn), so their 0x01/0x41 packets carry per-slot effect_ids and per-slot STOPs work. Each upload sends the 0x05 conditional packet twice (X axis on the parameter channel, Y axis on the envelope channel; the T500RS is a single-axis wheel).

Spring/damper/friction strength is capped by the corresponding module params (PARAM_SPRING_LEVEL and friends, advertised via the core params); coefficients are scaled to the device 0-10 range with rounding, center by /20, deadband by /65 (divisor unconfirmed), and saturation from the Linux range.

This completes the T500RS feature set.

Protocol reference updated: docs/T500RS_FFBEFFECTS.md gains the 0x05 condition section and condition rows in the slot/subtype and conversion sections.

cazzoo and others added 4 commits September 10, 2026 22:41
The input core invokes the FF gain and autocenter callbacks from
event context, which may run with IRQs disabled, and the sysfs gain
store calls them from process context. Model drivers issue blocking
HID output in these callbacks, which is illegal in atomic context
and races the effect worker on shared transfer buffers.

Route both through the existing effect workqueue instead: mark the
request pending in the device entry and apply it in the worker,
serialized with effect processing.

Gain follows the master x game model (as lg4ff): the sysfs gain
parameter acts as the master gain, the value written through the
input API is the game gain, and the worker sends their product to
the wheel via tmff2_scale_gain(). Both sources only mark the gain
pending; the worker recomputes the product from the live values on
each flush, so a sysfs change takes effect immediately without
having to replay the last in-game request.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add a T500RS driver on top of the core hid-tmff2 framework:

- HID-mode init sequence (0x42 sync, slot STOP sweep, 0x40 autocenter
  teardown, 0x43 gain default); the b65d bootloader -> b65e mode switch
  is handled by hid-tminit.
- Constant force effects only at this stage: hardware slot 0 with fixed
  subtypes (param 0x0e / env 0x1c), 0x03 level updates, mandatory
  zero-envelope 0x02, and a software expiry timer sending per-slot 0x41
  STOPs (the wheel never auto-stops on its own).
- Gain and range via the core parameters; autocentering routed through
  the core workqueue (T500RS callbacks do blocking HID I/O and must not
  run from atomic context).
- Protocol reference: docs/T500RS_FFBEFFECTS.md (constant force
  sections). The shared docs/FFBEFFECTS.md is renamed to
  docs/T300RS_FFBEFFECTS.md since it documents the T300RS protocol.
- udev rule for the SteamDeck variant.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Extend the T500RS driver with periodic (sine, square, triangle, saw) and
ramp effects.

The firmware has no periodic waveform engine, so these effects are
synthesized host-side: the first periodic/ramp upload declares slot 0 as
a sine (0x22) MAIN with the constant-force channels, and a software
synthesis engine computes the waveform, applies attack/fade envelopes in
software, sums in any playing constant force, and streams the combined
signed level as 0x04 0x0e packets from a delayed workqueue. Per-slot
periodic parameter declarations (0x04 with code != 0x0e) are known to
wedge the firmware and are never sent.

Periodic parameters (magnitude/offset/phase/period, ramp levels) never
travel the wire; FF_PERIODIC advertising also re-enables FF_RUMBLE via
the parent framework.

Protocol reference updated: docs/T500RS_FFBEFFECTS.md gains the 0x04
level-stream section; condition effects are still unsupported at this
stage.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…tia)

Extend the T500RS driver with condition (passive) effects: spring,
damper, friction, and inertia.

Condition effects are the only family that occupy their own hardware
slots: effect n gets slot n+1 with subtype channels derived from its
logical id (param_sub = 0x0e + 0x1c*n, env_sub = 0x1c + 0x1c*n), so
their 0x01/0x41 packets carry per-slot effect_ids and per-slot STOPs
work. Each upload sends the 0x05 conditional packet twice (X axis on
the parameter channel, Y axis on the envelope channel; the T500RS is a
single-axis wheel).

Spring/damper/friction strength is capped by the corresponding module
parameters (PARAM_SPRING_LEVEL and friends, advertised via the core
params); coefficients are scaled to the device 0-10 range with
rounding, center by /20, deadband by /65 (divisor unconfirmed), and
saturation from the Linux range.

This completes the T500RS feature set; the cumulative tree now matches
the full driver source of truth.

Protocol reference updated: docs/T500RS_FFBEFFECTS.md gains the 0x05
condition section and condition rows in the slot/subtype and conversion
sections.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@cazzoo
cazzoo force-pushed the t500rs/passive-effects branch from fe67a1e to f4eed4e Compare September 10, 2026 20:43
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