From 4984eb8c168d8c595d0fb0d1d62b47eec2da6f75 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 21 Dec 2025 08:40:21 -0800 Subject: [PATCH] Use udev to get the manufacturer name if possible (thanks gdb!) --- src/core/linux/SDL_udev.c | 6 ++++++ src/core/linux/SDL_udev.h | 6 ++++++ src/hidapi/SDL_hidapi_linux.h | 5 +++++ src/hidapi/linux/hid.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+) diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index 3aaa0fb4e9..00bed5e5fc 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -109,6 +109,12 @@ static bool SDL_UDEV_load_syms(void) SDL_UDEV_SYM(udev_unref); SDL_UDEV_SYM(udev_device_new_from_devnum); SDL_UDEV_SYM(udev_device_get_devnum); + + SDL_UDEV_SYM(udev_hwdb_new); + SDL_UDEV_SYM(udev_hwdb_unref); + SDL_UDEV_SYM(udev_hwdb_get_properties_list_entry); + SDL_UDEV_SYM(udev_list_entry_get_value); + #undef SDL_UDEV_SYM return true; diff --git a/src/core/linux/SDL_udev.h b/src/core/linux/SDL_udev.h index f2b1ce56e2..3f69ce6237 100644 --- a/src/core/linux/SDL_udev.h +++ b/src/core/linux/SDL_udev.h @@ -83,6 +83,12 @@ typedef struct SDL_UDEV_Symbols void (*udev_unref)(struct udev *); struct udev_device *(*udev_device_new_from_devnum)(struct udev *udev, char type, dev_t devnum); dev_t (*udev_device_get_devnum)(struct udev_device *udev_device); + + struct udev_hwdb *(*udev_hwdb_new)(struct udev *udev); + struct udev_hwdb *(*udev_hwdb_unref)(struct udev_hwdb *hwdb); + struct udev_list_entry *(*udev_hwdb_get_properties_list_entry)(struct udev_hwdb *hwdb, const char *modalias, unsigned flags); + const char *(*udev_list_entry_get_value)(struct udev_list_entry *list_entry); + } SDL_UDEV_Symbols; typedef struct SDL_UDEV_PrivateData diff --git a/src/hidapi/SDL_hidapi_linux.h b/src/hidapi/SDL_hidapi_linux.h index 8418e2e928..eaa04e4800 100644 --- a/src/hidapi/SDL_hidapi_linux.h +++ b/src/hidapi/SDL_hidapi_linux.h @@ -39,6 +39,11 @@ static const SDL_UDEV_Symbols *udev_ctx = NULL; #define udev_new udev_ctx->udev_new #define udev_unref udev_ctx->udev_unref +#define udev_hwdb_new udev_ctx->udev_hwdb_new +#define udev_hwdb_unref udev_ctx->udev_hwdb_unref +#define udev_hwdb_get_properties_list_entry udev_ctx->udev_hwdb_get_properties_list_entry +#define udev_list_entry_get_value udev_ctx->udev_list_entry_get_value + #undef HIDAPI_H__ #define HIDAPI_ALLOW_BUILD_WORKAROUND_KERNEL_2_6_39 #include "linux/hid.c" diff --git a/src/hidapi/linux/hid.c b/src/hidapi/linux/hid.c index c0cb6a7b0e..9bb781a79d 100644 --- a/src/hidapi/linux/hid.c +++ b/src/hidapi/linux/hid.c @@ -1008,6 +1008,13 @@ int HID_API_EXPORT hid_exit(void) struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { + struct udev_hwdb *hwdb = NULL; + struct udev_list_entry *entry; + + char modalias[64]; + const char *key; + const char *manufacturer_string; + struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; @@ -1060,8 +1067,30 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, if (!raw_dev) continue; + tmp = create_device_info_for_device(raw_dev); + if (tmp) { + if (!tmp->manufacturer_string) { + key = "ID_VENDOR_FROM_DATABASE"; + + if ((hwdb = udev_hwdb_new(udev)) != NULL) { + snprintf(modalias, sizeof(modalias), "usb:v%04X*", vendor_id); + + udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0)) { + if (strcmp(udev_list_entry_get_name(entry), key) == 0) { + manufacturer_string = udev_list_entry_get_value(entry); + if (manufacturer_string) { + tmp->manufacturer_string = utf8_to_wchar_t(manufacturer_string); + } + break; + } + } + + hwdb = udev_hwdb_unref(hwdb); + } + } + if (cur_dev) { cur_dev->next = tmp; }