diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/CONTRIBUTING.md | 122 | ||||
| -rw-r--r-- | docs/DRIVER.md | 49 | ||||
| -rw-r--r-- | docs/FFBEFFECTS.md | 558 | ||||
| -rw-r--r-- | docs/INTEGRATION.md | 6 | ||||
| -rw-r--r-- | docs/STRUCTURE.md | 42 | ||||
| -rw-r--r-- | docs/effects/FFBEFFECTS_T248.md | 7 | ||||
| -rw-r--r-- | docs/effects/FFBEFFECTS_T300RS.md | 541 |
7 files changed, 746 insertions, 579 deletions
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 -``` |
