Skip to content

Device naming: what /dev/serial/by-id/ covers, and what it does not

Generated 2026-10-03 from catalog/hardware/. 34 devices.

This project's stated highest-value hardware feature was persistent udev symlinks by serial. A Proxmark3 capture put that in doubt, because systemd's 60-serial.rules already composes /dev/serial/by-id/ paths from the descriptor strings, per unit, with no help from us — and if that covers the catalog, our symlink work is redundant.

So this is an accounting rather than an argument. Three questions per device, and the third column is the one that changed the plan.

The counts

Devices
Get a /dev/serial/by-id/ path for every confirmed identifier 9
Get one for some identifiers and not others 3
Get none at all — nothing they present is a serial interface 15
Not yet recorded either way 7
Where by-id is insufficient for at least one reason 29 of 34
Carry a udev symlink from this catalog 7
…of which duplicate a path by-id would have given anyway 0

The last row is the finding. Every symlink this catalog emits is on a device with no /dev/serial/by-id/ entry at all. The two mechanisms have not overlapped once — not by design, which makes it worth stating: the symlinks were written for SDRs, and SDRs are libusb devices that systemd's serial rule never sees. Nothing here is redundant, and nothing here was the main event either.

Why by-id is insufficient, by reason

A device can hit more than one, so these do not sum to the row above.

Reason Devices What it means
no-serial-subsystem 16 No /dev/serial/ entry exists. The device is claimed by libusb, or by a storage/HID class driver, and systemd's serial rule never sees it.
no-unit-serial 1 It is a serial device, but supplies no per-unit serial. by-id composes its path from manufacturer, product and serial, so two of these collide there exactly as they would under a naive symlink.
unlabelled-ports 4 One interface presents several ports. by-id hands out a stable path for each and labels none of them; a stable path to a port you cannot identify is not an answer.
unrecorded 9 Nobody has recorded what kind of interface this is, so the question cannot be answered yet. Counted as uncovered rather than assumed away.

Per device

by-id — does systemd give it a stable path. Ours — what this catalog adds on top. Insufficient because — empty means by-id genuinely settles it and we should not be inventing work.

Device by-id Ours Insufficient because
airspy no symlink /dev/airspy, access, packages no-serial-subsystem
bladerf no symlink /dev/bladerf, access, packages, firmware mode no-serial-subsystem
btech-uv-50pro yes (distro names it: /dev/serial/by-id/, from systemd's own 60-serial.rules), access, packages, documented gap unlabelled-ports
c5-wardriver yes access, packages, firmware mode —
catsniffer-v3 yes access, packages, documented gap —
clip-boy yes access, packages, firmware mode —
dell-dw5821e yes — unlabelled-ports
dell-dw5930e unknown documented gap unrecorded
flipper-zero partly access, packages, firmware mode, documented gap no-serial-subsystem
fobos-sdr no symlink /dev/fobos-sdr, access, packages, firmware mode, documented gap no-serial-subsystem
free-wili-2 partly access, interface map, packages, documented gap no-serial-subsystem, unlabelled-ports
funcube-dongle no packages no-serial-subsystem
hackrf-one no symlink /dev/hackrf, access, packages, firmware mode no-serial-subsystem
hackrf-pro no symlink /dev/hackrf-pro, access, packages, firmware mode no-serial-subsystem
hydrasdr-rfone no symlink /dev/hydrasdr-rfone, access, packages, firmware mode, documented gap no-serial-subsystem
intel-ax210-bluetooth no — unrecorded
krakensdr unknown access, packages, documented gap unrecorded
librevna unknown access, packages, documented gap unrecorded
limesdr no access, packages, documented gap no-serial-subsystem
meshtastic partly access, packages, firmware mode, documented gap no-serial-subsystem
minino yes access, packages, firmware mode —
orbic-rc400l unknown access, packages, documented gap unrecorded
plutosdr unknown access, packages, documented gap unrecorded
portapack-h4m unknown access, packages, documented gap unrecorded
proxmark3 yes access, firmware mode, documented gap no-unit-serial
rnode yes access, packages, firmware mode, documented gap —
rtl-sdr no access, packages no-serial-subsystem
sdrplay-rsp no access, packages, documented gap no-serial-subsystem
sunplus-integrated-webcam-fhd no — unrecorded
ubertooth-one no symlink /dev/ubertooth, access, packages no-serial-subsystem
uconsole unknown documented gap unrecorded
usrp no access, packages no-serial-subsystem
wi-spy no access, packages no-serial-subsystem
yaesu-ft-991a yes (distro names it: /dev/serial/by-id/, from systemd's own 60-serial.rules), access, packages, documented gap unlabelled-ports

Classes

A class is a naming subject too, and one of them carries the finding this table exists to make visible: some devices are already named by the package that drives them.

Class by-id Named by Devices in it
badgelife yes nothing device-specific 5
bluetooth-controller no nothing device-specific 1
camera no nothing device-specific 1
dmr-radio partly nothing device-specific 0
gps-receiver yes the distribution — /dev/gpsN, from gpsd's own 60-gpsd.rules 0
nfc-reader no us — /dev/nfc 0
programmer no nothing device-specific 0
rig yes the distribution — /dev/serial/by-id/, from systemd's own 60-serial.rules 2
wwan-modem yes nothing device-specific 1

What this changes

by-id gives a stable path. It does not give:

  • Permissions. A device only root can open is unusable however stable its path. This is what actually stops people, and by-id does nothing for it. Group membership and uaccess tagging are ours.
  • Non-serial devices. Every SDR in this catalog, the Ubertooth and the Proxmark in client mode are libusb devices with no /dev/serial/ entry at all.
  • Identical units. A device supplying no per-unit serial collides in by-id exactly as it would under a naive symlink. /dev/serial/by-path/ separates them and is topology, so it changes when the cable moves.
  • Knowing which interface is which. A multi-port device gets a stable path per port and a label on none of them.

  • A name somebody else already provides. gpsd ships SYMLINK+="gps%n", so a GNSS receiver is /dev/gps0 with nothing from us. Writing our own on top would be a D-022 displacement with no benefit; recording that the distribution did it is the useful act.

So the hardware layer's value is permissions, composite-device mapping, firmware-mode identification, and honest documentation of the cases nothing solves. Symlinks are one tactic, used where the evidence supports one — which, so far, is exactly where by-id cannot reach.