diff --git a/libs/libudev-zero/Makefile b/libs/libudev-zero/Makefile index e2e01057b5..0cda4c8cf2 100644 --- a/libs/libudev-zero/Makefile +++ b/libs/libudev-zero/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libudev-zero PKG_VERSION:=1.0.3 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/illiliti/libudev-zero/tar.gz/$(PKG_VERSION)? diff --git a/libs/libudev-zero/patches/0004-udev-implement-hwdb-USB-ID-lookup-from-usb.ids.patch b/libs/libudev-zero/patches/0004-udev-implement-hwdb-USB-ID-lookup-from-usb.ids.patch new file mode 100644 index 0000000000..890a00ef69 --- /dev/null +++ b/libs/libudev-zero/patches/0004-udev-implement-hwdb-USB-ID-lookup-from-usb.ids.patch @@ -0,0 +1,216 @@ +From 2bebebc9e0444ec53afd7f1f37aa80ff6b95f5f7 Mon Sep 17 00:00:00 2001 +From: Alexandru Ardelean +Date: Tue, 19 May 2026 17:52:47 +0300 +Subject: [PATCH] udev: implement hwdb USB ID lookup from usb.ids (#80) + +Replace the four stub udev_hwdb_*() functions with a working +implementation that looks up vendor and product names from a +usb.ids database file (e.g. provided by the hwdata package). + +udev_hwdb_get_properties_list_entry() parses the file for USB +modalias strings of the form "usb:vVVVVpPPPP" (product lookup) +or "usb:vVVVV" (vendor lookup), and populates the entry list with +ID_MODEL_FROM_DATABASE or ID_VENDOR_FROM_DATABASE properties. + +Lines are read via POSIX getline() so the buffer grows as needed +on long usb.ids entries. + +The path to the usb.ids file is set at build time via the +USB_IDS_PATH Makefile variable, which defaults to +${SHAREDIR}/hwdata/usb.ids. +--- + Makefile | 3 ++ + udev.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 144 insertions(+), 7 deletions(-) + +--- a/Makefile ++++ b/Makefile +@@ -3,9 +3,12 @@ + + PREFIX = /usr/local + LIBDIR = ${PREFIX}/lib ++SHAREDIR = ${PREFIX}/share + INCLUDEDIR = ${PREFIX}/include + PKGCONFIGDIR = ${LIBDIR}/pkgconfig ++USB_IDS_PATH = ${SHAREDIR}/hwdata/usb.ids + XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -D_XOPEN_SOURCE=700 \ ++ -DUSB_IDS_PATH=\"${USB_IDS_PATH}\" \ + -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes \ + -Wno-unused-parameter + XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 +--- a/udev.c ++++ b/udev.c +@@ -15,9 +15,13 @@ + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + ++#include ++#include + #include ++#include + + #include "udev.h" ++#include "udev_list.h" + + struct udev { + int refcount; +@@ -76,22 +80,152 @@ int udev_get_log_priority(struct udev *u + return 0; + } + +-/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_new(struct udev *udev) ++struct udev_hwdb { ++ struct udev_list_entry head; ++ int refcount; ++}; ++ ++static int usb_ids_lookup_vendor(uint16_t vendorid, char *buf, size_t buflen) + { +- return NULL; ++ char *line = NULL, *name; ++ size_t cap = 0, len; ++ unsigned int id; ++ FILE *f; ++ ++ f = fopen(USB_IDS_PATH, "r"); ++ if (!f) { ++ return 0; ++ } ++ while (getline(&line, &cap, f) != -1) { ++ if (line[0] == '#' || line[0] == '\t' || line[0] == '\n') { ++ continue; ++ } ++ if (sscanf(line, "%04x", &id) != 1 || id != vendorid) { ++ continue; ++ } ++ name = strchr(line, ' '); ++ if (name) { ++ while (*name == ' ') { ++ name++; ++ } ++ len = strlen(name); ++ while (len > 0 && (name[len - 1] == '\n' || name[len - 1] == '\r')) { ++ name[--len] = '\0'; ++ } ++ snprintf(buf, buflen, "%s", name); ++ } ++ break; ++ } ++ free(line); ++ fclose(f); ++ return buf[0] != '\0'; ++} ++ ++static int usb_ids_lookup_product(uint16_t vendorid, uint16_t productid, char *buf, size_t buflen) ++{ ++ char *line = NULL, *name; ++ size_t cap = 0, len; ++ int in_vendor = 0; ++ unsigned int id; ++ FILE *f; ++ ++ f = fopen(USB_IDS_PATH, "r"); ++ if (!f) { ++ return 0; ++ } ++ while (getline(&line, &cap, f) != -1) { ++ if (line[0] == '#' || line[0] == '\n') { ++ continue; ++ } ++ if (in_vendor) { ++ if (line[0] != '\t') { ++ break; ++ } ++ if (line[1] == '\t') { ++ continue; ++ } ++ if (sscanf(line + 1, "%04x", &id) != 1 || id != productid) { ++ continue; ++ } ++ name = strchr(line + 1, ' '); ++ if (name) { ++ while (*name == ' ') { ++ name++; ++ } ++ len = strlen(name); ++ while (len > 0 && (name[len - 1] == '\n' || name[len - 1] == '\r')) { ++ name[--len] = '\0'; ++ } ++ snprintf(buf, buflen, "%s", name); ++ } ++ break; ++ } ++ if (line[0] == '\t') { ++ continue; ++ } ++ if (sscanf(line, "%04x", &id) != 1 || id != vendorid) { ++ continue; ++ } ++ in_vendor = 1; ++ } ++ free(line); ++ fclose(f); ++ return buf[0] != '\0'; + } + +-/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) ++struct udev_hwdb *udev_hwdb_new(struct udev *udev) + { +- return NULL; ++ struct udev_hwdb *hwdb; ++ ++ hwdb = calloc(1, sizeof(*hwdb)); ++ if (!hwdb) { ++ return NULL; ++ } ++ hwdb->refcount = 1; ++ return hwdb; + } + +-/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) ++struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) + { +- return NULL; ++ if (!hwdb) { ++ return NULL; ++ } ++ hwdb->refcount++; ++ return hwdb; + } + +-/* XXX NOT IMPLEMENTED */ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) ++struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) + { ++ if (!hwdb) { ++ return NULL; ++ } ++ if (--hwdb->refcount > 0) { ++ return NULL; ++ } ++ udev_list_entry_free_all(&hwdb->head); ++ free(hwdb); + return NULL; + } ++ ++struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) ++{ ++ unsigned int vendorid, productid; ++ char name[64]; ++ ++ if (!hwdb || !modalias) { ++ return NULL; ++ } ++ udev_list_entry_free_all(&hwdb->head); ++ hwdb->head.next = NULL; ++ name[0] = '\0'; ++ if (sscanf(modalias, "usb:v%4xp%4x", &vendorid, &productid) == 2) { ++ if (usb_ids_lookup_product((uint16_t)vendorid, (uint16_t)productid, name, sizeof(name))) { ++ udev_list_entry_add(&hwdb->head, "ID_MODEL_FROM_DATABASE", name, 0); ++ } ++ } else if (sscanf(modalias, "usb:v%4x", &vendorid) == 1) { ++ if (usb_ids_lookup_vendor((uint16_t)vendorid, name, sizeof(name))) { ++ udev_list_entry_add(&hwdb->head, "ID_VENDOR_FROM_DATABASE", name, 0); ++ } ++ } ++ return hwdb->head.next; ++}