Getting rumble on the 8BitDo SN30 Pro+ to work properly with Linux

TLDR: After having owned the controller for a while I noticed that every time you install a new kernel update the fixes are undone again, and have to be re-applied. I also discovered that the controller UID is the same for all SN30 Pro+ controllers. So I’ve made the following script that fixes everything automatically instead. Save it somewhere, check that the config file paths are correct, install xpadneo using the github instructions, then run the script as root.

#!/bin/bash

if [[ $EUID -ne 0 ]]; then
    echo "This script must be run as root"
    exit 1
fi

# Config file paths
MP_PATH="/etc/modprobe.d/99-xpadneo-bluetooth.conf"
UDEV_PATH="/etc/udev/rules.d/99-xpadneo.rules"
ENV_PATH="/etc/environment"

# Look for already applied fixes
MPFIXED=$(grep -c "disable_ff=2" $MP_PATH)
UDEVFIXED=$(grep -c "RUN+=\"/bin/sh -c 'echo xpadneo udev: \$kernel > /dev/kmsg && { echo \$kernel > /sys/bus/hid/drivers/hid-generic/unbind; echo \$kernel > /sys/bus/hid/drivers/microsoft/unbind; echo \$kernel > /sys/bus/hid/drivers/xpadneo/bind; }; '\"" $UDEV_PATH)
ENVFIXED=$(grep -c "8BitDo SN30 Pro+" $ENV_PATH)

if [[ $MPFIXED -eq 0 ]]; then
  # Turn off trigger rumble
  echo "options hid_xpadneo debug_level=0 disable_ff=2 trigger_rumble_damping=4 fake_dev_version=4400 combined_z_axis=n" >> $MP_PATH
  echo "Applied fix to $MP_PATH."
else
  echo "Fix already applied to $MP_PATH. Skipping."
fi

if [[ $UDEVFIXED -eq 0 ]]; then
  # Apply dirty fix to udev rules
  sed -i 's/RUN/#RUN/g' $UDEV_PATH
  echo "RUN+=\"/bin/sh -c 'echo xpadneo udev: \$kernel > /dev/kmsg && { echo \$kernel > /sys/bus/hid/drivers/hid-generic/unbind; echo \$kernel > /sys/bus/hid/drivers/microsoft/unbind; echo \$kernel > /sys/bus/hid/drivers/xpadneo/bind; }; '\"" >> $UDEV_PATH
  echo "Applied fix to $UDEV_PATH"
else
  echo "Fix already applied to $UDEV_PATH. Skipping."
fi

if [[ $ENVFIXED -eq 0 ]]; then
  # Add SDL_CONTROLLERCONFIG environment variable
  echo "SDL_GAMECONTROLLERCONFIG=\"050000005e040000e002000030110000,8BitDo SN30 Pro+,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,\"" >> $ENV_PATH
  echo "Added 'SDL_CONTROLLERCONFIG' variable to $ENV_PATH."
else
  echo "'SDL_CONTROLLERCONFIG' variable already present in $ENV_PATH. Skipping."
fi

Original post follows:

I recently bought an 8BitDo SN30 Pro+ since my old gamepad was an ancient Logitech Dual Action. I wanted a gamepad that was wireless as well as having support for XInput. When I heard about the SN30 Pro+ I couldn’t contain myself, so I went and bought it the same day after reading a bit about it and how it works on Linux. It’s not officially supported, and there wasn’t really much definitive information regarding Linux compatibility, other than that the older SN30 Pro worked fine and it works on the raspberry pi. So I just took a gamble and bought it.

Continue reading “Getting rumble on the 8BitDo SN30 Pro+ to work properly with Linux”