aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2023-10-08 21:21:52 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2023-10-08 21:21:52 +0300
commit3027994d340f09892efa08e22c1f2e1ae6d7010d (patch)
tree0676e7e8be81700622921d1d1b5e793d768226da
parent4445da64240e9d5867dfdfefed6052586fb1148b (diff)
downloadhid-tmff2-3027994d340f09892efa08e22c1f2e1ae6d7010d.tar.gz
hid-tmff2-3027994d340f09892efa08e22c1f2e1ae6d7010d.zip
docs: mostly tweak structure and formatting
+ Still have to check that everything renders properly on GitHub.
-rw-r--r--README.md182
-rw-r--r--docs/CONTRIBUTING.md122
-rw-r--r--docs/DRIVER.md49
-rw-r--r--docs/FFBEFFECTS.md558
-rw-r--r--docs/INTEGRATION.md6
-rw-r--r--docs/STRUCTURE.md42
-rw-r--r--docs/effects/FFBEFFECTS_T248.md7
-rw-r--r--docs/effects/FFBEFFECTS_T300RS.md541
8 files changed, 868 insertions, 639 deletions
diff --git a/README.md b/README.md
index 49e4282..683fb79 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,10 @@
-# Linux kernel module for Thrustmaster T300RS, T248 and TX(experimental) wheels
-> **DISCLAIMER:** The module is now ready for near-stable USE in most force feedback games, supports rangesetting as well as gain and autocentering along with most force feedback effects. While I haven't personally come across any crashes or lockups with this version, I can't promise that they won't occur under any circumstances.
+# Linux kernel module for Thrustmaster T300RS, T248 and TX (experimental) wheels
+
+> **DISCLAIMER:** The module is now ready for near-stable USE in most force
+> feedback games, supports rangesetting as well as gain and autocentering along
+> with most force feedback effects. While I haven't personally come across any
+> crashes or lockups with this version, I can't promise that they won't occur
+> under any circumstances.
![GitHub last commit (master)](https://img.shields.io/github/last-commit/Kimplul/hid-tmff2/master)
![License](https://img.shields.io/github/license/Kimplul/hid-tmff2)
@@ -7,98 +12,155 @@
## Description
-A Linux kernel module for Thrustmaster T300RS, T248, and TX (experimental support) wheels is a software component designed to enhance the compatibility and functionality of these popular racing wheel peripherals when used with Linux-based operating systems. This kernel module allows seamless integration of Thrustmaster wheels with the Linux kernel, providing users with a robust and feature-rich experience for gaming and other applications with working force feedback effects.
-I've been working on enhancing the real-time updating of effects, and although it's not flawless yet, the overall experience is gradually improving. There are a couple of issues, though. First, there might be occasional inaccuracies in how the effects compare to the Windows driver. Second, in certain games, the mapping of pedal inputs can be inconsistent. This means that while all pedals should be recognized by the games, they might not be mapped correctly.
+A Linux kernel module for Thrustmaster T300RS, T248, and TX
+(experimental support) wheels.
+
+I've been working on enhancing the real-time updating of effects, and although
+it's not flawless yet, the overall experience is gradually improving. There are
+a couple of issues, though. First, there might be occasional inaccuracies in how
+the effects compare to the Windows driver. Second, in certain games, the mapping
+of pedal inputs can be inconsistent. This means that while all pedals should be
+recognized by the games, they might not be mapped correctly.
## Installation
-You can either install this kernel module by using DKMS or manually building from source:
+
+You can either install this kernel module by using DKMS or
+manually building from source:
### Dependencies
-Kernel modules require kernel headers to be installed. Use any one of the right command for your distribution:
+
+Kernel modules require kernel headers to be installed. Use any
+one of the right command for your distribution:
+
```shell
-$ sudo apt install linux-headers-$(uname -r) #Debian-based
-$ sudo pacman -S linux-headers #Arch-based
-$ sudo yum install kernel-devel kernel-headers #Fedora-based
+sudo apt install linux-headers-$(uname -r) # Debian-based
+sudo pacman -S linux-headers # Arch-based
+sudo yum install kernel-devel kernel-headers # Fedora-based
```
#### Manual installation
+ Unplug wheel from computer
-+ Use the following commands in your terminal of choice:
-```shell
-git clone --recurse-submodules https://github.com/Kimplul/hid-tmff2.git
-cd hid-tmff2/src
-make
-sudo make install
-```
++ Run
+ ```shell
+ git clone --recurse-submodules https://github.com/Kimplul/hid-tmff2.git
+ cd hid-tmff2
+ make
+ sudo make install
+ ```
+ Plug wheel back in
+ Reboot *(Optional, yet Recommended)*
#### DKMS (Dynamic Kernel Module Support)
+
+ Unplug wheel from computer
-+ Clone the repo `git clone --recurse-submodules https://github.com/Kimplul/hid-tmff2.git`
-+ Use `sudo bash hid-tmff2/dkms/dkms-install.sh` on your terminal of choice
++ Run
+ ```shell
+ git clone --recurse-submodules https://github.com/Kimplul/hid-tmff2.git
+ cd hid-tmff2
+ sudo ./dkms/dkms-install.sh
+ ```
+ Plug wheel back in
+ Reboot *(Optional, yet Recommended)*
-> **NOTE:** See [here](https://github.com/Kimplul/hid-tmff2/wiki/Integrating-driver-into-distros) for install instructions for other linux distributions.
+> **NOTE:** See [INTEGRATION](./docs/INTEGRATION.md)
+> for install instructions for other linux distributions.
-> **NOTE:** On some systems, you will get an error/warning about SSL. This is normal for unsigned modules. For info on signing modules yourself (completely optional), see [here](https://www.kernel.org/doc/html/latest/admin-guide/module-signing.html?highlight=module%20signing).
+> **NOTE:** On some systems, you will get an error/warning about SSL. This is
+> normal for unsigned modules. For info on signing modules yourself
+> (completely optional), see
+> [here](https://www.kernel.org/doc/html/latest/admin-guide/module-signing.html?highlight=module%20signing).
-> **NOTE:** Thrustmaster TX wheels aren't supported by `hid-tminit` as of yet, meaning that TX wheels have to be initialized with `tmrd`. Please see https://github.com/Kimplul/hid-tmff2/issues/48.
+> **NOTE:** Thrustmaster TX wheels aren't supported by `hid-tminit` as of yet,
+> meaning that TX wheels have to be initialized with `tmdrv`. Please see
+> https://github.com/Kimplul/hid-tmff2/issues/48.
-> :warning: **NOTE:** There have been reports that this driver does not work if the wheel's firmware version is older than v. 31.
-> To update the firmware, you will have to fire up a Windows installation and update the firmware using the official Thrustmaster tools.
+> **WARNING:** There have been reports that this driver does not work if
+> the wheel's firmware version is older than v. 31. To update the firmware, you
+> will have to fire up a Windows installation and update the firmware using the
+> official Thrustmaster tools.
-> :warning: **NOTE:** There was a name change when adding support for the T248 from `hid-tmt300rs` to `hid-tmff-new`,
-> and you may have to uninstall the older version of the driver.
+> **WARNING:** There was a name change when adding support for the T248
+> from `hid-tmt300rs` to `hid-tmff-new`, and you may have to uninstall the older
+> version of the driver.
## Contribute to project
-This project wants help from people who can contribute. If you would like to help add a wheel to this driver, please have a look through the [wiki](https://github.com/Kimplul/hid-tmff2/wiki#how-to-add-in-support-for-a-new-t-series-wheel) and/or [CONTRIBUTING.md](./docs/CONTRIBUTING.md) for what might need to be done. If you have a wheel that's not on the list, but suspect it might fit into the driver, please feel free to open up an issue about it.
-Currently open requests for wheels:
-- [T500 RS](https://github.com/Kimplul/hid-tmff2/issues/18)
-- [T818](https://github.com/Kimplul/hid-tmff2/issues/58)
-- [T-GT II](https://github.com/Kimplul/hid-tmff2/issues/55)
-- [T128P](https://github.com/Kimplul/hid-tmff2/issues/67)
+
+This project wants help from people who can contribute.
+If you would like to help add a wheel to this driver,
+please have a look through `docs` and/or [CONTRIBUTING.md](./docs/CONTRIBUTING.md)
+for what might need to be done.
+
+If you have a wheel that's not not supported, but suspect it might fit into the
+driver, please feel free to open up an issue about it. Currently open requests
+for wheels:
+
++ [T500 RS](https://github.com/Kimplul/hid-tmff2/issues/18)
++ [T818](https://github.com/Kimplul/hid-tmff2/issues/58)
++ [T-GT II](https://github.com/Kimplul/hid-tmff2/issues/55)
++ [T128P](https://github.com/Kimplul/hid-tmff2/issues/67)
## FAQ (Frequently Asked Questions)
-+ Reportedly some games running under Wine/Proton won't recognize wheels without the official Thrustmaster drivers installed within the prefix. See [#46](https://github.com/Kimplul/hid-tmff2/issues/46#issuecomment-1199080845). For installation instructions, see [wiki](https://github.com/Kimplul/hid-tmff2/wiki). Note that you will still need the Linux driver, the Windows driver just installs some files needed by games to correctly recognize the Linux driver. The Windows driver itself does not work under Wine/Proton.
++ Reportedly some games running under Wine/Proton won't recognize wheels without
+ the official Thrustmaster drivers installed within the prefix. See
+ [#46](https://github.com/Kimplul/hid-tmff2/issues/46#issuecomment-1199080845).
+ For installation instructions, see
+ [DRIVER](./docs/DRIVER.md).
+
+ Note that you will still need
+ the Linux driver, the Windows driver just installs some files needed by games to
+ correctly recognize the Linux driver. The Windows driver itself does not work
+ under Wine/Proton.
-+ Until the updated `hid-tminit` is [upstreamed](https://github.com/scarburato/hid-tminit), you might want to blacklist the kernel module `hid-thrustmaster`. Do this with
- ```shell
- echo 'blacklist hid_thrustmaster' > /etc/modprobe.d/hid_thrustmaster.con
- ```
++ Until the updated `hid-tminit` is
+ [upstreamed](https://github.com/scarburato/hid-tminit), you might want to
+ blacklist the kernel module `hid-thrustmaster`. Do this with
+ ```shell
+ echo 'blacklist hid_thrustmaster' > /etc/modprobe.d/hid_thrustmaster.con
+ ```
-+ If you've bought a new wheel, you will most likely have to update the firmware through Windows before it will work with this driver.
++ If you've bought a new wheel, you will most likely have to update the firmware
+ through Windows before it will work with this driver.
-+ T300 RS has an advanced F1 mode that can be activated with an F1 attachment when in PS3 mode. The base wheel will also work in PS4 mode,
- but it's less tested and if you encounter issues with this mode, please feel free to open up an issue about it.
-
-+ T248 isn't as extensively tested as T300 RS, please see issues and open new ones if you encounter problems.
- There is currently no support for the built-in screen.
++ T300 RS has an advanced F1 mode that can be activated with an F1 attachment
+ when in PS3 mode. The base wheel will also work in PS4 mode, but it's less
+ tested and if you encounter issues with this mode, please feel free to open up
+ an issue about it.
-+ TX support is considered experimental, please see issues (especially https://github.com/Kimplul/hid-tmff2/issues/48) and open new ones
- if you encounter issues.
++ T248 isn't as extensively tested as T300 RS, please see issues and open new
+ ones if you encounter problems. There is currently no support for the built-in
+ screen.
-+ To change gain, autocentering etc. use [Oversteer](https://github.com/berarma/oversteer).
++ TX support is considered experimental, please see issues
+ (especially https://github.com/Kimplul/hid-tmff2/issues/48)
+ and open new ones if you encounter any problems.
+
++ To change gain, autocentering etc. use
+ [Oversteer](https://github.com/berarma/oversteer).
+ If a wheel has a deadzone in games, you can try setting up a udev rule:
-
- `/etc/udev/rules.d/99-joydev.rules`
+ `/etc/udev/rules.d/99-joydev.rules`
+
+ ``` SUBSYSTEM=="input", ATTRS{idVendor}=="044f",
+ ATTRS{idProduct}=="WHEEL_ID", RUN+="/usr/bin/evdev-joystick --evdev
+ %E{DEVNAME} --deadzone 0" ```
+
+ where `WHEEL_ID` is
+
+ | Wheel | WHEEL_ID |
+ |----------------------------|------------|
+ | T300 RS, PS3 normal mode | b66e |
+ | T300 RS, PS3 advanced mode | b66f |
+ | T300 RS, PS4 normal mode | b66d |
+ | T248 | b696 |
- ```
- SUBSYSTEM=="input", ATTRS{idVendor}=="044f", ATTRS{idProduct}=="WHEEL_ID", RUN+="/usr/bin/evdev-joystick --evdev %E{DEVNAME} --deadzone 0"
- ```
-
- where `WHEEL_ID` is
- | Wheel | WHEEL_ID |
- |----------------------------|------|
- | T300 RS, PS3 normal mode | b66e |
- | T300 RS, PS3 advanced mode | b66f |
- | T300 RS, PS4 normal mode | b66d |
- | T248 | b696 |
+ This should make sure that the wheel behaves like you'd want from a wheel.
- This should make sure that the wheel behaves like you'd want from a wheel.
++ There have been reports that some games work better with a different timer
+ period (see [#11](https://github.com/Kimplul/hid-tmff2/issues/11) and
+ [#10](https://github.com/Kimplul/hid-tmff2/issues/10)).
-+ There have been reports that some games work better with a different timer period (see [#11](https://github.com/Kimplul/hid-tmff2/issues/11) and [#10](https://github.com/Kimplul/hid-tmff2/issues/10)). To change the timer period, create `/etc/modprobe.d/hid-tmff-new.conf` and add `options hid-tmff-new timer_msecs=NUMBER` into it. The default timer period is 8, but numbers as low as 2 should work alright.
+ To change the timer period, create `/etc/modprobe.d/hid-tmff-new.conf`
+ and add `options hid-tmff-new timer_msecs=NUMBER` into it.
+ The default timer period is 8, but numbers as low as 2 should work alright.
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index db937a1..46b8b26 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -1,50 +1,110 @@
# Contributing
-## Overview
-This file contains general contributing information. This project is seeking for help from people who can contribute. If you have a wheel that's not on the list, but suspect it might fit into the driver, please feel free to open up an issue about it.
+## Overview This file contains general contributing information.
+
+This project is seeking for help from people who can contribute. If you have a
+wheel that's not on the list, but suspect it might fit into the driver, please
+feel free to open up an issue about it.
Currently open requests for wheels:
-- [T500 RS](https://github.com/Kimplul/hid-tmff2/issues/18)
-- [T818](https://github.com/Kimplul/hid-tmff2/issues/58)
-- [T-GT II](https://github.com/Kimplul/hid-tmff2/issues/55)
-- [T128P](https://github.com/Kimplul/hid-tmff2/issues/67)
++ [T500 RS](https://github.com/Kimplul/hid-tmff2/issues/18)
++ [T818](https://github.com/Kimplul/hid-tmff2/issues/58)
++ [T-GT II](https://github.com/Kimplul/hid-tmff2/issues/55)
++ [T128P](https://github.com/Kimplul/hid-tmff2/issues/67)
Other documents available are linked here:
-- [FFBEffects-T300RS](./FFBEffects-T300RS.md): Force Feedback Effects example for T300RS
-- [FFBEffects-T248](./FFBEffects-T248.md): Force Feedback Effects example for T248
-- [Structure](https://github.com/Kimplul/hid-tmff2/wiki#structure-of-the-thrustmaster-device-stack): Structure of Thrustmaster device stack
-- [TO-DO](./TODO.md): TO-DO list for maintainers
++ [FFBEEFFECTS](./FFBEFFECTS.md):
+ Force feedback effects example for T300RS and compatible wheels
-## How to add in support for a new T-series wheel?
-Should probably not be too often that you need this info, but essentially use wireshark like in the previous example, but spin up a Windows virtual machine and install the Thrustmaster drivers on to it, and pass the device to the virtual machine. I prefer to use `qemu` with `virt-manager` as a frontend. With the wheel working under Windows, install [fedit.exe](https://gimx.fr/download/b882e209a0ac023d03abbf560dfc3f25fe6367ca/fedit.zip) and methodically go through all effects the device supports and compare the USB packets the driver sends out. You should be able to build up a table of what each value in the USB packet means, see [FFBEffects-T300RS.md](./FFBEffects-T300RS.md) for an example of what I found out about the T300.
++ [STRUCTURE](./STRUCTURE.md):
+ Structure of Thrustmaster device stack
+
++ [TODO](./TODO.md):
+ TO-DO list for maintainers
## How to capture what effects a game sends to the driver?
-Use ffbwrap from ffbtools: [github:berarma/ffbtools](https://github.com/berarma/ffbtools)
-The documentation gives good examples, but tl;dr; For steam, insert the following into a game's launch options:
+
+Use ffbwrap from ffbtools:
+[github:berarma/ffbtools](https://github.com/berarma/ffbtools)
+
+The documentation gives good examples, but tl;dr; For steam, insert the following
+into a game's launch options:
+
```shell
-$ ffbwrap --logger=/home/$USER/game.log /dev/input/by-id/usb-Thrustmaster_Thrustmaster_T300RS_Racing_wheel-event-joystick -- %command%
+ffbwrap --logger=/home/$USER/game.log /dev/input/by-id/usb-Thrustmaster_Thrustmaster_T300RS_Racing_wheel-event-joystick -- %command%
```
-This will create a file called `game.log` (with additional timestamp) in your home directory. Preferably change the name to suit the game, but you do you.
-> **NOTE:** Most fixes presented in the documentation are more or less obsolete by now, but the tool is still very useful for logging purposes.
+This will create a file called `game.log` (with additional timestamp) in your
+home directory. Preferably change the name to suit the game, but you do you.
+
+> **NOTE:** Most fixes presented in the documentation are more or less obsolete
+> by now, but the tool is still very useful for logging purposes.
## How to capture what USB packets the driver sends to the device?
-I'd recommend [wireshark](https://www.wireshark.org/)
-Usb capture setup is fairly straightforward: [wireshark/CaptureSetup](https://wiki.wireshark.org/CaptureSetup/USB#linux)
+I'd recommend
+[wireshark](https://www.wireshark.org/)
+
+Usb capture setup is fairly straightforward:
+[wireshark/CaptureSetup](https://wiki.wireshark.org/CaptureSetup/USB#linux)
+
+Here's what I typically do when starting a capture:
+
++ Run `sudo modprobe usbmon`. This will load a kernel module that allows
+ Wireshark to read the USB packets.
+
++ Open wireshark with root privileges. There are some ways to allow wireshark to
+ access the packets with regular user privileges, I just haven't bothered with
+ it.
-Here's what I typically do when starting capturing:
++ Select `usbmon0` from the view that opens up by default.
+
++ The screen will quickly fill up with noise from other devices connected to the
+ computer, so you will have to filter out the noise.
+
++ Run `lsusb` in a terminal. Look for the T300 in the list, you should see
+ something like `Bus 001 Device 006: ID 044f:b66e ThrustMaster, Inc.
+ Thrustmaster T300RS Racing wheel`
+
++ From the previous command, the Bus and Device fields can be used to filter
+ out only packets from/to the device. To see all packets coming from the
+ wheel, add in a filter `usb.src ~ "1\.6\..*"`, where `1` is in this case
+ from the `Bus` field and `6` from the `Device` field. To see all packets
+ being sent to the device, use `usb.dst`.
+
++ This data is probably also filled with a lot of cruft. Data to/from
+ endpoint 2 is button state info, which is probably unnecessary. To see FFB
+ data being sent to the device, use endpoint 1, i.e. `usb.dst == "1.6.1"`.
+ `~` is a Perl-compliant regex operator, whereas `==` just matches the string
+ directly. To see both data coming from the device and going to it, use
+ `usb.dst == "..." || usb.src == "..."`.
+
++ There is also endpoint 0, `usb.src == "1.6.0"` but it doesn't seem to be
+ used for much.
+
++ Use the three buttons in the top left of the screen to start, stop and restart
+ captures.
+
++ Do whatever you want with the device, packets should automatically be
+ captured. When you want to save your capture to a file, stop the recording and
+ go to `File > Export Specified Packets` and make sure `Displayed` is selected.
+ This will apply the filter you've been using, and will only include the packets
+ that are visible in Wireshark, i.e. it applies the filter you've specified.
+
+> **NOTE:** Every time you unplug and replug your wheel, its `Device` field will
+> probably change.
+
+## How to add in support for a new T-series wheel?
-- Run `sudo modprobe usbmon`. This will load a kernel module that allows Wireshark to read the USB packets.
-- Open wireshark with root privileges. There are some ways to allow wireshark to access the packets with regular user privileges, I just haven't bothered with it.
-- Select `usbmon0` from the view that opens up by default.
-- The screen will quickly fill up with noise from other devices connected to the computer, so you will have to filter out the noise.
- - Run `lsusb` in a terminal. Look for the T300 in the list, you should see something like `Bus 001 Device 006: ID 044f:b66e ThrustMaster, Inc. Thrustmaster T300RS Racing wheel`
- - From the previous command, the Bus and Device fields can be used to filter out only packets from/to the device. To see all packets coming from the wheel, add in a filter `usb.src ~ "1\.6\..*"`, where `1` is in this case from the `Bus` field and `6` from the `Device` field. To see all packets coming from the device, use `usb.dst`.
- - This data is probably also filled with a lot of cruft. Data to/from endpoint 2 is button state info, which is probably unnecessary. To see FFB data being sent to the device, use endpoint 1, i.e. `usb.dst == "1.6.1"`. `~` is a Perl-compliant regex operator, whereas `==` just matches the string directly. To see both data coming from the device and going to it, use `usb.dst == "..." || usb.src == "..."`.
- - There is also endpoint 0, `usb.src == "1.6.0"` but it doesn't seem to be used for much.
-- Use the three buttons in the top left of the screen to start, stop and restart captures.
-- Do whatever you want with the device, packets should automatically be captured. When you want to save your capture to a file, stop the recording and go to `File > Export Specified Packets` and make sure `Displayed` is selected. This will apply the filter you've been using, and will only include the packets that are visible in Wireshark, i.e. it applies the filter you've specified.
+Should probably not be too often that you need this info, but essentially use
+wireshark like in the previous example, but spin up a Windows virtual machine
+and install the Thrustmaster drivers on to it, and pass the device to the
+virtual machine. I prefer to use `qemu` with `virt-manager` as a frontend.
-> **NOTE:** Every time you unplug and replug your wheel, its `Device` field will probably change.
+With the wheel working under Windows, install
+[fedit.exe](https://gimx.fr/download/b882e209a0ac023d03abbf560dfc3f25fe6367ca/fedit.zip)
+and methodically go through all effects the device supports and compare the USB
+packets the driver sends out. You should be able to build up a table of what
+each value in the USB packet means, see [FFBEFFECTS.md](./FFBEFFECTS.md)
+for an example of what I found out about the T300.
diff --git a/docs/DRIVER.md b/docs/DRIVER.md
new file mode 100644
index 0000000..053ee41
--- /dev/null
+++ b/docs/DRIVER.md
@@ -0,0 +1,49 @@
+There are some reports that games will work better with the Thrustmaster Windows
+drivers installed.
+
+# Installing the Windows drivers inside a proton prefix
+
+1. Install [protontricks](https://github.com/Matoking/protontricks).
+
+2. Download the
+ [Thrustmaster drivers](https://support.thrustmaster.com/en/product/t300rs-en/).
+
+3. Look up the ID of your game with `protontricks -s NAME`. For example:
+ ```shell
+ $ protontricks -s Dirt
+ Found the following games:
+ DiRT 3 Complete Edition (321040)
+ DiRT 4 (421020)
+ DiRT Rally (310560)
+ DiRT Rally 2.0 (690790)
+
+ To run Protontricks for the chosen game, run: $ protontricks APPID COMMAND
+
+ NOTE: A game must be launched at least once before Protontricks can find the
+ game.
+ ```
+
+4. Run the driver installer with protontricks.
+ ```shell
+ protontricks -c 'wine ~/Downloads/DRIVER_INSTALL_EXE' APPID
+ ```
+
+ Dirt 4 for example:
+ ```shell
+ protontricks -c 'wine ~/Downloads/2022_TTRS_1.exe' 421020
+ ```
+
+Note that `protontricks` may change the working directory, so relative paths may
+end up not working as expected.
+
+# Installing the Windows drivers manually
+
+Assuming you've already downloaded the installer:
+
+```shell
+WINE_PREFIX=/path/to/prefix wine ./DRIVER_INSTALL_EXE
+```
+
+[Lutris](https://lutris.net/) is an excellent way to keep track of which
+non-steam games exist in which prefixes, and allows you to run executables in
+prefixes from a GUI if that's more your thing.
diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md
new file mode 100644
index 0000000..e2b3edc
--- /dev/null
+++ b/docs/FFBEFFECTS.md
@@ -0,0 +1,558 @@
+# Force Feedback Effects - Thrustmaster T300RS and compatible
+
+Here I will gather all info I can find out about the different force feedback
+effects and their USB commands. All values seem to be little-endian.
+
+Also, general note, it seems like some effects are affected by the direction of
+the force, denoted by `***`. As far as I can tell, `fade_level` and
+`attack_level` values are calculated by mapping the `u16` into `s16` and taking
+the absolute value, and after that multiplying by the direction.
+
+A full list of wheels that use USB packets in the format documented here is yet
+to be determined, but at least T300, T248 and TX seem to use it. Each wheel may
+have model specific peculiarities, though.
+
+> **NOTE:** All values are examples of actual commands that I captured on the
+> USB interface, not the only available ones.
+
+## GENERAL
+### Playing
+```
+ 60 00 - standard header
+ 01 - ID
+ 89 - playing options
+ 01 - play
+ 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+### Stopping/removing (why are they rolled into one?)
+```
+ 60 00 - standard header
+ 01 - ID
+ 89 - playing options
+ 00 - stop
+ 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+## Open:
+```
+ 60 01 - standard header?
+ 04 - ?
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ (this command doesn't appear every time, odd)
+ 60 12 - ?
+ bf 04 00 00 03 b7 1e - ? /* wow, this is different on different wheels? */
+ 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ 60 01 - ?
+ 05 - ?
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+## Close:
+```
+ 60 01 - standard header?
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+## Rotation angle:
+```
+ 60 08 - header plus settings?
+ 11 - set rotation angle
+ 55 d5 - angle (between ff ff and 7b 09, one degree is roughly 3c)
+ 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+## FF_AUTOCENTER:
+```
+ 60 08 - header plus settings?
+ 03 - set autocenter force
+ 8f 02 - force (between ff ff and 00 00)
+ 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+## FF_GAIN:
+```
+ 60 02 - header plus gain?
+ bf - gain (between ff and 00)
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+## FF_CONSTANT
+### Initialization
+```
+ 60 00 - standard header
+ 01 - ID
+ 6a - new constant effect(?)
+ fe ff - strength ***
+ 00 00 - attack_length
+ 00 00 - attack_level ***
+ 00 00 - fade_length
+ 00 00 - fade_level ***
+ 00 4f - ?
+ f7 17 - time in milliseconds, unsigned
+ 00 00
+ 07 00 - offset from start(?)
+ 00 ff ff - end of new effect(?)
+ 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+### Modifying (For dynamic updating of effects)
+
+#### Direction: ``N/A``
+
+#### Constant force:
+```
+ 60 00 - standard header
+ 01 - ID
+ 0a - modify constant force
+ 05 16 - constant force ***
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+#### Envelope:
+```
+ 60 00 - standard header
+ 01 - ID
+ 31 - modify envelope
+ 84 - ID of envelope attribute ( attack_level 82,
+ attack_length 81,
+ fade_level 88,
+ fade_length 84 )
+ 63 04 - value attribute should be set to ?***?
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+#### Duration:
+```
+ 60 00 - standard header
+ 01 - ID
+ 49 00 41 - modify timing?
+ 6c 20 - length in milliseconds
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+#### Offset: `N/A`
+
+## FF_RAMP
+
+Ramps seem to follow triangle wave parameters.
+
+### Init:
+```
+ 60 00 - standard header
+ 01 - ID
+ 6b - new ramp effect
+ f6 7f - difference ***
+ fe ff - level? *** (level = (if end_level > start_level, end_level, else
+ start_level) - difference?) (signed)
+ 00 00
+ f7 17 - time
+ 00 80 - some kind of marker
+ 00 00 - attack_length
+ f6 7f - attack_level ***
+ 00 00 - fade_length
+ f6 7f - fade_level***
+ 04 - invert (going "down", 05, going "up", 04)
+ 4f
+ f7 17 - time again?
+ 00 00
+ 00 00 - offset
+ 00 ff ff - end of init
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+### Modifying:
+```
+ 60 00 - standard header
+ 01 - ID
+ 0e - ???
+ 03 - ramp?
+ e3 04 - difference?
+ 7d 75 - "level"?
+ 05 - ????
+ 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+#### Envelope:
+```
+ 60 00 - standard header
+ 01 - ID
+ 31 - modify envelope
+ 84 - ID of envelope attribute ( attack_level 82,
+ attack_length 81,
+ fade_level 88,
+ fade_length 84 )
+ 63 04 - value attribute should be set to
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+#### Duration:
+```
+ 60 00
+ 01 - ID
+ 4e - ?
+ 08 - ?
+ 01 00 - time in milliseconds
+ 05 - ?
+ 41 - ?
+ 01 00 - time in milliseconds
+ 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+#### Offset: `N/A`
+
+## FF_SPRING:
+### Init:
+```
+ 60 00 - standard header
+ 01 - ID
+ 64 - new conditional effect
+ fc 7f - positive coefficient (right?)
+ fc 7f - negative coefficient (left?)
+ fe ff - deadband (left?) (deadband + offset) (fe ff means no deadband)
+ fe ff - deadband (right?) (deadband + offset)
+ a6 6a a6 6a fe ff fe ff fe ff fe ff df 58 a6 6a 06 - some weird hard-coded
+ values to do with springs?
+
+ 4f
+ f7 17 - duration
+ 00 00
+ 00 00 - offset
+ 00 ff ff - end of init
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+### Modifying:
+Same as below (FF_DAMPER + FF_FRICTION + FF_INERTIA)
+
+## FF_DAMPER + FF_FRICTION + FF_INERTIA:
+### Init:
+```
+ 60 00 - standard header
+ 02 -ID
+ 64 - new conditional effect
+ fc 7f - positive coefficient (right?)
+ fc 7f - negative coefficient (left?)
+ fe ff - deadband (left?) (deadband + offset) (fe ff means no deadband)
+ fe ff - deadband (right?) (deadband + offset)
+ fc 7f fc 7f fe ff fe ff fe ff fe ff fc 7f fc 7f 07 - some weird hard-coded
+ values to do with friction?
+ 4f
+ f7 17 - duration
+ 00 00
+ 00 00 - offset
+ 00 ff ff - end of init
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+### Modifying:
+```
+ positive coefficient:
+ 60 00
+ 02 - ID
+ 0e 41
+ 64 35 - value, signed (between 00 00 and 01 80?)
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ negative coefficient:
+ 60 00
+ 02 - ID
+ 0e 42
+ 64 35 - value, signed (between 00 00 and ff 7f?)
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ deadband/offset:
+ 60 00
+ 02 - ID
+ 0e 4c
+ 64 35 - deadband (right?) (deadband + offset) (fe ff means no deadband)
+ 00 00 - deadband (left?) (deadband + offset)
+ 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+### Duration:
+```
+ 60 00 - standard header
+ 01 - ID
+ 49 06 41 - modify timing?
+ 6c 20 - length in milliseconds
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+### Offset: `N/A`
+
+## FF_PERIODIC:
+### Init
+```
+ 60 00 - standard header
+ 01 - ID
+ 6b - new periodic effect
+ 00 00 - magnitude ***
+ fe ff - offset (up/down)
+ 00 00 - phase (left/right)
+ e8 03 - period
+ 00 80
+ 00 00 - attack_length
+ 00 00 - attack_level ***
+ 00 00 - fade_length
+ 00 00 - fade_level ***
+ 01 - type of periodic ( square 01,
+ sine 03,
+ triangle 02,
+ sawtooth down 05,
+ sawtooth up 04 )
+ 4f
+ f7 17 - duration
+ 00 00
+ 00 00 - offset
+ 00 ff ff - end of init
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+### Modifying:
+```
+ magnitude:
+ 60 00
+ 02 - ID
+ 0e 01
+ 64 35 - value, signed (between 00 00 and ff 7f?)
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ offset of effect:
+ 60 00
+ 02 - ID
+ 0e 02
+ 64 35 - value, signed (between 00 00 and ff 7f?)
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ phase:
+ 60 00
+ 02 - ID
+ 0e 04
+ 64 35 - value, signed (between 80 01 and ff 7f?)
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ period:
+ 60 00
+ 02 - ID
+ 0e 08
+ 64 35 - value, signed (between 00 00 and I guess ff 7f?) (max value in
+ wireshark is 0d 07, but I don't know if that's a driver or program issue)
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+```
+
+### Envelope:
+```
+ 60 00 - standard header
+ 01 - ID
+ 31 - modify envelope
+ 84 - ID of envelope attribute ( attack_level 82,
+ attack_length 81,
+ fade_level 88,
+ fade_length 84 )
+ 63 04 - value attribute should be set to
+ 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+
+### Duration:
+```
+ Square:
+ 60 00
+ 01 - ID
+ 49 - ?
+ 01 - Effect type
+ 41 - ?
+ 4e 0c - Time in milliseconds
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ Sine:
+ 60 00
+ 01 - ID
+ 49 - ?
+ 03 - Effect type
+ 41 - ?
+ ec 13 - Time in milliseconds
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ Triangle:
+ 60 00
+ 01 - ID
+ 49 - ?
+ 02 - Effect type
+ 41 - ?
+ 4e 0c - Time in milliseconds
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ Sawtooth up:
+ 60 00
+ 01 - ID
+ 49 - ?
+ 04 - Effect type
+ 41 - ?
+ 4e 0c - Time in milliseconds
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ Sawtooth down:
+ 60 00
+ 01 - ID
+ 49 - ?
+ 05 - Effect type
+ 41 - ?
+ ec 13 - Time in milliseconds
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+```
+### Offset: `N/A ?`
+
+## PS4 Input `rdesc`
+```
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 226 /* wheel */
+ ff00.0021 = 125 /* wheel */
+ ff00.0021 = 255 /* gas */
+ ff00.0021 = 255 /* gas */
+ ff00.0021 = 255 /* brake */
+ ff00.0021 = 255 /* brake */
+ ff00.0021 = 255 /* clutch */
+ ff00.0021 = 255 /* clutch */
+ ff00.0021 = 0
+ ff00.0021 = 255
+ ff00.0021 = 255
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+ ff00.0021 = 0
+```
diff --git a/docs/INTEGRATION.md b/docs/INTEGRATION.md
new file mode 100644
index 0000000..bcdb9f4
--- /dev/null
+++ b/docs/INTEGRATION.md
@@ -0,0 +1,6 @@
+Some distros require more complicated installation methods than what's outlined
+in the README. This page is intended to collect information about the topic.
+
+# NixOS
+
+See https://github.com/Kimplul/hid-tmff2/issues/71.
diff --git a/docs/STRUCTURE.md b/docs/STRUCTURE.md
new file mode 100644
index 0000000..e7778ba
--- /dev/null
+++ b/docs/STRUCTURE.md
@@ -0,0 +1,42 @@
+# Structure of the Thrustmaster device 'stack'
+
++ `hid-tmff`
+
+Driver for older Thrustmaster wheels, has existed in the Kernel for a long time
+and I have nothing to with it.
+
++ `hid-thrustmaster`
+
+Driver for initializing newer Thrustmaster wheels, initially added in version
+5.13. Essentially `hid-tminit`, with some modifications to better fit into the
+kernel.
+
++ `hid-tminit`
+
+Driver for initializing newer Thrustmaster wheels, currently maintained over at
+https://github.com/scarburato/hid-tminit.
+
+All newer Thrustmaster wheels initially identify themselves as `Thrustmaster FFB
+Wheel`, and it is up to the `hid-tminit` driver to boot the wheel into its
+correct designation, after which the corresponding driver can take over. No FFB
+takes place while this driver is active.
+
++ `hid-tmff-new`
+
+Active driver module for different wheels, responsible for handling FFB.
+At the moment only supports T300 RS and T248. Note that the T300 RS has a number
+of different modes, of which PS3, PS4, and PS3 F1 (advanced) mode are known to
+work (at least on some systems, please open up any issues you encounter.)
+
++ `hid-tmff2`
+
+Name of this projects, initially I intended to write `hid-tmff` but for newer
+wheels, hence the name. Because of some slight weirdness in the Kernel build
+configuration, I couldn't use `hid-tmff2` as the module name, so I chose
+`hid-tmff-new`.
+
+I don't know exactly which wheels are 'newer' and which are 'older', but at
+least T150/T248/T300/T500 are in the 'newer' category.
+
+Note that the T150 already has a driver in a separate module
+(https://github.com/scarburato/t150_driver).
diff --git a/docs/effects/FFBEFFECTS_T248.md b/docs/effects/FFBEFFECTS_T248.md
deleted file mode 100644
index f43fb55..0000000
--- a/docs/effects/FFBEFFECTS_T248.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Force Feedback Effects - Thrustmaster T248
-
-## Open:
-Identical to [T300RS](./FFBEFFECTST300RS)
-
-## Close:
-Identical to [T300RS](./FFBEFFECTST300RS)
diff --git a/docs/effects/FFBEFFECTS_T300RS.md b/docs/effects/FFBEFFECTS_T300RS.md
deleted file mode 100644
index f076ec7..0000000
--- a/docs/effects/FFBEFFECTS_T300RS.md
+++ /dev/null
@@ -1,541 +0,0 @@
-# Force Feedback Effects - Thrustmaster T300RS (incl. PS3/PS4 modes)
-Here I will gather all info I can find out about the different force feedback effects and their USB commands. All values seem to be little-endian. Also, general note, it seems like some effects are affected by the direction of the force, denoted by `***`. As far as I can tell, `fade_level` and `attack_level` values are calculated by mapping the `u16` into `s16` and taking the absolute value, and after that multiplying by the direction.
-
-> **NOTE:** All values are examples of actual commands that I captured on the USB interface, not the only available ones.
-
-
-## GENERAL
-### Playing
-```
- 60 00 - standard header
- 01 - ID
- 89 - playing options
- 01 - play
- 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-### Stopping/removing (why are they rolled into one?)
-```
- 60 00 - standard header
- 01 - ID
- 89 - playing options
- 00 - stop
- 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-## Open:
-```
- 60 01 - standard header?
- 04 - ?
- 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- (this command doesn't appear every time, odd)
- 60 12 - ?
- bf 04 00 00 03 b7 1e - ? /* wow, this is different on different wheels? */
- 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- 60 01 - ?
- 05 - ?
- 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-## Close:
-```
- 60 01 - standard header?
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-## Rotation angle:
-```
- 60 08 - header plus settings?
- 11 - set rotation angle
- 55 d5 - angle (between ff ff and 7b 09, one degree is roughly 3c)
- 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-## FF_AUTOCENTER:
-```
- 60 08 - header plus settings?
- 03 - set autocenter force
- 8f 02 - force (between ff ff and 00 00)
- 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-## FF_GAIN:
-```
- 60 02 - header plus gain?
- bf - gain (between ff and 00)
- 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-## FF_CONSTANT
-### Initialization
-```
- 60 00 - standard header
- 01 - ID
- 6a - new constant effect(?)
- fe ff - strength ***
- 00 00 - attack_length
- 00 00 - attack_level ***
- 00 00 - fade_length
- 00 00 - fade_level ***
- 00 4f - ?
- f7 17 - time in milliseconds, unsigned
- 00 00
- 07 00 - offset from start(?)
- 00 ff ff - end of new effect(?)
- 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-### Modifying (For dynamic updating of effects)
-
-#### Direction: ``N/A``
-
-#### Constant force:
-```
-60 00 - standard header
-01 - ID
-0a - modify constant force
-05 16 - constant force ***
-00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-#### Envelope:
-```
-60 00 - standard header
-01 - ID
- 31 - modify envelope
-84 - ID of envelope attribute ( attack_level 82,
- attack_length 81,
- fade_level 88,
- fade_length 84 )
- 63 04 - value attribute should be set to ?***?
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-#### Duration:
-```
- 60 00 - standard header
- 01 - ID
- 49 00 41 - modify timing?
- 6c 20 - length in milliseconds
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-#### Offset: `N/A`
-
-## FF_RAMP
-(Why on earth is it this difficult to figure out how a ramp works?)
-### Init:
-```
- 60 00 - standard header
- 01 - ID
- 6b - new ramp effect
- f6 7f - difference ***
- fe ff - level? *** (level = (if end_level > start_level, end_level, else
- start_level) - difference?) (signed)
- 00 00
- f7 17 - time
- 00 80 - some kind of marker
- 00 00 - attack_length
- f6 7f - attack_level ***
- 00 00 - fade_length
- f6 7f - fade_level***
- 04 - invert (going "down", 05, going "up", 04)
- 4f
- f7 17 - time again?
- 00 00
- 00 00 - offset
- 00 ff ff - end of init
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-### Modifying:
-(Sweet baby jesus. I'll figure this out later ``Ramp(?)``)
-```
- 60 00 - standard header
- 01 - ID
- 0e - ???
- 03 - ramp?
- e3 04 - difference?
- 7d 75 - "level"?
- 05 - ????
- 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-#### Envelope:
-```
- 60 00 - standard header
- 01 - ID
- 31 - modify envelope
- 84 - ID of envelope attribute ( attack_level 82,
- attack_length 81,
- fade_level 88,
- fade_length 84 )
- 63 04 - value attribute should be set to
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-#### Duration:
-```
- 60 00
- 01 - ID
- 4e - ?
- 08 - ?
- 01 00 - time in milliseconds
- 05 - ?
- 41 - ?
- 01 00 - time in milliseconds
- 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-#### Offset: `N/A`
-
-## FF_SPRING:
-### Init:
-```
- 60 00 - standard header
- 01 - ID
- 64 - new conditional effect
- fc 7f - positive coefficient (right?)
- fc 7f - negative coefficient (left?)
- fe ff - deadband (left?) (deadband + offset) (fe ff means no deadband)
- fe ff - deadband (right?) (deadband + offset)
- a6 6a a6 6a fe ff fe ff fe ff fe ff df 58 a6 6a 06 - some weird hard-coded
- values to do with springs?
-
- 4f
- f7 17 - duration
- 00 00
- 00 00 - offset
- 00 ff ff - end of init
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-### Modifying:
-Same as below (FF_DAMPER + FF_FRICTION + FF_INERTIA)
-
-## FF_DAMPER + FF_FRICTION + FF_INERTIA:
-### Init:
-```
- 60 00 - standard header
- 02 -ID
- 64 - new conditional effect
- fc 7f - positive coefficient (right?)
- fc 7f - negative coefficient (left?)
- fe ff - deadband (left?) (deadband + offset) (fe ff means no deadband)
- fe ff - deadband (right?) (deadband + offset)
- fc 7f fc 7f fe ff fe ff fe ff fe ff fc 7f fc 7f 07 - some weird hard-coded
- values to do with friction?
- 4f
- f7 17 - duration
- 00 00
- 00 00 - offset
- 00 ff ff - end of init
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-### Modifying:
-```
- positive coefficient:
- 60 00
- 02 - ID
- 0e 41
- 64 35 - value, signed (between 00 00 and 01 80?)
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- negative coefficient:
- 60 00
- 02 - ID
- 0e 42
- 64 35 - value, signed (between 00 00 and ff 7f?)
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- deadband/offset:
- 60 00
- 02 - ID
- 0e 4c
- 64 35 - deadband (right?) (deadband + offset) (fe ff means no deadband)
- 00 00 - deadband (left?) (deadband + offset)
- 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-### Duration:
-```
- 60 00 - standard header
- 01 - ID
- 49 06 41 - modify timing?
- 6c 20 - length in milliseconds
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-### Offset: `N/A`
-
-## FF_PERIODIC:
-### Init
-```
- 60 00 - standard header
- 01 - ID
- 6b - new periodic effect
- 00 00 - magnitude ***
- fe ff - offset (up/down)
- 00 00 - phase (left/right)
- e8 03 - period
- 00 80
- 00 00 - attack_length
- 00 00 - attack_level ***
- 00 00 - fade_length
- 00 00 - fade_level ***
- 01 - type of periodic ( square 01,
- sine 03,
- triangle 02,
- sawtooth down 05,
- sawtooth up 04 )
- 4f
- f7 17 - duration
- 00 00
- 00 00 - offset
- 00 ff ff - end of init
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-### Modifying:
-```
- magnitude:
- 60 00
- 02 - ID
- 0e 01
- 64 35 - value, signed (between 00 00 and ff 7f?)
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- offset of effect:
- 60 00
- 02 - ID
- 0e 02
- 64 35 - value, signed (between 00 00 and ff 7f?)
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- phase:
- 60 00
- 02 - ID
- 0e 04
- 64 35 - value, signed (between 80 01 and ff 7f?)
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- period:
- 60 00
- 02 - ID
- 0e 08
- 64 35 - value, signed (between 00 00 and I guess ff 7f?) (max value in
- wireshark is 0d 07, but I don't know if that's a driver or program issue)
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
-```
-
-### Envelope:
-```
- 60 00 - standard header
- 01 - ID
- 31 - modify envelope
- 84 - ID of envelope attribute ( attack_level 82,
- attack_length 81,
- fade_level 88,
- fade_length 84 )
- 63 04 - value attribute should be set to
- 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-
-### Duration:
-```
- Square:
- 60 00
- 01 - ID
- 49 - ?
- 01 - Effect type
- 41 - ?
- 4e 0c - Time in milliseconds
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- Sine:
- 60 00
- 01 - ID
- 49 - ?
- 03 - Effect type
- 41 - ?
- ec 13 - Time in milliseconds
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- Triangle:
- 60 00
- 01 - ID
- 49 - ?
- 02 - Effect type
- 41 - ?
- 4e 0c - Time in milliseconds
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- Sawtooth up:
- 60 00
- 01 - ID
- 49 - ?
- 04 - Effect type
- 41 - ?
- 4e 0c - Time in milliseconds
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
- Sawtooth down:
- 60 00
- 01 - ID
- 49 - ?
- 05 - Effect type
- 41 - ?
- ec 13 - Time in milliseconds
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-```
-### Offset: `N/A ?`
-
-## PS4 Input
-```
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 226 /* wheel */
-ff00.0021 = 125 /* wheel */
-ff00.0021 = 255 /* gas */
-ff00.0021 = 255 /* gas */
-ff00.0021 = 255 /* brake */
-ff00.0021 = 255 /* brake */
-ff00.0021 = 255 /* clutch */
-ff00.0021 = 255 /* clutch */
-ff00.0021 = 0
-ff00.0021 = 255
-ff00.0021 = 255
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-ff00.0021 = 0
-```