diff --git a/src/core/linux/SDL_evdev_capabilities.c b/src/core/linux/SDL_evdev_capabilities.c index 2d4e937d9c863c..f13c8a954561ef 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,18 @@ #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_FANATEC, USB_PRODUCT_FANATEC_CLUBSPORT_USB_HANDBRAKE }, /* https://github.com/ValveSoftware/Proton/issues/5126 */ + { 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, @@ -80,6 +94,16 @@ SDL_EVDEV_GuessDeviceClass(unsigned int bus_type, return SDL_UDEV_DEVICE_TOUCHPAD; } + 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, * although it could equally mean 3-axis driving sim pedals - * we can't actually tell the difference from the information diff --git a/test/testevdev.c b/test/testevdev.c index 50e2f0d8a141da..60ca0c6c90390e 100644 --- a/test/testevdev.c +++ b/test/testevdev.c @@ -90,6 +90,7 @@ typedef struct uint8_t props[(INPUT_PROP_MAX + 1) / 8]; int expected; const char *todo; + const char *caps_insufficient; size_t hid_report_descriptor_length; const unsigned char *hid_report_descriptor; } GuessTest; @@ -1992,11 +1993,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 */ @@ -2010,11 +2008,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 */ @@ -2045,11 +2040,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 */ @@ -2061,11 +2053,8 @@ static const GuessTest guess_tests[] = .vendor_id = 0x0eb7, .product_id = 0x1a93, .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 = "X axis is not enough to guess device class", /* SYN, ABS */ .ev = { 0x09 }, /* X only */ @@ -2206,6 +2195,38 @@ run_test(void) success = 0; } } + + actual = SDL_EVDEV_GuessDeviceClass(0, 0, 0, 0, + caps.props, 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 limitation, evdev caps are not enough information: %s\n", + t->caps_insufficient); + } else { + printf("\tFailed\n"); + success = 0; + } + } } return success;