Skip to content

Instantly share code, notes, and snippets.

@loopyd
Created August 7, 2024 02:40
Show Gist options
  • Save loopyd/a7ccbf37e27580ccbed859c26aa0a167 to your computer and use it in GitHub Desktop.
Save loopyd/a7ccbf37e27580ccbed859c26aa0a167 to your computer and use it in GitHub Desktop.
[bash] Fix for 8bitdo Ultimate Wireless Controller on Linux
#!/bin/bash
# Block script from running as non-root user
if [ "$EUID" -ne 0 ]; then
echo "Please run as root"
exit 1
fi
# Blacklist Nintendo Switch Pro Controller Driver
echo blacklist hid_nintendo | tee /etc/modprobe.d/notendo.conf
# Install xboxdrv
apt-get update
if ! dpkg -s 'xboxdrv' &> /dev/null; then
apt-get install -y xboxdrv
fi
# Create udev rules
if [ ! -f '/etc/udev/rules.d' ]; then
mkdir -p '/etc/udev/rules.d'
fi
udev_rules='/etc/udev/rules.d/99-8bitdo-ultimate.rules'
if [ -f $udev_rules ]; then
sudo rm $udev_rules
fi
echo 'SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="2dc8", ATTR{idProduct}=="3106", ATTR{manufacturer}=="8BitDo", RUN+="/bin/systemctl start 8bitdo-ultimate-xinput@2dc8:3106"' | tee $udev_rules
echo 'SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="2dc8", ATTR{idProduct}=="3109", ATTR{manufacturer}=="8BitDo", RUN+="/bin/systemctl stop 8bitdo-ultimate-xinput@2dc8:3106"' | tee -a $udev_rules
# Reload udev rules
udevadm control --reload-rules
udevadm trigger
# Create systemd service
service_file='/etc/systemd/system/[email protected]'
if [ -f $service_file ]; then
rm $service_file
fi
echo '[Unit]' | tee $service_file
echo 'Description=8BitDo Ultimate Controller XInput mode xboxdrv daemon' | tee -a $service_file
echo '' | tee -a $service_file
echo '[Service]' | tee -a $service_file
echo 'Type=simple' | tee -a $service_file
echo 'ExecStart=/usr/bin/xboxdrv --mimic-xpad --silent --type xbox360 --device-by-id %i --force-feedback --detach-kernel-driver' | tee -a $service_file
systemctl daemon-reload
# Now install jstest-gtk to test the controller, which also installs all the joystick dependencies
# This fixes:
# - /dev/input/js0 not found
if ! dpkg -s 'jstest-gtk' &> /dev/null; then
apt-get install -y jstest-gtk
fi
# Now open jstest-gtk and test the controller, remap the axis / buttons, then exit
# Save the configuration using the command:
# sudo jscal-store /dev/input/js0
@loopyd
Copy link
Author

loopyd commented Jan 20, 2025

For those that encounter this gist on the internet like me: #27 should say ACTION=="remove" and ATTR{idProduct}=="3106" as these are the instructions for what happens when the device gets removed.

Also i just got my hands on the Ultimate 2C Wukong Edition which had the product id 310a. The device was listed under /dev/input/mouseX in my case.

Aside from changing that the script works fine. Didn't need to blacklist the nintendo drivers or use js-test-gtk for Steam, though.

Both lines saying add is intentional. When the device is charging (its dock is plugged in), it is in firmware mode with id 3109, and then swithces to 3106 when paired with the controller (device forwarding mode), when taken off the dock. Notice /bin/systemctl stop 8bitdo-ultimate-xinput@2dc8:3106 is used on L27 to stop the xinput service when the controller is docked (switch back to 3109).

If you change it to remove, its killed the connection with the PC before device forwarding mode can be enabled properly and this results in a forkbomb/xinput service spawn loop from the service going up and down repeatedly that eats CPU to 100% the next time you put it back on the dock (nasty behavior in some games I tested, obviously). This was intentional to avoid a forkbomb. add events are used here to ensure that service is only started after device is ready to give io to kernel to avoid xinput service crash loop. udev rules listening for when both the devices are ready acts like a simple not gate in this config, as intended by the hardware.

jstest/jscal/jstest-gtk is used to save native pot calibration settings in easy UI for a gamer and adjust your button mappings as you need (solve issues like axis mapping flipped, bumper axis inverted, L and R not mapped properly, X and Y flipped, etc).

I recommend setitng a profile for calibration and correct button mapping, and forgetting them with jscal --save. when you are done in jstest-gtk . Is a simple command to run after configuring in jstest-gtk. Pretty fast to fix all issues and easy for most "gamer" types, so i included it.

If you run native linux games outside of steam, very useful to save calibrations and mappings once, then not have to touch them again. In addition to never having to remap buttons on steam launcher.

The reason to blacklist the nintendo driver is in case you happen to enter the Switch mode while the device is plugged in (this device posesses that). In which case depend soley on the kernel to figure out you haven't just try to plugin a switch controller. .. Thus it will ignore nintendo switch mode (safely).... as this config only works in xinput mode.

With all this said I was very deliberate about this config when I posted it in what I did/did not include and why certain things are certain ways.

I am glad you where able to get it working for your device with tweaks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment