Renaming an FT232R USB serial EEPROM serial on Linux (Debian, D2XX, udev)

April 18, 2026    Linux USB FTDI Debian

TL;DR

I needed stable /dev names for several USB–serial adapters. For genuine FT232R devices you can store a short serial string in the chip EEPROM (up to 16 characters), then point udev rules at ATTRS{serial}==....

On a fresh Debian desktop the annoying failure was the linker error cannot find -lftd2xx: that is FTDI’s D2XX library, not libftdi-dev from apt. After installing the correct libftd2xx.so for x86_64, a small helper script had to unload pl2303 / cp210x (and friends) before usbserial, otherwise rmmod usbserial fails while other UART drivers still depend on it.

Below is a real run from 2026-04-18 showing the full happy path plus verification with only_read_serial.sh.

Why EEPROM serial at all?

  • Same meaningful symlink regardless of which USB port you use (once udev rules match ATTRS{serial}).
  • Easier automation than chasing ttyUSBn rotation.
  • Caveat: many cheap “FTDI” cables are counterfeit; EEPROM writes often do not work on fakes. I only do this on adapters I trust.

D2XX vs Debian packages

  • libftdi-dev → open-source libFTDI (ftdi.h, -lftdi). Different stack.
  • FTDI D2XXlibftd2xx.so, ftd2xx.h, link with -lftd2xx. Download the Linux tarball from FTDI’s D2XX drivers page and install the .so (for amd64 use the x86_64 archive, not the x86_32 one).

On Debian with multiarch, installing under /usr/lib/x86_64-linux-gnu/ plus ldconfig is fine; the tooling I use also searches /usr/local/lib.

Script behaviour that bit me: usbserial still in use

read_then_write_serial.sh has to drop ftdi_sio and usbserial so userspace D2XX can talk to the device during the write. On my box usbserial was still referenced by pl2303 and cp210x, so rmmod usbserial failed until those client modules were removed first. The script now unloads those dependents, performs the EEPROM write, then reloads usbserial → clients → ftdi_sio in a sane order.

Example session (success)

$ sudo ./read_then_write_serial.sh SERTAC-WS7
[1/7] Current tty serial via udevadm (/dev/ttyUSB0)
ID_SERIAL=FTDI_FT232R_USB_UART_BG02PQ2N
ID_SERIAL_SHORT=BG02PQ2N
[2/7] Building EEPROM read tool
make: Nothing to be done for 'all'.
[3/7] Building EEPROM write tool
[4/7] Unloading kernel drivers (rmmod)
Unloaded: ftdi_sio
Unloaded usbserial client: pl2303
Unloaded usbserial client: cp210x
Unloaded: usbserial
[5/7] Writing new serial: SERTAC-WS7
=== FTDI EEPROM Serial Programmer ===
Found 1 FTDI device(s)
Current serial: BG02PQ2N
Programming new serial: SERTAC-WS7
✅ EEPROM updated successfully.
[7/7] Reloading kernel drivers (modprobe)
Loaded: usbserial
Loaded usbserial client: pl2303
Loaded usbserial client: cp210x
Loaded: ftdi_sio
$ ./only_read_serial.sh
Reading serial info from /dev/ttyUSB0
ID_SERIAL=FTDI_FT232R_USB_UART_SERTAC-WS7
ID_SERIAL_SHORT=SERTAC-WS7

So udevadm now sees ID_SERIAL_SHORT=SERTAC-WS7 without any extra rename tricks—this is coming from the device itself after reprogramming.

Tooling and repo

The scripts and README live in a small public repo (fork-friendly if you want to PR improvements):

Highlights from the README worth repeating here:

  • Official downloads live on FTDI’s D2XX Drivers page (pick Linux / x86_64 vs x86_32 vs the right ARM tarball—ABI must match uname -m and the ELF class of libftd2xx.so).
  • The script can optionally fetch the pinned Linux tarball if the linker still cannot find -lftd2xx (lab convenience; disable with FTDI_D2XX_NO_AUTO_DOWNLOAD=1 if you do not want network installs as root).

Next steps for udev

Once the hardware serial is what you want, add or adjust rules under /etc/udev/rules.d/, run udevadm control --reload-rules && udevadm trigger, and usually replug once so the kernel and udev pick up the new attributes cleanly.


This post is a field note from my own desk setup; YMMV on kernels, module names, and counterfeit hardware.



comments powered by Disqus