Presents a Google Stadia controller as an Xbox 360 gamepad over USB. The ESP32-S3 connects to the controller via BLE and appears to the host PC as a wired Xbox 360 controller — no drivers required on Windows, Linux, or macOS.
Plug the dongle into your PC, hold the Stadia button on the controller to pair, and it works.
After Google shut down Stadia, they released a firmware update enabling the controller's Bluetooth mode. On Windows, input works fine but rumble does not — and it cannot be fixed in software.
The root cause is a Windows kernel driver limitation: the Windows BLE HID driver holds
exclusive access to the controller's GATT service, blocking all output reports. Neither
WriteFile (returns error 87 — the BLE stack sends a write-without-response which the
Stadia firmware rejects) nor HidD_SetOutputReport (fails silently) can send the rumble
command. Direct GATT access via WinRT is also denied while the HID driver is active, and
disabling the driver drops the Bluetooth connection entirely.
The ESP32-S3 sidesteps all of this. Its BLE stack correctly issues a GATT write-with-response for the rumble characteristic — exactly what the Stadia firmware requires. The host PC only sees a standard wired Xbox 360 controller over USB, so no special software or drivers are needed on the PC side at all.
Any ESP32-S3 board with native USB (USB OTG on GPIO19/20). The USB port connected to the host must be the native USB port, not UART.
Easy — no software needed: use the web installer in Chrome or Edge.
👉 scalee.github.io/stadia-dongle
Connect the ESP32-S3 via the COM/UART USB port, click Install, then move it to the native USB port after flashing.
Building and flashing from source
Requires ESP-IDF v6.0 with target esp32s3.
idf.py build
idf.py -p <PORT> flashThe dongle bonds to the first Stadia controller it sees. The bond is stored in NVS (flash) and survives power cycles. To pair a different controller, erase NVS:
idf.py -p <PORT> erase-flash| Stadia | Xbox 360 |
|---|---|
| A / B / X / Y | A / B / X / Y |
| LB / RB | LB / RB |
| LT / RT | LT / RT |
| LS / RS | LS / RS |
| Menu | Start |
| Options | Back |
| Stadia button | Guide |
| D-pad | D-pad |
Rumble is fully supported in both directions.
Hold the Assistant button for 3 seconds to toggle rumble on/off. A short haptic pattern confirms the state change.
In bridge.h, set DONGLE_DEBUG 1 to enable raw HID report hex dumps over UART.
Set to 0 for production builds.