A human-friendly USB device lister for Linux and macOS. Think of it as a modern
alternative to lsusb — designed to show you what's actually plugged into your
machine, not kernel internals.
lsusb shows raw bus/device numbers and cryptic class codes. lsusb -t shows
a tree, but it's a separate view with different information. Figuring out which
physical port a device sits on, or why it's running slow, requires mental
gymnastics across multiple commands.
uwhat gives you one clear picture:
$ uwhat
Bus 002/001 xHCI Host Controller 20 Gbps
├── Port 3: 2109:8110 VIA Labs, Inc. USB3.0 Hub 5 Gbps
├── Port 4: 11b0:6298 Kingston SNA-DC/U 480 Mbps (of 20 Gbps) [usb-storage]
├── Port 6: 0db0:0076 MSI MYSTIC LIGHT 12 Mbps [usbhid]
└── Port 11: 0489:e10a Foxconn / Hon Hai 12 Mbps [btusb]
Bus 006/005 xHCI Host Controller 10 Gbps
└── Port 2: 05e3:0625 GenesysLogic USB3.2 Hub 10 Gbps
├── Port 1: 046d:c52b Logitech USB Receiver 12 Mbps (of 10 Gbps) [usbhid]
├── Port 2: 05e3:0625 GenesysLogic USB3.2 Hub 10 Gbps
│ └── Port 4: 046d:08b6 Logi Webcam C920e 480 Mbps (of 10 Gbps) [uvcvideo, snd-usb-audio]
└── Port 4: 174c:235c Ugreen Storage Device 480 Mbps (of 10 Gbps) [uas]
Bus 009 xHCI Host Controller 480 Mbps
└── Port 1: 05e3:0608 USB2.0 Hub 480 Mbps
├── Port 1: 1b1c:1bc0 Corsair K70 MAX RGB 480 Mbps [usbhid]
└── Port 2: 2717:5013 MI Mi Wireless Mouse 12 Mbps [usbhid]
Things you can see at a glance:
- Physical port topology — which device is plugged into which hub and port
- Speed warnings —
480 Mbps (of 10 Gbps)means a USB 2.0 device on a USB 3.x port. Maybe a bad cable, maybe the device only supports USB 2.0 - Drivers —
[uvcvideo, snd-usb-audio]tells you which kernel drivers claimed the device - Companion bus merging — USB 3.x controllers appear as two Linux buses
(one for USB 2.0, one for USB 3.x).
uwhatmerges them back into the physical reality:Bus 006/005is one controller
On Linux, uwhat reads directly from sysfs (/sys/bus/usb/devices/) — no
libusb or root permissions required. Device and vendor names come from the
system's USB ID database (/usr/share/hwdata/usb.ids).
On macOS, uwhat reads the IOKit USB tree via system_profiler
(SPUSBHostDataType). macOS already presents the merged physical topology, so
the companion-bus merging described below is a Linux concern only; names come
straight from the system. Per-interface drivers and full class-code detail are
not exposed through this source, so those -vv fields are Linux-only. The same
goes for port wiring: macOS does not say whether a port is USB 2.0-only, so the
(of 10 Gbps) throttling hint is shown for removable ports but withheld for
built-in devices, where it would usually be a false alarm.
A USB 3.x controller has two signal paths per port: USB 2.0 (the legacy pins) and USB 3.x (the additional pins). Linux exposes these as separate buses. For example, buses 005 and 006 might share the same PCI slot — they're the same physical controller.
uwhat merges them back together using the kernel's port peering information
(sysfs peer links, available since Linux 3.17): two peered ports are the
USB 2.0 and USB 3.x signal paths of the same physical connector. Buses whose
root ports peer with each other belong to the same controller. The bus label
Bus 006/005 lists the faster bus first (USB 3.x), then the slower one
(USB 2.0).
When a device negotiates USB 2.0 on a port that is wired for USB 3.x, the
speed annotation (of 10 Gbps) appears — a hint that the device could
potentially run faster. Ports without USB 3.x wiring (internal USB 2.0-only
headers, for example) never get this annotation.
uwhat [OPTIONS] [QUERY]
QUERY filters devices by case-insensitive substring match against product
name, manufacturer, and kernel driver — uwhat mouse, uwhat logitech,
uwhat uvcvideo. If it looks like a vendor:product ID (uwhat 046d:c52b),
it filters by ID instead.
| Option | Description |
|---|---|
-t, --tree |
Show device tree (the default) |
-l, --list |
Show flat list instead of tree |
-j, --json |
Output as JSON (always includes full details) |
-v |
Show speed, USB version, power, interfaces |
-vv |
Show full details (class codes, serial, endpoints) |
-d, --device VEND:PROD |
Filter by vendor:product ID (hex); either side may be empty, e.g. 046d:c52b, 046d: (all Logitech), :c52b |
-b, --bus N |
Filter by bus number. In tree mode this selects the whole physical controller the bus belongs to — companion-bus devices included, since the tree shows physical reality, not kernel bus boundaries. The list filters by exact bus |
--color WHEN |
Colored output: auto (default), always, never; auto honors NO_COLOR |
--completions SHELL |
Print completions for bash, zsh, fish, elvish, or powershell (e.g. uwhat --completions fish > ~/.config/fish/completions/uwhat.fish) |
Default tree view:
$ uwhat
Flat list with details:
$ uwhat -lv
Bus 005 Dev 003: 046d:c52b Logitech USB Receiver [Keyboard]
Full Speed (12 Mbps), USB 2.00, 98mA
Interfaces: usbhid (Keyboard), usbhid (Mouse), usbhid (HID)
Find a device by name:
$ uwhat mouse
Bus 008/007 xHCI Host Controller 10 Gbps
└── Port 1: 0424:7206 Microchip USB7206 Smart Hub 10 Gbps
└── Port 1: 05e3:0625 GenesysLogic USB3.2 Hub 10 Gbps
└── Port 1: 2717:5013 MI Mi Wireless Mouse 12 Mbps (of 10 Gbps) [usbhid]
Find a specific device in the tree:
$ uwhat -d 046d:c52b
Bus 006/005 xHCI Host Controller 10 Gbps
└── Port 2: 05e3:0625 GenesysLogic USB3.2 Hub 10 Gbps
└── Port 1: 046d:c52b Logitech USB Receiver 12 Mbps (of 10 Gbps) [usbhid]
JSON output for scripting (hierarchical tree by default, flat with -l):
$ uwhat --json | jq '.[].devices[] | select(.speed_limited) | {name, speed, port_max_speed}'
{
"name": "Kingston SNA-DC/U",
"speed": "480 Mbps",
"port_max_speed": "20 Gbps"
}
Fields the platform does not report are null, never 0 or [] — so a device
that genuinely has no interfaces stays distinguishable from one whose interfaces
the platform cannot see. On macOS that applies to class, class_name,
usb_version, num_interfaces, interfaces and drivers.
cargo install uwhat
cargo install --path .
Download from the releases page:
uwhat-vX.Y.Z-x86_64-linux-musl/-aarch64-linux-musl— statically linked, no runtime dependenciesuwhat-vX.Y.Z-aarch64-macos— macOS on Apple Silicon (Intel: build from source)
- Linux — reads from sysfs (
/sys/bus/usb/devices/); no libusb or root needed - macOS — reads the IOKit USB tree via
system_profiler(built in); no extra dependencies. Per-interface driver names and full-vvclass-code detail are not available from this source and are therefore Linux-only /usr/share/hwdata/usb.ids— optional on Linux, for human-readable vendor/product names when a device reports none of its own (provided byhwdataorusbutilspackages on most distributions). Not used on macOS: names come from the devices themselves, and a device that reports none is shown by its ID
GPLv3 — see LICENSE.