Skip to content

Instantly share code, notes, and snippets.

@pbelskiy
Created January 24, 2018 07:57
Show Gist options
  • Save pbelskiy/341d35e407cb74e51c4da0a4318547a5 to your computer and use it in GitHub Desktop.
Save pbelskiy/341d35e407cb74e51c4da0a4318547a5 to your computer and use it in GitHub Desktop.
How to associate logical to physical USB topology on Linux

How to associate logical to physical USB topology on Linux

As you know every time USB device is rebooted is devnum is changed, but physical USB port is the same as was.

Sometimes it's needed to convert static USB path from lsub -t to current device num on sysfs (/dev/bus/usb/XXX/YYY). It's useful for working with devices often are rebooted.

Some little solution that I've found, this script just convert static USB path from lsusb -t utility to current device on sysfs.

For example, you connected your device to your PC. And its physical topology, for example, is: 218, where 2 is USB bus, and 18 is nested port hierarchy, it's hierarchy will change only if you change physical USB port on your PC.

/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/2p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/8p, 480M
        |__ Port 5: Dev 8, If 0, Class=Vendor Specific Class, Driver=ftdi_sio, 12M
        |__ Port 6: Dev 4, If 0, Class=Human Interface Device, Driver=usbhid, 12M
        |__ Port 8: Dev 6, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M

And how to convert it:

def get_device_path(target_path):
    """
    Return current dynamic USB device path from static lsusb topology.

    Example:
        218 -> /dev/bus/usb/002/006

    Where 2 is bus number and 18 is topology level of `lsusb` utility.
    """
    root_dir = "/sys/bus/usb/devices"
    target_bus = int(target_path[0])

    for device in os.listdir(root_dir):
        if "usb" in device:
            continue

        device_path = device.split(":")[0].replace(".", "") \
                                          .replace("-", "")

        if device_path != target_path:
            continue

        devnum_path = os.path.join(root_dir, device, "devnum")

        if not os.path.exists(devnum_path):
            continue

        with open(devnum_path) as fh:
            device_num = int(fh.read().strip())

        return "/dev/bus/usb/{:03d}/{:03d}".format(target_bus, device_num)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment