Using udev to configure Fedora multi-seat automatically
When using a multi-seat configuration on Fedora 17, we need a method to automatically assign devices to seats. The simplest method is to use udev as explained rather tersely in the multiseat documentation. Following the setup in multi-seat configuration on Fedora 17, this article provides an example of setting up the correct udev rules.
If you followed the guidelines in multi-seat configuration on Fedora
17 to set up your configuration, you will find some rules in
/etc/udev/rules.d/72-* that Fedora automatically sets up for you.
Those rules are rather cryptic and hard to maintain; please move those
rules to a backup location (outside rules.d).
We will continue the example by developing our own udev rules. To recap,
here is the list of hardware that corresponds to seat2 in this
example:
Devices:
├ /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.0/drm/card1
│ (drm:card1)
├ /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.0/graphics/fb1
│ (graphics:fb1) "radeondrmfb"
├ /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.1/sound/card2
│ (sound:card2) "HDMI"
│ └ /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.1/sound/card2/input16
│ (input:input16) "HDA ATI HDMI HDMI/DP,pcm=3"
├ /sys/devices/pci0000:00/0000:00:12.1/usb4/4-1/4-1:1.0/input/input2
│ (input:input2) "CHESEN PS2 to USB Converter"
├ /sys/devices/pci0000:00/0000:00:12.1/usb4/4-1/4-1:1.1/input/input3
│ (input:input3) "CHESEN PS2 to USB Converter"
└ /sys/devices/pci0000:00/0000:00:12.1/usb4/4-2/4-2:1.0/input/input4
(input:input4) "Microsoft Microsoft 3-Button Mouse with IntelliEye(TM)"
We need to identify some feature of these devices that can be used to
specify udev rules assigning them to seat2. In order to do so, we will
first need to see the attributes of these devices and their parents. We
will tackle the keyboard first (a few lines were stripped for brevity):
[root@kaito]$ udevadm info -a -p /devices/pci0000:00/0000:00:12.1/usb4/4-1/4-1:1.0/input/input2 ...snip... looking at device '/devices/pci0000:00/0000:00:12.1/usb4/4-1/4-1:1.0/input/input2': KERNEL=="input2" SUBSYSTEM=="input" DRIVER=="" ATTR{name}=="CHESEN PS2 to USB Converter" ATTR{phys}=="usb-0000:00:12.1-1/input0" ATTR{uniq}=="" ATTR{properties}=="0" looking at parent device '/devices/pci0000:00/0000:00:12.1/usb4/4-1/4-1:1.0': KERNELS=="4-1:1.0" SUBSYSTEMS=="usb" DRIVERS=="usbhid" ATTRS{bInterfaceClass}=="03" ATTRS{bInterfaceSubClass}=="01" ATTRS{bInterfaceProtocol}=="01" ATTRS{bNumEndpoints}=="01" ATTRS{supports_autosuspend}=="1" ATTRS{bAlternateSetting}==" 0" ATTRS{bInterfaceNumber}=="00" ...snip...
The keyboard can be identified easily by its name and there are no other
devices on the machine with the same name. The udev rule needs to assign
an environment variable called ID_SEAT to the correct device:
TAG=="seat", ATTRS{name}=="CHESEN PS2 to USB Converter", ENV{ID_SEAT}="seat2"
Note that we have also added a match on the TAG attribute to ensure
that we do not try to use devices that are not assignable to a seat
(such as hard disks). A similar solution works for the mouse as well.
However, the video card is a little more complex. The udev attributes
for the video card is as follows:
[root@kaito]$ udevadm info -a -p /devices/pci0000:00/0000:00:04.0/0000:02:00.0/drm/card1 ...snip... looking at device '/devices/pci0000:00/0000:00:04.0/0000:02:00.0/drm/card1': KERNEL=="card1" SUBSYSTEM=="drm" DRIVER=="" looking at parent device '/devices/pci0000:00/0000:00:04.0/0000:02:00.0': KERNELS=="0000:02:00.0" SUBSYSTEMS=="pci" DRIVERS=="radeon" ATTRS{irq}=="45" ATTRS{subsystem_vendor}=="0x174b" ATTRS{broken_parity_status}=="0" ATTRS{class}=="0x030000" ATTRS{power_method}=="profile" ATTRS{consistent_dma_mask_bits}=="40" ATTRS{dma_mask_bits}=="40" ATTRS{local_cpus}=="00000000,00000000,00000000,0000000f" ATTRS{device}=="0x9588" ATTRS{power_profile}=="default" ATTRS{msi_bus}=="" ATTRS{local_cpulist}=="0-3" ATTRS{vendor}=="0x1002" ATTRS{subsystem_device}=="0x2e42" ATTRS{boot_vga}=="0" ATTRS{numa_node}=="0" looking at parent device '/devices/pci0000:00/0000:00:04.0': KERNELS=="0000:00:04.0" SUBSYSTEMS=="pci" DRIVERS=="pcieport" ATTRS{irq}=="41" ATTRS{subsystem_vendor}=="0x1849" ATTRS{broken_parity_status}=="0" ATTRS{class}=="0x060400" ATTRS{consistent_dma_mask_bits}=="32" ATTRS{dma_mask_bits}=="32" ATTRS{local_cpus}=="00000000,00000000,00000000,0000000f" ATTRS{device}=="0x597a" ATTRS{msi_bus}=="1" ATTRS{local_cpulist}=="0-3" ATTRS{vendor}=="0x1002" ATTRS{subsystem_device}=="0x5957" ATTRS{numa_node}=="0" ...snip...
There does not seem to be an obvious property on which to match. After trawling through various devices, we find that the one property that is different between the two video cards: they both have the same vendor id, but different subsystem device ids. (This makes sense since they are both RadeonHD cards, albeit with different model numbers.) Then the udev rules follow easily:
# Radeon 2600XT video and HDMI audio TAG=="seat", ATTRS{vendor}=="0x1002", ATTRS{subsystem_device}=="0x2e42", ENV{ID_SEAT}="seat2" TAG=="seat", ATTRS{vendor}=="0x1002", ATTRS{subsystem_device}=="0xaa08", ENV{ID_SEAT}="seat2"
Putting all of the rules into a udev rules file completes the process:
# Radeon 2600XT video and HDMI audio TAG=="seat", ATTRS{vendor}=="0x1002", ATTRS{subsystem_device}=="0x2e42", ENV{ID_SEAT}="seat2" TAG=="seat", ATTRS{vendor}=="0x1002", ATTRS{subsystem_device}=="0xaa08", ENV{ID_SEAT}="seat2" # Keyboard TAG=="seat", ATTRS{name}=="CHESEN PS2 to USB Converter", ENV{ID_SEAT}="seat2" # Mouse TAG=="seat", ATTRS{name}=="Microsoft Microsoft 3-Button Mouse with IntelliEye(TM)", ENV{ID_SEAT}="seat2"
On reboot, devices will be assigned correctly to their respective seats. In theory, everything should work fine. However, our current testing reveals a need to boot into runlevel 3 and then manually invoke runlevel 5. We believe that this may have something to do with a udev race in dracut. Until it is fixed, the manual step of booting into runlevel 3 and changing manually into runlevel 5 will be needed.
Occasionally, we find that the GDM login screen turns blank. Once logged
this case is to restart the X server for that particular seat by
pressing Ctrl-Alt-Backspace.