Lihuen
RSSRSS AtomAtom

Multiterminales con Xorg

Introducción

Objetivos

  • Obtener múltiples terminales con solo una estación de trabajo
  • Aprovechar monitores en desuso
  • Aprovechar el poder de procesamiento de un equipo nuevo

Ventajas

  • Menores costos de hardware
  • Administración centralizada
  • Ahorro de energía

Desventajas

  • Un único punto de falla


Materiales necesarios

Supongamos que queremos N terminales, entonces precisaremos:

  • Al menos N - 1 Teclados USB
  • Al menos N - 1 Mouses USB
  • Si son necesarios un teclado y/o un mouse miniPS/2
  • N monitores
  • N placas de vídeo (notar que algunas placas de vídeo integradas no pueden ser utilizadas al agregar una placa de vídeo extra)
  • Una motherboard con suficientes slots PCI/AGP/PCI-E libres para conectar todas las placas y suficientes conectores USB para todos los teclados y mouses

Teoría

Configuraremos XOrg de manera que quede un Teclado, un Mouse, un Monitor (podría utilizarse una sola sección de monitor si todos son similares en resolución y frecuencias vertical y horizontal), y una Placa de Vídeo por cada terminal que queramos.

Como con la configuración por defecto de XOrg, utilizando kbd o keyboard como driver, no podemos distinguir los eventos de un teclado u otro utilizaremos evdev como driver y especificaremos el path a cada teclado en la configuración.

Con el mouse no es necesario utilizar evdev pero si es necesario indicar el path a cada dispositivo (tener en cuenta que /dev/input/mice captura los eventos de varios mouses al mismo tiempo y no debe ser utilizado en este tipo de configuraciones)

Lo que precisamos saber del hardware

Después de conectar todo tenemos que averiguar:

  • Donde encontrar el dispositivo de cada Mouse
  • Donde encontrar el dispositivo de cada Teclado
  • Driver de cada placa de vídeo
  • BusId de cada placa de vídeo

Dispositivos de entrada

Primero encontraremos los Teclados y Mouses, para eso ejecutaremos

# cat /proc/bus/input/devices
I: Bus=0019 Vendor=0000 Product=0002 Version=0000
N: Name="Power Button (FF)"
P: Phys=button_power/button/input0
S: Sysfs=/class/input/input0
H: Handlers=kbd event0
B: EV=3
B: KEY=100000 0 0 0

I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button (CM)"
P: Phys=PNP0C0C/button/input0
S: Sysfs=/class/input/input1
H: Handlers=kbd event1
B: EV=3
B: KEY=100000 0 0 0

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/input2
H: Handlers=kbd event2
B: EV=120013
B: KEY=4 2000000 3802078 f840d001 feffffdf 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/input3
H: Handlers=mouse0 event3
B: EV=7
B: KEY=70000 0 0 0 0 0 0 0 0
B: REL=103

I: Bus=0003 Vendor=1241 Product=1111 Version=0110
N: Name="HID 1241:1111"
P: Phys=usb-0000:00:02.0-6/input0
S: Sysfs=/class/input/input4
H: Handlers=mouse1 event4
B: EV=7
B: KEY=70000 0 0 0 0 0 0 0 0
B: REL=103

Utilizaremos las líneas marcadas en negrita, los dispositivos cuyo primer handler es kbd (y su descripción diga que son teclados) son teclados y aquellos cuyo primer handler es mouseN obviamente son mouses.

Interpretaremos esta información de la siguiente manera:

  • El dispositivo de cada teclado es /dev/input/eventN con el N indicado en Handlers para cada teclado (en el ejemplo /dev/input/event2)
  • El dispositivo de cada mouse es /dev/input/mouseN con el N indicado en Handlers para cada mouse (en el ejemplo /dev/input/mouse0 y /dev/input/mouse1 mouses son utilizables)

De esta manera podemos configurar los siguientes dispositivos:

Section "InputDevice"
	Identifier	"KeyboardN"
	Driver		"evdev"		# Utilizamos evdev porque kbd no soporta múltiples dispositivos
	Option		"Device"	"/dev/input/event2"
	Option		"XkbModel"	"evdev" # Debemos indicar evdev como modelo también
	Option		"CoreKeyboard"
	Option		"XkbRules"	"xorg"
	Option		"XkbLayout"	"es"
EndSection

Section "InputDevice"
	Identifier	"Mouse0"
	Driver		"mouse"
	Option		"CorePointer"
	Option		"Device"		"/dev/input/mouse0"
	Option		"Protocol"		"imPS/2"
	Option		"Buttons"		"5"
	Option		"ZAxisMapping"		"4 5"
EndSection

Section "InputDevice"
	Identifier	"Mouse1"
	Driver		"mouse"
	Option		"CorePointer"
	Option		"Device"		"/dev/input/mouse1"
	Option		"Protocol"		"imPS/2"
	Option		"Buttons"		"5"
	Option		"ZAxisMapping"		"4 5"
EndSection
 

Placas de vídeo

Precisamos conocer el BusId y controlador de cada placa, para esto escribimos el siguiente comando

# lspci | grep VGA
06:00.0 VGA compatible controller: nVidia Corporation GeForce 7300 GS (rev a1)

Este comando retorna el BusId con el formato XX:XX.X en hexadecimal, para la configuración de Xorg tendremos que convertir los números a decimal y separar todo con ":" para que quede de la forma XX:XX:X o podemos utilizar el comando "X -scanpci"

# X -scanpci

entre otras lineas el comando muestra

(6:0:0) unknown card (0x1462/0x0345) using an unknown chip (DeviceId 0x01df) from nVidia Corporation

por lo que nuestro BusId es PCI:6:0:0

El driver va a depender de la marca y el modelo de nuestras placas, en este caso el driver nv es el apropiado.

La configuración de la placa de vídeo quedaría así en este ejemplo:

Section "Device"
	Identifier  "TarjetaN"
	Driver      "nv"
	BusID       "PCI:6:0:0"
	Option      "NoInt10"       "Yes" # Anulamos la inicialización de la placa por BIOS
	Option      "DDCMode" "True"
	Option      "MonitorLayout" "CRT, CRT"
EndSection
 

Nota: Preferentemente no usar el driver VESA en ningún dispositivo ya que puede no funcionar correctamente Xinerama y no se puede especificar el BusId para indicar a que dispositivo hacemos referencia.

Configuraciones

Configuración de Xorg

  • Ejemplo de xorg.conf:
Section "Files"
#       FontPath     "unix/:7100"
    RgbPath         "/usr/X11R6/lib/X11/rgb"
EndSection

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

# --- Desde aquí hay que repetir estas secciones tantas veces como terminales querramos ---
# --- cambiando los identificadores y las características del hardware según sea necesario ---
# Teclados
Section "InputDevice"
	Identifier	"Keyboard0"
	Driver		"evdev"
	Option		"Device"	"/dev/input/event0" # Cambiar event0 por lo que corresponda
	Option		"XkbModel"	"evdev"
	Option		"CoreKeyboard"
	Option		"XkbRules"	"xorg"
	Option		"XkbLayout"	"es"
EndSection

Section "InputDevice"
	Identifier	"Mouse"
	Driver		"mouse"
	Option		"CorePointer"
	Option		"Device"		"/dev/input/mouse0" # Cambiar mouse0 por lo que corresponda
	Option		"Protocol"		"imPS/2"
	Option		"Buttons"		"5"
	Option		"ZAxisMapping"		"4 5"
EndSection

Section "Device"
	Identifier  "Tarjeta0"
	Driver      "ati"
	BusID       "PCI:1:0:0"
	Option      "NoInt10"       "Yes" # Anulamos la inicialización de la placa por BIOS
	Option      "DDCMode" "True"
	Option      "MonitorLayout" "CRT, CRT"
EndSection

Section "Monitor"
	Identifier	"Monitor0"
	Option		"DPMS"
	HorizSync	30-70
	VertRefresh	50-160
EndSection

Section "Screen"
	Identifier  "Screen0"
	Device      "Tarjeta0"
	Monitor     "Monitor0"
	DefaultDepth	24
		Depth   24
		Modes		"1024x768" "800x600" "640x480"
	EndSubSection
EndSection

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

# --- De aquí en más lo que sigue no hay que repetirlo ---

# Este layout puede ser utilizado para probar las placas usando Xinerama
Section "ServerLayout"
      Identifier      "Xinerama"
      Screen          "Screen0" 0 0
      Screen		      "Screen1" RightOf "Screen0"
      Screen		      "Screen2" RightOf "Screen1"
      ...
      InputDevice     "Keyboard0" "SendCoreEvents"
      InputDevice     "Mouse0" "SendCoreEvents"
      Option          "Xinerama" "on"
EndSection

Section "DRI"
	Mode	0666
EndSection
 

Inicializando las placas de vídeo

Precisaremos una copia de esta configuración para inicializar las placas de vídeo. Copiamos la configuración realizada a /etc/X11/xorg.conf.probe, borrando todos los ServerLayout excepto el que usa Xinerama y enumera a todos los Devices, además modificamos para cada Device la opción "NoInt10" a "No" como se muestra a continuación.

Section "Device"
	Identifier  "Tarjeta0"
	Driver      "ati"
	BusID       "PCI:1:0:0"
	Option      "NoInt10"       "No" # Habilitamos la inicialización de la placa por BIOS
	Option      "DDCMode" "True"
	Option      "MonitorLayout" "CRT, CRT"
EndSection
 

Para inicializar todos los Devices cada vez que el equipo arranca debemos escribir un script en /etc/init.d/xorg-multiterminal

#!/bin/bash
file=/etc/X11/xorg.conf.probe
echo Configurando Xorg para MultiHead
/usr/X11R6/bin/X -config "$file" -probeonly 2>/dev/null

le cambiamos los permisos con

chmod 755 /etc/init.d/xorg-multiterminal

y agregamos los links en el runlevel correspondiente con

update-rc.d xorg-multiterminal start 70 S .

(notar que el comando termina con un '.')

Probando las configuraciones

Inicializamos el hardware

# /etc/init.d/xorg-multiterminal start

Probamos los dispositivos de a uno

# startx -- -layout Layout0
# startx -- -layout Layout1
...

Si funcionan pasamos a probar todos al mismo tiempo con Xinerama (esta es la parte divertida)

# startx -- -layout Xinerama

Configurando GDM

Para que GDM utilice todos los display por defecto tenemos que agregar las siguientes lineas en el archivo /etc/gdm/gdm.conf reemplazando el argumento de isolateDevice por el "BusId" de cada dispositivo

### Configuración del Servidor ###
[servers]
0=Server0
1=Server1
...

### Configuración por terminal ###
[server-Server0]
name=Server 0
command=/usr/X11R6/bin/X -novtswitch -sharevts -isolateDevice PCI:x:y:z -layout Layout0
flexible=true

[server-Server1]
name=Server 1
command=/usr/X11R6/bin/X -novtswitch -sharevts -isolateDevice PCI:p:q:t -layout Layout1
flexible=true
...

Enlaces

Multiterminales con Xorg

Multiterminal en Wikipedia

 Ante cualquier duda o inconveniente no dudes en visitar nuestros foros.
 http://lihuen.linti.unlp.edu.ar/foros