mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-13 23:08:13 +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:

committed by
Sam Lantinga

parent
1bf78ed544
commit
6daf2e943f
@@ -42,6 +42,9 @@ static SDL_UDEV_PrivateData *_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)
|
||||
@@ -218,7 +221,7 @@ int SDL_UDEV_Scan(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -246,6 +249,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");
|
||||
@@ -262,6 +266,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);
|
||||
}
|
||||
@@ -393,29 +402,23 @@ 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, "video4linux") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_VIDEO_CAPTURE;
|
||||
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_V4L_CAPABILITIES");
|
||||
if (!val || !SDL_strcasestr(val, "capture")) {
|
||||
return;
|
||||
if (val && SDL_strcasestr(val, "capture")) {
|
||||
devclass = SDL_UDEV_DEVICE_VIDEO_CAPTURE;
|
||||
}
|
||||
} else if (SDL_strcmp(subsystem, "input") == 0) {
|
||||
/* udev rules reference: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c */
|
||||
@@ -467,18 +470,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_HAS_KEYS | 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);
|
||||
|
Reference in New Issue
Block a user