Skip to content

libtrueforce

mescon edited this page Jul 20, 2026 · 1 revision

libtrueforce

A native Linux C implementation of the Logitech TrueForce SDK (trueforce_sdk_x64.dll, version 1.3.11), living at userspace/libtrueforce/. It lets native Linux applications drive TrueForce directly, no Wine involved: telemetry-driven haptic generators, custom test rigs, non-Steam game engines. Its first in-repo consumer is logi-tf-sim (Simulated TrueForce Internals).

It is not required for the Proton recipe: SDK games use Logitech's own signed DLLs through Wine (see Force Feedback in Games).

What it does

  • Talks to the wheel's interface-2 hidraw node directly, implementing the wire protocol documented in TrueForce Protocol: discovery, session bring-up (the 68-packet two-pass init), KF (constant-force) torque, TF (audio-haptic) streaming, gain, damping, pause/resume, and the version and capability getters. All verified end to end against a live RS50.
  • Supports the RS50 (046d:c276) and G Pro (046d:c272 / 046d:c268); the two wheels use byte-for-byte identical packets.
  • KF calls route through evdev on the same physical wheel; TF samples stream to the hidraw node at 1 kHz.

The API surface

include/trueforce.h mirrors the 62 named exports of the Windows SDK so a Linux app (or a Wine PE shim) can call the same API with minimal translation; Windows-isms (HANDLE, GUID, wide strings) are translated to plain C. Return codes are zero on success, negative errno-like on failure (LOGITF_ERR_INVALID_ARG, _NOT_FOUND, _NOT_SUPPORTED, _IO, _BUSY). The groups:

Group Representative calls
Module lifecycle dllOpen(), dllClose(), COM no-ops DllRegisterServer() / DllUnregisterServer()
Discovery logiTrueForceAvailable(index), logiTrueForceSupported(index), DirectInput-flavored variants
Session logiWheelOpenByDirectInputA/W(), logiWheelClose(), logiWheelSdkHasControl()
Versioning logiWheelGetCoreLibraryVersion(), logiWheelGetVersion()
Operating range logiWheelGet/SetOperatingRangeDegrees/Radians(), bounds getters, force mode
RPM / LEDs logiWheelGetRpmLedCaps(), logiWheelSetRpmLeds(), logiWheelPlayLeds(rpm, first, redline)
Angle logiTrueForceGetAngleDegrees/Radians(), angular velocity
Kinetic force (KF) logiTrueForceSetTorqueKF(nm), piecewise variant, clear, gain, max torque getters, reconstruction filter
TrueForce stream (TF) logiTrueForceSetTorqueTF{double,float,int8,int16,int32}(), logiTrueForceSetStreamTF(), clear, gain, rate bounds
Damping logiTrueForceSet/GetDamping(), GetDampingMax()
Haptic thread logiTrueForceGetHapticRate(), thread status
Pause / sync logiTrueForcePause/Resume/IsPaused/Sync()

Streaming semantics: all SetTorqueTF* / SetStreamTF calls feed a 4096-entry internal ring drained by a dedicated thread at the wheel's 1 kHz sample rate. If the ring fills, the calls block until space is available (up to ~4 s at full saturation); treat them as synchronous.

Linux-native extension

One API has no Windows counterpart: logitf_get_stream_feedback() exposes the wheel's type-0x02 responses collected while a stream is active (real-time wheel position on the same path and cadence as the stream, a device-side sample counter, and the still-undecoded motor/status fields). Useful for closed-loop haptics and for measuring the wheel's consumption rate.

Building and linking

cd userspace/libtrueforce
make                     # builds libtrueforce.so.1.3.11 and tests
sudo make install        # library + header under PREFIX (default /usr/local)
sudo make udev-install   # the hidraw access rule

Link with -ltrueforce and include <trueforce.h>. A static libtrueforce.a is also built (this is what logi-tf-sim links).

The udev rule (udev/99-logitech-trueforce.rules) grants read/write on the interface-2 hidraw node of the supported wheels to the input group and tags it uaccess for logind sessions. Replug the wheel after installing it.

Verify discovery:

./tests/discover
# libtrueforce 1.3.11
#   [0] available: supported=yes, paused=no

The LGPL boundary

libtrueforce is LGPL-2.1-or-later, while the rest of the repository is GPL-2.0-only. The intent: any application, including proprietary ones, may link libtrueforce (statically or dynamically) and drive TrueForce, but changes to the library itself must stay open. This is what lets the library serve as a general TrueForce ingest API for the Linux ecosystem, the same role the SDK DLL plays on Windows.

Safety

These are strong direct-drive wheels (RS50 up to 8 Nm, G PRO up to 11 Nm). The wheel may rotate when the kernel driver loads, on replug, on profile switch, and when the TrueForce init sequence first runs after library load (the first SetTorqueKF/SetTorqueTF* call in a session). Keep hands clear or firmly hold the rim at those moments. The library's test programs expect you to already be holding the wheel.

Clone this wiki locally