forza-trigger: rewrite
This commit is contained in:
@@ -171,7 +171,6 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
# PS5 DualSense adaptive triggers in Forza Horizon 4 / 5.
|
# PS5 DualSense adaptive triggers in Forza Horizon 4 / 5.
|
||||||
services.forzaTrigger.enable = true;
|
services.forzaTrigger.enable = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
# Forza emits a fixed-format UDP telemetry stream ("Data Out") at 60 Hz on a
|
# Forza emits a fixed-format UDP telemetry stream ("Data Out") at 60 Hz on a
|
||||||
# user-configured port. We listen on that port, parse each packet via fdp
|
# user-configured port. We listen on that port, parse each packet via fdp
|
||||||
# (nettrom/forza_motorsport, MIT), and drive the PS5 DualSense's adaptive
|
# (nettrom/forza_motorsport, MIT), and drive the PS5 DualSense's adaptive
|
||||||
# triggers via pydualsense (PyPI, MIT) which talks HID over hidraw.
|
# triggers via dualsense-controller (PyPI, MIT) which talks HID over hidraw.
|
||||||
#
|
#
|
||||||
# Setup on the user side, once enabled here:
|
# Setup on the user side, once enabled here:
|
||||||
# - plug the DualSense in over USB and disable Steam Input for the
|
# - plug the DualSense in over USB and disable Steam Input for the
|
||||||
@@ -23,11 +23,11 @@
|
|||||||
let
|
let
|
||||||
cfg = config.services.forzaTrigger;
|
cfg = config.services.forzaTrigger;
|
||||||
pythonPackages = import ./python-packages.nix { inherit lib pkgs; };
|
pythonPackages = import ./python-packages.nix { inherit lib pkgs; };
|
||||||
inherit (pythonPackages) pydualsense fdp;
|
inherit (pythonPackages) dualsense-controller fdp;
|
||||||
|
|
||||||
forzaTrigger = pkgs.writers.writePython3Bin "forza-trigger" {
|
forzaTrigger = pkgs.writers.writePython3Bin "forza-trigger" {
|
||||||
libraries = [
|
libraries = [
|
||||||
pydualsense
|
dualsense-controller
|
||||||
fdp
|
fdp
|
||||||
];
|
];
|
||||||
# The wrapped binary doesn't need style enforcement — readability of
|
# The wrapped binary doesn't need style enforcement — readability of
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -12,65 +12,64 @@ let
|
|||||||
py = python.pkgs;
|
py = python.pkgs;
|
||||||
in
|
in
|
||||||
rec {
|
rec {
|
||||||
# CFFI bindings to libhidapi (flok/hidapi-cffi on PyPI). pydualsense's
|
# DualSense controller library (yesbotics/dualsense-controller-python).
|
||||||
# `import hidapi` resolves to this — nixpkgs' python3Packages.hidapi is the
|
# Bundles its own hidapi-cffi binding; replaces the previous pydualsense +
|
||||||
# Cython wrapper from trezor/cython-hidapi which exposes a different
|
# hidapi-usb pair. The library's transport model writes the HID output
|
||||||
# `import hid` API and can't satisfy pydualsense.
|
# report on every input report tick BUT only when an output state actually
|
||||||
hidapi-usb = py.buildPythonPackage rec {
|
# changed since the last write — so we get on-demand HID writes for free
|
||||||
pname = "hidapi-usb";
|
# without disabling any background thread (the thing pydualsense made us
|
||||||
version = "0.3.2";
|
# work around at ~250 Hz). BT CRC32 is computed correctly inside the
|
||||||
format = "setuptools";
|
# library's Bt31OutReport.to_bytes.
|
||||||
|
dualsense-controller = py.buildPythonPackage rec {
|
||||||
|
pname = "dualsense-controller";
|
||||||
|
version = "0.3.1";
|
||||||
|
pyproject = true;
|
||||||
|
|
||||||
# PyPI's project URL slug uses a hyphen (`hidapi-usb`) but the sdist file
|
# PyPI normalizes the sdist filename to underscore form (PEP 625) but
|
||||||
# itself is PEP-625-normalized to an underscore (`hidapi_usb-…`). Stock
|
# the project URL slug is dasherized. fetchPypi assumes they match;
|
||||||
# fetchPypi assumes they match — they don't here, so fetch by direct URL.
|
# passing the underscored pname matches the on-disk filename.
|
||||||
src = pkgs.fetchurl {
|
src = py.fetchPypi {
|
||||||
url = "https://files.pythonhosted.org/packages/55/80/960ae94b615e26a7d1aeebe8e9fefda2f25608bf1016f9aec268b328c35e/hidapi_usb-${version}.tar.gz";
|
pname = "dualsense_controller";
|
||||||
hash = "sha256-oxp+2i+qqYd1uwiS2Dh8/PzO62iYQQXpR936MnDIFk0=";
|
inherit version;
|
||||||
|
hash = "sha256-yy1MQeRPqaLvoXaAigQd3gPFsFLbwKqrD4mP2zQqcFw=";
|
||||||
};
|
};
|
||||||
|
|
||||||
propagatedBuildInputs = [ py.cffi ];
|
nativeBuildInputs = [ py.poetry-core ];
|
||||||
|
|
||||||
# Upstream's hidapi.py walks a tuple of soname strings via ffi.dlopen()
|
# Upstream's pyproject pins pyee ^11 and cffi ^1.15. nixpkgs ships
|
||||||
# until one resolves. Pin the two Linux hidraw entries to absolute store
|
# pyee 13 and cffi 2. The library only uses stable APIs — pyee
|
||||||
# paths so the wrapped Python in our writePython3Bin closure finds them
|
# `EventEmitter`/`on`/`emit` and cffi `FFI`/`cdef`/`dlopen`/`new`/
|
||||||
# without LD_LIBRARY_PATH wrapping. The libusb / iohidmanager / dylib /
|
# `buffer` — that work unchanged on the newer versions. Relax both.
|
||||||
# dll entries are dead code on Linux. --replace-fail makes a rename in
|
pythonRelaxDeps = [
|
||||||
|
"pyee"
|
||||||
|
"cffi"
|
||||||
|
];
|
||||||
|
|
||||||
|
propagatedBuildInputs = with py; [
|
||||||
|
pyee
|
||||||
|
cffi
|
||||||
|
deprecated
|
||||||
|
];
|
||||||
|
|
||||||
|
# Same hidapi-binding pattern as our previous hidapi-usb derivation.
|
||||||
|
# The library walks a tuple of soname strings via ffi.dlopen() until
|
||||||
|
# one resolves; pin the two Linux hidraw entries to absolute store
|
||||||
|
# paths so the wrapped Python in writePython3Bin doesn't need
|
||||||
|
# LD_LIBRARY_PATH wrapping. The libusb / iohidmanager / dylib / dll
|
||||||
|
# entries are dead code on Linux. --replace-fail makes a rename in
|
||||||
# upstream's tuple a loud build error rather than a silent ImportError
|
# upstream's tuple a loud build error rather than a silent ImportError
|
||||||
# at runtime.
|
# at runtime.
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
substituteInPlace hidapi.py \
|
substituteInPlace src/dualsense_controller/core/hidapi/hidapi.py \
|
||||||
--replace-fail "'libhidapi-hidraw.so'," "'${pkgs.hidapi}/lib/libhidapi-hidraw.so'," \
|
--replace-fail "'libhidapi-hidraw.so'," "'${pkgs.hidapi}/lib/libhidapi-hidraw.so'," \
|
||||||
--replace-fail "'libhidapi-hidraw.so.0'," "'${pkgs.hidapi}/lib/libhidapi-hidraw.so.0',"
|
--replace-fail "'libhidapi-hidraw.so.0'," "'${pkgs.hidapi}/lib/libhidapi-hidraw.so.0',"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
pythonImportsCheck = [ "hidapi" ];
|
pythonImportsCheck = [ "dualsense_controller" ];
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "CFFI wrapper for hidapi (used by pydualsense)";
|
description = "Use DualSense Controller with Python";
|
||||||
homepage = "https://github.com/flok/hidapi-cffi";
|
homepage = "https://github.com/yesbotics/dualsense-controller-python";
|
||||||
license = lib.licenses.bsd3;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
pydualsense = py.buildPythonPackage rec {
|
|
||||||
pname = "pydualsense";
|
|
||||||
version = "0.7.5";
|
|
||||||
format = "pyproject";
|
|
||||||
|
|
||||||
src = py.fetchPypi {
|
|
||||||
inherit pname version;
|
|
||||||
hash = "sha256-YgX8AJE4f8p7geKT3xlCD0Mlh1GcyHpBz4rEIqdwKgs=";
|
|
||||||
};
|
|
||||||
|
|
||||||
nativeBuildInputs = [ py.poetry-core ];
|
|
||||||
propagatedBuildInputs = [ hidapi-usb ];
|
|
||||||
|
|
||||||
pythonImportsCheck = [ "pydualsense" ];
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
description = "Control your PS5 DualSense controller from Python";
|
|
||||||
homepage = "https://github.com/flok/pydualsense";
|
|
||||||
license = lib.licenses.mit;
|
license = lib.licenses.mit;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user