Skip to content

Commit

Permalink
linux: Pass bus/vendor/product/version tuple when guessing device type
Browse files Browse the repository at this point in the history
Helps: libsdl-org#7500
Signed-off-by: Simon McVittie <[email protected]>
  • Loading branch information
smcv committed Aug 6, 2024
1 parent e028212 commit 96e578c
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 16 deletions.
6 changes: 5 additions & 1 deletion src/core/linux/SDL_evdev_capabilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@
#endif

extern int
SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)],
SDL_EVDEV_GuessDeviceClass(unsigned int bus_type,
unsigned int vendor_id,
unsigned int product_id,
unsigned int version,
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)],
Expand Down
6 changes: 5 additions & 1 deletion src/core/linux/SDL_evdev_capabilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ 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_props[NBITS(INPUT_PROP_MAX)],
extern int SDL_EVDEV_GuessDeviceClass(unsigned int bus_type,
unsigned int vendor_id,
unsigned int product_id,
unsigned int version,
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)],
Expand Down
8 changes: 7 additions & 1 deletion src/core/linux/SDL_udev.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,10 @@ 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;
Uint16 bus = 0;
Uint16 vendor = 0;
Uint16 product = 0;
Uint16 version = 0;
unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)];
unsigned long bitmask_ev[NBITS(EV_MAX)];
unsigned long bitmask_abs[NBITS(ABS_MAX)];
Expand All @@ -408,13 +412,15 @@ static int guess_device_class(struct udev_device *dev)
return 0;
}

input_dev_get_product_info (dev, &bus, &vendor, &product, &version);
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_props[0],
return SDL_EVDEV_GuessDeviceClass(bus, vendor, product, version,
&bitmask_props[0],
&bitmask_ev[0],
&bitmask_abs[0],
&bitmask_key[0],
Expand Down
28 changes: 16 additions & 12 deletions src/joystick/linux/SDL_sysjoystick.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ static SDL_bool GetSteamVirtualGamepadSlot(int fd, int *slot)
return SDL_FALSE;
}

static int GuessDeviceClass(int fd)
static int GuessDeviceClass(const struct input_id *inpid, int fd)
{
unsigned long propbit[NBITS(INPUT_PROP_MAX)] = { 0 };
unsigned long evbit[NBITS(EV_MAX)] = { 0 };
Expand All @@ -255,21 +255,25 @@ static int GuessDeviceClass(int fd)
* device just doesn't have any properties. */
(void) ioctl(fd, EVIOCGPROP(sizeof(propbit)), propbit);

return SDL_EVDEV_GuessDeviceClass(propbit, evbit, absbit, keybit, relbit);
return SDL_EVDEV_GuessDeviceClass(inpid->bustype,
inpid->vendor,
inpid->product,
inpid->version,
propbit, evbit, absbit, keybit, relbit);
}

static int GuessIsJoystick(int fd)
static int GuessIsJoystick(const struct input_id *inpid, int fd)
{
if (GuessDeviceClass(fd) & SDL_UDEV_DEVICE_JOYSTICK) {
if (GuessDeviceClass(inpid, fd) & SDL_UDEV_DEVICE_JOYSTICK) {
return 1;
}

return 0;
}

static int GuessIsSensor(int fd)
static int GuessIsSensor(const struct input_id *inpid, int fd)
{
if (GuessDeviceClass(fd) & SDL_UDEV_DEVICE_ACCELEROMETER) {
if (GuessDeviceClass(inpid, fd) & SDL_UDEV_DEVICE_ACCELEROMETER) {
return 1;
}

Expand Down Expand Up @@ -300,13 +304,13 @@ static int IsJoystick(const char *path, int *fd, char **name_return, Uint16 *ven
}

if (ioctl(*fd, JSIOCGNAME(sizeof(product_string)), product_string) <= 0) {
/* When udev enumeration or classification, we only got joysticks here, so no need to test */
if (enumeration_method != ENUMERATION_LIBUDEV && !class && !GuessIsJoystick(*fd)) {
/* Could have vendor and product already from udev, but should agree with evdev */
if (ioctl(*fd, EVIOCGID, &inpid) < 0) {
return 0;
}

/* Could have vendor and product already from udev, but should agree with evdev */
if (ioctl(*fd, EVIOCGID, &inpid) < 0) {
/* When udev is enabled we only get joystick devices here, so there's no need to test them */
if (enumeration_method != ENUMERATION_LIBUDEV && !GuessIsJoystick(&inpid, *fd)) {
return 0;
}

Expand Down Expand Up @@ -365,11 +369,11 @@ static int IsSensor(const char *path, int *fd)
return 0;
}

if (!class && !GuessIsSensor(*fd)) {
if (ioctl(*fd, EVIOCGID, &inpid) < 0) {
return 0;
}

if (ioctl(*fd, EVIOCGID, &inpid) < 0) {
if (!class && !GuessIsSensor(&inpid, *fd)) {
return 0;
}

Expand Down
4 changes: 3 additions & 1 deletion test/testevdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2175,7 +2175,9 @@ run_test(void)
caps.rel[j] = SwapLongLE(caps.rel[j]);
}

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

if (actual == t->expected) {
Expand Down

0 comments on commit 96e578c

Please sign in to comment.