linux: Pass evdev properties when guessing device type

In newer kernels, devices that can be positively identified as a
particular device type (for example accelerometers) get a property
bit set. Plumb this information through into the function, but don't
use it for anything just yet.

Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
Simon McVittie 2023-06-16 15:14:33 +01:00 committed by Sam Lantinga
parent a4ce721d7a
commit 0d5aa70e62
5 changed files with 26 additions and 6 deletions

View file

@ -37,7 +37,8 @@
#endif #endif
extern int 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_abs[NBITS(ABS_MAX)],
const unsigned long bitmask_key[NBITS(KEY_MAX)], const unsigned long bitmask_key[NBITS(KEY_MAX)],
const unsigned long bitmask_rel[NBITS(REL_MAX)]) const unsigned long bitmask_rel[NBITS(REL_MAX)])

View file

@ -28,6 +28,10 @@
#include <linux/input.h> #include <linux/input.h>
#ifndef INPUT_PROP_MAX
#define INPUT_PROP_MAX 0x1f
#endif
/* A device can be any combination of these classes */ /* A device can be any combination of these classes */
typedef enum typedef enum
{ {
@ -48,7 +52,8 @@ typedef enum
#define EVDEV_LONG(x) ((x) / BITS_PER_LONG) #define EVDEV_LONG(x) ((x) / BITS_PER_LONG)
#define test_bit(bit, array) ((array[EVDEV_LONG(bit)] >> EVDEV_OFF(bit)) & 1) #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_abs[NBITS(ABS_MAX)],
const unsigned long bitmask_key[NBITS(KEY_MAX)], const unsigned long bitmask_key[NBITS(KEY_MAX)],
const unsigned long bitmask_rel[NBITS(REL_MAX)]); const unsigned long bitmask_rel[NBITS(REL_MAX)]);

View file

@ -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) static int guess_device_class(struct udev_device *dev)
{ {
struct udev_device *pdev; struct udev_device *pdev;
unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)];
unsigned long bitmask_ev[NBITS(EV_MAX)]; unsigned long bitmask_ev[NBITS(EV_MAX)];
unsigned long bitmask_abs[NBITS(ABS_MAX)]; unsigned long bitmask_abs[NBITS(ABS_MAX)];
unsigned long bitmask_key[NBITS(KEY_MAX)]; unsigned long bitmask_key[NBITS(KEY_MAX)];
@ -377,12 +378,14 @@ static int guess_device_class(struct udev_device *dev)
return 0; 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/ev", bitmask_ev, SDL_arraysize(bitmask_ev));
get_caps(dev, pdev, "capabilities/abs", bitmask_abs, SDL_arraysize(bitmask_abs)); 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/rel", bitmask_rel, SDL_arraysize(bitmask_rel));
get_caps(dev, pdev, "capabilities/key", bitmask_key, SDL_arraysize(bitmask_key)); 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_abs[0],
&bitmask_key[0], &bitmask_key[0],
&bitmask_rel[0]); &bitmask_rel[0]);

View file

@ -204,6 +204,7 @@ static SDL_bool IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version,
static int GuessIsJoystick(int fd) static int GuessIsJoystick(int fd)
{ {
unsigned long propbit[NBITS(INPUT_PROP_MAX)] = { 0 };
unsigned long evbit[NBITS(EV_MAX)] = { 0 }; unsigned long evbit[NBITS(EV_MAX)] = { 0 };
unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
@ -217,7 +218,11 @@ static int GuessIsJoystick(int fd)
return 0; 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) { if (devclass & SDL_UDEV_DEVICE_JOYSTICK) {
return 1; return 1;

View file

@ -1794,6 +1794,7 @@ run_test(void)
int actual; int actual;
struct struct
{ {
unsigned long props[NBITS(INPUT_PROP_MAX)];
unsigned long ev[NBITS(EV_MAX)]; unsigned long ev[NBITS(EV_MAX)];
unsigned long abs[NBITS(ABS_MAX)]; unsigned long abs[NBITS(ABS_MAX)];
unsigned long keys[NBITS(KEY_MAX)]; unsigned long keys[NBITS(KEY_MAX)];
@ -1803,11 +1804,16 @@ run_test(void)
printf("%s...\n", t->name); printf("%s...\n", t->name);
memset(&caps, '\0', sizeof(caps)); memset(&caps, '\0', sizeof(caps));
memcpy(caps.props, t->props, sizeof(t->props));
memcpy(caps.ev, t->ev, sizeof(t->ev)); memcpy(caps.ev, t->ev, sizeof(t->ev));
memcpy(caps.keys, t->keys, sizeof(t->keys)); memcpy(caps.keys, t->keys, sizeof(t->keys));
memcpy(caps.abs, t->abs, sizeof(t->abs)); memcpy(caps.abs, t->abs, sizeof(t->abs));
memcpy(caps.rel, t->rel, sizeof(t->rel)); 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++) { for (j = 0; j < SDL_arraysize(caps.ev); j++) {
caps.ev[j] = SwapLongLE(caps.ev[j]); caps.ev[j] = SwapLongLE(caps.ev[j]);
} }
@ -1824,8 +1830,8 @@ run_test(void)
caps.rel[j] = SwapLongLE(caps.rel[j]); caps.rel[j] = SwapLongLE(caps.rel[j]);
} }
actual = SDL_EVDEV_GuessDeviceClass(caps.ev, caps.abs, caps.keys, actual = SDL_EVDEV_GuessDeviceClass(caps.props, caps.ev, caps.abs,
caps.rel); caps.keys, caps.rel);
if (actual == t->expected) { if (actual == t->expected) {
printf("\tOK\n"); printf("\tOK\n");