forza-trigger: patch dualsense-controller for vibration freq propagation
Live strace on yarn during gameplay revealed the daemon was correctly
calling effect.vibration(freq=35) on slip events, but the OUT report
on the wire showed mode=0x26 (VIBRATION) with byte 31 (param9 =
frequency) = 0. The controller firmware treats freq=0 as "no
oscillation" — trigger sits silent in vibration mode. That's why the
user reported "doesn't react to slipping or anything" even after the
pedal-off early-return fix.
Root cause is in dualsense-controller 0.3.1 itself:
- WriteStates.__init__ registers individual write-states for trigger
effect params 1-7 only. params 8/9/10 are not registered.
- update_out_report copies from per-state values to the OutReport,
again only params 1-7.
- The OutReport dataclass DEFINES params 1-10 (with defaults of 0)
and Usb01OutReport.to_bytes writes all 10 to the wire.
- effect.vibration() puts frequency in param9 — silently dropped.
- Same hits effect.machine() (params 8,9,10) and effect.galloping()
(param10). effect.feedback/weapon/bow only use params 1-7 so
they happen to work.
Fix is a small upstream-style patch added under patches/dualsense-
controller/ and wired into the dualsense-controller derivation in
hosts/yarn/forza-trigger/python-packages.nix via the patches attr:
in update_out_report, after the param7 assignments, read param8/9/10
directly from the parent TriggerEffect state value (which already
carries them correctly from the call site through _set_value).
Verified post-patch by source-reading the installed library:
out_report.left_trigger_effect_param9 = self.left_trigger_effect.value.param9
out_report.right_trigger_effect_param9 = self.right_trigger_effect.value.param9
(and 4 more for left/right param8/10)
Build-sandbox tests (54/54) pass via the forza-trigger-tests build
gate; full yarn NixOS closure builds clean.
Filing upstream against yesbotics/dualsense-controller-python is the
follow-up; until then this is a local patch.
This commit is contained in:
@@ -34,6 +34,17 @@ rec {
|
|||||||
hash = "sha256-yy1MQeRPqaLvoXaAigQd3gPFsFLbwKqrD4mP2zQqcFw=";
|
hash = "sha256-yy1MQeRPqaLvoXaAigQd3gPFsFLbwKqrD4mP2zQqcFw=";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
# Library bug fix: trigger-effect params 8-10 are never propagated to
|
||||||
|
# the OUT report. effect.vibration() puts the frequency in param9, so
|
||||||
|
# without this patch every vibration call ships frequency=0 to the
|
||||||
|
# controller and the trigger sits silently in vibration mode. The
|
||||||
|
# patch fixes update_out_report to read params 8/9/10 directly off
|
||||||
|
# the parent TriggerEffect state. Confirmed live with strace before
|
||||||
|
# patching: byte 31 (= L2 param9) was 0 every tick during slip events.
|
||||||
|
patches = [
|
||||||
|
../../../patches/dualsense-controller/0001-propagate-trigger-effect-params-8-10.patch
|
||||||
|
];
|
||||||
nativeBuildInputs = [ py.poetry-core ];
|
nativeBuildInputs = [ py.poetry-core ];
|
||||||
|
|
||||||
# Upstream's pyproject pins pyee ^11 and cffi ^1.15. nixpkgs ships
|
# Upstream's pyproject pins pyee ^11 and cffi ^1.15. nixpkgs ships
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
From: forza-trigger maintenance <none@local>
|
||||||
|
Date: 2026-05-07
|
||||||
|
Subject: [PATCH] WriteStates: propagate trigger-effect params 8-10
|
||||||
|
|
||||||
|
The library's update_out_report only copies trigger-effect params 1-7
|
||||||
|
from per-state values to the OUT report. Params 8/9/10 are never
|
||||||
|
propagated and stay at their OutReport-dataclass defaults of 0. This
|
||||||
|
silently breaks effects that use those slots — most painfully
|
||||||
|
effect.vibration() puts frequency in param9, so vibration mode ships
|
||||||
|
frequency=0 in the wire and the trigger does nothing while in
|
||||||
|
vibration mode. Confirmed live with strace on yarn: byte 31 (L2
|
||||||
|
param9) wire-byte was 0 every tick despite the daemon calling
|
||||||
|
effect.vibration(frequency=35).
|
||||||
|
|
||||||
|
Fix: read params 8-10 directly off the parent TriggerEffect state
|
||||||
|
(which already carries them correctly through _set_value), bypassing
|
||||||
|
the per-param individual states. No new WriteStateName enum members
|
||||||
|
needed.
|
||||||
|
|
||||||
|
Upstream: needs filing against yesbotics/dualsense-controller-python.
|
||||||
|
|
||||||
|
--- a/src/dualsense_controller/core/state/write_state/WriteStates.py
|
||||||
|
+++ b/src/dualsense_controller/core/state/write_state/WriteStates.py
|
||||||
|
@@ -269,6 +269,19 @@
|
||||||
|
WriteStateName.RIGHT_TRIGGER_EFFECT_PARAM6).value_raw
|
||||||
|
out_report.right_trigger_effect_param7 = self._get_state_by_name(
|
||||||
|
WriteStateName.RIGHT_TRIGGER_EFFECT_PARAM7).value_raw
|
||||||
|
+ # Library bug workaround: params 8-10 are never registered as
|
||||||
|
+ # individual write states so the per-param fan-out in
|
||||||
|
+ # _on_*_trigger_effect_changed drops them. Read directly off the
|
||||||
|
+ # parent TriggerEffect state. Without this, effect.vibration(freq=N)
|
||||||
|
+ # ships frequency=0 to the controller and the trigger sits silent
|
||||||
|
+ # in vibration mode (confirmed live with strace on yarn before
|
||||||
|
+ # patching: byte 31 = L2 param9 was 0 every tick).
|
||||||
|
+ out_report.left_trigger_effect_param8 = self.left_trigger_effect.value.param8
|
||||||
|
+ out_report.left_trigger_effect_param9 = self.left_trigger_effect.value.param9
|
||||||
|
+ out_report.left_trigger_effect_param10 = self.left_trigger_effect.value.param10
|
||||||
|
+ out_report.right_trigger_effect_param8 = self.right_trigger_effect.value.param8
|
||||||
|
+ out_report.right_trigger_effect_param9 = self.right_trigger_effect.value.param9
|
||||||
|
+ out_report.right_trigger_effect_param10 = self.right_trigger_effect.value.param10
|
||||||
|
|
||||||
|
def _create_and_register_state(
|
||||||
|
self,
|
||||||
Reference in New Issue
Block a user