Skip to content

Commit

Permalink
linux: Have a table of known joysticks
Browse files Browse the repository at this point in the history
These simulation control devices are known to be joysticks, but don't
all have enough information in their evdev capabilities for us to be
able to distinguish them from an accelerometer by capabilities alone.
If we look at the bus type, vendor ID and product ID as well, then
that gives us enough information to distinguish.

Resolves: libsdl-org#7500
Co-authored-by: Felix Hädicke <[email protected]>
Signed-off-by: Simon McVittie <[email protected]>
  • Loading branch information
smcv and felixhaedicke committed Jun 13, 2023
1 parent 950ad17 commit 860c3c7
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 13 deletions.
23 changes: 23 additions & 0 deletions src/core/linux/SDL_evdev_capabilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

#ifdef HAVE_LINUX_INPUT_H

#include "../../joystick/usb_ids.h"

/* missing defines in older Linux kernel headers */
#ifndef BTN_TRIGGER_HAPPY
#define BTN_TRIGGER_HAPPY 0x2c0
Expand All @@ -36,6 +38,17 @@
#define KEY_ALS_TOGGLE 0x230
#endif

static const struct input_id known_joysticks[] = {
{ BUS_USB, USB_VENDOR_CH_PRODUCTS, USB_PRODUCT_CH_PRO_PEDALS }, /* https://github.com/libsdl-org/SDL/issues/7500 */
{ BUS_USB, USB_VENDOR_HEUSINKVELD, USB_PRODUCT_HEUSINKVELD_SIM_PEDALS_ULTIMATE }, /* https://github.com/ValveSoftware/Proton/issues/5126 */
{ BUS_USB, USB_VENDOR_LEO_BODNAR, USB_PRODUCT_LEO_BODNAR_G25_PEDAL_ADAPTER }, /* https://github.com/ValveSoftware/Proton/issues/5126 */
{ BUS_USB, USB_VENDOR_STMICRO, USB_PRODUCT_STMICRO_VRS_DIRECTFORCE_PRO_PEDALS }, /* https://github.com/ValveSoftware/Proton/issues/5126 */
{ BUS_USB, USB_VENDOR_THRUSTMASTER, USB_PRODUCT_THRUSTMASTER_TFRP_RUDDER }, /* https://github.com/ValveSoftware/steam-devices/pull/36 */
{ BUS_USB, USB_VENDOR_THRUSTMASTER, USB_PRODUCT_THRUSTMASTER_TWCS_THROTTLE }, /* https://github.com/ValveSoftware/steam-devices/pull/36 */
{ BUS_USB, USB_VENDOR_THRUSTMASTER, USB_PRODUCT_THRUSTMASTER_T16000M_JOYSTICK }, /* https://github.com/ValveSoftware/steam-devices/pull/36 */
};
#define N_KNOWN_JOYSTICKS (sizeof(known_joysticks) / sizeof(known_joysticks[0]))

extern int
SDL_EVDEV_GuessDeviceClass(unsigned int bus_type,
unsigned int vendor_id,
Expand All @@ -62,6 +75,16 @@ SDL_EVDEV_GuessDeviceClass(unsigned int bus_type,
unsigned long keyboard_mask;
unsigned i;

for (i = 0; i < N_KNOWN_JOYSTICKS; i++) {
const struct input_id *known = &known_joysticks[i];

if (vendor_id == known->vendor &&
product_id == known->product &&
(known->bustype == 0 || bus_type == known->bustype)) {
return SDL_UDEV_DEVICE_JOYSTICK;
}
}

/* X, Y, Z axes but no buttons probably means an accelerometer
* (TODO: or it could mean 3-axis driving sim pedals, we can't tell!) */
if (test_bit(EV_ABS, bitmask_ev) &&
Expand Down
51 changes: 38 additions & 13 deletions test/testevdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ typedef struct
uint8_t props[INPUT_PROP_MAX / 8];
int expected;
const char *todo;
const char *caps_insufficient;
} GuessTest;

/*
Expand Down Expand Up @@ -1290,11 +1291,8 @@ static const GuessTest guess_tests[] =
.vendor_id = 0x0483, /* STMicroelectronics */
.product_id = 0xa3be, /* VRS DirectForce Pro Pedals */
.version = 0x0111,
/* TODO: Ideally we would identify this as a joystick, but there
* isn't currently enough information to do that without a table
* of known devices. */
.expected = SDL_UDEV_DEVICE_JOYSTICK,
.todo = "https://github.com/ValveSoftware/Proton/issues/5126",
.caps_insufficient = "can't distinguish from an accelerometer",
/* SYN, ABS */
.ev = { 0x09 },
/* X, Y, Z */
Expand All @@ -1306,11 +1304,8 @@ static const GuessTest guess_tests[] =
.vendor_id = 0x30b7, /* Heusinkveld Engineering */
.product_id = 0x1003, /* Heusinkveld Sim Pedals Ultimate */
.version = 0x0000,
/* TODO: Ideally we would identify this as a joystick, but there
* isn't currently enough information to do that without a table
* of known devices. */
.expected = SDL_UDEV_DEVICE_JOYSTICK,
.todo = "https://github.com/ValveSoftware/Proton/issues/5126",
.caps_insufficient = "can't distinguish from an accelerometer",
/* SYN, ABS */
.ev = { 0x09 },
/* RX, RY, RZ */
Expand Down Expand Up @@ -1339,11 +1334,8 @@ static const GuessTest guess_tests[] =
.vendor_id = 0x1dd2, /* Leo Bodnar Electronics Ltd */
.product_id = 0x100c,
.version = 0x0110,
/* TODO: Ideally we would identify this as a joystick, but there
* isn't currently enough information to do that without a table
* of known devices. */
.expected = SDL_UDEV_DEVICE_JOYSTICK,
.todo = "https://github.com/ValveSoftware/Proton/issues/5126",
.caps_insufficient = "can't distinguish from an accelerometer",
/* SYN, ABS */
.ev = { 0x09 },
/* RX, RY, RZ */
Expand Down Expand Up @@ -1415,7 +1407,9 @@ run_test(void)
caps.rel[j] = SwapLongLE(caps.rel[j]);
}

actual = SDL_EVDEV_GuessDeviceClass(caps.ev, caps.abs, caps.keys,
actual = SDL_EVDEV_GuessDeviceClass(t->bus_type, t->vendor_id,
t->product_id, t->version,
caps.ev, caps.abs, caps.keys,
caps.rel);

if (actual == t->expected) {
Expand Down Expand Up @@ -1444,6 +1438,37 @@ run_test(void)
success = 0;
}
}

actual = SDL_EVDEV_GuessDeviceClass(0, 0, 0, 0, caps.ev, caps.abs,
caps.keys, caps.rel);

if (actual == t->expected) {
printf("\tOK\n");
} else {
printf("\tExpected 0x%08x\n", t->expected);

for (j = 0; device_classes[j].code != 0; j++) {
if (t->expected & device_classes[j].code) {
printf("\t\t%s\n", device_classes[j].name);
}
}

printf("\tGot 0x%08x using only evdev caps\n", actual);

for (j = 0; device_classes[j].code != 0; j++) {
if (actual & device_classes[j].code) {
printf("\t\t%s\n", device_classes[j].name);
}
}

if (t->caps_insufficient) {
printf("\tKnown issue, evdev caps are not enough information: %s\n",
t->caps_insufficient);
} else {
printf("\tFailed\n");
success = 0;
}
}
}

return success;
Expand Down

0 comments on commit 860c3c7

Please sign in to comment.