Impossible OS Docs

Game Controllers and Haptics

What is it?

The game controller roadmap plans first-class support for gamepads and joysticks: a controller device class separate from the keyboard and mouse, a HID gamepad parser, Xbox-compatible (XInput-style) profiles, Bluetooth controllers, rumble, battery and LED control, calibration and a live tester. Nothing in it has shipped. A gamepad plugged in today is not used at all, and this page explains why and what the plan is.

Why does a gamepad not work today?

The USB driver only accepts two kinds of HID device: boot-protocol keyboards and boot-protocol mice. When it enumerates a device, xhci_dev.c looks for an interface with class USB_CLASS_HID (0x03), the boot subclass and the keyboard or mouse protocol (xhci_dev.h). A gamepad reports class 0x03 with no boot subclass, so it is skipped with a debug line:

Slot <n>: no HID boot interface (hid=0, int_in=0)

Boot keyboards and mice work because their reports have a fixed layout. Gamepads describe their buttons, sticks and triggers in a HID report descriptor, and the kernel has no report descriptor parser yet. Bluetooth controllers additionally need the Bluetooth stack, which does not exist.

How will it work?

A class of its own. Controllers register as controller_device_t, not as mice or keyboards, and report a fixed event packet of axes, buttons, hats and triggers. The HID parser reads the Generic Desktop game pad and joystick usages and normalises sticks to signed 16-bit values and triggers to unsigned values.

Stable players. Xbox-compatible layouts map to fixed player slots and profile ids that user-mode game APIs can rely on, the role XInput plays on Windows. A Bluetooth controller keeps its identity and battery state across reconnects.

Output and tuning. Rumble and simple haptics go out through HID output reports and fail gracefully on devices without them. Battery level, player LEDs and light bars are handled where the device supports them. Dead zones, axis inversion and calibration are stored in the Registry per device.

Low latency. The event path allocates nothing once a controller is open, and add and remove events are published to user mode.

flowchart LR
    U[USB HID gamepad] --> P[HID gamepad parser]
    BT[Bluetooth HID gamepad] --> P
    P --> C[controller_device_t: axes, buttons, triggers]
    C --> X[XInput-style profiles, player slots]
    C --> E[Low-latency events to user mode]
    O[Rumble, LEDs] --> C
    R[Registry: calibration] --> C

What are its interfaces?

None yet. The planned surface is the controller_device_t class and event packet, profile ids for user-mode game APIs, Registry calibration values, a joy.cpl style tester and Device Manager details.

How do I use it?

You cannot yet. The existing HID tests cover the keyboard and mouse boot path this roadmap will build beside (test_usb_hid.c), in the storage suite:

bash scripts/test.sh SUITE=storage

What is not implemented yet?

Everything:

How does it compare with Windows 11 and Linux?

Windows 11 handles gamepads through HIDClass with XInput and Windows.Gaming.Input on top, and ships the joy.cpl tester. Linux parses them in the HID and input layers into evdev devices, with force feedback through ff-memless, and tests them with evtest and jstest. Impossible OS plans a dedicated controller class plus a unified live tester, and ignores gamepads today.

See also

Impossible OS is free software under the GPL-3.0-only license. Last updated Edit this page on GitHub