How to get USB vendor and product info programmatically on Linux?
lsusb
command queries information about currently plugged USB devices. You can use its -d
option to query a certain vendor/product (but it seems to work only for currently plugged devices):
$ lsusb -d 0e21:0750Bus 001 Device 005: ID 0e21:0750 Cowon Systems, Inc.
You can show information for all devices:
$ lsusbBus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hubBus 001 Device 004: ID 0421:01c7 Nokia Mobile PhonesBus 001 Device 003: ID 0bda:8187 Realtek Semiconductor Corp. RTL8187 Wireless AdapterBus 001 Device 005: ID 0e21:0750 Cowon Systems, Inc.Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hubBus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hubBus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hubBus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hubBus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hubBus 006 Device 002: ID 046d:c01b Logitech, Inc. MX310 Optical MouseBus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hubBus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
You can also make it be verbose (lsusb -v
) and printing a lot of stuff.
Note that when accessing information about the system in Linux OS, it's much preferred to do it via shell commands (such as lsusb
) than to directly parse the system files these commands access.
Haven't tried this myself, but libudev's udev_device_get_property_value should be it; it is used in pulseaudio's udev-util.c as udev_device_get_property_value(card, "ID_VENDOR_FROM_DATABASE"))
.
Here is a small example I just put together, based on udev-util.c
- note that I've used an Arduino Duemillanove with FTDI FT232 chip, whose udev path I find using udevadm
(see comments in code below), and then I hardcoded it in the below program, udevl.c
:
// sudo apt-get install libudev-dev// build with: gcc -o udevl -ludev -Wall -g udevl.c#include <stdio.h>#include <libudev.h>int main( int argc, char **argv ){ const char *v; char t[256]; struct udev *udev; struct udev_device *card = NULL; if (!(udev = udev_new())) { fprintf(stderr, "Failed to allocate udev context.\n"); return -1; } // $ lsusb | grep FT232 // Bus 002 Device 002: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC // $ udevadm info --name=/dev/ttyUSB0 --attribute-walk | grep "looking at device" // looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/ttyUSB0/tty/ttyUSB0' // (that one is under /sys) // hardcode that path below: // udev_get_sys_path(udev) for me: '/sys' sprintf(t, "%s/devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/ttyUSB0/tty/ttyUSB0", udev_get_sys_path(udev)); fprintf(stdout, " path: %s\n", t); card = udev_device_new_from_syspath(udev, t); fprintf(stdout, " udev_device: 0x%08X\n", (unsigned int)card); if ((v = udev_device_get_property_value(card, "ID_MODEL_FROM_DATABASE")) ) fprintf(stdout, "got ID_MODEL_FROM_DATABASE: %s\n", v); else fprintf(stdout, "failed getting ID_MODEL_FROM_DATABASE: %s\n", v); fprintf(stdout, "Done.\n"); if (card) udev_device_unref(card); if (udev) udev_unref(udev); return 0;}
This program (with the Arduino attached) outputs:
$ ./udevl path: /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/ttyUSB0/tty/ttyUSB0 udev_device: 0x09FBF080got ID_MODEL_FROM_DATABASE: FT232 USB-Serial (UART) ICDone.
... and "FT232 USB-Serial (UART) IC" is the right entry for VID:PID 0403:6001 in usb.ids.
Hope this helps,
Cheers!
On my Ubuntu system, the lsusb(1)
manpage says that /var/lib/usbutils/usb.ids
is the location of the id file; in fact, there are two symlinks, one of which is your /usr/share/misc/usb.ids
. I'd trust the actual location before trusting the symlinks:
$ ls -l /usr/share/misc/usb.ids /var/lib/misc/usb.ids /var/lib/usbutils/usb.idslrwxrwxrwx 1 root root 25 2010-04-29 18:08 /usr/share/misc/usb.ids -> /var/lib/usbutils/usb.idslrwxrwxrwx 1 root root 19 2010-04-29 18:08 /var/lib/misc/usb.ids -> ../usbutils/usb.ids-rw-r--r-- 1 root root 368377 2009-11-06 09:26 /var/lib/usbutils/usb.ids