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:
Most of the hints that I used came from the following pages (thanks a lot to the maintainers of these pages!):
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).
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.
Xkb*
entries reflect a German keyboard setup and may have to be adapted to your locale.evdev
driver needs to be patched since otherwise it will forward the wrong scan codes to VMWare. See below.nvidia
provided by the manufacturer. The driver nv
does not seem to work.`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
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);
}
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.
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.
[server-*]
can be chosen freely.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.-sharevts
option. Using this option for both instances
somehow did not work for me!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
...
What works so far:
What does not work yet:
-q
.