esptest.devices.usb_topology module

Read the Linux USB topology from /sys/bus/usb/devices.

This is a focused, line-based port of the topology viewer in huby. It builds a root-hub/port/device tree (no root privileges needed for viewing) so it can be used to:

  • ls – print the current USB tree, including the /dev/tty* nodes and the location string (e.g. 1-6.1.2) that can be fed straight into the esp-uhubctl power commands.

  • monitor – poll the tree and report plug/unplug events.

It is Linux specific (sysfs); on other platforms scan_usb returns an empty snapshot with an error message.

class esptest.devices.usb_topology.UsbDevice(name: str, bus: int, port_path: Tuple[int, ...], parent_name: str | None, product: str | None = None, manufacturer: str | None = None, serial: str | None = None, id_vendor: str | None = None, id_product: str | None = None, speed: str | None = None, maxchild: int = 0, device_class: str | None = None, dev_nodes: Tuple[str, ...] = ())[source]

Bases: object

Parameters:
  • name (str)

  • bus (int)

  • port_path (Tuple[int, ...])

  • parent_name (str | None)

  • product (str | None)

  • manufacturer (str | None)

  • serial (str | None)

  • id_vendor (str | None)

  • id_product (str | None)

  • speed (str | None)

  • maxchild (int)

  • device_class (str | None)

  • dev_nodes (Tuple[str, ...])

name: str
bus: int
port_path: Tuple[int, ...]
parent_name: str | None
product: str | None = None
manufacturer: str | None = None
serial: str | None = None
id_vendor: str | None = None
id_product: str | None = None
speed: str | None = None
maxchild: int = 0
device_class: str | None = None
dev_nodes: Tuple[str, ...] = ()
property is_root: bool
property is_hub: bool
property port: int | None
property usb_id: str | None
property location: str

root hub -> bus number, otherwise sysfs name.

Type:

uhubctl-style location

property tty_nodes: Tuple[str, ...]

/dev nodes excluding the raw usbfs node under /dev/bus/usb.

label()[source]
Return type:

str

class esptest.devices.usb_topology.UsbSnapshot(devices: Dict[str, esptest.devices.usb_topology.UsbDevice] = <factory>, children: Dict[str, List[str]] = <factory>, errors: Tuple[str, ...] = ())[source]

Bases: object

Parameters:
devices: Dict[str, UsbDevice]
children: Dict[str, List[str]]
errors: Tuple[str, ...] = ()
property roots: List[str]
esptest.devices.usb_topology.parse_device_name(name)[source]
Parameters:

name (str)

Return type:

Tuple[int, Tuple[int, …], str | None] | None

esptest.devices.usb_topology.scan_usb(sysfs=PosixPath('/sys/bus/usb/devices'))[source]

Scan sysfs and return a UsbSnapshot of the USB tree.

Parameters:

sysfs (Path)

Return type:

UsbSnapshot

esptest.devices.usb_topology.format_tree(snapshot, show_empty=False)[source]

Render the snapshot as an indented tree (one line per port/device).

Parameters:
Return type:

str

esptest.devices.usb_topology.diff_snapshots(old, new)[source]

Return (added, removed) device names between two snapshots.

Parameters:
Return type:

Tuple[List[str], List[str]]

esptest.devices.usb_topology.monitor_usb(sysfs=PosixPath('/sys/bus/usb/devices'), interval=1.0, on_event=None)[source]

Poll the USB tree forever, invoking on_event(action, device) on changes.

action is 'plugged' or 'unplugged'. Runs until interrupted.

Parameters:
Return type:

None