Skip to content
Reading the report

Reading the report

plugii with no arguments prints one report and exits. This is a real one, from a Dell XPS 13 9320 with a USB-C hub (a webcam, a keyboard and a billboard device behind it) on the left port, and a monitor plus a 47 W charger on the right one.

$ plugii
USB ports

  USB-C (left)         0000:00:14.0-1
    USB 3 half: linked
      └ 05e3:0626  5G (USB 3 Gen 1)       USB3.1 Hub
        └ 328f:009b  5G (USB 3 Gen 1)       EMEET SmartCam S800
    USB 2 half: linked
      └ 05e3:0610  480M (USB 2)           USB2.1 Hub
        └ 1d5c:7102  12M (USB 1 full)       Generic Billboard Device
        └ 1d50:615e  12M (USB 1 full)       Eyelash Sofle
    USB-C:      partner (port0)

  USB-C (right)        0000:00:14.0-3
    USB 3 half: idle
    USB 2 half: idle
    USB-C:      partner (port1)
      └ display in DP alt mode → DP-3

USB-C (UCSI)
  port0 (USB-C (left)): partner  pd=no  alt-modes=1  power-in=no
  port1 (USB-C (right)): partner  pd=yes  alt-modes=1  power-in=charging
    offers: 5V 1A · 9V 1A · 12V 1.5A · 15V 1.8A · ▶20V 2.35A (47 W)

Thunderbolt / USB4
  domain0  security user, IOMMU DMA protection  INTEL Gen12, gen 4
  domain1  security user, IOMMU DMA protection  INTEL Gen12, gen 4
  no Thunderbolt/USB4 devices attached

Display connectors
  DP-3 connected (USB-C alt mode)

Power
  AC: online  via USB-C port1 (USB-C (right)) 20V 2.35A ≈ 47W  battery: 78% Not charging  (charge limit 80%)

Kernel log (this boot)
  no USB, USB-C or link-training errors

Health
  ✓ USB 3 links up (SuperSpeed lanes working)
  ✓ USB-C status driver (UCSI) up: 2 port(s)
  ✓ Thunderbolt/USB4: 2 domain(s), security user, 0 device(s) attached
  ✓ external display on USB-C (DP alt mode working)
  ✓ charging power arriving via USB-C port1 (USB-C (right)) 20V 2.35A ≈ 47W (best offer 47 W)
  ✓ kernel log clean
  → all good

Note

The reports on this page are the snapshots plugii’s test suite checks (machine captures under tests/fixtures/, collected offline), so they match what the current code prints. In a terminal the states and marks are coloured: green for linked and ✓, yellow for ⚠, red for ✗.

USB ports

USB ports

  USB-C (left)         0000:00:14.0-1
    USB 3 half: linked
      └ 05e3:0626  5G (USB 3 Gen 1)       USB3.1 Hub
        └ 328f:009b  5G (USB 3 Gen 1)       EMEET SmartCam S800
    USB 2 half: linked
      └ 05e3:0610  480M (USB 2)           USB2.1 Hub
        └ 1d5c:7102  12M (USB 1 full)       Generic Billboard Device
        └ 1d50:615e  12M (USB 1 full)       Eyelash Sofle
    USB-C:      partner (port0)

  USB-C (right)        0000:00:14.0-3
    USB 3 half: idle
    USB 2 half: idle
    USB-C:      partner (port1)
      └ display in DP alt mode → DP-3

One block per physical socket: every root port whose connect_type is hotplug, visited from its USB 2 side. The title is the socket’s label (or unlabeled), then its key, the USB 2 root port’s <pci-address>-<port>. Labels come from the labels file.

Each socket has two halves. A USB-C or USB 3 Type-A socket is wired to two root ports, one on a USB 2 bus and one on a USB 3 (SuperSpeed) bus, and a device links on one or the other:

  • USB 3 half: linked: something is on the SuperSpeed lanes; its tree follows. A USB 3 hub shows on both halves, since it is two hubs in one.
  • USB 2 half: linked: something is on the USB 2 pair: a USB 2 device, or the USB 2 side of a hub.
  • idle: nothing on that half.
  • unknown: on machines whose firmware has no peer links at all, plugii can’t find a socket’s USB 3 half unless a peer: line pairs it. Where the firmware does have them, a socket without one is USB 2-only and gets no USB 3 line.

Under a half, each device is vid:pid, the link speed, and its name (the device: label if there is one, else the product string), indented by hub depth:

SpeedMeaning
20G (USB 3 Gen 2x2)SuperSpeed+ over two lanes
10G (USB 3 Gen 2)SuperSpeed+
5G (USB 3 Gen 1)SuperSpeed
480M (USB 2)High speed
12M (USB 1 full)Full speed: keyboards, mice, receivers
1.5M (USB 1 low)Low speed

The USB-C: line appears when the labels tie a UCSI port to the socket (a typec: line with the same label). With no USB data on either half, it says what the partner probably is: display in DP alt mode → DP-3, or no USB data, no DisplayPort (charger only?).

Two warnings can follow a socket:

  • ⚠ hub linked at USB 2 only — its USB 3 half is missing: a hub (class 09) on the USB 2 half while the USB 3 half is idle. A USB 3 hub’s SuperSpeed link didn’t come up, and with it no DisplayPort alt mode either. See Health checks.
  • ⚠ over-current reported on this socket (N×): the root ports counted over-current events.

The report shows the linked speed. The TUI’s detail view adds the speed a device is capable of, from its BOS descriptor, and whether something holds it back: see capable vs. linked.

USB-C (UCSI)

USB-C (UCSI)
  port0 (USB-C (left)): partner  pd=no  alt-modes=1  power-in=no
  port1 (USB-C (right)): partner  pd=yes  alt-modes=1  power-in=charging
    offers: 5V 1A · 9V 1A · 12V 1.5A · 15V 1.8A · ▶20V 2.35A (47 W)

Linux learns about USB-C through UCSI, the firmware interface to the USB-C controller. Each port is portN, with its label when a typec: line gives one, then:

  • partner or empty: whether something is plugged in.
  • pd=yes|no: whether the partner speaks USB Power Delivery.
  • alt-modes=N: alternate modes the partner offers (DisplayPort, on a monitor or a dock).
  • power-in=charging|no: whether power comes in through this port.
  • cable=passive|active, when UCSI reports the cable.

offers: lists the partner’s source PDOs, what a charger offers: fixed 20V 2.35A, variable 5-20V 3A, PPS 3.3-21V 3A, or battery …W. The one in use is marked ▶ with its watts. offers: not reported means power comes in but the partner listed no PDOs: some chargers and docks don’t, and Lenovo’s UCSI never does. That isn’t an error.

If UCSI didn’t start at all, the section says no USB-C ports registered and Health has a ✗ with the fix.

Thunderbolt / USB4

Thunderbolt / USB4
  domain0  security user, IOMMU DMA protection  INTEL Gen12, gen 4
  domain1  security user, IOMMU DMA protection  INTEL Gen12, gen 4
  no Thunderbolt/USB4 devices attached

Only on machines with a Thunderbolt or USB4 controller. A line per domain (controller) with its security level (user: devices need authorizing) and whether IOMMU DMA protection is on; then a line per attached device: its route, vendor and name, authorized or not authorized, generation and link speed (rx 20.0 Gb/s×2). A device that isn’t authorized gets no PCIe tunnels; Health says how to authorize it.

Display connectors

Display connectors
  DP-3 connected (USB-C alt mode)

Lit external connectors from DRM: DP-N connected (USB-C alt mode) is a monitor over USB-C, HDMI-A-N connected one on HDMI. When niri is running, each line adds the mode and the VRR state.

Power

Power
  AC: online  via USB-C port1 (USB-C (right)) 20V 2.35A ≈ 47W  battery: 78% Not charging  (charge limit 80%)

AC is the mains supply (online, offline, or no mains supply on a machine without one), then the USB-C port the power arrives through, as port1 (USB-C (right)) 20V 2.35A ≈ 47W. Some UCSI firmware (Lenovo’s) reports the current but no voltage: then it says — power level not reported (drawing 3.25 A). Then the battery: percentage, status, and the charge limit when one is set.

When plugii can sample the CPU, a second line follows. This one is from a laptop on battery:

Power
  AC: offline  battery: 88% Discharging  (charge limit 80%)
  CPU: 25% busy  1.9 GHz avg (max 3.3, floor 0.4)  package 4 W  61 °C  battery −23.1 W
  CPU mostly idle — load it (e.g. a build) to test whether this power source throttles

How busy the CPU is, the average clock with the maximum and the floor (the lowest clock the CPU allows), RAPL package power, package temperature, and the battery’s flow (− discharging, + charging). The throttling check reads this line: a busy CPU held near its floor on AC means the embedded controller doesn’t trust the power source. When the CPU is mostly idle there’s nothing to judge, so the report asks you to load it (a build, for example) and run plugii again.

Kernel log (this boot)

Kernel log (this boot)
  no USB, USB-C or link-training errors

plugii runs journalctl -k -b and keeps the lines that name a real USB, USB-C or link-training failure: UCSI failures and errors, over-current, device descriptor read, not accepting address, unable to enumerate, cannot enable, failed link training, HC died, xHCI errors. Lines inside a kernel WARNING: stack trace don’t count. Known-benign warnings (amdgpu’s LTTPR and REG_WAIT) are only counted.

With errors, the section shows the last five with their time since boot, the socket they happened on (← USB-C (left)) when the device can be placed, and (at boot) in the first minute; then the link resets (reset SuperSpeed / reset high-speed lines) per socket or port:

Kernel log (this boot)
  [   23s] usb usb2-port1: Cannot enable. Maybe the USB cable is bad? (at boot)
  [  130s] i915 0000:00:02.0: [drm] *ERROR* [ENCODER:265:DDI TC1/PHY TC1] Link Training failed at link rate = 270000, lane count = 
  [  200s] xhci_hcd 0000:06:00.4: HC died; cleaning up
  [  300s] xhci_hcd 0000:00:14.0: ERROR unknown event type 37
  kernel: usb 3-1: device descriptor read/64, error -110
  8 USB link reset(s): port 1-1 ×2, port 1-2 ×1, port 2-1 ×3, port 4-2 ×1, unknown port ×1

Firmware

Only with --firmware: BIOS and EC versions from DMI, the vendor catalog’s verdict, labelled firmware and fwupd’s updates. See Firmware.

Health

Health
  ✓ USB 3 links up (SuperSpeed lanes working)
  ✓ USB-C status driver (UCSI) up: 2 port(s)
  ✓ Thunderbolt/USB4: 2 domain(s), security user, 0 device(s) attached
  ✓ external display on USB-C (DP alt mode working)
  ✓ charging power arriving via USB-C port1 (USB-C (right)) 20V 2.35A ≈ 47W (best offer 47 W)
  ✓ kernel log clean
  → all good

The verdict: a line per check, ✓ fine, ⚠ worth a look, ✗ broken, each with what to do. It ends in → all good, or in → something needs a look when any line is ⚠ or ✗, and then plugii exits 1. plugii -H prints only this section. Health checks lists every finding.

As JSON

plugii --json prints {"snapshot": …, "findings": […]}: everything the report is made from, and each finding as {"level": "ok" | "warn" | "fail", "message": …}. The exit status is the report’s.

plugii --json | jq -r '.findings[] | select(.level != "ok") | .message'