Skip to content

Commit f3ba1d3

Browse files
committed
device: support for Steam Controller on Linux
Adds lgrip and rgrip button handles, which are present on Steam Controller but also on the Oculus Touch
1 parent 4699dfc commit f3ba1d3

File tree

6 files changed

+70
-10
lines changed

6 files changed

+70
-10
lines changed

panda/src/device/evdevInputDevice.cxx

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ enum QuirkBits {
5757

5858
// ABS_THROTTLE maps to rudder
5959
QB_rudder_from_throttle = 16,
60+
61+
// Special handling for Steam Controller, which has many peculiarities.
62+
QB_steam_controller = 32,
6063
};
6164

6265
static const struct DeviceMapping {
@@ -71,6 +74,10 @@ static const struct DeviceMapping {
7174
{0x044f, 0xb108, InputDevice::DeviceClass::flight_stick, QB_centered_throttle | QB_reversed_throttle | QB_rudder_from_throttle},
7275
// Xbox 360 Wireless Controller
7376
{0x045e, 0x0719, InputDevice::DeviceClass::gamepad, QB_connect_if_nonzero},
77+
// Steam Controller (wired)
78+
{0x28de, 0x1102, InputDevice::DeviceClass::unknown, QB_steam_controller},
79+
// Steam Controller (wireless)
80+
{0x28de, 0x1142, InputDevice::DeviceClass::unknown, QB_steam_controller},
7481
// Jess Tech Colour Rumble Pad
7582
{0x0f30, 0x0111, InputDevice::DeviceClass::gamepad, 0},
7683
// Trust GXT 24
@@ -299,6 +306,13 @@ init_device() {
299306
++mapping;
300307
}
301308

309+
// The Steam Controller reports as multiple devices, one of which a gamepad.
310+
if (quirks & QB_steam_controller) {
311+
if (test_bit(BTN_GAMEPAD, keys)) {
312+
_device_class = DeviceClass::gamepad;
313+
}
314+
}
315+
302316
// Try to detect which type of device we have here
303317
if (_device_class == DeviceClass::unknown) {
304318
int device_scores[(size_t)DeviceClass::spatial_mouse] = {0};
@@ -378,7 +392,7 @@ init_device() {
378392
for (int i = 0; i <= KEY_MAX; ++i) {
379393
if (test_bit(i, keys)) {
380394
ButtonState button;
381-
button.handle = map_button(i, _device_class);
395+
button.handle = map_button(i, _device_class, quirks);
382396

383397
int button_index = (int)_buttons.size();
384398
if (button.handle == ButtonHandle::none()) {
@@ -527,6 +541,18 @@ init_device() {
527541
}
528542
}
529543
break;
544+
case ABS_HAT2X:
545+
if (quirks & QB_steam_controller) {
546+
axis = InputDevice::Axis::right_trigger;
547+
have_analog_triggers = true;
548+
}
549+
break;
550+
case ABS_HAT2Y:
551+
if (quirks & QB_steam_controller) {
552+
axis = InputDevice::Axis::left_trigger;
553+
have_analog_triggers = true;
554+
}
555+
break;
530556
}
531557

532558
// Check the initial value and ranges.
@@ -740,7 +766,7 @@ process_events() {
740766
* Static function to map an evdev code to a ButtonHandle.
741767
*/
742768
ButtonHandle EvdevInputDevice::
743-
map_button(int code, DeviceClass device_class) {
769+
map_button(int code, DeviceClass device_class, int quirks) {
744770
if (code >= 0 && code < 0x80) {
745771
// See linux/input.h for the source of this mapping.
746772
static const ButtonHandle keyboard_map[] = {
@@ -897,7 +923,11 @@ map_button(int code, DeviceClass device_class) {
897923
}
898924

899925
} else if ((code & 0xfff0) == BTN_JOYSTICK) {
900-
if (device_class == DeviceClass::gamepad) {
926+
if (quirks & QB_steam_controller) {
927+
// BTN_THUMB and BTN_THUMB2 detect touching the touchpads.
928+
return ButtonHandle::none();
929+
930+
} else if (device_class == DeviceClass::gamepad) {
901931
// Based on "Jess Tech Colour Rumble Pad"
902932
static const ButtonHandle mapping[] = {
903933
GamepadButton::face_x(),
@@ -991,6 +1021,13 @@ map_button(int code, DeviceClass device_class) {
9911021
case BTN_TRIGGER_HAPPY4:
9921022
return GamepadButton::dpad_down();
9931023

1024+
// The next two are for the Steam Controller's grip buttons.
1025+
case BTN_GEAR_DOWN:
1026+
return GamepadButton::lgrip();
1027+
1028+
case BTN_GEAR_UP:
1029+
return GamepadButton::rgrip();
1030+
9941031
default:
9951032
return ButtonHandle::none();
9961033
}

panda/src/device/evdevInputDevice.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ class EXPCL_PANDA_DEVICE EvdevInputDevice : public InputDevice {
6464
int _rtrigger_code;
6565

6666
public:
67-
static ButtonHandle map_button(int code, DeviceClass device_class = DeviceClass::unknown);
67+
static ButtonHandle map_button(int code,
68+
DeviceClass device_class = DeviceClass::unknown,
69+
int quirks = 0);
6870

6971
public:
7072
static TypeHandle get_class_type() {

panda/src/device/linuxJoystickDevice.cxx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ open_device() {
113113
ioctl(_fd, JSIOCGNAME(sizeof(name)), name);
114114
_name = name;
115115

116+
bool emulate_dpad = true;
116117
bool have_analog_triggers = false;
117118

118119
// Get the number of axes.
@@ -138,6 +139,8 @@ open_device() {
138139
_device_class = DeviceClass::gamepad;
139140
} else if (handle == GamepadButton::trigger()) {
140141
_device_class = DeviceClass::flight_stick;
142+
} else if (handle == GamepadButton::dpad_left()) {
143+
emulate_dpad = false;
141144
} else if (handle == GamepadButton::ltrigger()) {
142145
_ltrigger_button = i;
143146
} else if (handle == GamepadButton::rtrigger()) {
@@ -220,7 +223,7 @@ open_device() {
220223
break;
221224

222225
case ABS_HAT0X:
223-
if (_dpad_left_button == -1) {
226+
if (emulate_dpad) {
224227
// Emulate D-Pad or hat switch.
225228
_dpad_x_axis = i;
226229
_dpad_left_button = (int)_buttons.size();
@@ -236,7 +239,7 @@ open_device() {
236239
break;
237240

238241
case ABS_HAT0Y:
239-
if (_dpad_up_button == -1) {
242+
if (emulate_dpad) {
240243
// Emulate D-Pad.
241244
_dpad_y_axis = i;
242245
_dpad_up_button = (int)_buttons.size();
@@ -251,6 +254,18 @@ open_device() {
251254
}
252255
break;
253256

257+
case ABS_HAT2X:
258+
if (_device_class == DeviceClass::gamepad) {
259+
axis = InputDevice::Axis::right_trigger;
260+
}
261+
break;
262+
263+
case ABS_HAT2Y:
264+
if (_device_class == DeviceClass::gamepad) {
265+
axis = InputDevice::Axis::left_trigger;
266+
}
267+
break;
268+
254269
default:
255270
if (device_cat.is_debug()) {
256271
device_cat.debug() << "Unmapped /dev/input/js" << _index
@@ -278,7 +293,7 @@ open_device() {
278293

279294
if (_ltrigger_button >= 0 && _rtrigger_button >= 0 && !have_analog_triggers) {
280295
// Emulate analog triggers.
281-
_ltrigger_control = (int)_axes.size();
296+
_ltrigger_axis = (int)_axes.size();
282297
add_axis(Axis::left_trigger, 0, 1, false);
283298
add_axis(Axis::right_trigger, 0, 1, false);
284299
} else {
@@ -398,9 +413,9 @@ process_events() {
398413

399414
if (events[i].type & JS_EVENT_BUTTON) {
400415
if (index == _ltrigger_button) {
401-
axis_changed(_ltrigger_control, events[i].value);
416+
axis_changed(_ltrigger_axis, events[i].value);
402417
} else if (index == _rtrigger_button) {
403-
axis_changed(_ltrigger_control + 1, events[i].value);
418+
axis_changed(_ltrigger_axis + 1, events[i].value);
404419
}
405420
button_changed(index, (events[i].value != 0));
406421

panda/src/device/linuxJoystickDevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class EXPCL_PANDA_DEVICE LinuxJoystickDevice : public InputDevice {
5050
int _dpad_up_button;
5151

5252
// This is used for axis emulation.
53-
int _ltrigger_control;
53+
int _ltrigger_axis;
5454
int _ltrigger_button;
5555
int _rtrigger_button;
5656

panda/src/putil/gamepadButton.cxx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ DEFINE_GAMEPAD_BUTTON_HANDLE(lshoulder)
2424
DEFINE_GAMEPAD_BUTTON_HANDLE(rshoulder)
2525
DEFINE_GAMEPAD_BUTTON_HANDLE(ltrigger)
2626
DEFINE_GAMEPAD_BUTTON_HANDLE(rtrigger)
27+
DEFINE_GAMEPAD_BUTTON_HANDLE(lgrip)
28+
DEFINE_GAMEPAD_BUTTON_HANDLE(rgrip)
2729

2830
DEFINE_GAMEPAD_BUTTON_HANDLE(dpad_left)
2931
DEFINE_GAMEPAD_BUTTON_HANDLE(dpad_right)
@@ -87,6 +89,8 @@ init_gamepad_buttons() {
8789
ButtonRegistry::ptr()->register_button(_rshoulder, "rshoulder");
8890
ButtonRegistry::ptr()->register_button(_ltrigger, "ltrigger");
8991
ButtonRegistry::ptr()->register_button(_rtrigger, "rtrigger");
92+
ButtonRegistry::ptr()->register_button(_lgrip, "lgrip");
93+
ButtonRegistry::ptr()->register_button(_rgrip, "rgrip");
9094

9195
ButtonRegistry::ptr()->register_button(_dpad_left, "dpad_left");
9296
ButtonRegistry::ptr()->register_button(_dpad_right, "dpad_right");

panda/src/putil/gamepadButton.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class EXPCL_PANDA_PUTIL GamepadButton {
3030
static ButtonHandle rshoulder();
3131
static ButtonHandle ltrigger();
3232
static ButtonHandle rtrigger();
33+
static ButtonHandle lgrip();
34+
static ButtonHandle rgrip();
3335

3436
static ButtonHandle dpad_left();
3537
static ButtonHandle dpad_right();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy