Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try SDL_UDEV_deviceclass to detect joysticks even if in a container #8645

Merged
merged 1 commit into from
Dec 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions src/core/linux/SDL_udev.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ static _THIS = NULL;
static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr);
static int SDL_UDEV_load_syms(void);
static SDL_bool SDL_UDEV_hotplug_update_available(void);
static void get_caps(struct udev_device *dev, struct udev_device *pdev, const char *attr, unsigned long *bitmask, size_t bitmask_len);
static int guess_device_class(struct udev_device *dev);
static int device_class(struct udev_device *dev);
static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev);

static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr)
Expand Down Expand Up @@ -222,7 +225,7 @@ void SDL_UDEV_Scan(void)
_this->syms.udev_enumerate_unref(enumerate);
}

SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version)
SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class)
{
struct udev_enumerate *enumerate = NULL;
struct udev_list_entry *devs = NULL;
Expand Down Expand Up @@ -250,6 +253,7 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16

existing_path = _this->syms.udev_device_get_devnode(dev);
if (existing_path && SDL_strcmp(device_path, existing_path) == 0) {
int class_temp;
found = SDL_TRUE;

val = _this->syms.udev_device_get_property_value(dev, "ID_VENDOR_ID");
Expand All @@ -266,6 +270,11 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16
if (val) {
*version = (Uint16)SDL_strtol(val, NULL, 16);
}

class_temp = device_class(dev);
if (class_temp) {
*class = class_temp;
}
}
_this->syms.udev_device_unref(dev);
}
Expand Down Expand Up @@ -394,20 +403,17 @@ static int guess_device_class(struct udev_device *dev)
&bitmask_rel[0]);
}

static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
static int device_class(struct udev_device *dev)
{
const char *subsystem;
const char *val = NULL;
int devclass = 0;
const char *path;
SDL_UDEV_CallbackList *item;

path = _this->syms.udev_device_get_devnode(dev);
if (!path) {
return;
subsystem = _this->syms.udev_device_get_subsystem(dev);
if (!subsystem) {
return 0;
}

subsystem = _this->syms.udev_device_get_subsystem(dev);
if (SDL_strcmp(subsystem, "sound") == 0) {
devclass = SDL_UDEV_DEVICE_SOUND;
} else if (SDL_strcmp(subsystem, "input") == 0) {
Expand Down Expand Up @@ -455,18 +461,33 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
devclass = SDL_UDEV_DEVICE_MOUSE;
} else if (SDL_strcmp(val, "kbd") == 0) {
devclass = SDL_UDEV_DEVICE_KEYBOARD;
} else {
return;
}
} else {
/* We could be linked with libudev on a system that doesn't have udev running */
devclass = guess_device_class(dev);
}
}
} else {
}

return devclass;
}

static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
{
int devclass = 0;
const char *path;
SDL_UDEV_CallbackList *item;

path = _this->syms.udev_device_get_devnode(dev);
if (!path) {
return;
}

devclass = device_class(dev);
if (!devclass) {
return;
}

/* Process callbacks */
for (item = _this->first; item; item = item->next) {
item->callback(type, devclass, path);
Expand Down
2 changes: 1 addition & 1 deletion src/core/linux/SDL_udev.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ extern void SDL_UDEV_UnloadLibrary(void);
extern int SDL_UDEV_LoadLibrary(void);
extern void SDL_UDEV_Poll(void);
extern void SDL_UDEV_Scan(void);
extern SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version);
extern SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class);
extern int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb);
extern void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb);
extern const SDL_UDEV_Symbols *SDL_UDEV_GetUdevSyms(void);
Expand Down
12 changes: 7 additions & 5 deletions src/joystick/linux/SDL_sysjoystick.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,18 +260,20 @@ static int IsJoystick(const char *path, int fd, char **name_return, SDL_Joystick
struct input_id inpid;
char *name;
char product_string[128];
int class = 0;

if (ioctl(fd, JSIOCGNAME(sizeof(product_string)), product_string) >= 0) {
SDL_zero(inpid);
SDL_zero(inpid);
#ifdef SDL_USE_LIBUDEV
SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version);
SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version, &class);
#endif
} else {
if (ioctl(fd, JSIOCGNAME(sizeof(product_string)), product_string) <= 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(fd)) {
if (enumeration_method != ENUMERATION_LIBUDEV &&
!(class & SDL_UDEV_DEVICE_JOYSTICK) && ( class || !GuessIsJoystick(fd))) {
return 0;
}

/* Could have vendor and product already from udev, but should agree with evdev */
if (ioctl(fd, EVIOCGID, &inpid) < 0) {
return 0;
}
Expand Down