diff options
Diffstat (limited to 'src/hid_linux.c')
-rw-r--r-- | src/hid_linux.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/src/hid_linux.c b/src/hid_linux.c index 841a95b..cc6957a 100644 --- a/src/hid_linux.c +++ b/src/hid_linux.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 Yubico AB. All rights reserved. + * Copyright (c) 2019-2024 Yubico AB. All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the LICENSE file. * SPDX-License-Identifier: BSD-2-Clause @@ -77,12 +77,13 @@ out: 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; char *s; - int ok = -1; + bool found_id = false; + bool found_name = false; short unsigned int x; short unsigned int y; short unsigned int z; @@ -91,20 +92,25 @@ parse_uevent(const char *uevent, int *bus, int16_t *vendor_id, return (-1); while ((p = strsep(&cp, "\n")) != NULL && *p != '\0') { - if (strncmp(p, "HID_ID=", 7) == 0) { + if (!found_id && strncmp(p, "HID_ID=", 7) == 0) { if (sscanf(p + 7, "%hx:%hx:%hx", &x, &y, &z) == 3) { *bus = (int)x; *vendor_id = (int16_t)y; *product_id = (int16_t)z; - ok = 0; - break; + found_id = true; } + } else if (!found_name && strncmp(p, "HID_NAME=", 9) == 0) { + if ((*hid_name = strdup(p + 9)) != NULL) + found_name = true; } } free(s); - return (ok); + if (!found_name || !found_id) + return (-1); + + return (0); } static char * @@ -137,6 +143,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 +155,8 @@ 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; } @@ -161,9 +169,16 @@ copy_info(fido_dev_info_t *di, struct udev *udev, #endif di->path = strdup(path); - if ((di->manufacturer = get_usb_attr(dev, "manufacturer")) == NULL) + di->manufacturer = get_usb_attr(dev, "manufacturer"); + di->product = get_usb_attr(dev, "product"); + + if (di->manufacturer == NULL && di->product == NULL) { + di->product = hid_name; /* fallback */ + hid_name = NULL; + } + if (di->manufacturer == NULL) di->manufacturer = strdup(""); - if ((di->product = get_usb_attr(dev, "product")) == NULL) + if (di->product == NULL) di->product = strdup(""); if (di->path == NULL || di->manufacturer == NULL || di->product == NULL) goto fail; @@ -174,6 +189,7 @@ fail: udev_device_unref(dev); free(uevent); + free(hid_name); if (ok < 0) { free(di->path); |