Go bindings for Xbox-compatible controllers.
On Linux, this package targets the kernel xpad driver (evdev, joystick,
sysfs). On Windows, it uses XInput and exposes connected controllers as
xinput://0 through xinput://3. On macOS, it uses IOKit HID and exposes
connected controllers as iokit://... devices.
- Linux: wired Xbox 360 controller only (this is the only device tested/supported today).
- Windows: XInput-compatible controllers, with discovery, input polling, and rumble.
- macOS: IOKit HID game controllers, with discovery and input polling. Rumble is not supported.
- PRs welcome for broader controller support and other features.
If you need something implemented, be the change you want to see in the world and open a PR!
Linux-only APIs: joystick devices, sysfs LED control, and kernel module
parameters. Windows and macOS native controller paths do not have an underlying
os.File or file descriptor, so File and FD return ErrNotImplemented.
The macOS IOKit backend requires cgo; builds with cgo disabled return
ErrNotImplemented for discovery/opening.
The xpad driver ships with the Linux kernel. In most distros it is already
available as a loadable kernel module.
- Plug in the Xbox 360 controller (USB or wireless receiver).
- Load the module if it is not already loaded:
sudo modprobe xpad- Verify the devices are present:
ls -l /dev/input/event*
ls -l /dev/input/js*
ls -l /sys/class/leds/xpad*If you do not see the devices, confirm the kernel module is loaded:
lsmod | grep xpadPermissions: reading /dev/input/* and writing to /sys/class/leds/* typically
require elevated privileges or a udev rule that grants your user access.
go get github.com/roryl23/xpad-gopackage xpad
func ExampleDevice_ReadEvent() {
devices, err := FindXpadDevices()
if err != nil {
panic(err)
}
if len(devices) == 0 {
panic(ErrNotFound)
}
dev, err := OpenDevice(devices[0])
if err != nil {
panic(err)
}
defer func() {
if err := dev.Close(); err != nil {
panic(err)
}
}()
event, err := dev.ReadEvent(-1)
if err != nil {
panic(err)
}
_ = event
}On Windows, FindXpadDevices scans XInput slots and returns paths like
xinput://0. On macOS, it scans IOKit HID game controllers and returns paths
like iokit://.... ReadEvent polls platform state changes and maps them to
the existing event constants.
package xpad
func ExampleDeviceInfo_SetLED() {
devices, err := FindXpadDevices()
if err != nil {
panic(err)
}
if len(devices) == 0 {
panic(ErrNotFound)
}
info := devices[0]
if err := info.SetLED(LEDPlayer1); err != nil {
panic(err)
}
}LED command values:
- 0: off
- 1: all blink, then previous setting
- 2-5: 1-4 blink, then on
- 6-9: 1-4 on
- 10: rotate
- 11: blink based on previous setting
- 12: slow blink based on previous setting
- 13: rotate with two lights
- 14: persistent slow all blink
- 15: blink once, then previous setting
package xpad
import "time"
func ExampleDevice_Rumble() {
dev, err := OpenFirstXpad()
if err != nil {
panic(err)
}
defer func() {
if err := dev.Close(); err != nil {
panic(err)
}
}()
id, err := dev.UploadRumble(NewRumbleEffect(0xffff, 0x7fff, 500*time.Millisecond))
if err != nil {
panic(err)
}
if err := dev.PlayEffect(id, 1); err != nil {
panic(err)
}
}package xpad
func ExampleJoystick_ReadEvent() {
devices, err := FindXpadDevices()
if err != nil {
panic(err)
}
if len(devices) == 0 {
panic(ErrNotFound)
}
js, err := devices[0].OpenJoystick()
if err != nil {
panic(err)
}
defer func() {
if err := js.Close(); err != nil {
panic(err)
}
}()
evt, err := js.ReadEvent(-1)
if err != nil {
panic(err)
}
_ = evt
}The integration tests require a controller connected on Linux. If one is not present, the tests that require it will be skipped.
XPAD_INTERACTIVE=1 go test -run TestIntegrationControllerButtons -vUse XPAD_EVENT_PATH or XPAD_JOYSTICK_PATH to point tests at a specific
controller if discovery fails.
To verify the Windows build from another platform:
GOOS=windows GOARCH=amd64 go test -exec true ./...To verify the macOS fallback build from another platform:
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go test -exec true ./...- Linux Kernel driver: https://github.com/paroj/xpad