Recently I’ve been playing around with building various alternative controller projects for games, typically using an Arduino-compatible microcontroller acting as an HID input device of some sort. The Arduino ecosystem makes it easy to set up these projects to act as either a Keyboard, a Mouse, a DirectInput Joystick, or a composite device that’s a combination of the above. Unfortunately back in 2005 DirectInput was supplanted by XInput with the release of the Xbox 360 controllers, and modern games have been weaning off of it ever since.
These days, many mainstream games barely support DirectInput at all. Games like Rocket League and Overwatch won’t even recognize a DirectInput joystick – you have to use XInput controller emulation software that can be tricky to set up and doesn’t work with every game.
Wouldn’t it be great if there was a simple, turnkey way to make your Arduino emulate an Xbox controller and work out of the box with these newer games?
Introducing: Arduino XInput!
The Arduino XInput Library makes it easy to convert most USB capable Arduino boards into a fully fledged Xbox controller that is plug and play with Windows. The library gives you access to all of the controls available on an Xbox 360 controller:
- 10 + 1 Digital Buttons
- 2 Analog Joysticks (16 bit)
- 2 Analog Triggers (8 bit)
- 1 Four-Way Directional Pad (D-Pad)
The library also processes received data, so you can read the status of the controller’s 2 rumble motors (8-bit), the assigned player number (1-4), and the index of the current LED animation. Data is sent and received automatically over USB, so the Arduino is free to do whatever else you want in your main sketch.
The Arduino framework makes it easy to append the USB descriptors but not to replace them altogether. This means that unlike most USB mode libraries (Keyboard, Joystick, MIDI, etc.), this library will not work out of the box without some additional configuration. In this case, a boards package specific to the Arduino you’re trying to use.
I’m launching the library with three boards packages, which add support for the USB capable Arduino AVR boards, SparkFun AVR boards, and the Teensy 3 boards. Over twenty microcontrollers are supported, including:
For a full list of supported boards, see here. Note that Arduino boards without native USB support (Uno, Nano, Mega) are not supported.
Much as I hate to say it, unlike most of my other projects this library comes with two main caveats – two main limitations that make this significantly less useful than it could potentially be.
No Console Support
Unfortunately although this will enable the Arduino to act like an Xbox controller for a PC, it will not work with an Xbox console. The Xbox 360 controller contains a dedicated security chip that is used to verify that only authorized devices can communicate with the console. As far as I’m aware this security method has not been fully broken (at least not openly). Without this security chip or a software approximation of it, the Arduino will not be able to communicate with the console.
With some reverse engineering it should be possible to filter for these requests and build a system to pass them on to a security chip that has been desoldered from a genuine controller, but that’s a project for another day.
No Commercial Use
This is a harder pill to swallow but it’s a necessary evil. For this to work the Arduino board emulates an Xbox 360 wired controller, which means it also borrows the use of Microsoft’s USB VID and PID so that the Windows driver will pick it up. Without this VID/PID combination the driver will ignore it, and it won’t function as a controller.
Because this project makes use of Microsoft’s identifiers to work, this is strictly for non-commercial use. Sorry!
For the Future
There’s still some room to grow with this project, mostly in regards to supported boards. Originally this started as a spinoff of Zach Littell’s XInput project working for the Teensy, but I’ve since added support for AVR boards using the Arduino USB stack. With the Arduino IDE’s ability to reference other core files, it’s quite easy to add support for additional boards that use the same architecture (see the SparkFun AVR changes for reference). I believe I’ve covered the basic boards most people will want to use, although with the core defined additional USB capable AVR boards should take only a few minutes to add.
Eventually I’d like this to support other architectures such as ARM. I’ve added some documentation to the library repository explaining how the library’s USB API works, so if anyone wants to build support for other boards please be my guest!