Multi-seat Setup Using XWindows and VMWare Running WindowsXP


Published on December 02, 2006 by Marcus Rickert

Debian Multi-Seat VM Windows-XP

9 min READ

Motivation

The starting point for the multi-seat setup was our newborn child Joshua who needed a room to himself. So my wife and I decided to “merge” our two offices and turn my office into my son’s new bedroom. This implied that wife’s ancient PC running Microsoft Windows and my PC running Linux had to be moved into the same room.

In order to save space, energy and administration time I decided to try the following setup:

  • One PC running Linux as the primary operating system.
  • Two monitors, two keyboards and two mice.
  • X-Windows with GDM logins running on both screens.
  • Regular Gnome desktop configurations for all users (e.g. for myself).
  • Special setup for my wife starting a VMWare instance running Microsoft Windows.

Most of the hints that I used came from the following pages (thanks a lot to the maintainers of these pages!):

How to do it

X Server

The X server configuration file located at /etc/X11 has to be modified to include two “server layout” sections referring to two sets of graphics cards, keyboards and mice respectively. In our case the first X server uses the PCI-AGP NVidia card, the “regular” keyboard and the serial mouse. The second X server uses the PCI ATI card, a USB keyboard (Cherry) and a USB mouse (Logitech).

Remarks on the X server configuration file

  • For the USB keyboard and mouse I used the evdev driver which requires the “name” of the USB device. This can be found by executing cat /proc/bus/usb/devices, looking for the device in question and using the string found in the S: Manufacturer= column. Note that I do not use the evdev keyboard rules since my patched version of the driver is compatible with the regular xfree86 rules.
  • The BusID can be found by executing lspci and using the value in the first column:

      ...
      00:0a.0 VGA compatible controller: ATI Technologies Inc RV280 [Radeon 9200 PRO] (rev 01)
      00:0a.1 Display controller: ATI Technologies Inc RV280 [Radeon 9200 PRO] (Secondary) (rev 01)
      ...
      01:00.0 VGA compatible controller: nVidia Corporation NV18 [GeForce4 MX 440 AGP 8x] (rev a4)
      ...
    

Note that lspci returns values in hexadecimal format whereas the configuration file expects decimal values. Also note that my secondary graphics adapter has two logical cards on it of which only the first one is used. This will give a warning of the kind

(WW) RADEON: No matching Device section for instance (BusID PCI:0:10:1) found

in your /var/log/Xorg.*.log file during startup which can be ignored.

  • The Xkb* entries reflect a German keyboard setup and may have to be adapted to your locale.
  • The evdev driver needs to be patched since otherwise it will forward the wrong scan codes to VMWare. See below.
  • You have to use the driver nvidia provided by the manufacturer. The driver nv does not seem to work.`

XF86Config-4 File

Note that the following XF86Config-4 setup only reflects an excerpt of the configuration file. I left out all the stuff that is more or less standard or easy to adapt.

...

Section "InputDevice"
    Identifier	"Keyboard0"
    Driver		"keyboard"
    Option		"CoreKeyboard"
    Option		"XkbRules"	"xfree86"
    Option		"XkbModel"	"pc105"
    Option		"XkbLayout"	"de"
    Option		"XkbVariant"	"nodeadkeys"
EndSection

Section "InputDevice"
        Identifier      "Keyboard1"
        Driver          "evdev"
        Option          "Name"          "Cherry GmbH"
    Option		"CoreKeyboard"
    Option		"XkbRules"	"xfree86"
    Option		"XkbModel"	"pc105"
    Option		"XkbLayout"	"de"
    Option		"XkbVariant"	"nodeadkeys"
EndSection

Section "InputDevice"
    Identifier	"Mouse0"
    Driver		"mouse"
    Option		"CorePointer"
    Option		"Device"		"/dev/ttyS1"
    Option		"Protocol"		"Microsoft"
    Option		"ZAxisMapping"		"4 5"
EndSection

Section "InputDevice"
    Identifier	"Mouse1"
    Driver		"evdev"
    Option		"SendCoreEvents"	"true"
        Option          "Name"                  "Logitech USB-PS/2 Optical Mouse"
    Option		"ZAxisMapping"		"4 5"
EndSection

Section "Device"
    Identifier	"Card0"
    Driver		"nvidia"
    BusID           "PCI:1:0:0"
EndSection

Section "Device"
    Identifier      "Card1"
    Driver          "ati"
    VendorName      "Sigma"
    BoardName       "Radeon"
    BusID           "PCI:0:10:0"
        Option          "VGAAccess" "false"
EndSection

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

...

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

Patch to evdev

Making the keyboard layout work under VMWare turned out to be the most time-consuming aspect of the whole endeavor. This is due to the following intricate detail. All tools (e.g. xkeydb or xmodmap) to configure your specific keyboard to meet the interface of X usually do elaborate mappings of the scan codes onto logical key codes. So if you use a USB keyboard you will also use a corresponding evdev setup which maps the somewhat awkward scan codes. In a virtual machine, however, the guest operating system (e.g. MS Windows) is made to believe that the keyboard is a regular PS/2 type which has well-defined scan codes. The VMWare driver simply forwards the original scan codes of the USB keyboard (and not the mapped logical keys) to the guest operating system which tries to interpret them as coming from a PS/2 keyboard. Of course, this proves to be a mess, especially for all keys on or near the numerical key pad.

I spent hours and hours searching the web for a remedy to this problem but did not find any. VMWare may be aware of the problem but has not reacted to it so far. At least, a search for evdev on their website did not yield any result.

This is what I did: I retrieved the source package of the evdev driver and applied a very crude patch to the procedure EvdevKeyProcess of source file src/evdev_key.c which consists of a case statement mapping the scan codes of the USB keyboard onto the “standard” scan codes of a regular 105 key keyboard. This driver needs to be compiled and placed in the modules directory /usr/lib/xorg/modules/input of the X server. In case you don’t want to go through all this trouble you can try my compiled evdev_drv.so. Of course, there’s no guarantee that this driver will work for your specific setup. Please, make a copy of your current driver before trying.

Here’s the modified C procedure:

void
EvdevKeyProcess (InputInfoPtr pInfo, struct input_event *ev)
{
    int keycode = ev->code + MIN_KEYCODE;

    int newkeycode = keycode;

    switch (keycode) {
    case 107:
      newkeycode = 111;
      break;
    case 127:
      newkeycode = 110;
      break;
    case 118:
      newkeycode = 106;
      break;
    case 110:
      newkeycode = 97;
      break;
    case 112:
      newkeycode = 99;
      break;
    case 119:
      newkeycode = 107;
      break;
    case 115:
      newkeycode = 103;
      break;
    case 117:
      newkeycode = 105;
      break;
    case 111:
      newkeycode = 98;
      break;
    case 113:
      newkeycode = 100;
      break;
    case 116:
      newkeycode = 104;
      break;
    case 114:
      newkeycode = 102;
      break;
    case 133:
      newkeycode = 115;
      break;
    case 108:
      newkeycode = 113;
      break;
    case 134:
      newkeycode = 116;
      break;
    case 135:
      newkeycode = 117;
      break;
    case 105:
      newkeycode = 109;
      break;
    }
    keycode = newkeycode;

    /* filter repeat events for chording keys */
    if (ev->value ## 2) {
    DeviceIntPtr device = pInfo->dev;
    KeyClassRec  *keyc = device->key;
    KbdFeedbackClassRec *kbdfeed = device->kbdfeed;
    int num = keycode >> 3;
    int bit = 1 << (keycode & 7);

    if (keyc->modifierMap[keycode] ||
        !(kbdfeed->ctrl.autoRepeats[num] & bit))
        return;
    }

    xf86PostKeyboardEvent(pInfo->dev, keycode, ev->value);
}

.xinitrc

If you don’t want automatic starting of VMWare you can skip this section. Otherwise, you have to install a very simple .xinitrc in the home directory of all users for whom the VMWare should be started automatically upon login into X windows. The configuration consists of a single line executing the VMWare startup script:

VMWARE_HOME=...
VMWARE_CONFIG=...
$VMWARE_HOME/vmware $VMWARE_CONFIG -X -q 

where VMWARE_HOME must be set to the binary directory of your VMWare installation and VMWARE_CONFIG must be set to the configuration file of the virtual machine to start. Latter have the suffix .vmx. The option -X starts the virtual machine automatically. The option -q exits the VMWare binary after the guest operating system has been shut down. Please, also see the summary below.

GDM

The configuration file of the GDM also needs to be adapted to the multi-seat setup. The changes consist of starting a second X server. Both the first and the second x servers need to be given some special parameters.

Remarks on the GDM configuration file

  • The suffix of the [server-*] can be chosen freely.
  • The names of the layouts have to match the layout identifiers in the x server configuration.
  • X1 and X2 are hard links to X. As recommended by Chris Tyler this comes in handy when you try to debug the setup. For example this allows you to see the individual CPU loads of the two instances.
  • Note that the second instance does not have the -sharevts option. Using this option for both instances somehow did not work for me!

GDM configuration file

As above, please, note that this is only a small excerpt of the file located in /etc/gdm/gdm.conf.

...
[server-Standard]
name=Standard server
command=/usr/bin/X1 -dpi 96 -layout Layout0 :0 -novtswitch
flexible=false

[server-Second]
name=Second server
command=/usr/bin/X2 -dpi 96 -layout Layout1 :1 -sharevts -novtswitch
flexible=false
...

Summary

What works so far:

  • Two screens running X windows with two graphics cards, two keyboards and two mice.
  • User sensitive automatic start up of Microsoft Windows under VMWare.

What does not work yet:

  • The virtual terminals are not available once the X servers have been started. This is why another PC on the same network always comes in handy if you have to fix a broken setup.
  • The automatic termination of the VMWare application does not work. After logging out of Microsoft Windows the WMWare application appears in an almost inactive state. Most of the menu elements are deactivated. One has to manually call the “quit” menu item to terminate. This is despite the fact that the application is called using the parameter -q.