Saturday, September 09, 2006

Multiseat (VI): Final notes

(...comes from step V)

This project is just an evaluation prototype. It has been developed in a Hospital environment to determine if the computer on every medical examination room can be used simultaneously by two people.

Currently there is a computer on every examination room. Through the computer, some administrative tasks related to the patient are carried on by a nurse. There is also a web based information system, used by the physician to access to the medical information of every patient.

The goal is to share the same computer for administrative and medical tasks simultaneously (that is why only two seats are necessary in our case study) and evaluate the opinions of the final users about the new system.

Friday, September 08, 2006

Multiseat (V): gdm and xkb

(...comes from step IV)

The next step is to configure gdm to indicate how to execute (the wrapper script). The call includes a couple of parameters (display and xauthority) that will be converted to environment variables . The other pair of parameters are the physical addresses of the input devices, that will be converted to the event numbers to be used as keyboard and mouse events.

# cp /etc/gdm/gdm.conf /etc/gdm/gdm.conf.bak
# vi /etc/gdm/gdm.conf

Only the servers section of the gdm.conf file is shown



command=/usr/bin/X -ac -br

command=/usr/sbin/ -display :0.0 -xauthority /var/lib/gdm/:0.Xauth -fullscreen -kbdphys isa0060/serio0/input0 -mousephys isa0060/serio1/input0 -use-evdev

command=/usr/sbin/ -display :0.1 -xauthority /var/lib/gdm/:0.Xauth -fullscreen -kbdphys usb-0000:00:1d.1-1/input0 -mousephys usb-0000:00:1d.1-2/input0 -use-evdev

Notice theat the command lines have been split for better readability.

Right now, you already have a multiseat computer. If you start the graphic mode, you will see the two monitors showing the gdm login screen.

# /etc/init.d/gdm start

In this moment there is only one problem remaining: To be able to obtain a proper configuration of the keyboards.

According to messages in several forums on Internet, evdev seems to have some problems still waiting to be patched related to keyboard configuration. Some options are ignored, some others can lead to a fully missconfigured keyboard (no one key mapping to the correct one). After many hours looking for information, and dozens of trial-error tests with setxkbmap, we finally achieved to obtain a correct keyboard configuration.

The best solution is to create a keyboard configuration file for every Xephyr session (change the layout according to your particular locale):

# vi /etc/X11/xkb/X1-config.keyboard
model = "pc105"
keycodes = "evdev"
layout = "es"

# cp /etc/X11/xkb/X1-config.keyboard /etc/X11/xkb/X2-config.keyboard

Do never include this line rules = "evdev" in the Xn-config.keyboard file. Every test we did (and we did really lots of tests!) having such line present, the result was a useless keyboard with no correct keys at all!

Update (4-May-2007): Since we are using a Xephyr compiled on another distribution, there seem to be an issue with the directories, and some configuration files can not be found. Including these additional lines, you can avoid all the keyboard related problems:

# ln -s /usr/share/X11/xkb /usr/lib/X11/xkb
# cp /etc/X11/xkb/X*.keyboard /usr/lib/X11/xkb
# cp `which xkbcomp` /usr/lib/X11/xkb
# mkdir /usr/lib/X11/xkb/compiled

Launch again the gdm, and have a coffee break. Your new toy is ready to play with!

(continues on step VI...)

Multiseat (IV): evdev and Xephyr

(...comes from step III)

What is evdev?

evdev is the generic input event device driver. It passes the events generated in the kernel (since version 2.6.8) straight to the program, with timestamps.

The evdev driver is able to separate and distinguish events coming from different keyboards and mouses plugged into the computer. The xorg supports evdev input driver module since version 6.9/7.0 . This way, it can get separated input events coming from every seat (keyboard and mouse pair) on the system.

This is a great step compared to previous multiseat solutions, since it makes possible to have multiterminal systems without having to patch neither the kernel nor the X server.

What is Xephyr?

Xephyr is a kdrive based X Server which targets a window on a host X Server as its framebuffer. In other words, it is a piece of software which creates a X server on top of another X server. That will allow us to run as many Xephyr instances as seats we have in our system. Every Xephyr instance will cover the area shown in a given display, and finally, evdev will allow us to separate the different input devices.

The good news

Xephyr is included in the universe repository from Ubuntu.

The bad news

The Xephyr version included in the Ubuntu repository, does not support evdev. I hope in a near future Xephyr comes with evdev upport.

Right now, you will have either to patch the Xephyr sources and compile it, or download an already patched solution. Download links for both solutions are available here.

# wget
# tar -xjf xephyr-precompiled.tar.bz2 --directory /usr/local/

Now it is time to plug your second set of keyboard and mouse. The evdev driver will access the input coming from every device by means of a given event in the form of /dev/input/eventNN. You must obtain the event id associated to every input device.

A new problem arises, since the event number assigned can change (in fact, it changes) between different boots. To solve this problem we well use a wrapper script. The script is the same as proposed here, but modified in order to obtain the event number given the physical connection of the device. We are assuming that the devices will be always plugged in the same position (you can label the back connectors to remember the correct position). Since the physical device addresses do not change between boots, the script can obtain the corresponding event id and match it properly with one physical keyboard or mouse.

Input devices and events, once plugged the second keyboard and mouse:

# cat /proc/bus/input/devices
I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/class/input/input0
H: Handlers=kbd event0
B: EV=120013
B: KEY=4 2000000 3802078 f840d001 f2ffffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=7

I: Bus=0011 Vendor=0002 Product=0005 Version=0000
N: Name="ImPS/2 Generic Wheel Mouse"
P: Phys=isa0060/serio1/input0
S: Sysfs=/class/input/input1
H: Handlers=mouse0 event1 ts0
B: EV=7
B: KEY=70000 0 0 0 0 0 0 0 0
B: REL=103

I: Bus=0010 Vendor=001f Product=0001 Version=0100
N: Name="PC Speaker"
P: Phys=isa0061/input0
S: Sysfs=/class/input/input2
H: Handlers=kbd event2
B: EV=40001
B: SND=6

I: Bus=0003 Vendor=0d62 Product=001c Version=0202
N: Name="Darfon USB Combo Keyboard"
P: Phys=usb-0000:00:1d.1-1/input0
S: Sysfs=/class/input/input5
H: Handlers=kbd event4
B: EV=120003
B: KEY=10000 7 ff87207a c14057ff febeffdf ffefffff ffffffff fffffffe
B: LED=7

I: Bus=0003 Vendor=0d62 Product=001c Version=0202
N: Name="Darfon USB Combo Keyboard"
P: Phys=usb-0000:00:1d.1-1/input1
S: Sysfs=/class/input/input6
H: Handlers=kbd event5
B: EV=3
B: KEY=3078 d801d101 1e0000 0 0 0

I: Bus=0003 Vendor=046d Product=c03f Version=2000
N: Name="Logitech USB-PS/2 Optical Mouse"
P: Phys=usb-0000:00:1d.1-2/input0
S: Sysfs=/class/input/input8
H: Handlers=mouse1 event3 ts1
B: EV=7
B: KEY=f0000 0 0 0 0 0 0 0 0
B: REL=103

The Name section will help us to identify the device. The Phys section is the parameter that we will send to the wrapper script in order to start every Xephyr instance.

The Xephyr wrapper

Now, it is time to create the wrapper script. The original one is modified to obtain the event numbers from the physical addresses

# vi /usr/sbin/

This is the final wrapper script:


# 20060905 - josean - added get_event() function to obtain eventNN from a physical address
# Original version:

trap "" usr1


evento=`grep -A2 $1 /proc/bus/input/devices | grep 'H: Handlers=' | grep --only-matching -e 'event[0-9]*'`


while [ ! -z "$1" ]; do
if [[ "$1" == "-xauthority" ]]; then
if [ ! -z "$1" ]; then
export XAUTHORITY="$1"
elif [[ "$1" == "-display" ]]; then
if [ ! -z "$1" ]; then
export DISPLAY="$1"
elif [[ "$1" == "-kbdphys" ]]; then
if [ ! -z "$1" ]; then
get_event $1
args=("${args[@]}" "-keyboard")
args=("${args[@]}" "/dev/input/$evento")
elif [[ "$1" == "-mousephys" ]]; then
if [ ! -z "$1" ]; then
get_event $1
args=("${args[@]}" "-mouse")
args=("${args[@]}" "/dev/input/$evento,5")
if ! expr match $1 'vt[0-9][0-9]*' >/dev/null; then
args=("${args[@]}" "$1")


# echo $XEPHYR "${args[@]}" >> /tmp/logXephyr

exec $XEPHYR "${args[@]}"

Finally, be sure to allow the script to be executed.

# chmod +x /usr/sbin/

(continues on step V...)

Thursday, September 07, 2006

Multiseat (III): xorg.conf

(...comes from step II)

Changes on the xorg.conf file

Since the system automatically generated a correct configuration file, this step is not really necessary. Anyway, if you need to obtain information about the bus in which your card is plugged, the lspci command will give you such data.

Obtaining the information for the graphic card.

# lspci | grep VGA
0000:01:00.0 VGA compatible controller: nVidia Corporation NV34 [GeForce FX 5200] (rev a1)

Before making any change, it is advisable to make a backup of the original configuration file. Then edit it using your favorite text editor.

# cp /etc/X11/xorg.conf /etc/X11/xorg.conf.bak
# vi /etc/X11/xorg.conf

The next step is the edition of the xorg.conf according to your configuration. In particular, we must create the corresponding device, monitor and screen sections for every seats.

Section "Files"
FontPath "/usr/share/X11/fonts/misc"
# FontPath "/usr/share/X11/fonts/cyrillic"
FontPath "/usr/share/X11/fonts/100dpi/:unscaled"
FontPath "/usr/share/X11/fonts/75dpi/:unscaled"
FontPath "/usr/share/X11/fonts/Type1"
FontPath "/usr/share/X11/fonts/100dpi"
FontPath "/usr/share/X11/fonts/75dpi"
# path to defoma fonts
FontPath "/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType"

Section "Module"
Load "bitmap"
Load "ddc"
# Load "dri"
Load "extmod"
Load "freetype"
Load "glx"
Load "int10"
Load "type1"
Load "vbe"

# ------------------------------------------------------------------------
# Input devices
# ------------------------------------------------------------------------

Section "InputDevice"
Identifier "Keyboard-base"
Driver "kbd"

Section "InputDevice"
Identifier "Mouse-base"
Driver "mouse"
Option "Device" "/dev/input/mice"

# ------------------------------------------------------------------------
# Dual head system. Notice the two devices sharing the same BusID
# ------------------------------------------------------------------------

Section "Device"
Identifier "Card0.0" # CRT-0 (VGA output)
Driver "nvidia"
VendorName "nVidia Corporation"
BoardName "NV34 [GeForce FX 5200]"
BusID "PCI:1:0:0"
Screen 0
Option "NoLogo"

Section "Device"
Identifier "Card0.1" # CRT-1 (Analog-DVI, DFP-0 : Digital-DVI)
Driver "nvidia"
VendorName "nVidia Corporation"
BoardName "NV34 [GeForce FX 5200]"
BusID "PCI:1:0:0"
Screen 1
Option NoLogo"

# ------------------------------------------------------------------------
# Monitor section: Most of the parameters are optional
# ------------------------------------------------------------------------

Section "Monitor"
Identifier "Monitor0"
VendorName "HP"
ModelName "HP D8904"
Option "DPMS"
HorizSync 30-70
VertRefresh 50-160
DisplaySize 320 240 # CRT 17" (81 DPI @ 1024x768)

Section "Monitor"
Identifier "Monitor1"
VendorName "Compaq"
ModelName "Compaq 5500"
HorizSync 30-54
VertRefresh 50-120
DisplaySize 280 210 # CRT 15" (72 DPI @ 800x600)
Option "DPMS"

# ------------------------------------------------------------------------
# Screen section: Pairing video cards and monitors
# ------------------------------------------------------------------------

Section "Screen"
Identifier "Screen0"
Device "Card0.0"
Monitor "Monitor0"
SubSection "Display"
Depth 24
Modes "1024x768" "800x600" "640x480"

Section "Screen"
Identifier "Screen1"
Device "Card0.1"
Monitor "Monitor1"
SubSection "Display"
Depth 24
Modes "800x600" "640x480"

# ------------------------------------------------------------------------
# Layout section
# ------------------------------------------------------------------------

Section "ServerLayout"
Identifier "Multihead"
Screen 0 "Screen0" 0 0
Screen 1 "Screen1" LeftOf "Screen0"
InputDevice "Keyboard-base" "CoreKeyboard"
InputDevice "Mouse-base" "CorePointer"

# ------------------------------------------------------------------------
# Additional sections
# ------------------------------------------------------------------------

# Xephyr can not use DRI, so it is not enabled
# Section "DRI"
# Mode 0666
# EndSection

Section "ServerFlags"
# Xinerama does not affect this configuration, so it is not enabled
# Option "Xinerama" "on"

# Even if mouse detection fails, X will start
Option "AllowMouseOpenFail" "yes"

# VT switching is disabled
Option "DontVTSwitch" "yes"

# X restart (Ctrl+Alt+Backspace) is disabled
Option "DontZap" "yes"

If everything was OK, when you log into your computer, you should have either two independent adjacent desktops (Xinerama disabled) or a bigger desktop extended through the two monitors (Xinerama enabled)

Do not worry in this moment about configuring your keyboard layout. This X configuration will not be seen by the final user of the system. The only goal in this moment is to define properly your video hardware in order to have the two monitors working simultaneously.

Take into account that the login greeter will appear in only one of the screens, but as soon as you log into the system you will see your desktop along the two screens.

The next step is to create a true multiseat computer. We will use Xephyr: A software able to act as an intermediary between the input devices and the underlying X.

(Continues on step IV...)

Multiseat (II): Let's start

(...comes from step I)

Step by step installation


First of all, obviously, we need the hardware. In the prototype here presented, we had this configuration
  • Computer: Pentium IV 2.0GHz, 512MB RAM, 20GB hard disk
  • Graphic card: nVidia GeForce 5200 AGP 8x, 128MB, VGA + DVI + TV outputs (the blue one on the picture)
  • Seat 1: PS/2 keyboard and mouse, 17" CRT monitor (the right one in the photo)
  • Seat 2: USB keyboard and mouse, 15" CRT monitor (the left one)

Additional requirements:
  • Network connection to a second computer, in order to have remote access during the configuration of the system (It is also possible to do without an additional computer, but this option is not recommendable at all).
  • Internet access, to download drivers, additional packages, and (optionally) to keep updated the system.

Standard Ubuntu install

In this step it is not necessary to have all your hardware plugged. If you have only a set of KVM (keyboard, video, mouse), that is enough right now. We used a PS/2 keyboard and a PS/2 mouse, and a VGA monitor plugged in the VGA output of the graphic card. Nothing special at the moment.

Insert the Ubuntu CD. The CD of the 6.06 version is a live one, which offers the possibility of being installed on youy hard drive.

Follow the instructions and Install Ubuntu on your hard drive. Your hard drive will be deleted and its contents will be lost. Any spyware and virus you may previously have there, will be lost.

After the installation if everything was OK, you should have an Ubuntu with the X working properly on one of your monitors.

Before going into the next step, we recommend you to enable the root account. May be this is against the philosophy of Ubuntu, but it can be annoying to type sudo just before each command when you have to change many things at one time, such as in this project. After this step, the next commands will have to be executed as the root user. Otherwise, you will have to prepend sudo to all the commands needing root access.

$ sudo passwd root

If you want to make changes from another computer in your network, you must install a SSH server

# apt-get install openssh-server

The next step is to download the binary drivers from nVidia, because of limitations of the open source ones in graphic cards having more than one output.

# apt-get install nvidia-glx

Multihead install

Now it is time to plug the second monitor and modify your system configuration editing your xorg.conf file

(Continues on step III...)

Wednesday, September 06, 2006

Multiseat computer with Ubuntu

After having spent many hours working with the goal in mind of achieving a multiseat (also called multiterminal) computer, I have decided to write some lines to help anybody interested in building this kind of system.

Update (20090619): New tutorial for Multiseat in Ubuntu 9.04 available

The concept of multiseat

A multiseat computer is a particular configuration which allow a computer to be used for several people simultaneously. There are many fields of application of such kind of systems: Companies can achieve big savings on hardware and maintenance while giving service to many users. The main sites where this can be useful are all those in which users do not have great graphical requirements, i.e. almost everything except CPU hungry applications, such as recent 3D games or video encoding.

The sites which most can benefit from this technique are typically libraries, schools, public Internet access sites, and in general almost every site intended for administrative work.

Obviously the underlying operating system is a Linux distribution. Unfortunately, nowadays there are still too much sites tightly tied to proprietary operating systems, due to the fact that they must use some corporate applications developed for exclusive use on such proprietary operating systems. I hope in a near future that will be just bad memories belonging to the past, since the main trend in current developments is based on corporate intranets offering the necessary tools and software to the employees.

The configuration

I have choosen Ubuntu 6.06LTS as the OS, and a dual head video card to obtain two seats from a computer.

Why Ubuntu?

Yeah, why Ubuntu?... I have also made myself this question many times in recent days! I must confess that almost all my previous Linux experience had been with Fedora Core / RedHat systems (dealing with them since RedHat 5.x versions). I had only worked previously with Debian and its derived distributions in just a few ocasions, so obviously there were some new things to learn.

The reason for choosing Ubuntu is its popularity as a desktop based distribution. Several governments are choosing or creating Ubuntu or other Debian based distributions, and the supporting community is growing quickly. I think it is the distribution in which this kind of systems can catch most interest.

Why the 6.06LTS version?

A system based on recent software is easier to be reproduced, and will be more interesting for users willing to reproduce it than an alternative based on outdated software. Apart from beta versions, this is the latest Ubuntu version available right now.

The main goal is to give here the necesary steps to reproduce this configuration. A second goal is to ease the installation as much as possible. The ideal scenario would be to install only standard packages, without the need to use patched pieces of code. With the latest kernel inprovements, and the changes in xorg this is already possible in some cases.

Why a dual-head video card?

Let's start saying that the use of different cards with one video output each one would result in
a easier configuration, involving less packages of software. The reason to use dual head cards is just to adjust to a more realistic situation. The use of different cards, means either using additional PCI or PCIe cards.

The first ones (PCI) are almost impossible to obtain in most local stores (at least in Spain). You will have to buy them in sites such as eBay or you will have to use old recovered computer parts.

Our particular case was to create a prototype with evaluation purposes. Depending on the success of the prototype (stability and users satisfaction) the project can be extended to about 50 computers. We worked initially with cards coming from dead computers (very old cards manufactured between 1994 and 1997). That was a total waste of time: problems with video drivers, available video modes too poor for today screens, and the impossibility to extend the prototype for a large number of computers.

The second option is to use a modern motherboard having PCIe slots, but that means spending money in buying new hardware. In our project, the plans are intended to use computers whith motherboards having AGP slots. The only reasonable option for such computers is to plug in every computer a dual head AGP graphic card.

The last step was choosing the graphic card. We decided to use a card widely available and supported (i.e. using ATI or nVidia chips) with dual output, and in the lowest price range. The first prototype was built using a nVidia 5200 AGP 8x, with VGA output (D-sub), TV output (unused) and DVI-I output (either analog output using an adaptor or digital output). This card is well supported and widely available for about 30 euros (40 USD). For the second prototype, we are using a ATI 9250 AGP 8x.

(Continues on step II ...)

UPDATE: There is a new tutorial covering the setup of a multiseat computer with Ubuntu 8.04

Sunday, September 03, 2006

Blogger, at last!


I told myself tens of times that I won't be writing a blog. I used to create and host my own websites to publish the contents which I considered worth being shared.

Now I'm going to use for the first time a website managed by others, just to test and compare...

Let's the show start!