diff --git a/src/core/linux/SDL_evdev_capabilities.c b/src/core/linux/SDL_evdev_capabilities.c index 054a8b9b6bbc4..233426da44829 100644 --- a/src/core/linux/SDL_evdev_capabilities.c +++ b/src/core/linux/SDL_evdev_capabilities.c @@ -37,7 +37,8 @@ #endif extern int -SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_ev[NBITS(EV_MAX)], +SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)], + const unsigned long bitmask_ev[NBITS(EV_MAX)], const unsigned long bitmask_abs[NBITS(ABS_MAX)], const unsigned long bitmask_key[NBITS(KEY_MAX)], const unsigned long bitmask_rel[NBITS(REL_MAX)]) diff --git a/src/core/linux/SDL_evdev_capabilities.h b/src/core/linux/SDL_evdev_capabilities.h index aa0ddb41a019d..91364df6a8ffe 100644 --- a/src/core/linux/SDL_evdev_capabilities.h +++ b/src/core/linux/SDL_evdev_capabilities.h @@ -28,6 +28,10 @@ #include +#ifndef INPUT_PROP_MAX +#define INPUT_PROP_MAX 0x1f +#endif + /* A device can be any combination of these classes */ typedef enum { @@ -48,7 +52,8 @@ typedef enum #define EVDEV_LONG(x) ((x) / BITS_PER_LONG) #define test_bit(bit, array) ((array[EVDEV_LONG(bit)] >> EVDEV_OFF(bit)) & 1) -extern int SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_ev[NBITS(EV_MAX)], +extern int SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)], + const unsigned long bitmask_ev[NBITS(EV_MAX)], const unsigned long bitmask_abs[NBITS(ABS_MAX)], const unsigned long bitmask_key[NBITS(KEY_MAX)], const unsigned long bitmask_rel[NBITS(REL_MAX)]); diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index 71fbcf00551fe..9e72d79ed1cbf 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -362,6 +362,7 @@ static void get_caps(struct udev_device *dev, struct udev_device *pdev, const ch static int guess_device_class(struct udev_device *dev) { struct udev_device *pdev; + unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)]; unsigned long bitmask_ev[NBITS(EV_MAX)]; unsigned long bitmask_abs[NBITS(ABS_MAX)]; unsigned long bitmask_key[NBITS(KEY_MAX)]; @@ -377,12 +378,14 @@ static int guess_device_class(struct udev_device *dev) return 0; } + get_caps(dev, pdev, "properties", bitmask_props, SDL_arraysize(bitmask_props)); get_caps(dev, pdev, "capabilities/ev", bitmask_ev, SDL_arraysize(bitmask_ev)); get_caps(dev, pdev, "capabilities/abs", bitmask_abs, SDL_arraysize(bitmask_abs)); get_caps(dev, pdev, "capabilities/rel", bitmask_rel, SDL_arraysize(bitmask_rel)); get_caps(dev, pdev, "capabilities/key", bitmask_key, SDL_arraysize(bitmask_key)); - return SDL_EVDEV_GuessDeviceClass(&bitmask_ev[0], + return SDL_EVDEV_GuessDeviceClass(&bitmask_props[0], + &bitmask_ev[0], &bitmask_abs[0], &bitmask_key[0], &bitmask_rel[0]); diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 25c71b85edee5..e7628f112891e 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -204,6 +204,7 @@ static SDL_bool IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version, static int GuessIsJoystick(int fd) { + unsigned long propbit[NBITS(INPUT_PROP_MAX)] = { 0 }; unsigned long evbit[NBITS(EV_MAX)] = { 0 }; unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; @@ -217,7 +218,11 @@ static int GuessIsJoystick(int fd) return 0; } - devclass = SDL_EVDEV_GuessDeviceClass(evbit, absbit, keybit, relbit); + /* This is a newer feature, so it's allowed to fail - if so, then the + * device just doesn't have any properties. */ + (void) ioctl(fd, EVIOCGPROP(sizeof(propbit)), propbit); + + devclass = SDL_EVDEV_GuessDeviceClass(propbit, evbit, absbit, keybit, relbit); if (devclass & SDL_UDEV_DEVICE_JOYSTICK) { return 1; diff --git a/test/testevdev.c b/test/testevdev.c index 0ab85aefd2942..e8315b1baff5e 100644 --- a/test/testevdev.c +++ b/test/testevdev.c @@ -1794,6 +1794,7 @@ run_test(void) int actual; struct { + unsigned long props[NBITS(INPUT_PROP_MAX)]; unsigned long ev[NBITS(EV_MAX)]; unsigned long abs[NBITS(ABS_MAX)]; unsigned long keys[NBITS(KEY_MAX)]; @@ -1803,11 +1804,16 @@ run_test(void) printf("%s...\n", t->name); memset(&caps, '\0', sizeof(caps)); + memcpy(caps.props, t->props, sizeof(t->props)); memcpy(caps.ev, t->ev, sizeof(t->ev)); memcpy(caps.keys, t->keys, sizeof(t->keys)); memcpy(caps.abs, t->abs, sizeof(t->abs)); memcpy(caps.rel, t->rel, sizeof(t->rel)); + for (j = 0; j < SDL_arraysize(caps.props); j++) { + caps.props[j] = SwapLongLE(caps.props[j]); + } + for (j = 0; j < SDL_arraysize(caps.ev); j++) { caps.ev[j] = SwapLongLE(caps.ev[j]); } @@ -1824,8 +1830,8 @@ run_test(void) caps.rel[j] = SwapLongLE(caps.rel[j]); } - actual = SDL_EVDEV_GuessDeviceClass(caps.ev, caps.abs, caps.keys, - caps.rel); + actual = SDL_EVDEV_GuessDeviceClass(caps.props, caps.ev, caps.abs, + caps.keys, caps.rel); if (actual == t->expected) { printf("\tOK\n");