Skip to content

Sysfs API Reference

mescon edited this page Jul 20, 2026 · 1 revision

Sysfs API Reference

Every setting the hid-logitech-dd driver exposes, as sysfs attributes under:

/sys/bus/hid/devices/<DEVICE_ID>/

<DEVICE_ID> is typically 0003:046D:C276.XXXX (RS50), 0003:046D:C272.XXXX (G Pro Xbox/PC or RS50 in compat mode), or 0003:046D:C268.XXXX (G Pro PS/PC). To find your device path:

find /sys/bus/hid/devices -name "*046D*C276*"    # RS50 native
find /sys/bus/hid/devices -name "*046D*C27[28]*" # G Pro / compat
# or, path-stable across models:
H=$(ls -d /sys/class/hidraw/*/device/wheel_range | head -1 | xargs dirname)

Most attributes are shared between the RS50 and G Pro; per-model exceptions are called out inline. The friendly way to drive all of this is Configuring the Wheel; the wire-level encodings live in the Protocol Specification.

Mode and profile

wheel_mode (RW: desktop / onboard)

The operating mode. Desktop (profile 0): settings controlled by host software; sensitivity available. Onboard (profiles 1-5): settings stored in wheel profiles; brake force available.

wheel_profile (RW: 0-5)

The active profile: 0 = desktop mode, 1-5 = onboard slots.

wheel_profile_names (RW)

The five onboard slots' names, queried live from the wheel:

cat wheel_profile_names
# 1: RACE
# 2: DRIFT
# 3: PROFILE 3
# ...
echo "3:RACE" > wheel_profile_names   # rename slot 3

The wheel persists the name to its own NVM. On an RS50 the name may be up to 9 characters, may contain spaces, and is stored uppercased. A longer name is refused by the wheel itself and surfaces as -EIO; a bad slot or empty name gives -EINVAL.

Force feedback

wheel_range (RW: 90-2700 degrees)

Steering rotation range. On the G PRO PID (compat mode included) the write only takes effect while the wheel is in desktop mode; write 0 to wheel_profile first.

The driver re-reads the true range from the wheel every 20 seconds (paused while force feedback is actively playing). An external change is logged in dmesg (rotation range changed externally), the attribute is updated to the real value, and poll()ers are notified via sysfs_notify().

wheel_range_restore (RW: 0/1, default 1)

Automatic recovery from the launch-time 90° reset: some games' SDK sessions push an operating range of 90° once at session start via a TrueForce interface-2 packet, invisible to HID++ (see TrueForce Protocol). With this enabled the driver restores the pre-reset range automatically (detection to restore in under 100 ms once the poll samples the change).

Safety gates: fires only for an external silent change landing exactly on 90 (a game applying its real steering lock is respected); desktop mode only; the wheel must be stationary; restores only ever widen the range; at most 3 restores per session; an explicit wheel_range write supersedes any pending restore. 0 = detect-and-report only.

wheel_strength (RW: 0-100 %)

Overall force-feedback strength. 100% corresponds to the wheel's maximum torque (8.0 Nm on the RS50).

wheel_damping (RW: 0-100 %)

Wheel damping (firmware-side resistance when turning).

wheel_trueforce (RW: 0-100 %)

TrueForce haptic intensity. 0 disables.

wheel_brake_force (RW: 0-100 %, onboard mode only)

Brake pedal force threshold (load cell sensitivity). Returns -EPERM in desktop mode.

wheel_sensitivity (RW: 0-100, writes desktop mode only)

Shapes the steering response via feature 0x80A4: a 64-point cubic Bezier (G HUB's Sensitivity slider). Below 50 softens the response near centre, above 50 sharpens it, 50 reverts to the wheel's built-in curve. Reads return the last value written (write-through cache; the wheel has no read-back for the slider). Writes in onboard mode fail with -EPERM.

wheel_ffb_filter (RW: 1-15)

Force-feedback smoothing level. G HUB's labels: Minimum (1), Low (7), Medium (11), Maximum (15). Out-of-range values are clamped.

wheel_ffb_filter_auto (RW: 0/1)

Automatic FFB filter adjustment. The driver splits the wire flag byte across the two attributes: wheel_ffb_filter stamps the "user set this level" bit, this one toggles only the "auto mode" bit.

wheel_ffb_constant_sign (RW: 0/1, default 1)

Whether the driver inverts the sign of every FF_CONSTANT level. Wine's DirectInput-to-evdev translation and native evdev apps disagree on sign by one flip, and the driver cannot tell them apart at runtime:

  • 1 (default): invert. Correct for Wine/Proton games. If centring forces push the wheel away from centre, the toggle is at the wrong setting.
  • 0: pass-through. Correct for native evdev apps following Documentation/input/ff.rst (fftest, ffcfstress, custom tools).

Only affects FF_CONSTANT; all other effect types feel identical either way. Note: strong FFB when reverse-driving is the sim's physics surfacing through a direct-drive motor (verified identical on Windows), not a sign error.

wheel_spring_damping (RW: 0-100 %, default 25)

Synthetic damping applied to emulated FF_SPRING effects, as a percentage of a FF_DAMPER running the spring's own coefficient. The driver emulates condition effects host-side; loop latency on a low-friction direct-drive motor makes a stiff undamped game spring ring until the wheel's over-torque failsafe cuts power (observed live with AC EVO's map-load centring spring). Real wheels damp the spring inside the firmware servo loop; this knob restores that behaviour. 0 disables.

wheel_texture_route (RW: tf / kf, default tf)

Where vibration-class effects (FF_RUMBLE and periodics at 20 Hz or faster) are actuated:

  • tf (default): streamed on the wheel's TrueForce audio-haptic channel, the same physical path the Windows SDK uses for texture. Steering-shaping effects stay on the force channel, so rumble no longer modulates the steering axis.
  • kf: legacy; everything summed into the single steering force. Kept as a fallback and for A/B comparison.

The TrueForce session is brought up lazily on the first texture-class playback (dmesg: TrueForce texture channel ready); if init fails, texture falls back to the steering channel (degraded feel, never lost). Texture amplitude respects FF_GAIN and wheel_strength and is capped at half of full scale so a synthetic full-scale rumble cannot hijack steering torque.

wheel_calibrate (W: 0-65535)

Low-level centre calibration primitive: writes a raw 16-bit encoder value to adopt as the new centre (HID++ sub-device 0x05, page 0x812C). Use wheel_calibrate_here for the common case.

wheel_calibrate_here (W: any value)

One-shot "use the wheel's current physical position as the new centre"; performs the GET+SET internally, mirroring G HUB's Calibrate button. The wheel's firmware persists the new centre across power cycles.

LIGHTSYNC LEDs

The RS50 has 10 RGB LEDs in a strip across the faceplate, with 5 custom slots (0-4). These attributes exist on the RS50 in both native and compat enumeration. On a real G PRO they are hidden: that rim has level-based rev lights with no per-LED RGB, exposed as wheel_rev_level instead.

Workflow: select a slot, set direction/colors, apply:

echo 2 > wheel_led_slot
echo 1 > wheel_led_direction
echo "FF0000 FF0000 FF0000 FF0000 FF0000 FF0000 FF0000 FF0000 FF0000 FF0000" > wheel_led_colors
echo 1 > wheel_led_apply
Attribute Access Values Notes
wheel_led_slot RW 0-4 selects the active custom slot and renders it (on the wire a custom slot IS effect 5 + slot)
wheel_led_slot_name RW string, max 8 chars name of the selected slot, stored on the device
wheel_led_slot_brightness RW 0-100 per-slot brightness
wheel_led_direction RW 0-3 animation direction: 0 = L to R, 1 = R to L, 2 = inside out, 3 = outside in
wheel_led_colors RW 10 space-separated RRGGBB LED1 is leftmost
wheel_led_brightness RW 0-100 global brightness; changes made on the wheel's OLED are tracked and poll()able
wheel_led_effect RW 1-9 1-4 = built-in animations (inside-out, outside-in, R-to-L, L-to-R); 5-9 ARE the five custom slots. External effect changes are tracked
wheel_led_apply W 1 re-applies the current slot configuration

wheel_rev_level (RW: 0-10)

Rev-light level: how many LEDs are lit. Available on the real G PRO rim AND the RS50's strip (on the RS50 the fill renders the selected custom slot's stored colors and direction). Writes return immediately; the driver coalesces them and flushes only the newest level at G HUB's ~160 ms cadence, so a fast telemetry feeder always shows the latest value. The wheel reverts an unrefreshed level after a while; feeders should refresh at ~1 Hz or faster. Write wheel_led_effect to restore the normal idle pattern.

Pedals and handbrake

The pedal unit is a separate MCU (HID++ sub-device 0x02) applying a 64-point 0x80A4 response curve to each axis it reports (hardware-verified with a two-plateau curve). Each pedal <p> in {throttle, brake, clutch} has three attributes. They all write the single curve the axis holds, so the last write wins; to combine a deadzone with a custom shape, author it as one _curve upload (what the logi-dd editor does).

wheel_<p>_curve (RW)

The raw curve: reset for the built-in linear curve, or 2-64 whitespace-separated in:out pairs (0-65535, strictly increasing in, non-decreasing out, from 0:0 to 65535:65535; fewer than 64 pairs are resampled). Reads back "<loaded>/<max> points loaded" from the wheel, the honest motion-free check.

echo "0:0 19660:0 65535:65535" > wheel_throttle_curve   # dead until 30%
echo reset > wheel_throttle_curve

wheel_<p>_sensitivity (RW: 0-100, 50 = linear)

G HUB's simple slider; generates the same symmetric-Bezier curve G HUB uploads. Reads back the last written value.

wheel_<p>_deadzone (RW: "<lower> <upper>" percent)

Dead travel at each end. lower + upper must be at most 99; "0 0" reverts to the built-in curve.

wheel_response_curve (RW)

The steering axis's 64-point curve, same format as the pedal curves; the store behind G HUB's Sensitivity slider. wheel_sensitivity and this attribute write the same axis-0 curve, so the last one wins. Note the wheel sends no reports while held still, so an upload appears to do nothing until the wheel moves; cat reads the loaded point count back.

wheel_handbrake_curve / wheel_handbrake_sensitivity (RW)

Same shaping for the RS Shifter & Handbrake's analog axis (base axis 4, evdev ABS_Z). The handbrake input itself needs no configuration.

wheel_combined_pedals (RW: 0/1, desktop mode only)

G HUB's "combined pedals": merges throttle and brake into a single centred axis for legacy games (released = centre, one pedal up, the other down); the brake's own axis goes silent.

Identity

wheel_serial (RO)

The wheel's 12-character serial, read from HID++ DeviceInfo at init; matches the USB iSerial.

wheel_firmware (RO)

Firmware versions read at init: the base's active main firmware and the motor unit's servo firmware. Include this in bug reports.

base: U1 65.03.B0038
motor: SC 02.01.B0042

Oversteer compatibility aliases

Created for every wheel this driver binds, using the de-facto new-lg4ff attribute names and scales (raw device units, not percent) so Oversteer and similar tools work unmodified:

Attribute Values Notes
range 90-2700 same as wheel_range
gain 0-65535 same setting as wheel_strength, raw FF_GAIN scale; the two stay in sync
autocenter 0-65535 a real driver-emulated centring spring (also reachable via evdev FF_AUTOCENTER); games that write 0 before taking over FFB correctly disable it
spring_level / damper_level / friction_level 0-100, default 100 global output scales for the emulated effect classes; damper_level scales game DAMPER effects, the wheel's own firmware damping is wheel_damping

Debug

wheel_hidpp_debug (RW, root only, debug builds)

Raw HID++ command shell for protocol bring-up; only present when the module is built with CONFIG_HID_LOGITECH_HIDPP_DEBUG (make DEBUG=1). Write feature fn [params...] in hex, read the last response.

Error codes

Error Meaning
-ENODEV device not found or driver not ready
-EPERM operation not permitted in the current mode
-EINVAL invalid value
-ERANGE value out of range
-EOPNOTSUPP feature not supported by this device/firmware
-EIO communication error with the device (including wheel-refused values, like an over-length profile name)

Compat-mode notes (G PRO PID)

On 046d:c272 / 046d:c268 (real G PRO and RS50-in-compat), most settings work via fallback feature paths: wheel_range, wheel_strength, wheel_trueforce, wheel_damping, wheel_ffb_filter, wheel_profile and wheel_calibrate. LIGHTSYNC works the same as native on an RS50 in compat. wheel_brake_force, wheel_ffb_filter_auto and wheel_sensitivity are unsupported by the compat firmware surface and return -EOPNOTSUPP once their mode gating is satisfied; configure those via the wheel's OLED menu. Remember compat mode boots in onboard mode: write 0 to wheel_profile first for live host settings to take effect.

Clone this wiki locally