- Rust 96.2%
- Just 2.6%
- Fluent 1.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| i18n/en | ||
| res | ||
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| i18n.toml | ||
| justfile | ||
| LICENSE | ||
| README.md | ||
COSMIC USB Tree Applet
A COSMIC panel applet that shows what is plugged into the machine, how it is plugged in, and — the part nothing else on the panel answers — the link speed each device actually negotiated.
What it does
- The real topology. Devices are drawn as the tree they form: each one under the hub it hangs off, in port order, with the tree guides to match. A hub chain looks like a hub chain.
- Negotiated speed, per device. Every row carries the rate its link came up at — 12 Mb/s, 480 Mb/s, 5 Gb/s — not the speed of the port it is in and not the speed printed on the box.
- Slow links called out. A device that supports SuperSpeed but came up at USB 2.0 speeds is behind a slow port, cable or hub. Those rows are marked, and the panel icon turns the theme's warning colour so it is visible without opening the popup.
- What each device is. Class and interface descriptors pick the icon: keyboards, mice, controllers, webcams, storage, network adapters, audio, Bluetooth radios, hubs.
- Live. The kernel multicasts a uevent whenever a device appears or leaves, so the tree updates as it happens rather than on a timer.
How it reads devices
Everything comes from /sys/bus/usb/devices: no daemon, no kernel module, no
libusb, no elevated privileges. The kernel already knows what came up at what
speed, and reading sysfs cannot disturb a device — no probing, no resets.
| Attribute | Used for |
|---|---|
speed, rx_lanes, tx_lanes |
The negotiated link |
version (bcdUSB) |
What the device supports, and so whether the link is slow for it |
bDeviceClass, bInterfaceClass/Protocol |
What kind of device it is |
idVendor, idProduct, product, manufacturer |
Names and IDs |
maxchild |
Hub port counts |
Hardware that ships with empty product strings — cheap hubs, mostly — is looked
up in usb.ids from hwdata, if that file is present. It is optional: without
it such a device simply shows its IDs.
One thing that surprises people and is not a bug: a USB 3 hub appears twice,
once per bus. The specification requires it to present separate USB 2 and USB 3
hubs, and Linux enumerates them on separate buses. lsusb -t shows the same.
Settings
In the popup, behind the settings disclosure:
| Setting | Default | |
|---|---|---|
| Show hubs | on | Off flattens the tree into a plain device list |
| Show host controllers | off | The root hub of each bus, one per controller |
| Show device IDs | on | 1234:abcd beneath each device |
| Flag slow links | on | Mark devices running below what they support |
| Show count in the panel | on | Attached devices, next to the icon |
Requirements
- COSMIC desktop
- Linux (the applet reads sysfs)
- A Rust toolchain and
justto build hwdata— optional, for naming devices that name themselves poorly
Install
just build-release
sudo just install
To install into a user prefix instead:
just build-release
just install prefix=~/.local
Then add USB Tree to the panel in COSMIC Settings → Desktop → Panel → Configure panel applets.
From a terminal
The tree can be printed without a panel, which is also the quickest way to see what the applet would show:
just dump
Bus 5 root hub 480 Mb/s High-Speed 1d6b:0002 Linux xhci-hcd
└─ USB2.1 Hub 480 Mb/s High-Speed 0bda:5411 Generic
├─ USB2.0 Hub 480 Mb/s High-Speed 2109:2211 VIA Labs, Inc.
│ └─ MSI Gaming Controller 12 Mb/s Full-Speed 1462:3fa4 MS
└─ USB2.1 Hub 480 Mb/s High-Speed 0bda:5411 Generic
├─ Razer Basilisk V3 Pro 12 Mb/s Full-Speed 1532:00ab Razer
└─ B248Y E 480 Mb/s High-Speed 0bda:4cb1 Generic
Licence
GPL-3.0-only.