3
\$\begingroup\$

Is there any reason why a Steam Controller would think it has two hats?

steam controller

The pad on the left is HAT 0, as expected. Note that the pad on the right is not a HAT/DPAD, it is two axes (Axis2 and Axis3) also, as expected.

03000000de2800000211000011010000 "Steam Controller" axes:4 buttons:21 hats:2 balls:0 

Still, SDL_JoystickNumHats() returns 2. And bottom hat values on change if a trigger is pressed?

Tested with latest SDL 2.0.14 version.

I think ultimately, this info comes from the kernel via ioctl JSIOCGAXMAP that identifies the triggers as HAT, not as triggers?

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

For reference, hid-steam maps Steam Controller inputs to these input events:

ABS_HAT2Y: left trigger ABS_HAT2X: right trigger ABS_X/ABS_HAT0X: X value ABS_Y/ABS_HAT0Y: Y value ABS_RX: right-pad X value ABS_RY: right-pad Y value BTN_TR2: right trigger fully pressed BTN_TL2: left trigger fully pressed BTN_TR: right shoulder BTN_TL: left shoulder BTN_Y: button Y BTN_B: button B BTN_X: button X BTN_A: button A BTN_DPAD_UP: left-pad up BTN_DPAD_RIGHT: left-pad right BTN_DPAD_LEFT: left-pad left BTN_DPAD_DOWN: left-pad down BTN_SELECT: menu left BTN_MODE: steam logo BTN_START: menu right BTN_GEAR_DOWN: left back lever BTN_GEAR_UP: right back lever BTN_THUMBR: right-pad clicked BTN_THUMB: left-pad touched BTN_THUMB2: right-pad touched BTN_THUMBL: joystick clicked 

This mapping follows the Linux Gamepad Specification which specifies how gamepad trigger buttons (named ZL and ZR in the spec) should be mapped to input event codes.

Triggers:

Trigger buttons can be available as digital or analog buttons or both. User- space must correctly deal with any situation and choose the most appropriate mode. Upper trigger buttons are reported as BTN_TR or ABS_HAT1X (right) and BTN_TL or ABS_HAT1Y (left). Lower trigger buttons are reported as BTN_TR2 or ABS_HAT2X (right/ZR) and BTN_TL2 or ABS_HAT2Y (left/ZL). If only one trigger-button combination is present (upper+lower), they are reported as “right” triggers (BTN_TR/ABS_HAT1X). (ABS trigger values start at 0, pressure is reported as positive values)

hid-steam maps the triggers to both BTN_TR2/BTN_TL2 and ABS_HAT2X/ABS_HAT2Y, which causes SDL2 to detect another Hat Switch.

\$\endgroup\$
2
\$\begingroup\$

The problem, of course, is that the Steam Controller's D-Pad isn't actually a D-Pad (with 9 possible input states), it's a touchpad (with two continuous axes). The hid-steam driver implies this by indicating that ABS_HAT0X/Y have a range of -32767 .. 32767, but SDL seems to ignore that and treat it like a regular hat, where Y < 0 => UP, X > 0 => RIGHT, etc.

This in turn makes the D-Pad all but unusable via SDL: it is impossible to touch the pad perfectly centered on either axis, so in practice SDL will only ever report the hat to be in the corners; trying to touch "UP" will waver between UP-LEFT and UP-RIGHT depending whether your finger is just barely left or right of center on the touchpad.

I'm in the midst of trying to find a solution to this problem (which arose for me in the context of RetroPie's version of EmulationStation) but haven't found the right place to address it yet. There may be an environment variable or some other way to make SDL handle this input correctly, or it may require a patch to notice that (for example) the "hat" input range is far wider than -1 / 0 / 1 and to just expose it as an axis instead.

(I've raised this issue with SDL, so hopefully this will be fixed in a future release.)

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.