From 760050d2831d7957726e4374a8b51eef78d704f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3=20=C3=81gila=20Bitsch?= Date: Tue, 9 Jan 2024 10:55:53 +0100 Subject: [PATCH] hidraw: fallback to HID_NAME if we can't get the vendor/product string of the USB attributes, fallback to the HID_NAME string collected from the uevent. --- src/hid_linux.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/hid_linux.c b/src/hid_linux.c index 841a95b0..bbde0ef5 100644 --- a/src/hid_linux.c +++ b/src/hid_linux.c @@ -77,7 +77,7 @@ is_fido(const char *path) static int parse_uevent(const char *uevent, int *bus, int16_t *vendor_id, - int16_t *product_id) + int16_t *product_id, char **hid_name) { char *cp; char *p; @@ -86,6 +86,7 @@ parse_uevent(const char *uevent, int *bus, int16_t *vendor_id, short unsigned int x; short unsigned int y; short unsigned int z; + char name[80]; if ((s = cp = strdup(uevent)) == NULL) return (-1); @@ -97,8 +98,14 @@ parse_uevent(const char *uevent, int *bus, int16_t *vendor_id, *vendor_id = (int16_t)y; *product_id = (int16_t)z; ok = 0; - break; } + continue; + } + if (strncmp(p, "HID_NAME=", 9) == 0 && hid_name != NULL) { + if (sscanf(p + 9, "%79[^\n]s", name) == 1) { + *hid_name = strdup(name); + } + continue; } } @@ -137,6 +144,7 @@ copy_info(fido_dev_info_t *di, struct udev *udev, char *uevent = NULL; struct udev_device *dev = NULL; int bus = 0; + char *hid_name = NULL; int ok = -1; memset(di, 0, sizeof(*di)); @@ -148,7 +156,7 @@ copy_info(fido_dev_info_t *di, struct udev *udev, goto fail; if ((uevent = get_parent_attr(dev, "hid", NULL, "uevent")) == NULL || - parse_uevent(uevent, &bus, &di->vendor_id, &di->product_id) < 0) { + parse_uevent(uevent, &bus, &di->vendor_id, &di->product_id, &hid_name) < 0) { fido_log_debug("%s: uevent", __func__); goto fail; } @@ -165,6 +173,24 @@ copy_info(fido_dev_info_t *di, struct udev *udev, di->manufacturer = strdup(""); if ((di->product = get_usb_attr(dev, "product")) == NULL) di->product = strdup(""); + if (strnlen(di->manufacturer, 1) == 0 && strnlen(di->product, 1) == 0) { + char* first_space = strchr(hid_name, ' '); + if (first_space == NULL) { + free(di->manufacturer); + di->manufacturer = strdup(hid_name); + } else { + size_t manufacturer_length = (size_t) (first_space - hid_name); + + free(di->manufacturer); + di->manufacturer = malloc(manufacturer_length + 1); + strncpy(di->manufacturer, hid_name, manufacturer_length); + di->manufacturer[manufacturer_length] = '\0'; + + free(di->product); + di->product = strdup(first_space+1); + + } + } if (di->path == NULL || di->manufacturer == NULL || di->product == NULL) goto fail; @@ -174,6 +200,7 @@ copy_info(fido_dev_info_t *di, struct udev *udev, udev_device_unref(dev); free(uevent); + free(hid_name); if (ok < 0) { free(di->path);