Connecting a Nintendo Switch Pro Controller Wirelessly to Ubuntu 26.04
(Courtesy of the Kagi Assistant and saved for posterity...)
Context & Symptoms
System: Ubuntu 26.04 (Linux), using the in-kernel hid_nintendo driver
(057e:2009), connecting a Nintendo Switch Pro Controller over Bluetooth.
Symptoms: The controller paired successfully and hid_nintendo bound to it
in dmesg, but two problems appeared:
-
The controller would immediately disconnect when
evtest(or any program) tried to read from the device, with the error:expected 24 bytes, got -1 — No such device. -
After fixing the disconnect,
evtestcould see the controller's input node but no button or stick events appeared when pressing anything. The controller worked perfectly when connected via USB-C cable — the problem was Bluetooth-only.
The root causes were two separate BlueZ/Bluetooth configuration issues: a firmware quirk in the controller that rejects adapters with unexpected names, and BlueZ's default UHID transport silently failing to forward HID input reports to the kernel.
Step 1: Rename the Bluetooth adapter to “Nintendo”
The Pro Controller's firmware has a quirk where it disconnects if the Bluetooth adapter name doesn't match what it expects. Renaming the adapter satisfies the handshake.
Edit /etc/bluetooth/main.conf:
sudo nano /etc/bluetooth/main.conf
Under [General], set:
[General]
Name = Nintendo
Alias = Nintendo
Restart Bluetooth:
sudo systemctl restart bluetooth
This fixed the immediate disconnection observed when evtest tried to read from the device.
Step 2: Disable UHID (use kernel HIDP instead)
BlueZ's default UHID (userspace HID) transport was creating the input device but
not forwarding input reports from the controller to the kernel — so
evtest saw the device but no button events ever arrived. Switching to kernel HIDP
fixed this.
The telltale sign in dmesg was the input device path containing
/devices/virtual/misc/uhid/, indicating the UHID transport was in use:
input: Pro Controller as /devices/virtual/misc/uhid/0005:057E:2009.000E/input/input31
Edit /etc/bluetooth/input.conf:
sudo nano /etc/bluetooth/input.conf
Under [General], set:
[General]
UserspaceHID=false
Restart Bluetooth:
sudo systemctl restart bluetooth
Note: This requires the hidp kernel module. On stock Ubuntu it should be available,
but if the controller fails to connect after this change, load it manually:
sudo modprobe hidp
echo "hidp" | sudo tee /etc/modules-load.d/hidp.conf
Step 3: Re-pair the controller
Remove the old pairing and re-pair fresh, since the Bluetooth configuration has changed:
bluetoothctl
[bluetooth]# remove <MAC_ADDRESS>
[bluetooth]# scan on
# (hold the Sync button on the Pro Controller until LEDs flash)
[bluetooth]# pair <MAC_ADDRESS>
[bluetooth]# trust <MAC_ADDRESS>
[bluetooth]# connect <MAC_ADDRESS>
[bluetooth]# quit
The trust command is important — without it, the controller may disconnect after pairing.
Step 4: Verify
Confirm the input device is no longer on the UHID path:
dmesg | grep -i "057e:2009" | tail -10
The input: line should now reference a real Bluetooth device path rather than
/devices/virtual/misc/uhid/.
Test with:
sudo evtest
Select “Pro Controller” (not “Pro Controller (IMU)”) and press buttons — events should now stream.
Summary of problems and fixes
| Problem | Cause | Fix |
|---|---|---|
Controller disconnects when evtest opens it |
BT adapter name doesn't match controller's firmware expectation | Rename adapter to “Nintendo” in main.conf |
evtest sees the device but no button events |
BlueZ UHID transport creates input node but doesn't forward HID reports | Set UserspaceHID=false in input.conf to use kernel HIDP |
| USB worked but Bluetooth didn't | USB bypasses BlueZ entirely; Bluetooth was broken at the BlueZ → UHID bridge | Same — switching to HIDP bypasses the broken bridge |

No comments:
Post a Comment