diff options
author | Daniel Schaefer <git@danielschaefer.me> | 2018-12-21 03:58:21 +0100 |
---|---|---|
committer | Daniel Schaefer <git@danielschaefer.me> | 2018-12-22 01:08:35 +0100 |
commit | dddb696e01720eea60dfebba29000233e7585bdf (patch) | |
tree | 123c5768d8153d5faed340926a1ecd421b1cbcc6 | |
parent | 7c8ec816dbf0ca5882211dffd0646ba4e59afe80 (diff) | |
download | usbutils-dddb696e01720eea60dfebba29000233e7585bdf.tar.gz |
lsusb: Read unkown names from sysfs device desc.
lsusb tries to get the names for manufacturer and product of a device by
asking the udev hwdb for the names of the device id.
Not every manufacturer and device are in this database. Most devices
however provide those names in the standard USB descriptors, namely
iManufacturer and iProduct.
To get those with libusb we would have to open the device which
requires superuser privileges. To get those values anyway the kernel
provides them in sysfs.
Signed-off-by: Daniel Schaefer <git@danielschaefer.me>
-rw-r--r-- | lsusb.c | 16 | ||||
-rw-r--r-- | names.c | 24 | ||||
-rw-r--r-- | names.h | 3 |
3 files changed, 40 insertions, 3 deletions
@@ -3693,7 +3693,7 @@ static int list_devices(libusb_context *ctx, int busnum, int devnum, int vendori struct libusb_device_descriptor desc; char vendor[128], product[128]; int status; - ssize_t num_devs, i; + ssize_t num_devs, i, vendor_len, product_len; status = 1; /* 1 device not found, 0 device found */ @@ -3705,6 +3705,7 @@ static int list_devices(libusb_context *ctx, int busnum, int devnum, int vendori libusb_device *dev = list[i]; uint8_t bnum = libusb_get_bus_number(dev); uint8_t dnum = libusb_get_device_address(dev); + uint8_t pnum = libusb_get_port_number(dev); if ((busnum != -1 && busnum != bnum) || (devnum != -1 && devnum != dnum)) @@ -3714,9 +3715,18 @@ static int list_devices(libusb_context *ctx, int busnum, int devnum, int vendori (productid != -1 && productid != desc.idProduct)) continue; status = 0; - get_vendor_string(vendor, sizeof(vendor), desc.idVendor); - get_product_string(product, sizeof(product), + + vendor_len = get_vendor_string(vendor, sizeof(vendor), desc.idVendor); + if (vendor_len == 0) + read_sysfs_prop(vendor, sizeof(vendor), bnum, pnum, + "manufacturer"); + + product_len = get_product_string(product, sizeof(product), desc.idVendor, desc.idProduct); + if (product_len == 0) + read_sysfs_prop(product, sizeof(product), bnum, pnum, + "product"); + if (verblevel > 0) printf("\n"); printf("Bus %03u Device %03u: ID %04x:%04x %s %s\n", @@ -20,6 +20,7 @@ #include <unistd.h> #include <stdio.h> #include <ctype.h> +#include <linux/limits.h> #include <libudev.h> @@ -31,6 +32,8 @@ #define HASH2 0x02 #define HASHSZ 512 +#define SYSFS_DEV_ATTR_PATH "/sys/bus/usb/devices/%d-%d/%s" + static unsigned int hashnum(unsigned int num) { unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27; @@ -403,6 +406,27 @@ static void print_tables(void) } */ +int read_sysfs_prop(char *buf, size_t size, uint8_t bnum, uint8_t pnum, char *propname) +{ + int n, fd; + char path[PATH_MAX]; + + buf[0] = '\0'; + snprintf(path, sizeof(path), SYSFS_DEV_ATTR_PATH, bnum, pnum, propname); + fd = open(path, O_RDONLY); + + if (fd == -1) + return 0; + + n = read(fd, buf, size); + + if (n > 0) + buf[n-1] = '\0'; // Turn newline into null terminator + + close(fd); + return n; +} + int names_init(void) { int r; @@ -9,6 +9,7 @@ #define _NAMES_H #include <sys/types.h> +#include <stdint.h> /* ---------------------------------------------------------------------- */ @@ -34,6 +35,8 @@ extern int get_product_string(char *buf, size_t size, u_int16_t vid, u_int16_t p extern int get_class_string(char *buf, size_t size, u_int8_t cls); extern int get_subclass_string(char *buf, size_t size, u_int8_t cls, u_int8_t subcls); +extern int read_sysfs_prop(char *buf, size_t size, uint8_t bnum, uint8_t pnum, char *propname); + extern int names_init(void); extern void names_exit(void); |