Option 1: Use libusb
Can you depend on libusb? There is a similar question and answer over on the Linux and Unix StackExchange, with this sample code:
#include <stdio.h>
#include <usb.h>
main(){
struct usb_bus *bus;
struct usb_device *dev;
usb_init();
usb_find_busses();
usb_find_devices();
for (bus = usb_busses; bus; bus = bus->next)
for (dev = bus->devices; dev; dev = dev->next){
printf("Trying device %s/%s\n", bus->dirname, dev->filename);
printf("\tID_VENDOR = 0x%04x\n", dev->descriptor.idVendor);
printf("\tID_PRODUCT = 0x%04x\n", dev->descriptor.idProduct);
}
}
Option 2: Parse udevadm info
If you can use udev there is a different lsusb-like approach that may point you in the right direction. Using this answer from the Linux and Unix StackExchange, the udevadm program may help. First, get the 'raw' device path:
$ udevadm info -q path -n /dev/usb/hiddev0
/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.6/1-4.6:1.0/usbmisc/hiddev0
And then you can query it:
$ udevadm info [-q <type>] -p /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.6/1-4.6:1.0/usbmisc/hiddev0
I don't have any actual USB devices to show you the output, but type can be one of: name, symlink, path, property, or all. You would have to parse the output, but it is relatively easy given output resembling:
P: /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.6/1-5.6:1.0/usbmisc/hiddev1
N: usb/hiddev1
L: 0
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.6/1-5.6:1.0/usbmisc/hiddev1
E: DEVNAME=/dev/usb/hiddev1
E: MAJOR=180
E: MINOR=1
E: SUBSYSTEM=usbmisc
In your C code you'd have to popen() the commands and parse them like you're reading a file. Unfortunately if you want to operate at an even-lower level I'd have to suggest looking to the source code for udevadm.
Option 3: Maybe the pavlinux udev?
As you mentioned, a while ago systemd did take over udev development; I forget exactly when that happened. However, this udev fork from pavlinux was created that does not depend on systemd. It may also be helpful. The file src/udev-builtin-usb_id.c is parsing vendor information so maybe that's a better route?
I'm making an assumption that this is simply a copy of udev before the integration with systemd, but I cannot attest to that. You may feel more comfortable checking out an older version of udev before the integration happened.
ID_MODELis not a USB device attribute. It is composed by udev fromproductattribute by default (but differently for SCSI/ATA devices), and may be overriden by installed udev rules.ID_VENDORis taken frommanufacturerattribute by default. Explore your/sys/bus/usb/devices/. Perhaps you can read attributes directly.