How to Use Your Modded Nintendo Switch as a Wii U GamePad

By Coulter Peterson
Consoles & Gaming

The Nintendo Wii U GamePad is one of the more unusual pieces of gaming hardware ever made — a controller with its own screen, its own battery, and its own wireless connection to the console. It's also increasingly difficult to replace. Nintendo never sold it separately in the West, stopped repairing them years ago, and the consoles that depend on it are getting older every day.

Enter Vanilla, an open-source project by MattKC that reverse-engineered the GamePad's wireless protocol and reimplements it in software. With Vanilla, you can use a Linux device — a Steam Deck, a Raspberry Pi, a laptop, or in our case a modded Nintendo Switch — as a fully functional Wii U GamePad replacement.

This guide covers the complete setup process for a Nintendo Switch running L4T Ubuntu (Linux for Tegra), including a non-obvious fix for a hardware decoder issue that trips up every Switch user. By the end, you'll have Vanilla launching at the tap of a desktop icon, in fullscreen, connecting to your Wii U without any password prompts.


What You'll Need

  • A Nintendo Switch with a hardware exploit (unpatched unit) running L4T Ubuntu 24.04
  • A Wii U in working order with its original GamePad (you need the GamePad at least once for initial pairing — after that, Vanilla replaces it)
  • An internet connection on your Switch during setup

How This Works

The Wii U GamePad communicates with the console over a custom 5GHz Wi-Fi protocol — a slightly obfuscated variant of 802.11n. Vanilla intercepts that protocol and speaks it from your device instead.

The Switch's built-in Wi-Fi chip (a Broadcom BCM4356) supports 5GHz 802.11n, but there's a catch: it's a FullMAC adapter, meaning the 802.11 protocol stack runs on the chip itself rather than in software. This makes it impossible for Vanilla to inject the custom protocol tweaks it needs — at least without patching the chip's firmware.

Fortunately, the Vanilla team maintains a fork of the Nexmon firmware patching framework (github.com/vanilla-wiiu/nexmon) that adds exactly the patches needed to the BCM4356. Once applied, your Switch's built-in Wi-Fi can talk directly to the Wii U. No USB adapter required.


Step 1: Back Up Your Wi-Fi Firmware

Before touching anything, back up the existing BCM4356 firmware. The Switch uses the PCIe variant of this chip, so the file you want is brcmfmac4356-pcie.bin.zst (the .zst suffix means it's compressed — that's normal on Ubuntu 24.04).

sudo cp /lib/firmware/brcm/brcmfmac4356-pcie.bin.zst ~/brcmfmac4356-pcie.bin.zst.bak

Keep this backup somewhere safe. If anything goes wrong with the patched firmware, this is how you get your Wi-Fi back.


Step 2: Install the Nexmon Firmware Patch

Head to github.com/vanilla-wiiu/nexmon/releases in a browser on your Switch and download the latest release. Extract the archive — you should have three files: brcmfmac4356-pcie.bin, brcmfmac4356-pcie.txt, and brcmfmac.ko.

Copy the patched firmware into place:

sudo cp brcmfmac4356-pcie.bin /lib/firmware/brcm/
sudo cp brcmfmac4356-pcie.txt /lib/firmware/brcm/

The Nexmon firmware is uncompressed while your original was .zst. That's fine — the kernel's firmware loader handles both formats.

Now load the custom kernel module. You have two options: temporary (resets on reboot) or permanent. Unless you're just testing, go permanent:

sudo rmmod brcmfmac
sudo cp brcmfmac.ko /lib/modules/$(uname -r)/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/
sudo modprobe brcmfmac

Your Wi-Fi will still work after this. You may notice slightly reduced network performance since the custom firmware doesn't include the Switch-specific optimizations from the stock firmware, but it's generally fine for normal use.

If the pre-built release doesn't work on your kernel version, you'll need to compile Nexmon from source. See the appendix at the end of this post for those instructions.


Step 3: Install Vanilla's Build Dependencies

Now let's get Vanilla itself built. Start with the dependencies:

sudo apt install build-essential cmake \
  libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev \
  libavformat-dev libavcodec-dev libavutil-dev libswscale-dev \
  libnl-genl-3-dev libnl-route-3-dev \
  libssl-dev libxml2-dev libnm-dev libpolkit-agent-1-dev

Note libpolkit-agent-1-dev at the end — this one is missing from some versions of Vanilla's documented dependency list but is required. Without it, cmake will fail with a polkit-agent-1 not found error.


Step 4: Build a Clean Version of FFmpeg

This step isn't in Vanilla's official documentation, but it's essential on L4T Ubuntu. Skip it and Vanilla will connect to your Wii U but never show a picture.

Here's the problem: L4T Ubuntu ships a heavily patched version of FFmpeg (you can see the l4t2 suffix on all the package versions if you run dpkg -l | grep libav). This patched FFmpeg includes a Tegra-specific hardware H.264 decoder called h264_nvv4l2. FFmpeg auto-selects this decoder for the Wii U's video stream, but the decoder fails because it tries to allocate GPU memory before it has received the stream headers that tell it the frame dimensions. The result is an endless loop of Picture size 0x0 is invalid errors in the terminal and a Vanilla UI permanently stuck on "Connecting to Wii U."

Environment variables like LIBVA_DRIVER_NAME=none don't fix this — the h264_nvv4l2 decoder is compiled directly into the L4T FFmpeg libraries and registers itself at startup regardless.

The solution is to build a clean, unpatched FFmpeg from source and point Vanilla at that instead:

cd ~
git clone --depth=1 https://github.com/FFmpeg/FFmpeg.git ffmpeg-src
cd ffmpeg-src
./configure \
  --prefix=/opt/ffmpeg-vanilla \
  --enable-shared \
  --enable-gpl
make -j$(nproc)
sudo make install

This will take a while — expect 15–30 minutes on the Switch's Tegra X1. The --prefix=/opt/ffmpeg-vanilla puts everything in its own directory so it doesn't conflict with the system L4T FFmpeg.


Step 5: Build Vanilla

Clone the Vanilla repository and build it, pointing CMake at the clean FFmpeg you just compiled:

git clone https://github.com/vanilla-wiiu/vanilla.git
cd vanilla
mkdir build && cd build
PKG_CONFIG_PATH=/opt/ffmpeg-vanilla/lib/pkgconfig cmake ..
cmake --build .

The PKG_CONFIG_PATH variable tells CMake to find FFmpeg headers and libraries from your clean build rather than the system L4T version.


Step 6: First Launch and Configuration

Launch Vanilla with the clean FFmpeg loaded at runtime. The LD_LIBRARY_PATH prefix ensures the system loads your unpatched libavcodec instead of the L4T version:

LD_LIBRARY_PATH=/opt/ffmpeg-vanilla/lib ./vanilla

The first thing you should do once Vanilla opens is go to Settings → Enable Root Password Skip. This installs a Polkit rule that allows vanilla-pipe (Vanilla's background component that handles the low-level Wi-Fi work) to run as root without prompting you for a password. Without this, every single time you connect to your Wii U, you'll need to type your sudo password on a touchscreen keyboard — which gets old fast.

There is a security note here: allowing an executable to run as root without a password prompt has inherent risks. Vanilla's settings screen will show you a warning before you enable it. Read it and make the call for yourself.

While you're in Settings, you can also enable full screen mode so Vanilla launches straight into a full-screen GamePad view.


Step 7: Connect to Your Wii U

Turn on your Wii U and leave it sitting on the home menu. Pairing will not work if a game is already running.

Back in Vanilla, select your wireless interface (typically wlan0) and hit Connect. Vanilla will invoke vanilla-pipe in the background, perform the Wi-Fi handshake with the Wii U, and after a few seconds the GamePad screen should appear.

Your Switch's buttons map directly to the GamePad controls. The touchscreen works as the GamePad touchscreen. If gyroscope input isn't working, add a udev rule and reboot:

echo 'SUBSYSTEM=="input", ENV{ID_INPUT_ACCELEROMETER}=="?*", TAG+="uaccess"' | sudo tee /etc/udev/rules.d/70-gyro.rules

Step 8: Create a Desktop Shortcut

Typing the full LD_LIBRARY_PATH command every time is tedious. Create a .desktop file to launch Vanilla properly from the app launcher:

nano ~/.local/share/applications/vanilla.desktop

Paste in the following, adjusting the path to match wherever you cloned Vanilla:

[Desktop Entry]
Name=Vanilla (Wii U GamePad)
Exec=env LD_LIBRARY_PATH=/opt/ffmpeg-vanilla/lib /home/YOUR_USERNAME/vanilla/build/vanilla -f
Icon=input-gaming
Terminal=false
Type=Application
Categories=Game;

If you installed Vanilla system-wide and want the branded icon:

[Desktop Entry]
Name=Vanilla (Wii U GamePad)
Exec=env LD_LIBRARY_PATH=/opt/ffmpeg-vanilla/lib vanilla -f
Icon=com.mattkc.vanilla_rounded
Terminal=false
Type=Application
Categories=Game;

In both cases, the -f flag forces fullscreen on launch. Remove it if you'd prefer to launch windowed and toggle with F11.

Make the file executable and optionally copy it to your desktop:

chmod +x ~/.local/share/applications/vanilla.desktop
cp ~/.local/share/applications/vanilla.desktop ~/Desktop/

Vanilla will now appear in your app launcher and on your desktop. One tap to launch, straight into full screen, no password prompt.


Usage Notes

  • Exiting fullscreen: Press F11 to toggle
  • Getting back to the Vanilla menu: Press the screenshot button on the switch to toggle out of gamepad mode and into keyboard/mouse mode, then press X (which acts as Esc in that mode) to back out to the Vanilla menu
  • Showing the taskbar in fullscreen on KDE: Tap and drag up slowly from the very bottom edge of the screen
  • If the Wii U disconnects: Just re-launch Vanilla and connect again — you don't need to redo any of the firmware steps
  • On reboot: If you installed the Nexmon kernel module permanently, Wi-Fi and Vanilla work right away. If you used the temporary load option, you'll need to re-run the rmmod/insmod commands before launching Vanilla

Appendix: Compiling Nexmon from Source

If the pre-built Nexmon release doesn't match your kernel version, you'll need to compile it yourself. This is more involved but well-documented.

sudo -i

# Dependencies
apt install git libgmp3-dev gawk qpdf bison flex make autoconf libtool texinfo

# Add 32-bit ARM support — required for Nexmon's build toolchain on aarch64
dpkg --add-architecture armhf
apt-get update
apt-get install libc6:armhf libisl23:armhf libmpfr6:armhf libmpc3:armhf libstdc++6:armhf
ln -s /usr/lib/arm-linux-gnueabihf/libisl.so.23 /usr/lib/arm-linux-gnueabihf/libisl.so.10
ln -s /usr/lib/arm-linux-gnueabihf/libmpfr.so.6 /usr/lib/arm-linux-gnueabihf/libmpfr.so.4

# Update kernel headers
apt upgrade

# Some of Nexmon's build scripts were compiled for x86 and won't run on aarch64
# Recompile them for the current architecture
cd /usr/src/linux-headers-$(uname -r)/scripts/basic
make -B fixdep
cd ../mod
make modpost.o
make file2alias.o
make sumversion.o
gcc modpost.o file2alias.o sumversion.o -o modpost

# Clone and build Nexmon
cd ~
git clone https://github.com/vanilla-wiiu/nexmon.git
cd nexmon
source setup_env.sh
make

# Navigate to the BCM4356 Wii U patch and install
cd patches/bcm4356/7_35_101_5_sta/wiiu
make backup-firmware
make install-firmware

After make install-firmware, the patched firmware is permanently in place but the kernel module is only loaded temporarily. To make it persist across reboots, run the permanent module install from Step 2:

sudo rmmod brcmfmac
sudo cp brcmfmac.ko /lib/modules/$(uname -r)/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/
sudo modprobe brcmfmac

Further Resources