sweh
November 27, 2021, 12:02am
1
Now RedHat have documented a process for spinning up agetty on serial ports with custom parameters: How to configure serial getty with systemd - Red Hat Customer Portal
Basically,
# cp /usr/lib/systemd/system/serial-getty@.service /etc/systemd/system/serial-getty@ttyS0.service
Then edit the file and modify the agetty line:
[Service]
ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 %I $TERM <-- Change this parameter
Type=idle
Finally
# systemctl enable serial-getty@ttyS0.service
# systemctl start serial-getty@ttyS0.service
This works fine if the serial port has a fixed name.
But with USB serial ports (/dev/ttyUSB*
) the name can change depending on what is plugged into the machine at boot time. Today it might be ttyUSB0
, but tomorrow it could be ttyUSB2
.
With CentOS6 I used the by-id path to ensure it was always discovered.
agetty -h -L -w /dev/serial/by-id/usb-utek_USB__-__Serial_Cable_FTVW64JR-if01-port0 9600 vt102
The “template” file from RedHat won’t work this way, though, because it has
After=dev-%i.device
as part of the unit definition. Looking at the output of systemctl -a | grep dev-tty
these entries are all based on the ttyUSB
name.
So how can I create a service defintion for agetty
based on the by-id
pathname?
I can’t think of a clear way of doing this in systemd units itself, but what you can do is try to force udev to keep a constant name. So for example, I’ll find my current serial adapter, get some ID information, and make a udev rule for it.
[label@sani ~]$ lsusb
Bus 002 Device 004: ID 0557:2410 ATEN International Co., Ltd 4-Port USB 3.0 Hub
Bus 002 Device 002: ID 174c:55aa ASMedia Technology Inc. ASM1051E SATA 6Gb/s bridge, ASM1053E SATA 6Gb/s bridge, ASM1153 SATA 3Gb/s bridge, ASM1153E SATA 6Gb/s bridge
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 009: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port / Mobile Action MA-8910P
Bus 001 Device 007: ID 0557:2200 ATEN International Co., Ltd ATEN CS1942DP_1944DP
Bus 001 Device 006: ID 0557:8021 ATEN International Co., Ltd Hub
Bus 001 Device 005: ID 046d:08e5 Logitech, Inc. HD Pro Webcam C920
Bus 001 Device 004: ID 14ed:1012 Shure Inc. Shure MV7
Bus 001 Device 003: ID 0557:5411 ATEN International Co., Ltd 4-Port USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
[label@sani ~]$ ls /dev/ttyUSB*
/dev/ttyUSB0
[label@sani ~]$ udevadm info -a -n /dev/ttyUSB0 | egrep 'idVendor|idProduct|serial'
SUBSYSTEMS=="usb-serial"
ATTRS{idProduct}=="2303"
ATTRS{idVendor}=="067b"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{serial}=="0000:00:14.0"
# So now I can see that my vendor and product match from my lsbusb output, I'll make a udev rule with that information
[label@sani ~]$ sudo rvim /etc/udev/rules.d/99-usb-serial.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", ATTRS{serial}=="0000:00:14.0", SYMLINK+="ttyUSB0"
[label@sani ~]$ sudo udevadm control --reload-rules
[label@sani ~]$ sudo udevadm trigger
And see if that helps keeping your device name the same at all times. You could always name it ttyUSBSerial
also, so that it’s consistent that way too.
sweh
November 27, 2021, 2:47am
3
Huh, that’s an interesting work around to a systemd limitation (which is an odd limitation 'cos I thought the whole point of systemd was to handle dynamic stuff! Never mind…)
Now I don’t get the same output as you 'cos -a
follows the chain of parents and produces a lot more information, but I think it’s leading me down a possible path. In my case I have two 2-port FTDI adapters, so a combination of vendorID, modelID, serial and interface might work…
… and now I have no idea why this isn’t working!
% cat /etc/udev/rules.d/90-usbserial.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ATTRS{serial}=="FTVW64JR", ATTRS{bInterfaceNumber}=="00", SYMLINK+="ttyTubeHost"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ATTRS{serial}=="FTVW64JR", ATTRS{bInterfaceNumber}=="01", SYMLINK+="ttyBBC"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ATTRS{serial}=="FTWKU6FP", ATTRS{bInterfaceNumber}=="01", SYMLINK+="ttyRouter"
This is the output for what I’d expect to be remapped as ttyBBC.
% udevadm info -a /dev/serial/by-id/usb-utek_USB__-__Serial_Cable_FTVW64JR-if01-port0
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5/1-1.5.1/1-1.5.1:1.1/ttyUSB1/tty/ttyUSB1':
KERNEL=="ttyUSB1"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5/1-1.5.1/1-1.5.1:1.1/ttyUSB1':
KERNELS=="ttyUSB1"
SUBSYSTEMS=="usb-serial"
DRIVERS=="ftdi_sio"
ATTRS{latency_timer}=="16"
ATTRS{port_number}=="0"
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5/1-1.5.1/1-1.5.1:1.1':
KERNELS=="1-1.5.1:1.1"
SUBSYSTEMS=="usb"
DRIVERS=="ftdi_sio"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bInterfaceNumber}=="01"
ATTRS{bInterfaceProtocol}=="ff"
ATTRS{bInterfaceSubClass}=="ff"
ATTRS{bNumEndpoints}=="02"
ATTRS{interface}=="USB <-> Serial Cable"
ATTRS{supports_autosuspend}=="1"
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5/1-1.5.1':
KERNELS=="1-1.5.1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{bMaxPower}=="100mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 2"
ATTRS{bcdDevice}=="0500"
ATTRS{bmAttributes}=="80"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="4"
ATTRS{devpath}=="1.5.1"
ATTRS{idProduct}=="6010"
ATTRS{idVendor}=="0403"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="utek"
ATTRS{maxchild}=="0"
ATTRS{product}=="USB <-> Serial Cable"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{rx_lanes}=="1"
ATTRS{serial}=="FTVW64JR"
ATTRS{speed}=="12"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="1433013"
ATTRS{version}==" 2.00"
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5':
KERNELS=="1-1.5"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="100mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0702"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="3"
ATTRS{devpath}=="1.5"
ATTRS{idProduct}=="0608"
ATTRS{idVendor}=="05e3"
ATTRS{ltm_capable}=="no"
ATTRS{maxchild}=="4"
ATTRS{product}=="USB2.0 Hub"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="removable"
ATTRS{rx_lanes}=="1"
ATTRS{speed}=="480"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="128"
ATTRS{version}==" 2.00"
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1':
KERNELS=="1-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0000"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="2"
ATTRS{devpath}=="1"
ATTRS{idProduct}=="0020"
ATTRS{idVendor}=="8087"
ATTRS{ltm_capable}=="no"
ATTRS{maxchild}=="6"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="fixed"
ATTRS{rx_lanes}=="1"
ATTRS{speed}=="480"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="31"
ATTRS{version}==" 2.00"
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{authorized_default}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0418"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{interface_authorized_default}=="1"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 4.18.0-348.2.1.el8_5.x86_64 ehci_hcd"
ATTRS{maxchild}=="6"
ATTRS{product}=="EHCI Host Controller"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{rx_lanes}=="1"
ATTRS{serial}=="0000:00:1a.0"
ATTRS{speed}=="480"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="32"
ATTRS{version}==" 2.00"
looking at parent device '/devices/pci0000:00/0000:00:1a.0':
KERNELS=="0000:00:1a.0"
SUBSYSTEMS=="pci"
DRIVERS=="ehci-pci"
ATTRS{ari_enabled}=="0"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x0c0320"
ATTRS{companion}==""
ATTRS{consistent_dma_mask_bits}=="32"
ATTRS{d3cold_allowed}=="1"
ATTRS{device}=="0x3b3c"
ATTRS{dma_mask_bits}=="32"
ATTRS{driver_override}=="(null)"
ATTRS{enable}=="1"
ATTRS{irq}=="16"
ATTRS{local_cpulist}=="0-3"
ATTRS{local_cpus}=="0f"
ATTRS{msi_bus}=="1"
ATTRS{numa_node}=="-1"
ATTRS{revision}=="0x06"
ATTRS{subsystem_device}=="0x3b3c"
ATTRS{subsystem_vendor}=="0x1849"
ATTRS{uframe_periodic_max}=="100"
ATTRS{vendor}=="0x8086"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
When I parse your output, I get this:
[label@sani ~]$ egrep 'idVendor|idProduct|serial|InterfaceNumber' /tmp/out
SUBSYSTEMS=="usb-serial"
ATTRS{bInterfaceNumber}=="01"
ATTRS{idProduct}=="6010"
ATTRS{idVendor}=="0403"
ATTRS{serial}=="FTVW64JR"
ATTRS{idProduct}=="0608"
ATTRS{idVendor}=="05e3"
ATTRS{idProduct}=="0020"
ATTRS{idVendor}=="8087"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{serial}=="0000:00:1a.0"
I think you should be using the serial that looks like a PCI ID rather than the ID that looks like the SN of the device itself.
sweh
November 27, 2021, 2:27pm
5
To try and see what’s going on I created a simpler rule that just chmod’s the object.
This works:
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ATTRS{serial}=="FTWKU6FP", MODE="0661"
...
crw-rw---- 1 root dialout 188, 0 Nov 27 09:20 /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 1 Nov 27 09:20 /dev/ttyUSB1
crw-rw---x 1 root root 188, 2 Nov 27 09:20 /dev/ttyUSB2
crw-rw---x 1 root root 188, 3 Nov 27 09:20 /dev/ttyUSB3
We can see it correctly distinguishes between the units. But, of course, it applies to both ports.
However as soon as we add the interface number to it then it fails…
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ATTRS{serial}=="FTWKU6FP", ATTRS{bInterfaceNumber}=="01", MODE="0661"
...
crw-rw---- 1 root dialout 188, 0 Nov 27 09:25 /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 1 Nov 27 09:25 /dev/ttyUSB1
crw-rw---- 1 root dialout 188, 2 Nov 27 09:25 /dev/ttyUSB2
crw-rw---- 1 root dialout 188, 3 Nov 27 09:25 /dev/ttyUSB3
Hmm…
sweh
November 27, 2021, 4:30pm
6
So I think creating a custom unit may be simplest. It’s not as clean, but it seems to work…
[Unit]
Description=USB Getty
After=systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target
After=rc-local.service
ConditionPathExists=/dev/serial/by-id/usb-utek_USB__-__Serial_Cable_FTVW64JR-if01-port0
[Install]
WantedBy=multi-user.target
[Service]
ExecStart=-/usr/sbin/agetty -h -L -w /serial/by-id/usb-utek_USB__-__Serial_Cable_FTVW64JR-if01-port0 9600 vt102
Type=idle
Restart=always
RestartSec=0
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes
UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
Hopefully the ConditionPathExists
line will be the magic I need!
It doesn’t seem to correctly report on logouts, but otherwise seems to work!
% last -3
sweh ttyUSB1 Sat Nov 27 11:25 gone - no logout
sweh ttyUSB1 Sat Nov 27 11:18 - 11:25 (00:07)
sweh ttyUSB1 Sat Nov 27 11:17 - 11:18 (00:00)