diff --git a/src/core/linux/SDL_evdev_capabilities.c b/src/core/linux/SDL_evdev_capabilities.c index eaa6319c4ed9b0..15bf7346bf0603 100644 --- a/src/core/linux/SDL_evdev_capabilities.c +++ b/src/core/linux/SDL_evdev_capabilities.c @@ -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 @@ -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, @@ -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) && diff --git a/test/testevdev.c b/test/testevdev.c index 147391a0391cca..c60d5e9e81c073 100644 --- a/test/testevdev.c +++ b/test/testevdev.c @@ -72,6 +72,7 @@ typedef struct uint8_t props[INPUT_PROP_MAX / 8]; int expected; const char *todo; + const char *caps_insufficient; } GuessTest; /* @@ -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 */ @@ -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 */ @@ -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 */ @@ -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) { @@ -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;