aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Schaefer <git@danielschaefer.me>2018-12-21 03:58:21 +0100
committerDaniel Schaefer <git@danielschaefer.me>2018-12-22 01:08:35 +0100
commitdddb696e01720eea60dfebba29000233e7585bdf (patch)
tree123c5768d8153d5faed340926a1ecd421b1cbcc6
parent7c8ec816dbf0ca5882211dffd0646ba4e59afe80 (diff)
downloadusbutils-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.c16
-rw-r--r--names.c24
-rw-r--r--names.h3
3 files changed, 40 insertions, 3 deletions
diff --git a/lsusb.c b/lsusb.c
index b6fff4e..7884309 100644
--- a/lsusb.c
+++ b/lsusb.c
@@ -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",
diff --git a/names.c b/names.c
index c2db79f..2434fa5 100644
--- a/names.c
+++ b/names.c
@@ -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;
diff --git a/names.h b/names.h
index cd44a68..5049abb 100644
--- a/names.h
+++ b/names.h
@@ -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);