Skip to content

Instantly share code, notes, and snippets.

@barraIhsan
Last active January 6, 2026 22:18
Show Gist options
  • Select an option

  • Save barraIhsan/783a82bcf32bed896c85d27dbb8018a5 to your computer and use it in GitHub Desktop.

Select an option

Save barraIhsan/783a82bcf32bed896c85d27dbb8018a5 to your computer and use it in GitHub Desktop.
8BitDo Ultimate 2 Wireless on GNU/Linux, SteamOS, and Windows

Most of the source comes from: Steam Beta Forum

Thank you so much to everyone in the forum for contributing, for reaching out to 8BitDo to request switching between XInput/DInput/Switch mode on the dongle, to Valve for adding support on DInput mode, to the SDL developers (and 8bitdo) for adding support on DInput mode, and finally, to the Linux kernel developers for adding support on XInput mode.

This gist summarizes everything from that forum.

Switching Mode

So after the latest firmware update (as the time of writing: Controller 1.06, Adapter 1.04), its now possible to switch to DInput and Switch mode by holding B (DInput) or Y (Switch) while turning on the controller.

Note: If you try holding B or Y while in the dock and pick that up, it will not change the mode. You have to manually turn off the controller undocked (hold the home/guide button for 3 second) and turn it back (press home/guide button) while holding either B or Y

Wired         - XInput only
Dongle/2.4Ghz - XInput, DInput (B), Switch (Y)
Bluetooth     - DInput only

Hopefully, a future firmware update will allow switching between modes when using wired or Bluetooth.

On windows, all three modes is supported ootb. Games could properly detect XInput and Switch mode. However, you should use Steam Input for translating DInput mode into XInput

XInput Mode

8bitdo Ultimate 2 Wireless on XInput mode work ootb now on kernel 6.15+ (using built-in xpad driver)
https://github.com/torvalds/linux/commit/22cd66a5db56a07d9e621367cb4d16ff0f6baf56

In this mode, just like with other XInput controller, will not register gyro and additional button.

Nintendo Switch (Pro Controller) Mode

Hold Y while turning on your controller

Switch mode works ootb since kernel 5.16 by hid_nintendo driver. Switch mode supports native gyro but no additional button and no capture button. Thus, you can use it with a Switch emulator or the actual device.

Do note that your XYAB will be swapped (so the bottom button is now B not A, just like a Switch/Pro Controller).

image

Works great if you use Switch emulator, rumble and gyro works ootb and you don't need to configure it manually. Except if you want to swap the XYAB

Battery Reporting

Oh, for battery reporting on Switch mode, yeah it doesn't work and it's always at 55% image

If you want an actual battery percentage, you have to use bluetooth. image

Direct Input (DInput) Mode

Hold B while turning on your controller

The DInput mode will register the 4 additional button (R4, L4, PL, PR) and native gyro after using udev, see below. Thus, you can map those with steam input and be translated into XInput for games.

Note: If you map any of the additional buttons using the Ultimate Software or the square button, it will register the mapped button instead of the original one. For example, if you map PL to LB, pressing PL will register as LB, not PL.

It will shows the correct icon for the controller and with the additional button, as well the gyro on Steam

Additional button

image

Gyro

image

udev rule for DInput

If you use SteamOS/Bazzite, it seems that it's already configured by default.

To get the additional button, gyro, and rumble working on DInput. You need to specify a udev rule.

# 2.4GHz/Dongle
KERNEL=="hidraw*", ATTRS{idProduct}=="6012", ATTRS{idVendor}=="2dc8", MODE="0660", TAG+="uaccess"
# Bluetooth
KERNEL=="hidraw*", KERNELS=="*2DC8:6012*", MODE="0660", TAG+="uaccess"

Save it in /etc/udev/rules.d/71-8bitdo-u2w.rules, then reload udev (# udevadm control --reload)

udev rule for other 8bitdo controllers

Simply change idProduct to the controller's idProduct. You can check them using $ lsusb

OR

You can omit idProduct to make it work for all 8bitdo controller. So it'll become:

# 2.4GHz/Dongle
KERNEL=="hidraw*", ATTRS{idVendor}=="2dc8", MODE="0660", TAG+="uaccess"
# Bluetooth
KERNEL=="hidraw*", KERNELS=="*2DC8:*", MODE="0660", TAG+="uaccess"
@ErifEci0
Copy link

ErifEci0 commented Dec 7, 2025

Noted! Thank You! So if I heard you correctly, as far as using a controller with D-Input and 2.4Ghz, you’d opt for the Ultimate 2? Again thank you for your help :D

Yes, I would get the Ultimate 2, if you're going for all the extra buttons and gyro of D-input in 2.4ghz mode.

So far, I only managed to get X-input out of the Pro 3 when using 2.4ghz mode. It's a big downside for me and why I only use that for 2D games.

@ItsPercent
Copy link

So far, I only managed to get X-input out of the Pro 3 when using 2.4ghz mode. It's a big downside for me and why I only use that for 2D games.

I’ll be sure to get the Ultimate 2! Thank you!

@mateogs01
Copy link

mateogs01 commented Dec 12, 2025

Hi, first, thanks for such useful thread. Second, i have an ultimate 2c wireless connected trough dongle but I cant pair it in D-input mode. I already update the firmware with a windows pc that I have but didnt worked. I turn off the controller and then turn it on again while pressing B but it keeps detecting it as Xinput. What else can i try?

Also, I'm in linux mint. Thanks!

@Maegima
Copy link

Maegima commented Dec 13, 2025

Hello @mateogs01, have you tried to update the dongle firmware too? I was having the same issue with my 8bitdo ultimate 2 because I have only updated the controller firmware.

@mateogs01
Copy link

Hi @Maegima, Thanks for the reply. I did update the dongle firmware, but actually realized that I'm not sure what the difference between XInput and Dinput should be. Like, the r4 and l4 buttons should be detectable by steam on DInput? Or these buttons are only mappable from the controller?

@churuz-fyi
Copy link

@mateogs01 XInput is limited to the Xbox controller layout which means 10 face buttons, 2 bumpers, 2 triggers, and 2 joysticks. The format doesn't support the bandwidth to support everything else unlike DInput which directly links to every function that the controller supports. This means that in DInput the controller's extra bumpers, back buttons, and gyro are all detected individually with the caveat of only working on any game that officially supports it.

When I play Hollow Knight with the DInput mode, all the buttons are swapped around for whatever reason so you can either switch to XInput or you should be able to mask it with Steam Input as XInput controls which I haven't tested.

@mateogs01
Copy link

@churuz-fyi Thanks for the answer. So well, that means I was right in DInput not working. I'll try updating the firmware again and check a few more things and if I can get it to work I'll update. Thanks again

@churuz-fyi
Copy link

churuz-fyi commented Dec 15, 2025

@mateogs01 Easiest way i found to test whether its working is to go into the Steam Big Picture controller settings. The 4 additional buttons should appear on there and you can test whether they're working and the UI should now be using the 8BitDo controller instead of the Xbox logo.

Also for my use case, both the dongle and controller on 1.06 has been working with switching between each mode with no problems if its a version issue.

@nift4
Copy link

nift4 commented Dec 25, 2025

If you want an actual battery percentage, you have to use bluetooth.

In DInput mode the SDL driver can read the battery level (it works both via bluetooth, where it offers less delay for updated data, and via 2.4G where we currently don't have any other way to read it).

You can test it like this after cloning SDL repository:

diff --git a/test/gamepadutils.c b/test/gamepadutils.c
index dbfa98c1f..51b6fd90e 100644
--- a/test/gamepadutils.c
+++ b/test/gamepadutils.c
@@ -725,6 +725,7 @@ void UpdateGamepadImageFromGamepad(GamepadImage *ctx, SDL_Gamepad *gamepad)
 
     ctx->connection_state = SDL_GetGamepadConnectionState(gamepad);
     ctx->battery_state = SDL_GetGamepadPowerInfo(gamepad, &ctx->battery_percent);
+    SDL_Log("battery:%d\n", ctx->battery_percent);
 
     if (SDL_GetNumGamepadTouchpads(gamepad) > 0) {
         int num_fingers = SDL_GetNumGamepadTouchpadFingers(gamepad, 0);
cmake .
make testcontroller
./test/testcontroller

It does behave a bit oddly, like jumping from 100% to 88% when I unplug power cable, however, Bluetooth has the same issue, albeit with more delay (it only seems to update every minute or so), hence it's less obvious.

Sadly it seems someone would have to write a kernel driver (as UPower does not seem to allow userland drivers) doing what the SDL driver does in order to have proper integration in DEs in 2.4G mode.

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