Skip to content

Ambiguous USB identifiers

Generated by scripts/gen_usb_ambiguity.py. Do not edit by hand — regenerate.

Generated: 2026-09-12, Debian 13
Kernel id→driver pairs read: 7694
udev rule identifiers read: 2788
LoRa mesh board definitions read: 299
Identifiers that name a chip, not a device: 1259

Basis Count
distribution_disabled 4
kernel_generic_driver 1169
shared_across_products 86

777 pairs were considered and NOT flagged: they sit in a bridge driver's table but usb.ids names a product, which means a vendor bought an identifier for a device rather than reusing the chip maker's default. ftdi_sio alone knows about hundreds of those.

Why this is enforced rather than reviewed

A udev rule matching 10c4:ea60 alone claims every CP2102 adapter on the machine — a rig-control cable, a GPS puck, a Meshtastic node — after whichever device the rule was written for. The operator gets a symlink pointing at the wrong hardware and no error anywhere.

That is the mirror image of the gap that started this work: rtl-sdr carried three identifiers where Debian carries 42, so a Hauppauge stick got no symlink and no error either. Under-matching is silent and over-matching is silent. Neither can be left to review, which is why this is catalog data the schema enforces against rather than a document somebody is meant to have read.

DeviceManifest and DeviceClass refuse a symlink resting on an identifier marked ambiguous unless the rule also carries match_product or match_serial. Same shape as the missing method: script and the mandatory sha256: unrepresentable, not discouraged.

Where the evidence comes from

kernel_generic_driver — the kernel's own modules.alias, generated by depmod from the module tree. If a pair sits in cp210x's or ftdi_sio's table, the kernel maintainers put it in a bridge driver, which is as close to an authoritative statement of "this is silicon, not a product" as exists. The driver list is explicit rather than pattern-matched on the name, because pn533_usb also ends in _usb and is a device driver — getting that backwards would suppress a legitimate symlink.

shared_across_products — the archive sweep found the pair in two or more packages' rules under different device names. The different-names requirement matters: libnitrokey-common and scdaemon both name the same Nitrokey, which is agreement, not ambiguity.

The identifiers shared between unrelated devices

The kernel_generic_driver findings are mostly unsurprising — they are the bridge chips. These are the ones the sweep caught by seeing the same pair used for genuinely different hardware:

Identifier usb.ids Packages Named as
16c0:05dc shared ID for use with libusb avrdude, libhamlib4t64, ola, qlcplus USBasp; VOTI USBasp AVR Programmer; them. The devices nodes are found under /dev/bus/usb/xxx/yyy.
0483:df11 STM Device in DFU Mode dfu-util, dmrconfig, qdmr, qflipper Flipper Zero DFU; STM32; TYT MD-UV380
058f:6254 USB Hub consolekit, elogind, systemd Match child, look for parent's ID_AVOID_LOOP; Match child, retrigger parent; Match parent
17e9:401a — consolekit, elogind, systemd Match child, look for parent's ID_AVOID_LOOP; Match child, retrigger parent; Match parent
0403:6015 Bridge(I2C/SPI/UART/FIFO) infnoise, openfpgaloader, openocd Original FT231X VID:PID; Original FT231XQ VID:PID
0765:5001 Huey PRO Colorimeter argyll, colord Huey, built into Thinkpad w700; HueyL (not tested)
0765:5010 X-Rite Pantone Color Sensor argyll, colord Huey, built into Thinkpad w700; HueyL (not tested)
0765:5020 i1 Display Pro argyll, colord i1Display 3; i1Display3
0971:2007 ColorMunki Photo argyll, colord ColorMunki; ColorMunki Photo
04d8:f8da Hughski Ltd. ColorHug argyll, colord ColorHug (legacy); ColorHug, old and new USB ID's, ColorHug 2
273f:1001 ColorHug argyll, colord ColorHug; ColorHug, old and new USB ID's, ColorHug 2
273f:1004 ColorHug2 argyll, colord ColorHug; ColorHug, old and new USB ID's, ColorHug 2
273f:1002 ColorHug+ argyll, colord ColorHug Plus; ColorHug Spectro
03eb:2103 JTAG ICE mkII avarice, avrdude Atmel Corp. JTAG ICE mkII; JTAG ICE mkII
03eb:2107 AVR Dragon avarice, avrdude AVR Dragon; Atmel Corp. AVR Dragon
03eb:2110 AVR JTAGICE3 Debugger and Programmer avarice, avrdude AVR JTAGICE3; Atmel Corp. AVR Dragon
03eb:2ff1 at32uc3a3 DFU bootloader avrdude, libnitrokey-common Nitrokey Storage Bootloader; at32uc3a3 DFU
28e9:018a — dmrconfig, qdmr Anytone AT-D868UV; Anytone AT-D868UV, AT-D878UV
2c7c:0125 EC25 LTE modem eg25-manager, modemmanager Default attributes values; We can identify the PPP by looking for the string "pinephone-pro" in the device tree "compati
0403:cff8 Amontec JTAGkey flashrom, openocd Amontec JTAGkey and JTAGkey-tiny; http://www.amontec.com/jtagkey.shtml
1457:5118 OpenMoko Neo1973 Debug board (V2+) flashrom, openocd Debug Board for Neo1973; http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v2
15ba:0003 OpenOCD JTAG flashrom, openocd Olimex ARM-USB-OCD; http://olimex.com/dev/arm-usb-ocd.html
15ba:002b ARM-USB-OCD-H JTAG+RS232 flashrom, openocd Olimex ARM-USB-OCD-H; http://olimex.com/dev/arm-usb-ocd-h.html
15ba:0004 OpenOCD JTAG TINY flashrom, openocd Olimex ARM-USB-OCD-TINY; http://olimex.com/dev/arm-usb-tiny.html
15ba:002a ARM-USB-TINY-H JTAG interface flashrom, openocd Olimex ARM-USB-OCD-TINY-H; http://olimex.com/dev/arm-usb-tiny-h.html

What hardware found that this could not

Three identifiers were captured against real hardware on 2026-08-26 that this list does not contain, and each one is a different limit of the method:

Identifier Why the sweep missed it
303a:1001 Espressif's native USB-serial-JTAG. No Debian package names it and the kernel claims it by interface class, so neither source sees it. Two captures — a Clip-Boy and the ESP32-S3 inside a Free-WiLi 2 — report the same pair and the same product string.
2e8a:00c0 A bare RP2040 running Arduino-core firmware, which is what a CatSniffer v3 presents. Claimed by cdc_acm on class, invisible to both sources for the same reason.
1a86:55d3 Flagged correctly by the sweep — noted here because it is the one the catalog had GUESSED WRONG. badgelife carried 1a86:55d4 as a "widely reported" CH9102 identifier; the C5 Wardriver actually presents 55d3. One digit out, and the guess is still unconfirmed.
2d2d:504d Not ambiguous at all — proxmark.org registered its own vendor id. Listed here for the opposite problem: the device supplies no product string and no serial, so two units are indistinguishable even to /dev/serial/by-id/. The identifier is fine; the descriptor is empty.
1fc9:000c Shared, and Debian's rule says so in a comment — "NXP Semiconductors DFU mode (HackRF and rad1o)". The sweep missed it because shared_across_products requires the pair in TWO packages, and here one rule names two devices in one comment.
1d50:6089 A false negative, not a blind spot. The sweep saw this pair and excluded it: usb.ids calls it "Great Scott Gadgets HackRF One SDR", a product name, which the generator treats as evidence a vendor bought an id for one device. A HackRF Pro capture shows the successor board reuses it, differing only in product string.

The first two are honest limits — a pair no package names and no driver claims by id cannot be inferred from packages and drivers. The third is a wrong inference, and the useful one: a product name in usb.ids is evidence that an identifier once meant one device, not that it still does. Vendors reuse identifiers across a product line, and the database records the first name it was given.

That rule is not tightened in response, because tightening it — treating every product-named pair as ambiguous — would flag the 777 currently excluded and make the list useless. The correct handling is what happened: the sweep produces a floor, hardware raises it, and an entry may carry a hand-written ambiguity block the generator never suggested. Both hackrf-one and hackrf-pro now do.

What this does not do

It does not decide which device an identifier belongs to. An ambiguous pair is still the right identifier to match on for permissions and for firmware tools, where the operator has chosen the device — it is only unsafe as the sole basis for a name in /dev, where the kernel matches whatever is attached.

That distinction is why flipper-zero records 0483:df11 under firmware and not under usb_ids, and it is stated as a rule in D-028 rather than re-derived per entry.