# 
# Dual-head dual-user patch for xorg-x11 (or multi-head multi-user, if you
# prefer that). Based on the work of Miguel Freitas and others.
# Look at http://cambuca.ldhs.cetuc.puc-rio.br/multiuser/ for detailed
# information on how to use this.
#
# Modified for xorg-x11-6.8.1 by Jan "Yenya" Kasprzak <kas@fi.muni.cz>
#
# KNOWN BUGS:
# - Keyboard LED support is still buggy and unfinished.
# - on my setup it destroys font on the text console or something like that.
#   I have no time to investigate this and I don't use text console on this
#   box (except for booting).
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86Config.c xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86Config.c
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86Config.c	2004-08-16 22:17:51.000000000 +0200
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86Config.c	2004-11-19 21:49:47.000000000 +0100
@@ -1195,6 +1195,16 @@
 	     return FALSE;
      }
 #endif
+  } else if (xf86NameCmp(s, "usbev") == 0) {
+     xf86Info.kbdProc    = xf86KbdProc;
+     xf86Info.kbdEvents  = xf86USBKbdEvents;
+     xf86Msg(X_CONFIG, "Keyboard: Protocol: usbev\n");
+     s = xf86SetStrOption(inputp->commonOptions, "Device", "/dev/input/event0");
+     xf86Info.kbdFd = open(s, O_RDWR | O_NONBLOCK | O_EXCL);
+     if (xf86Info.kbdFd == -1) {
+       xf86ConfigError("Keyboard device: cannot open \"%s\"", s);
+       return FALSE;
+     }
   } else {
     xf86ConfigError("\"%s\" is not a valid keyboard protocol name", s);
     xfree(s);
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86Globals.c xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86Globals.c
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86Globals.c	2004-07-06 16:37:47.000000000 +0200
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86Globals.c	2004-11-19 21:49:47.000000000 +0100
@@ -245,3 +245,6 @@
  * only to be used when using dlopen() modules for debugging purposes.
  */
 #endif
+
+Bool xf86NoVTSwitches = FALSE;
+Bool xf86NoPCIAccessDisable = FALSE;
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86Init.c xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86Init.c
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86Init.c	2004-11-18 22:19:31.000000000 +0100
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86Init.c	2004-11-19 21:49:47.000000000 +0100
@@ -1429,6 +1429,28 @@
     xf86ProbeOnly = TRUE;
     return 1;
   }
+  if (!strcmp(argv[i],"-delay"))
+  {
+    int delay;
+
+    if (!argv[i + 1] || (delay = atoi(argv[i + 1])) <= 0) {
+      sleep(10);
+      return 1;
+    } else {
+      sleep((unsigned) delay);
+      return 2;
+    }
+  }
+  if (!strcmp(argv[i],"-novtswitches"))
+  {
+    xf86NoVTSwitches = TRUE;
+    return 1;
+  }
+  if (!strcmp(argv[i],"-nopciaccessdisable"))
+  {
+    xf86NoPCIAccessDisable = TRUE;
+    return 1;
+  }
   if (!strcmp(argv[i],"-flipPixels"))
   {
     xf86FlipPixels = TRUE;
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c	2004-11-18 22:19:29.000000000 +0100
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c	2004-11-19 21:49:47.000000000 +0100
@@ -606,6 +606,9 @@
 static void
 pciIoAccessDisable(void* arg)
 {
+    if (xf86NoPCIAccessDisable)
+	return;
+
 #ifdef DEBUG
     ErrorF("pciIoAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
 #endif
@@ -628,6 +631,9 @@
 static void
 pciIo_MemAccessDisable(void* arg)
 {
+    if (xf86NoPCIAccessDisable)
+	return;
+
 #ifdef DEBUG
     ErrorF("pciIo_MemAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
 #endif
@@ -650,6 +656,9 @@
 static void
 pciMemAccessDisable(void* arg)
 {
+    if (xf86NoPCIAccessDisable)
+	return;
+
 #ifdef DEBUG
     ErrorF("pciMemAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
 #endif
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86Priv.h xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86Priv.h
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86Priv.h	2004-01-29 09:08:26.000000000 +0100
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86Priv.h	2004-11-19 21:49:47.000000000 +0100
@@ -115,6 +115,9 @@
 
 extern RootWinPropPtr *xf86RegisteredPropertiesTable;
 
+extern Bool xf86NoVTSwitches;
+extern Bool xf86NoPCIAccessDisable;
+
 #ifndef DEFAULT_VERBOSE
 #define DEFAULT_VERBOSE		0
 #endif
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86Privstr.h xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86Privstr.h
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/common/xf86Privstr.h	2004-01-29 09:08:26.000000000 +0100
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/common/xf86Privstr.h	2004-11-19 21:49:47.000000000 +0100
@@ -82,6 +82,7 @@
     int			bell_pitch;
     int			bell_duration;
     Bool		autoRepeat;
+    int			ledsave;
     unsigned long	leds;
     unsigned long	xleds;
     char *		vtinit;
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_init.c xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_init.c
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_init.c	2004-04-23 21:54:08.000000000 +0200
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_init.c	2004-11-19 21:49:47.000000000 +0100
@@ -121,22 +121,35 @@
 		FatalError(
 		    "xf86OpenConsole: Cannot open /dev/tty0 (%s)\n",
 		    strerror(errno));
-	    if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) ||
-		(xf86Info.vtno == -1)) {
-		FatalError("xf86OpenConsole: Cannot find a free VT\n");
+
+	    if (xf86NoVTSwitches) {
+		if (ioctl(fd, VT_GETSTATE, &vts) == 0)
+		{
+		    xf86Info.vtno = vts.v_active;
+		} else {
+		    FatalError("xf86OpenConsole: Cannot find the current VT\n");
+		}
+	    } else {
+		if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) ||
+		    (xf86Info.vtno == -1)) {
+		    FatalError("xf86OpenConsole: Cannot find a free VT\n");
+		}
 	    }
+
 	    close(fd);
 	}
 
 #ifdef USE_DEV_FB
-	fb_dev_name=getenv("FRAMEBUFFER");
-	if (!fb_dev_name)
-	    fb_dev_name="/dev/fb0current";
-	if ((fbfd = open(fb_dev_name, O_RDONLY)) < 0)
-	    FatalError("xf86OpenConsole: Cannot open %s (%s)\n",
-	fb_dev_name, strerror(errno));
-	if (ioctl(fbfd, FBIOGET_VSCREENINFO, &var))
-	    FatalError("xf86OpenConsole: Unable to get screen info\n");
+	if (!xf86NoVTSwitches) {
+	    fb_dev_name=getenv("FRAMEBUFFER");
+	    if (!fb_dev_name)
+		fb_dev_name="/dev/fb0current";
+	    if ((fbfd = open(fb_dev_name, O_RDONLY)) < 0)
+		FatalError("xf86OpenConsole: Cannot open %s (%s)\n",
+	    fb_dev_name, strerror(errno));
+	    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &var))
+		FatalError("xf86OpenConsole: Unable to get screen info\n");
+	}
 #endif
 	xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
 
@@ -167,8 +180,12 @@
 		  "xf86OpenConsole: Could not save ownership of VT\n");
 	}
 
-	/* change ownership of the vt */
-	chown(vtname, getuid(), getgid());
+	/* humm, not a good idea if we don't really use this vt, chowning it would
+	   probably mess with the first XFree instance. Right? i don't know! */
+	if (!xf86NoVTSwitches) {
+	    /* change ownership of the vt */
+	    chown(vtname, getuid(), getgid());
+	}
 
 	/*
 	 * the current VT device we're running on is not "console", we want
@@ -213,37 +230,42 @@
 	{
 	    xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
 	}
-	SYSCALL(result = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT));
-	if (result < 0)
-	{
-	    FatalError("xf86OpenConsole: VT_GETMODE failed\n");
-	}
 
-	signal(SIGUSR1, xf86VTRequest);
+	if (xf86NoVTSwitches) {
+	    close(xf86Info.consoleFd);
+	} else {
+	    SYSCALL(result = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT));
+	    if (result < 0)
+	    {
+	        FatalError("xf86OpenConsole: VT_GETMODE failed\n");
+	    }
 
-	VT.mode = VT_PROCESS;
-	VT.relsig = SIGUSR1;
-	VT.acqsig = SIGUSR1;
-	if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
-	{
-	    FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n");
-	}
-	if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0)
-	{
-	    FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed\n");
-	}
+	    signal(SIGUSR1, xf86VTRequest);
+
+	    VT.mode = VT_PROCESS;
+	    VT.relsig = SIGUSR1;
+	    VT.acqsig = SIGUSR1;
+	    if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
+	    {
+	        FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n");
+	    }
+	    if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0)
+	    {
+	        FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed\n");
+	    }
 
-	/* we really should have a InitOSInputDevices() function instead
-	 * of Init?$#*&Device(). So I just place it here */
-	
+	    /* we really should have a InitOSInputDevices() function instead
+	     * of Init?$#*&Device(). So I just place it here */
+	    
 #ifdef USE_DEV_FB
-	/* copy info to new console */
-	var.yoffset=0;
-	var.xoffset=0;
-	if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &var))
-	    FatalError("Unable to set screen info\n");
-	close(fbfd);
+	    /* copy info to new console */
+	    var.yoffset=0;
+	    var.xoffset=0;
+	    if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &var))
+	        FatalError("Unable to set screen info\n");
+	    close(fbfd);
 #endif
+	}
     }
     else
     {
@@ -251,16 +273,18 @@
 	/*
 	 * now get the VT
 	 */
-	SYSCALL(result = ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno));
-	if (result != 0)
-	{
-	    xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
-	}
-	SYSCALL(result =
-		ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno));
-	if (result != 0)
-	{
-	    xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
+	if (!xf86NoVTSwitches) {
+	    SYSCALL(result = ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno));
+	    if (result != 0)
+	    {
+		xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
+	    }
+	    SYSCALL(result =
+		    ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno));
+	    if (result != 0)
+	    {
+		xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
+	    }
 	}
     }
     return;
@@ -275,22 +299,23 @@
     ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno);
     ioctl(xf86Info.consoleFd, VT_WAITACTIVE, 0);
 #endif
-    ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT);  /* Back to text mode ... */
-    if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
-    {
-	VT.mode = VT_AUTO;
-	ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* set dflt vt handling */
-    }
-    /*
-     * Perform a switch back to the active VT when we were started
-     */
-    if (activeVT >= 0)
-    {
-	ioctl(xf86Info.consoleFd, VT_ACTIVATE, activeVT);
-	activeVT = -1;
+    if (!xf86NoVTSwitches) {
+        ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT);  /* Back to text mode ... */
+        if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
+        {
+	    VT.mode = VT_AUTO;
+	    ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* set dflt vt handling */
+        }
+        /*
+         * Perform a switch back to the active VT when we were started
+         */
+        if (activeVT >= 0)
+        {
+	    ioctl(xf86Info.consoleFd, VT_ACTIVATE, activeVT);
+	    activeVT = -1;
+        }
+        close(xf86Info.consoleFd);                /* make the vt-manager happy */
     }
-    close(xf86Info.consoleFd);                /* make the vt-manager happy */
-
     restoreVtPerms();		/* restore the permissions */
 
     return;
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c	2004-04-23 21:54:08.000000000 +0200
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c	2004-11-19 21:49:47.000000000 +0100
@@ -33,12 +33,19 @@
 #include "xf86.h"
 #include "xf86Priv.h"
 #include "xf86_OSlib.h"
+#include <linux/input.h>
+#include <linux/kd.h>
 
 #define KBC_TIMEOUT 250        /* Timeout in ms for sending to keyboard controller */
 
 void
 xf86SoundKbdBell(int loudness, int pitch, int duration)
 {
+	/* i guess it should be safe to beep even on a diferent keyboard (?) */
+	/* the beep will be on the system speaker anyway... */
+	if (xf86Info.kbdEvents == xf86USBKbdEvents)
+		return;
+
 	if (loudness && pitch)
 	{
 		ioctl(xf86Info.consoleFd, KDMKTONE,
@@ -51,7 +58,35 @@
 void
 xf86SetKbdLeds(int leds)
 {
- 	ioctl(xf86Info.consoleFd, KDSETLED, leds);
+	struct s_output_event {
+	       struct timeval time;
+	       unsigned short type;
+	       unsigned short code;
+	       unsigned int value;
+	} output_event;
+
+	fprintf(stderr, "xf86SetKbdLeds(0x%x) called\n", leds);
+	if (xf86Info.kbdEvents != xf86USBKbdEvents) {
+		ioctl(xf86Info.consoleFd, KDSETLED, leds);
+		return;
+	}
+
+	output_event.type = EV_LED;
+	output_event.code = LED_NUML;
+	output_event.value = (leds&(LED_NUM)) ? 1 : 0;
+	write( xf86Info.kbdFd, (char *)&output_event, sizeof(output_event));
+
+	output_event.type = EV_LED;
+	output_event.code = LED_CAPSL;
+	output_event.value = (leds&(LED_CAP)) ? 1 : 0;
+	write( xf86Info.kbdFd, (char *)&output_event, sizeof(output_event));
+
+	output_event.type = EV_LED;
+	output_event.code = LED_SCROLLL;
+	output_event.value = (leds&(LED_SCR)) ? 1 : 0;
+	write( xf86Info.kbdFd, (char *)&output_event, sizeof(output_event));
+
+	xf86Info.ledsave = leds;
 }
 
 int
@@ -59,7 +94,13 @@
 {
 	int leds = 0;
 
- 	ioctl(xf86Info.consoleFd, KDGETLED, &leds);
+	if (xf86Info.kbdEvents == xf86USBKbdEvents) {
+		leds = xf86Info.ledsave;
+	} else {
+		ioctl(xf86Info.consoleFd, KDGETLED, &leds);
+	}
+
+	fprintf(stderr, "xf86GetKbdLeds called, returing 0x%x\n", leds);
 	return(leds);
 }
 
@@ -173,6 +214,10 @@
   if (xf86Info.kbdDelay >= 0)
     delay = xf86Info.kbdDelay;
 
+  /* FIXME: just returning so we don't mess with any other keyboards... */
+  if (xf86Info.kbdEvents == xf86USBKbdEvents)
+    return;
+
   if(KDKBDREP_ioctl_ok(rate, delay)) 	/* m68k? */
     return;
 
@@ -223,14 +268,24 @@
 void
 xf86KbdInit()
 {
-	ioctl (xf86Info.consoleFd, KDGKBMODE, &kbdtrans);
-	tcgetattr (xf86Info.consoleFd, &kbdtty);
+	if (xf86Info.kbdEvents == xf86USBKbdEvents) {
+		int data;
+		data=1;
+		if (ioctl(xf86Info.kbdFd, EVIOCGRAB, &data) == 0)
+			printf("exclusive access granted");
+	} else {
+		ioctl (xf86Info.consoleFd, KDGKBMODE, &kbdtrans);
+		tcgetattr (xf86Info.consoleFd, &kbdtty);
+	}
 }
 
 int
 xf86KbdOn()
 {
 	struct termios nTty;
+ 
+	if (xf86Info.kbdEvents == xf86USBKbdEvents)
+		return(xf86Info.kbdFd);
 
 #ifdef __powerpc__
 	if (xf86Info.kbdCustomKeycodes)
@@ -255,6 +310,9 @@
 int
 xf86KbdOff()
 {
+	if (xf86Info.kbdEvents == xf86USBKbdEvents)
+		return(xf86Info.kbdFd);
+
 	ioctl(xf86Info.consoleFd, KDSKBMODE, kbdtrans);
 	tcsetattr(xf86Info.consoleFd, TCSANOW, &kbdtty);
 	return(xf86Info.consoleFd);
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c	2004-04-23 21:54:08.000000000 +0200
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c	2004-11-19 21:49:47.000000000 +0100
@@ -22,11 +22,13 @@
 #include "xf86OSKbd.h"
 #include "atKeynames.h"
 #include "lnx_kbd.h"
+#include <linux/input.h>
 
 #define KBC_TIMEOUT 250        /* Timeout in ms for sending to keyboard controller */
 
 static KbdProtocolRec protocols[] = {
    {"standard", PROT_STD },
+   {"usbev", PROT_USB },
    { NULL, PROT_UNKNOWN_KBD }
 };
 
@@ -76,6 +78,45 @@
     ioctl(pInfo->fd, KDSETLED, real_leds);
 }
 
+static void
+SetUSBKbdLeds(InputInfoPtr pInfo, int leds)
+{
+    struct s_output_event {
+           struct timeval time;
+           unsigned short type;
+           unsigned short code;
+           unsigned int value;
+    } output_event;
+    int real_leds = 0;
+    fprintf(stderr, "SetUSBKbdLeds called with leds=0x%x\n", leds);
+    fprintf(stderr, "CAP=0x%x, NUM=0x%x, SCR=0x%x\n", LED_CAP, LED_NUM, LED_SCR);
+#ifdef LED_CAP
+    if (leds & XLED1)  real_leds |= LED_CAP;
+    if (leds & XLED2)  real_leds |= LED_NUM;
+    if (leds & XLED3)  real_leds |= LED_SCR;
+#ifdef LED_COMP
+    if (leds & XLED4)  real_leds |= LED_COMP;
+#else
+    if (leds & XLED4)  real_leds |= LED_SCR;
+#endif
+#endif
+    output_event.type = EV_LED;
+    output_event.code = LED_NUML;
+    output_event.value = (leds&(LED_NUM)) ? 1 : 0;
+    write(pInfo->fd, (char *)&output_event, sizeof(output_event));
+
+    output_event.type = EV_LED;
+    output_event.code = LED_CAPSL;
+    output_event.value = (leds&(LED_CAP)) ? 1 : 0;
+    write(pInfo->fd, (char *)&output_event, sizeof(output_event));
+
+    output_event.type = EV_LED;
+    output_event.code = LED_SCROLLL;
+    output_event.value = (leds&(LED_SCR)) ? 1 : 0;
+    write(pInfo->fd, (char *)&output_event, sizeof(output_event));
+
+    xf86Info.ledsave = leds;
+}
 static int
 GetKbdLeds(InputInfoPtr pInfo)
 {
@@ -87,6 +128,7 @@
     if (real_leds & LED_NUM) leds |= XLED2;
     if (real_leds & LED_SCR) leds |= XLED3;
 
+    fprintf(stderr, "GetKbdLeds called, returing 0x%x\n", leds);
     return(leds);
 }
 
@@ -442,6 +484,62 @@
        }
 }
 
+static unsigned short x86_keycodes[256] =
+       { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+        16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+        48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+        64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+        80, 81, 82, 83, 43, 85, 86, 87, 88,115,119,120,121,375,123, 90,
+       284,285,309,311,312, 91,327,328,329,331,333,335,336,337,338,339,
+       367,294,293,286,350, 92,334,512,116,377,109,111,373,347,348,349,
+       360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355,
+       103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361,
+       291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114,
+       118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269,
+       271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307,
+       308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330,
+       332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 };
+
+static void handle_scancode(InputInfoPtr pInfo, int code, int down)
+{
+    KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+    pKbd->PostEvent(pInfo, code & 0x7f, down);
+}
+    	
+	
+static void
+usbReadInput(InputInfoPtr pInfo)
+{
+    struct input_event {
+           struct timeval time;
+           unsigned short type;
+           unsigned short code;
+           unsigned int value;
+    } ev;
+
+    int nBytes;
+    if ((nBytes = read( pInfo->fd, (char *)&ev, sizeof(ev))) > 0) {
+       if (ev.type == EV_KEY) {
+          unsigned int keycode = ev.code;
+	  
+	  if (keycode > 255 || !x86_keycodes[keycode])
+	  	return;
+
+	  if (keycode == KEY_PAUSE) {
+	  	handle_scancode(pInfo, 0xe1, 1);
+		handle_scancode(pInfo, 0x1d, ev.value);
+		handle_scancode(pInfo, 0x45, ev.value);
+	  	return;
+	  }
+	  if (x86_keycodes[keycode] & 0x100)
+		  handle_scancode(pInfo, 0xe0, 1);
+
+	  handle_scancode(pInfo, x86_keycodes[keycode] & 0x7f, ev.value);
+       }
+    }
+}
+
 static Bool
 OpenKeyboard(InputInfoPtr pInfo)
 {
@@ -449,6 +547,7 @@
     int i;
     KbdProtocolId prot = PROT_UNKNOWN_KBD;
     char *s;
+    int flag = O_RDONLY;
 
     s = xf86SetStrOption(pInfo->options, "Protocol", NULL);
     for (i = 0; protocols[i].name; i++) {
@@ -461,6 +560,12 @@
     switch (prot) {
         case PROT_STD:
            pInfo->read_input = stdReadInput;
+           pKbd->SetLeds = SetKbdLeds;
+           break;
+	case PROT_USB:
+           pInfo->read_input = usbReadInput;
+           pKbd->SetLeds = SetUSBKbdLeds;
+	   flag = O_RDWR;
            break;
         default:
            xf86Msg(X_ERROR,"\"%s\" is not a valid keyboard protocol name\n", s);
@@ -476,7 +581,7 @@
        pInfo->fd = xf86Info.consoleFd;
        pKbd->isConsole = TRUE;
     } else {
-       pInfo->fd = open(s, O_RDONLY | O_NONBLOCK | O_EXCL);
+       pInfo->fd = open(s, flag | O_NONBLOCK | O_EXCL);
        if (pInfo->fd == -1) {
            xf86Msg(X_ERROR, "%s: cannot open \"%s\"\n", pInfo->name, s);
            xfree(s);
@@ -501,7 +606,6 @@
     pKbd->KbdOn         = KbdOn;
     pKbd->KbdOff        = KbdOff;
     pKbd->Bell          = SoundBell;
-    pKbd->SetLeds       = SetKbdLeds;
     pKbd->GetLeds       = GetKbdLeds;
     pKbd->SetKbdRepeat  = SetKbdRepeat;
     pKbd->KbdGetMapping = KbdGetMapping;
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/shared/std_kbdEv.c xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/shared/std_kbdEv.c
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/shared/std_kbdEv.c	2004-04-23 21:54:12.000000000 +0200
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/shared/std_kbdEv.c	2004-11-19 21:49:47.000000000 +0100
@@ -25,10 +25,53 @@
  */
 /* $XConsortium: std_kbdEv.c /main/4 1996/03/11 10:47:33 kaleb $ */
 
+/* 2001/01/14 Miguel Freitas <miguel@cetuc.puc-rio.br>
+ *
+ * USB Keyboard to PC-AT Keyboard HACK
+ *
+ * Included routines from Linux Kernel to handle usb keyboard events.
+ * I don't know if there are any license issues here. Any code written
+ * by me in this file is under the terms of the GNU General Public
+ * License as described below.
+ *
+*/
+
+/*
+ * $Id: keybdev.c,v 1.3 2000/05/28 17:31:36 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *
+ *  Input driver to keyboard driver binding.
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+
 #include "X.h"
 #include "xf86.h"
 #include "xf86Priv.h"
 #include "xf86_OSlib.h"
+#include <linux/input.h>
 
 void
 xf86KbdEvents()
@@ -44,3 +87,68 @@
 	}
 }
 
+static unsigned short x86_keycodes[256] =
+	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+	 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+	 80, 81, 82, 83, 43, 85, 86, 87, 88,115,119,120,121,375,123, 90,
+	284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
+	367,294,293,286,350, 92,334,512,116,377,109,111,373,347,348,349,
+	360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355,
+	103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361,
+	291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114,
+	118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269,
+	271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307,
+	308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330,
+	332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 };
+
+static void handle_scancode(unsigned char scancode, int down)
+{
+        char up_flag = down ? 0 : 0200;
+
+        xf86PostKbdEvent(scancode | up_flag);
+}
+
+static int emulate_raw(unsigned int keycode, int down)
+{
+	if (keycode > 255 || !x86_keycodes[keycode])
+		return -1; 
+
+	if (keycode == KEY_PAUSE) {
+		handle_scancode(0xe1, 1);
+		handle_scancode(0x1d, down);
+		handle_scancode(0x45, down);
+		return 0;
+	} 
+
+	if (x86_keycodes[keycode] & 0x100)
+		handle_scancode(0xe0, 1);
+
+	handle_scancode(x86_keycodes[keycode] & 0x7f, down);
+
+	if (keycode == KEY_SYSRQ) {
+		handle_scancode(0xe0, 1);
+		handle_scancode(0x37, down);
+	}
+
+	return 0;
+}
+
+void
+xf86USBKbdEvents()
+{
+	struct input_event {
+	       struct timeval time;
+	       unsigned short type;
+	       unsigned short code;
+	       unsigned int value;
+	} ev;
+
+	int nBytes;
+
+	while ((nBytes = read(xf86Info.kbdFd, (char *)&ev, sizeof(ev))) > 0)
+	    if (ev.type == EV_KEY)
+		emulate_raw(ev.code, ev.value);
+}
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/shared/VTsw_usl.c xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/shared/VTsw_usl.c
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/shared/VTsw_usl.c	2004-04-23 21:54:12.000000000 +0200
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/shared/VTsw_usl.c	2004-11-19 21:49:47.000000000 +0100
@@ -41,6 +41,9 @@
 void
 xf86VTRequest(int sig)
 {
+	if (xf86NoVTSwitches)
+		return;
+
 	signal(sig, (void(*)(int))xf86VTRequest);
 	xf86Info.vtRequestsPending = TRUE;
 	return;
@@ -49,12 +52,15 @@
 Bool
 xf86VTSwitchPending()
 {
-    return(xf86Info.vtRequestsPending ? TRUE : FALSE);
+    	return(!xf86NoVTSwitches && xf86Info.vtRequestsPending ? TRUE : FALSE);
 }
 
 Bool
 xf86VTSwitchAway()
 {
+	if (xf86NoVTSwitches)
+		return FALSE;
+
 	xf86Info.vtRequestsPending = FALSE;
 	if (ioctl(xf86Info.consoleFd, VT_RELDISP, 1) < 0)
 	{
@@ -69,6 +75,9 @@
 Bool
 xf86VTSwitchTo()
 {
+	if (xf86NoVTSwitches)
+		return TRUE;
+
 	xf86Info.vtRequestsPending = FALSE;
 	if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0)
 	{
diff -uNr xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/xf86_OSproc.h xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/xf86_OSproc.h
--- xorg-x11-6.8.1-rhbuild/xc/programs/Xserver/hw/xfree86/os-support/xf86_OSproc.h	2004-04-23 21:54:07.000000000 +0200
+++ xorg-x11-6.8.1/xc/programs/Xserver/hw/xfree86/os-support/xf86_OSproc.h	2004-11-19 21:49:47.000000000 +0100
@@ -229,6 +229,7 @@
 extern int xf86KbdOn(void);
 extern int xf86KbdOff(void);
 extern void xf86KbdEvents(void);
+extern void xf86USBKbdEvents(void);
 #ifdef XQUEUE
 extern int  xf86XqueKbdProc(DeviceIntPtr, int);
 extern void xf86XqueEvents(void);
