mirror of
https://github.com/Ryujinx/SDL.git
synced 2025-01-03 18:55:40 +00:00
Try SDL_UDEV_deviceclass to detect joysticks even if in a container
The udev container issue is mostly to do with device notifications and netlink. The device classification stuff just pokes file in /sys and /run/udev. Doesn't hurt to try it first for classifying joysticks and then fall to the guess heuristics if it fails.
This commit is contained in:
parent
857e5b08c3
commit
3b1e0e163b
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
if (SDL_strcmp(subsystem, "sound") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_SOUND;
|
||||
} else if (SDL_strcmp(subsystem, "input") == 0) {
|
||||
|
@ -455,15 +461,30 @@ 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -278,18 +278,20 @@ static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vend
|
|||
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);
|
||||
#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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue