Re: How to pin USB serial devices to a specific probe order

From: Tomek CEDRO <tomek_at_cedro.info>
Date: Mon, 10 Mar 2025 00:53:39 UTC
On Fri, Mar 7, 2025 at 5:36 AM Dan Mahoney (Ports) <freebsd@gushi.org> wrote:
>
> Hey there folks,
>
> At the dayjob we have some 16-port USB serial console expanders, and we recently also plugged in the USB console for a Netgate firewall, which lacks a traditional DE9 port, but instead has a USB micro port that bridges to its own internal Prolific PL2032 port and presents a usb-to-serial adapter there.  (They also default to 115200, grr).
>
> Here’s the problem: after a reboot, the probe order changed, and the netgate box became ttyU0.
>
> We need them to stay consistently ordered, i.e. such that the device with a given USB ID will always turn out to be ttyU1, and the 16-port pod that has 16 serials will always be ttyU1-ttyU16 (or vice versa).
>
> Is there something one can put in devfs.rules to enforce this, or something that once can do to force a given device to be probed earlier or later in the process?
>
> I imagine there’s a similar issue for USB ethernet devices and the like.

Hey Dan :-) I had similar problem but found an utility to program
CP21XX USB-to-UART bridges [1]. Its a Python utility and for my boards
it allows changing Serial (SN) in descriptor several times. If you can
use different adapters that would make your life a lot easier :-)

I just looked at my CP2303 cable and it has SN set to 0 (no string),
there is no way to distingush them by SN. There are variants of the
chips (-D vs -X) that can have external EEPROM that allows
reprogramming of the SN fields several times.. but most of them are
OTP and probably that SN was already written to 0? You may play around
with that but I did not find any utility quickly.

% usbconfig -d 0.7 dump_device_desc
ugen0.7: <PL2303 Serial Port / Mobile Phone Data Cable Prolific
Technology, Inc.> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON
(100mA)

  bLength = 0x0012
  bDescriptorType = 0x0001
  bcdUSB = 0x0110
  bDeviceClass = 0x0000  <Probed by interface class>
  bDeviceSubClass = 0x0000
  bDeviceProtocol = 0x0000
  bMaxPacketSize0 = 0x0040
  idVendor = 0x067b
  idProduct = 0x2303
  bcdDevice = 0x0400
  iManufacturer = 0x0001  <Prolific Technology Inc. >
  iProduct = 0x0002  <USB-Serial Controller D>
  iSerialNumber = 0x0000  <no string>
  bNumConfigurations = 0x0001

I  have only one cable like this so I cannot help with bus
identification locally sorry.. usually device nodes are named by path
i.e. /dev/usb/X.Y.Z, that might help in identification, but I am not
sure if the enumeration order is always the same?

Another solution is UHUBCTL [2] that allows control of single USB HUB
ports, it is advertised to work on FreeBSD, did not see the port and
did not use it yet, but with that you may turn off all hub ports and
then turn them on one by one and then assign devices that show up some
names with devfs/devd?

Tomek

[1] https://github.com/DiUS/cp210x-cfg
[2] https://github.com/mvp/uhubctl

-- 
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info