Multiple local XFree users under Linux

Version 0.99 by Miguel Freitas <miguel@cetuc.puc-rio.br>

Updated Dec 7, 2005


You can always get the latest version of this document from: http://cambuca.ldhs.cetuc.puc-rio.br/multiuser

Keywords (for bots)

I've wasted a lot of time trying to find this kind of document in google, hotbot and so on. Let me add some keywords to help people finding it: true dual-head, multi-user support, XFree86 4.0, multiple keyboard, multiple mouse, multiple video card, dual user, XFree86 instances, dual keyboard, USB keyboard under X.
 

Motivation
 

I have one girlfriend and one computer. In normal conditions, we both couldn't use the computer at the same time, in spite of the fact that it usually has a lot of processing power available. I also have a spare monitor and a second video card for playing 3D games (voodoo) so this idea came to me as something very obvious. New XFree86 4.0 support for dualhead suggests that most of the hard work is already done. And it has to be on Linux, because no closed source OS would allow me to make the changes that I need.

As several reports confirm, Linux is been successfully used in educational institutions and projects due to it's great benefits and low cost. Using the same computer for two (or more) simultaneous students, workers, etc. is something that can reduce even more these costs.

This is also a great option for companies to simplify the management and upgrades of the shared resources (motherboard, processor, hds).

For everybody who may be asking: don't it get too slow? No. The performance difference is barely perceptible as most of the time the computer is waiting some command from the user. And if you haven't figured it out by yourself let me tell something: we live in a time of computing power in excess or do you think most of the users needs a GigaHertz Pentium 3 machine just to do their word processing and surf the web?
 

Problems
 

There are some problems that need to be addressed in order to support multiple XFree instances (and users):

My solution

My hack is surely not the best one, I know thousands of things that could be better implemented in XFree86 and Linux Kernel to support true dual-head (and dual-input) in a clean way. But it works for me. Don't blame me if you spend your money and time buying videocards, monitors, keyboards, mouses and it doesn't work. You've been warned.

Although I would love to see XFree86 supporting simultaneous layouts (without another instance) and a brand new keyboard driver, I don't have the necessary understanding of the project to implement it by myself. Anyway, my regards to the XFree86 developers for this great piece of software!

My idea is to have two instances of XFree86. The first will be using a normal XFree86 server, it will initialize the main video card and attach it to a VT. It will also use the standard system AT keyboard and something (PS/2, serial, USB emulated as PS/2, whatever you want) as a mouse.

The second instance of XFree will be my modified X server. It does not support VT switching at all because it's been used to control a hardware that is not normally used by any other VT. Read my lips, this is very important: The video card can't be the primary one, the mouse can't be the same used by gpm and the keyboard must be USB and must not generate scancodes to the normal Linux console!

As the keyboard doesn't look like a normal AT keyboard (no keys to standard console) the keyboard driver of my modified X server must take care of USB events translating them to normal scancodes.
 

Procedure (step by step)
 

1) You need to get XFree 4.0.x (RedHat 7.0 and a lot of recent distros comes with it) and configure it for two video cards and monitors. I suggest that you first try it with Xinerama extension following this HowTo: http://linuxdocs.org/HOWTOs/Xinerama-HOWTO.html

Then modify your XF86Config or XF86Config-4 to separate your screens in two layouts, instead of using them with Xinerama extension. Don't know what I am talking about? Then it's time to read XF86Config, do a ``man XF86Config''

With two layouts your XF86Config should look like this:
 

Section "ServerLayout"
    Identifier "Layout0"
    Screen 0 "Screen0"
    InputDevice "Mouse0" "CorePointer"
    InputDevice "Keyboard0" "CoreKeyboard"
EndSection

Section "ServerLayout"
    Identifier "Layout1"
    Screen 0 "Screen1"
    InputDevice "Mouse0" "CorePointer"
    InputDevice "Keyboard0" "CoreKeyboard"
EndSection

Section "InputDevice"
    Identifier "Keyboard0"
    Driver "keyboard"
    # this is for supporting deadkeys
    Option "XkbRules" "xfree86"
    Option "XkbModel" "pc101"
    Option "XkbLayout" "us_intl"
EndSection

Section "InputDevice"
    Identifier "Mouse0"
    Driver "mouse"
    Option "Device" "/dev/mouse"
    Option "Protocol" "IMPS/2"
    Option "Emulate3Buttons" "off"
    Option "ZAxisMapping" "4 5"
EndSection

Section "Monitor"
    Identifier "Plex17"
    VendorName "Unknown"
    ModelName "Unknown"
    HorizSync 31.5 - 79.0
    VertRefresh 50-90
EndSection

Section "Monitor"
    Identifier "Syncmaster3"
    HorizSync 31.5 - 79.0
    VertRefresh 50-70
EndSection

Section "Device"
    Identifier "FireGL 1000 PRO"
    Driver "glint"
    BusID "pci:1:0:0"
    BoardName "Unknown"
EndSection

Section "Device"
    Identifier "Voodoo"
    Driver "glide"
    BusID "pci:0:12:0"
EndSection

Section "Screen"
    Identifier "Screen0"
    Device "FireGL 1000 PRO"
    Monitor "Plex17"
    DefaultDepth 16
    Subsection "Display"
       Depth 16
       Modes "1024x768"
    EndSubSection
EndSection

Section "Screen"
    Identifier "Screen1"
    Device "Voodoo"
    Monitor "SyncMaster 3"
    DefaultDepth 16
    SubSection "Display"
       Depth 16
       Modes "800x600"
    EndSubSection
EndSection

This should be trivial to do because it's almost the same as Xinerama configuration but with two layouts. Then switch your box to runlevel 3 (init 3) and try both layouts, one at a time:

# XFree86 -layout Layout0
# XFree86 -layout Layout1

Pay attention to BusID settings as described in howto. Note that a dualhead board (like Matrox G400) should NOT work through the next steps, as we will be using 2 instances talking to the same hardware. But I haven't tried myself (I'd be happy to try it if any reader wants to donate such video card...).

Not all video cards can be used with XFree86 dualhead support. Don't email me saying that you couldn't get your cards to work up to here or you will burn in hell! Read the Xinerama HowTo instead, thanks.
 

2) Plug your second mouse on the system and configure XF86Config to use it in the second layout. This mouse must not be used by any other program, like gpm. XF86Config will look like this (only the changed sections):

Section "ServerLayout"
    Identifier "Layout1"
    Screen 0 "Screen1"
    InputDevice "Mouse1" "CorePointer"
    InputDevice "Keyboard0" "CoreKeyboard"
EndSection

 
Section "InputDevice"
    Identifier "Mouse1"
    Driver "mouse"
    Option "Device" "/dev/ttyS1"
    Option "Protocol" "Microsoft"
EndSection
 
Again, test this layout to make sure it's working.
 

3) Get Linux Kernel 2.4.0 so we can play with USB support. Some 2.2.x kernels may work as they have backported USB support, but in doubt, stick with 2.4.0.

In the kernel configuration, enable USB support (CONFIG_USB) and keyboard (either CONFIG_USB_HID or CONFIG_USB_KBD if your don't need USB mouse support). You must enable "input core support" (CONFIG_INPUT) and MUST NOT enable "keyboard support" (CONFIG_INPUT_KEYBDEV) as we don't want the USB one to be the system keyboard. Also enable "event interface" (CONFIG_INPUT_EVDEV) as I will use it to receive scancodes.

Compile and install the kernel. Now plug your USB keyboard, once the kernel enters you should not see any pressed keys from it at the console. Now try reading the keyboard events (assuming the keyboard is the only USB device you have):

# cat /dev/input/event0

You should see some garbage on the screen as you type. That's all right, your keyboard is working. If you don't see anything or get "No such device", something is wrong with your USB system. Read Documentation/usb in your kernel sources for more information.

Update: you don't need to recompile your kernel, but just have the right modules loaded/unloaded. See Kevin Crudup's modules.conf for a possible solution.
 

4) Get the sources of your XFree86 4.0.x if you haven't already done so. The sources are available from www.xfree86.org. There should be 3 or 4 big .tgz files, but you will only need the first one.

Expand the tree and apply my patch, which can be downloaded here (4.0.1) and here (4.0.2). Follow the instructions from the package to build the X server (make World). You should get a new XFree86 executable on directory xc/programs/Xserver. Copy it to your /usr/X11R6/bin with another name (like XFree86-2nd).

Or if you like the easy way, try one of my XFree86-2nd servers (compiled against glibc-2.1):

XFree86-4.0.1-2nd.gz

XFree86-4.0.2-2nd.gz

This server supports only USB keyboards and do not grab a VT. The only VT code it has is to switch to a given console through XFree86-2nd vtxx parameter.

Applying the patch is intended only for developers that can help me improving this scheme. It will also require you hundreds of MB of disk space. If my provided X servers doesn't work with your system there's little I can do about it. If you can, try to discover the problem and fix it.
 

5) Modify the second layout to use the USB keyboard. This will require you to use the protocol "usbev" I created and specify the /dev/input/eventx you like as the device. The XF86Config should now look like this (only the changed sections):

Section "ServerLayout"
    Identifier "Layout1"
    Screen 0 "Screen1"
    InputDevice "Mouse1" "CorePointer"
    InputDevice "Keyboard1" "CoreKeyboard"
EndSection
 
Section "InputDevice"
    Identifier "Keyboard1"
    Driver "keyboard"
    Option "Protocol" "usbev"
    Option "Device" "/dev/input/event0"
EndSection
 
Now try this X server with the command:

# XFree86-2nd -layout Layout1

It should initialize your second video card, the second mouse and the usb keyboard without interfering with your console. You can even do this from a xterm window inside your running X server. Yes! It works! Now move on to the grand finale...
 

6) If you use gdm as display manager and to provide you a graphical login, you can edit the file /etc/X11/gdm/gdm.conf as follows:

[servers]
0=/usr/bin/X11/XFree86-2nd -delay -layout layout1 vt07
1=/usr/bin/X11/X vt07

Getting this one to work may be a major challenge. It took me a lot of trial and error until I got this stable configuration. I had to add a option "-delay" (my hack) to cause a 10 second delay at one of the servers so they would not initialize the hardware at the same time. I don't know why this is needed. Playing with the order they are initialized (by exchanging 0= and 1=) also does the trick.
 

Known Bugs
 

This thing mess up with my text console. I have to switch between the VTs a couple of times before the text looks good again. Update: this is no longer a problem with latest patches. I'm running RH9 now (binaries below) and VT switching works nicely.

Also a main problem may be that the whole thing does not work with other hardware and you may be wasting your time reading all this. But the idea is here and I can guarantee that it worked for me. So it must be some little issue that I'm sure will be quickly resolved by another developer somewhere....
 

Updates

  • Brad Midgley pointed that support for Matrox G400 and similar dualhead cards should be possible using framebuffer interface. I still don't have the hardware to do any tests on this, but if you want to try please note that I may have removed something important for framebuffer from the init routines. Please check for any mistakes the patch might have. Any updates on this issue are greatly appreciated... note: read my G450 page below!

  • Daniel Tarbuck reported success with XFree86 4.1.0 with an additional patch:
    "I have implemented your patch on XF86 4.1.0 and I found that I had to comment out the following line:
        /*((pciArg*)arg)->func(((pciArg*)arg)->tag, PCI_CMD_STAT_REG, ((pciArg*)arg)->ctrl); */
        in xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c. (pciIoAccessDisable function)

    I don't know what the problem was, and I don't know why my fix worked for me. I also don't know if there will be serious problems as a result of my fix.
    Here is a few details on my setup:
        primary card: ATI Mach64 GT+ (PCI)
        secondary card: S3 VirgeDX (AGP)
        kernel 2.4.5 (Redhat 7.0)"


  • Jan "Yenya" Kasprzak did some tests with Daniel's patch and got two hardware configurations to work:

    S3 ViRGE VX PCI (primary)
    SIS 6xxx AGP (secondary - USB keyb.)
      I was not able to set up the AGP card as primary.

    Matrox G450 AGP (primary)
    S3 ViRGE VX PCI (secondary - USB keyb.)
      I was not able to set up the S3 card as primary.

    Yenya wrote: "I still have one problem: IMHO the above patch should be applied to primary X server as well, because otherwise it locks up the secondary card when the user on the primary display logs out."

  • Another success report, thanks Nathan Hoult for the information:

    "Geforce2pro 64meg AGP (MSI)-slave,AGP" and a "TNT 16 meg (Diamond Viper550)-master,PCI"
    Nathan wrote: "I used the official NVIDIA drivers too and get OpenGL to work on both quite well... well except i have permission problems all over the place but just got it working anyhow." (Mandrake8.1, XFree 4.1, linux 2.4.16)

    I rebuilt the patch against XFree86-4.1.0 (from rawhide sources XFree86-4.1.0-0.9.11.src.rpm). Applying Daniel's patch to both X servers, now we have XFree86-1st and XFree86-2nd (I hope everybody knows how to use them!).

    The 2nd server is using usbev keyboard as usual (thanks to Vojtech Pavlik help now we should have keyboard leds working). Please note that binary files where compiled under RedHat 7.1, so you need glibc >= 2.2.2.


      Precompiled XFree86 4.1.0-1st server.
      Precompiled XFree86 4.1.0-2nd server.
      Patch for XFree86 4.1.0-1st
      Patch for XFree86 4.1.0-2nd

    Notes:
      1) This binaries were tested over RedHat Linux 7.1. The gdm provided by ximian gnome desktop refused to work with my dual login, I had to downgrade to RH7.1 gdm package.
      2) My usbev keyboard got wrong key mapping if I don't specify XkbModel and XkbLayout. Something seems to have changed since 4.0.2, so don't forget these settings (specially if you get a working server with no keyboard...).
      3) When testing the XFree86-4.1.0-2nd inside the first instance I got errors of xauthorization. Calling the 2nd server with "-ac" may help.
      4) Usb keyboard leds still don't work. I will debug it as soon as I have time to do so, there must be some mistake.

  • These are modified binaries for XFree86-4.2.0-8 (RedHat 7.3). Sorry, i don't have the patch because i accidentaly erased my XFree86 sources. however it's easy to port the 4.1.0 patches to this version.

      Precompiled XFree86 4.2.0-1st server.
      Precompiled XFree86 4.2.0-2nd server.

  • New report from Jan "Yenya" Kasprzak:
    "I have XFree86-4.2.99.3 (the release from Red Hat beta "phoebe") working with ATI Radeon 8500LE AGP as a primary head, and S3 ViRGE VX PCI as a secondary head. I'll send you a patch which apply to XFree86 4.2.99.3 snapshot (and will probably apply to 4.3 sources when it is released) as soon as I get some more time."

  • Kevin Crudup wrote:
    "I have created the XFree86 4.3 patch files for you. They are attached. Also below can be added to modules.conf so that all of usb can be compiled as a module and keybdev will be removed automatically. I am using a G550 on Mandrake 9.1 and all has been working fine. Thanks for your help, now I am giving mine. Let me know if you need and more info."

      XFree86-4.3.0-1st.patch
      XFree86-4.3.0-2nd.patch
      modules.conf-mdk91

    Note that above patches disable additional PCI commands that may improve hardware compatibility over previous versions (changes borrowed from backstreet-ruby folks). Thanks to Kevin Crudup for taking his time to update the patch. For additional discussion see here.

    Precompiled 4.3.0 versions (created on Mandrake 9.1 with glibc 2.3.1 10mdk):
      XFree86-4.3.0-1st.gz
      XFree86-4.3.0-2nd.gz

    Precompiled 4.3.0 versions (created on RedHat 9):
      XFree86-4.3.0-1st.gz
      XFree86-4.3.0-2nd.gz

  • Dennis Vshivkov sent me a unified and improved version of the XFree86 patch. He added two new parameters so the two different executables (1st and 2nd) aren't needed anymore. This is something I wanted to do for a long time but I was too lazy... Thanks a lot Dennis! ;)

    Quoting his original message: "It is much easier to use because there's no need to have separate dedicated binaries -- two new options may be used instead. If you do not use them, the server is just like the unpatched one, but it still supports `usbev' keyboard type, and device defaults to /dev/input/event0. Also, `-delay' option now accepts optional decimal argument."

    Example of use (/etc/X11/xdm/Xservers):
    :0 local /usr/X11R6/bin/X :0 -nolisten tcp vt6 -layout Second -nopciaccessdisable -novtswitches -delay 6
    :1 local /usr/X11R6/bin/X :1 -nolisten tcp vt6 -layout First  -nopciaccessdisable

    Grab it here:
      XFree86-4.3.0-unified.patch

  • After having recently updated my system to fedora core 1, I decided to rebuilt the original XFree86 rpms to include Dennis' patch. As usual, this is just for my own use but as I know some people may like it too here they are:

    XFree86-4.3.0-42mf.i386.rpm (compiled package)
    XFree86-4.3.0-42mf.src.rpm (source package)

    You might need to uninstall your old XFree86 rpm (hint: use --nodeps) before installing this one. I had to keep the same version number as fedora to avoid dependencies problems... enjoy!

  • (Hacky) Kernel 2.6 support
    Ok, people keep asking me about kernel 2.6 support. I decided to give it a try and noticed that 2.6 has an overhauled and much cleaner input layer. This input layer is based on the concepts of "devices" and "handlers". Keyboard is a handler, it will convert the events it receives into key presses to the console. So is the generic event handler, responsible for exposing events at /dev/input/event<number>. This new input layer is supposed to be very smart because, when a new device is connected, it will figure out by itself which handlers should be bound to it. So, when running a 2.6 kernel with 2 keyboards you should get something like that from /proc/bus/input:

    I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
    N: Name="AT Translated Set 2 keyboard"
    P: Phys=isa0060/serio0/input0
    H: Handlers=kbd event1
    B: EV=120003
    B: KEY=4 2000000 3802078 f840d001 f2ffffdf ffefffff ffffffff fffffffe
    B: LED=7

    I: Bus=0003 Vendor=05c7 Product=2011 Version=0112
    N: Name="QTRONIX USB Keyboard and Mouse"
    P: Phys=usb-0000:00:10.0-1/input0
    H: Handlers=kbd event2
    B: EV=120003
    B: KEY=10000 7 ff87207a c14057ff febeffdf ffefffff ffffffff fffffffe
    B: LED=7

    Here is the catch: the usb keyboard was automaticaly bound to the system's keyboard handler. That is, the hack should still work *except* that the second keyboard will generate key presses at both heads. I can think of two ways of workarounding this problem:

    1) Have the XFree86 patched with the unified patch above. Then "usbev" protocol may be used on both heads and no kernel patching would needed, great! No, not so fast... Both keyboards are still connected by the keyboard handler, even though nobody read key presses from there. The drawback is that keyboard leds will be messed together very badly.
    2) I could not find a way to force unbinding a handler from a device, so i decided to patch my kernel. The patch for kernel 2.6.2 (pretty simple, should work with other versions as well) is available here. Of course, patching the kernel is never a desirable solution. Let me know if you have a better idea.

  • Proper kernel 2.6 support
    Aivils Stoss notified me that multiple keyboards are possible without any kind of 2.6 kernel patching (see above). The trick is to request exclusive access to the event device, so that keyboard handler would not receive any event. This requires only small changes to the XFree86 patch (actually x.org fork as i expect the old XFree86 to die silently with their new license...). Aivils explains:

    data[0]=1;
    if (ioctl(fd, EVIOCGRAB, data) == 0)
    printf("exclusive access granted");

    "where fd is file descriptor of /dev/input/eventXX. I dont know wherethat is documented.

    If You will highly polish Your solution, then take a look into Debian testing distro: Debian testing xf86 already includes 2.6.XX event device support.

    Please check out this patch against xf86 4.3.0: http://ftp.debian.org/debian/pool/main/x/xfree86/xfree86_4.3.0-7.diff.gz (grep evdev). You can find this link via www.debian.org. Unfortunately i do not know how to works Debian. I know only some linux-ruby tester suse this event interface. xf86 event interface means usage of /dev/input/eventXX instead standard /dev/ttyXX for keyboard and /dev/input/mouseXX for mouse.If You will run multiple local Debian xf86 You should applay manualy Your own "TTY dependency remove" patch and seems add EVIOCGRAB to disable 2nd, 3rd ... keyboard presence on TTY and "xf86 PCI interference remove" patch.

    Advantage: kernel remain unpatched. You can use two PS/2 keyboards under 2.6.XX."

  • Secondary PS/2 keyboard
    Michael Wiedemann sent me this message: "Hi Miguel, Your XFree patch for multiple consoles under linux is great. Unfortunatly it only applies to a second USB keyboard. I only have a PS/2 keyboard left, so I changed your code to add support for a second PS/2 keyboard plugged into the PS/2 mouse port. I also fixed a bug in xf86Globals.c which caused vt-switches to fail. The patch is here. It is based on the unified patch. The XF86Config file may now have the following lines in the keyboard section:

    Option "Protocol" "mouseport"
    Option "Device" "/dev/psaux" # optional

  • Dual-head Xorg in FC2
    As usual, Jan "Yenya" Kasprzak sent me some great stuff:

    "I have modified your multi-head X11 patch for use with xorg-x11 as present in Fedora Core 2. I have added a ioctl(EVIOCGRAB) call so that I can run unpatched 2.6 kernel. Now I run the same X server with event-interface driven keyboard both on the primary head with PS/2 keyboard, and on the secondary head with USB keyboard."

    "The patch itself, source and binary RPM of xorg-x11, my xorg.conf and gdm.conf files together with a short README are available at ftp://ftp.linux.cz/pub/linux/people/jan_kasprzak/xorg-dualhead/. Please add the link to the above URL to your multiuser-X11 page or mirror the patch (and possibly other files) to your site (it is not necessary as ftp.linux.cz has more than enough of free bandwidth)."

    These files are also mirrored here.

  • Multiseat X Under X11R6.9/7.0
    It seems that "multiple local XFree users" or "XFree local multi-user" is finally reaching the masses under the new term "Multiseat X". Admittedly i like the new term, specially because i know how difficult it was, back in 2001, to describe what i did in a couple of words. Since then, XFree86 was forked and x.org is probably the most used free X11 implementation, so saying "XFree users" proved to be a bad choice anyway.

    So the good news are: xorg 6.9 is reported to have accepted patches for new command line parameters, "-novtswitch", "-sharevts" and "-isolateDevice". (note: i have not tested this)

    -novtswitch don't immediately switch to new VT
    -sharevts share VTs with another X server
    -isolateDevice bus_id restrict device resets to bus_id (PCI only)

    For additional information please follow the links bellow or search for "novtswitch sharevts" in google.

    Now with official x.org support, i believe some (most?) of the hands-on information in my page should be keept just for historical purposes. But a careful reader will also note that the entire solution for multiseat X remains basically the same. The differences are patches that have been accepted here are there, parameters that received official names (Dennis Vshivkov sent me a patch for the "-novtswitches" quite some time ago, now it is called "-novtswitch" in x.org), my hacky keyboard protocol "usbev" is replaced by a new "evdev" driver... So i'm happy to have contributed with this feature in some way, even though i'm not currently using it (short story: we got married and moved and now we have 3 computers for 2 people). Free software is about freedom of choice - users should be able to use their computers the way they like.

    Links

  • Sharing your computer with Matrox G450 dualhead HOWTO.

  • Console Kernel patch (backstreet-ruby).

  • A different approach that doesn't requires patching neither kernel or XFree86 here. I heard that this is not available anymore due a harddisk crash. unfortunately i don't have any copy either, i just remember that vnc and xinerama were used in order to have two desktops.

  • Multi-seat XFree solution under Linux with framebuffers.

  • Another Quick How-To for Dual-X-Headed/Legged Linux

  • Another Multiple XFree86 idea to run MythTV in background

  • Dual-head RPM packages for Fedora Core 2

  • Dual-head patches for gentoo

  • XFree Local Multi-User HOWTO

  • Multiseat X Under X11R6.9/7.0 - Chris Tyler's Blog

  • Multiseat X: Three-Headed/Three-User X

    Contact

    Miguel Freitas <miguel@cetuc.puc-rio.br >
    Center for Telecommunications Studies of the
    Catholic University of Rio de Janeiro (CETUC/PUC-Rio)
    Brazil
    please send your spam to this email

    Picture of my room: one computer (behind me), 2 monitors, 2 keyboards, 2 mice, me and Cris.