Get unique serial number of USB device mounted to /dev folder

37.1k views Asked by At

I attach 2 webcam to computer and it was listed in /dev folder: /dev/video0; /dev/video1.

Can you help me write C code to get serial number of webcam with input: /dev/video[0;1]

5

There are 5 answers

0
Basile Starynkevitch On

Looking at lsusb you find out that it uses libusb, it has many functions, notably for usb device handling and enumeration. libudev might be relevant too.

Alternatively, popen the lsusb command...

1
Dennis Hoer On

You can use lsusb, but you need to add verbose flag and make sure you use sudo with it, otherwise the serial will be incorrect.

sudo lsusb -v

If that is too verbose, then run lsusb to get the device id:

$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 012: ID 1ab1:0e11 Rigol Technologies
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Then run lsusb with device flag and grep the serial number.

So for the serial number of Rigol device:

$ sudo lsusb -s 012 -v|grep -i iserial
  iSerial                 3 DP8C221100000
0
chouger On

Based on the hint of using udevadm and the tutorial from http://www.signal11.us/oss/udev/ I got below code to get the serial info of my webcam.

#include "stdio.h"
#include <libudev.h>

int main(int argc, char **argv)
{
  struct udev *udev;
  struct udev_device *dev;
  struct udev_enumerate *enumerate;
  struct udev_list_entry *list, *node;
  const char *path;

  udev = udev_new();
  if (!udev) {
    printf("can not create udev");
    return 0;
  }

  enumerate = udev_enumerate_new(udev);
  udev_enumerate_add_match_subsystem(enumerate, "video4linux");
  udev_enumerate_scan_devices(enumerate);

  list = udev_enumerate_get_list_entry(enumerate);
  udev_list_entry_foreach(node, list) {
    path = udev_list_entry_get_name(node);
    dev = udev_device_new_from_syspath(udev, path);

    printf("Printing serial for %s\n", path);
    printf("ID_SERIAL=%s\n",
        udev_device_get_property_value(dev, "ID_SERIAL"));
    printf("ID_SERIAL_SHORT=%s\n",
        udev_device_get_property_value(dev, "ID_SERIAL_SHORT"));

    udev_device_unref(dev);
  }
  return 0;
}
0
Cerin On

Playing around with libusb, it looks like there's a standard getSerialNumber() method. Unfortunately, not all USB devices implement this. I have a couple cheap $4 webcams that return None for it. These interfaces expose other metadata, like VendorID and ProductID, which I've seen some code try and use as a unique identifier, but it's not guaranteed to be unique, especially if you have multiple devices of the same make and model.

But assuming you get a serial number for your device, the next problem is figuring out which /dev/videoN file it corresponds to. I have an old version of libusb installed, so I couldn't get the method working that returned the full sysfs path of the USB device, so instead I scrapped the output from hwinfo. I extracted all the chunks corresponding to cameras, and then from those I extracted the piece that looked like:

SysFS BusID: 1-1.2:1.0

USB devices actually form a complicated tree, and that BusID encodes where the device is located in that tree.

You can then take that BusID to find where the device lives in the filesystem as well as the video path, which should be at:

/sys/bus/usb/devices/<BusID>/video4linux/

That's a directory, and inside it you'll find a videoN file matching one in /dev.

3
lessthanoptimal On

Just ran into this same problem and it took a bit to find the solution. Any solution which starts with "just use lsusb" is incorrect. You can figure out the devices serial, but none of the extra information it provides help you determine which /dev/video it links to.

Solution:

/bin/udevadm info --name=/dev/video1 | grep SERIAL_SHORT

Output:

E: ID_SERIAL_SHORT=256DEC57