Sophie

Sophie

distrib > Mandriva > 2007.1 > x86_64 > by-pkgid > e9d7306cbb3d13290c9b1281bcbf9c3a > files > 4

x11-server-1.2.0-9.1mdv2007.1.src.rpm

From b061edca8111be033a3505bfb3f45509eafec123 Mon Sep 17 00:00:00 2001
From: C3SL UFPR <boiko@new-host.(none)>
Date: Mon, 3 Jul 2006 15:16:55 +0200
Subject: [PATCH] Xephyr evdev support

Add support for evdev in kdrive/Xephyr. This is used by multi-head/multi-seat
projects. It has been developed by researchers at C3SL.
---
 hw/kdrive/ephyr/ephyr.c     |    6 +
 hw/kdrive/ephyr/ephyr.h     |    1 
 hw/kdrive/ephyr/ephyrinit.c |   21 ++
 hw/kdrive/ephyr/hostx.c     |   31 +++
 hw/kdrive/ephyr/hostx.h     |    6 +
 hw/kdrive/linux/evdev.c     |  385 ++++++++++++++++++++++++++++++++++++++++++-
 hw/kdrive/src/kdrive.c      |    9 +
 hw/kdrive/src/kdrive.h      |    4 
 hw/kdrive/src/kinput.c      |    2 
 9 files changed, 448 insertions(+), 17 deletions(-)

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index a9ea0eb..d0a687f 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -436,7 +436,8 @@ ephyrRandRGetInfo (ScreenPtr pScreen, Ro
   *rotations = RR_Rotate_All|RR_Reflect_All;
   
   if (!hostx_want_preexisting_window()
-      && !hostx_want_fullscreen()) /* only if no -parent switch */
+      && !hostx_want_fullscreen()
+      && !hostx_want_user_geometry()) /* only if no -parent switch */
     {
       while (sizes[n].width != 0 && sizes[n].height != 0)
 	{
@@ -745,6 +746,9 @@ ephyrPoll(void)
 
   while (hostx_get_event(&ev))
     {
+      if (use_evdev)
+        continue;
+	
       switch (ev.type)
 	{
 	case EPHYR_EV_MOUSE_MOTION:
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
index 707cb01..d059c8b 100644
--- a/hw/kdrive/ephyr/ephyr.h
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -69,6 +69,7 @@ typedef struct _ephyrScrPriv {
 } EphyrScrPriv;
 
 extern KdCardFuncs  ephyrFuncs;
+extern int use_evdev;
 
 Bool
 ephyrInitialize (KdCardInfo *card, EphyrPriv *priv);
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index 58478e6..0d38692 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -28,6 +28,8 @@ #include <kdrive-config.h>
 #endif
 #include "ephyr.h"
 
+int use_evdev = FALSE;
+
 extern Window EphyrPreExistingHostWin;
 extern Bool   EphyrWantGrayScale;
 
@@ -51,7 +53,10 @@ InitOutput (ScreenInfo *pScreenInfo, int
 void
 InitInput (int argc, char **argv)
 {
-  KdInitInput (&EphyrMouseFuncs, &EphyrKeyboardFuncs);
+  if (use_evdev)
+    KdInitInput (&LinuxEvdevMouseFuncs, &LinuxEvdevKeyboardFuncs);
+  else
+    KdInitInput (&EphyrMouseFuncs, &EphyrKeyboardFuncs);
 }
 
 void
@@ -65,6 +70,7 @@ ddxUseMsg (void)
   ErrorF("-fullscreen   Attempt to run Xephyr fullscreen\n");
   ErrorF("-grayscale    Simulate 8bit grayscale\n");
   ErrorF("-fakexa	Simulate acceleration using software rendering\n");
+  ErrorF("-use-evdev  Use the evdev input driver\n");
   ErrorF("\n");
 
   exit(1);
@@ -109,10 +115,23 @@ ddxProcessArgument (int argc, char **arg
       ephyrFuncs.finiAccel = ephyrDrawFini;
       return 1;
     }
+  else if (!strcmp (argv[i], "-geometry"))
+    {
+      if(i+1 < argc) 
+	{
+	  hostx_use_user_geometry (argv[i+1]);
+	  return 2;
+	}
+    }
   else if (argv[i][0] == ':')
     {
       hostx_set_display_name(argv[i]);
     }
+  else if (!strcmp (argv[i], "-use-evdev"))
+    {
+      use_evdev = TRUE;
+      return 1;
+    }
 
   return KdProcessArgument (argc, argv, i);
 }
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index ae776a7..6dd2c14 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -59,9 +59,10 @@ struct EphyrHostXVars
   int             depth;
   int             server_depth;
   XImage         *ximg;
-  int             win_width, win_height;
+  int             win_width, win_height, win_x, win_y;
   Bool            use_host_cursor;
   Bool            use_fullscreen;
+  Bool            use_user_geometry;
   Bool            have_shm;
 
   long            damage_debug_msec;
@@ -73,7 +74,7 @@ struct EphyrHostXVars
 };
 
 /* memset ( missing> ) instead of below  */
-static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 
 static int            HostXWantDamageDebug = 0;
 
@@ -124,7 +125,8 @@ int
 hostx_want_screen_size(int *width, int *height)
 {
  if (HostX.win_pre_existing != None
-     || HostX.use_fullscreen == True)
+     || HostX.use_fullscreen == True
+     || HostX.use_user_geometry == True)
     {
       *width  = HostX.win_width;
       *height = HostX.win_height;
@@ -174,6 +176,21 @@ hostx_want_preexisting_window(void)
 }
 
 void
+hostx_use_user_geometry(char *geometry)
+{
+  if (XParseGeometry (geometry,
+		      &HostX.win_x, &HostX.win_y,
+		      &HostX.win_width, &HostX.win_height))
+    HostX.use_user_geometry = True;
+}
+
+int
+hostx_want_user_geometry(void)
+{
+  return HostX.use_user_geometry;
+}
+
+void
 hostx_use_fullscreen(void)
 {
   HostX.use_fullscreen = True;
@@ -456,6 +473,7 @@ hostx_screen_init (int width, int height
   int         bitmap_pad;
   Bool        shm_success = False;
   XSizeHints *size_hints;
+  XWindowChanges values;
 
   EPHYR_DBG("mark");
 
@@ -531,6 +549,13 @@ hostx_screen_init (int width, int height
 
   XResizeWindow(HostX.dpy, HostX.win, width, height);
 
+  if (HostX.use_user_geometry)
+    {
+      values.x = HostX.win_x;
+      values.y = HostX.win_y;
+      XConfigureWindow(HostX.dpy, HostX.win, CWX | CWY, &values);
+    }
+
   /* Ask the WM to keep our size static */
   size_hints = XAllocSizeHints();
   size_hints->max_width = size_hints->min_width = width;
diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h
index d3f6da3..4649e68 100644
--- a/hw/kdrive/ephyr/hostx.h
+++ b/hw/kdrive/ephyr/hostx.h
@@ -89,6 +89,12 @@ hostx_want_host_cursor(void);
 void
 hostx_use_host_cursor(void);
 
+int
+hostx_want_user_geometry(void);
+
+void
+hostx_use_user_geometry(char *);
+
 void
 hostx_use_fullscreen(void);
 
diff --git a/hw/kdrive/linux/evdev.c b/hw/kdrive/linux/evdev.c
index d83b13a..f7d4a59 100644
--- a/hw/kdrive/linux/evdev.c
+++ b/hw/kdrive/linux/evdev.c
@@ -31,9 +31,11 @@ #include <linux/input.h>
 #include <X11/X.h>
 #include <X11/Xproto.h>
 #include <X11/Xpoll.h>
+#include <X11/keysym.h>
 #include "inputstr.h"
 #include "scrnintstr.h"
 #include "kdrive.h"
+#include "kkeymap.h"
 
 #define NUM_EVENTS  128
 #define ABS_UNSET   -65535
@@ -105,9 +107,10 @@ EvdevRead (int evdevPort, void *closure)
 {
     KdMouseInfo		*mi = closure;
     Kevdev		*ke = mi->driver;
-    int			i;
+    int			i, j;
     struct input_event	events[NUM_EVENTS];
     int			n;
+    int                 flags;
 
     n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event));
     if (n <= 0)
@@ -115,22 +118,64 @@ EvdevRead (int evdevPort, void *closure)
     n /= sizeof (struct input_event);
     for (i = 0; i < n; i++)
     {
+	flags = KD_MOUSE_DELTA | kdMouseInfo->buttonState;
 	switch (events[i].type) {
 	case EV_SYN:
 	    break;
 	case EV_KEY:
-	    EvdevMotion (mi);
-	    ASSIGNBIT(ke->key,events[i].code, events[i].value);
-	    if (events[i].code < 0x100)
-		ErrorF ("key %d %d\n", events[i].code, events[i].value);
-	    else
-		ErrorF ("key 0x%x %d\n", events[i].code, events[i].value);
+	  if (events[i].code >= BTN_MOUSE && events[i].code < BTN_JOYSTICK) {
+	        switch (events[i].code) {
+		case BTN_LEFT:
+		  if (events[i].value == 1)
+		    flags |= KD_BUTTON_1;
+		  else
+		    flags &= ~KD_BUTTON_1;
+		  break;
+		case BTN_MIDDLE:
+		  if (events[i].value == 1)
+		    flags |= KD_BUTTON_2;
+		  else
+		    flags &= ~KD_BUTTON_2;
+		  break;
+		case BTN_RIGHT:
+		  if (events[i].value == 1)
+		    flags |= KD_BUTTON_3;
+		  else
+		    flags &= ~KD_BUTTON_3;
+		  break;
+		default:
+		  /* Unknow button */
+		  break;
+       	        }
+		KdEnqueueMouseEvent (kdMouseInfo, flags, 0, 0);
+	    }
 	    break;
 	case EV_REL:
-	    ke->rel[events[i].code] += events[i].value;
+	    if (events[i].code == REL_X) {
+	      KdEnqueueMouseEvent (kdMouseInfo, flags, events[i].value, 0);
+	    }
+	    else if (events[i].code == REL_Y) {
+	      KdEnqueueMouseEvent (kdMouseInfo, flags, 0, events[i].value);
+	    }
+	    else if (events[i].code == REL_WHEEL) {	      
+	      for (j = 0; j < abs (events[i].value); j++) {
+		if (events[i].value > 0)
+		  flags |= KD_BUTTON_4;
+		else
+		  flags |= KD_BUTTON_5;
+
+		KdEnqueueMouseEvent (kdMouseInfo, flags, 0, 0);
+
+		if (events[i].value > 0)
+		  flags &= ~KD_BUTTON_4;
+		else
+		  flags &= ~KD_BUTTON_5;
+
+		KdEnqueueMouseEvent (kdMouseInfo, flags, 0, 0);
+	      } /* events[i].code == REL_WHEEL */
+	    }
 	    break;
 	case EV_ABS:
-	    ke->abs[events[i].code] = events[i].value;
 	    break;
 	}
     }
@@ -173,6 +218,12 @@ EvdevInit (void)
 		fd = open (kdefaultEvdev[i], 2);
 		if (fd >= 0)
 		{
+                    if (ioctl (fd, EVIOCGRAB, 1) < 0)
+                    {
+                        close (fd);
+                        continue;
+                    }
+
 		    mi->name = KdSaveString (kdefaultEvdev[i]);
 		    break;
 		}
@@ -287,7 +338,319 @@ KdMouseFuncs LinuxEvdevMouseFuncs = {
     EvdevFini,
 };
 
-#if 0
+/* Keyboard */
+
+int kbd_fd = -1;
+int EvdevInputType = 0;
+
+KeySym evdevKeymap[(194 - 1 + 1) * 2] = {
+/* These are directly mapped from DOS scanset 0 */
+/*      1     8 */       XK_Escape, NoSymbol,
+/*      2     9 */       XK_1,  XK_exclam,
+/*      3    10 */       XK_2,  XK_at,
+/*      4    11 */       XK_3,  XK_numbersign,
+/*      5    12 */       XK_4,  XK_dollar,
+/*      6    13 */       XK_5,  XK_percent,
+/*      7    14 */       XK_6,  XK_asciicircum,
+/*      8    15 */       XK_7,  XK_ampersand,
+/*      9    16 */       XK_8,  XK_asterisk,
+/*     10    17 */       XK_9,  XK_parenleft,
+/*     11    18 */       XK_0,  XK_parenright,
+/*     12    19 */       XK_minus,      XK_underscore,
+/*     13    20 */       XK_equal,      XK_plus,
+/*     14    21 */       XK_BackSpace,  NoSymbol,
+/*     15    22 */       XK_Tab,        NoSymbol,
+/*     16    23 */       XK_Q,  NoSymbol,
+/*     17    24 */       XK_W,  NoSymbol,
+/*     18    25 */       XK_E,  NoSymbol,
+/*     19    26 */       XK_R,  NoSymbol,
+/*     20    27 */       XK_T,  NoSymbol,
+/*     21    28 */       XK_Y,  NoSymbol,
+/*     22    29 */       XK_U,  NoSymbol,
+/*     23    30 */       XK_I,  NoSymbol,
+/*     24    31 */       XK_O,  NoSymbol,
+/*     25    32 */       XK_P,  NoSymbol,
+/*     26    33 */       XK_bracketleft,        XK_braceleft,
+/*     27    34 */       XK_bracketright,       XK_braceright,
+/*     28    35 */       XK_Return,     NoSymbol,
+/*     29    36 */       XK_Control_L,  NoSymbol,
+/*     30    37 */       XK_A,  NoSymbol,
+/*     31    38 */       XK_S,  NoSymbol,
+/*     32    39 */       XK_D,  NoSymbol,
+/*     33    40 */       XK_F,  NoSymbol,
+/*     34    41 */       XK_G,  NoSymbol,
+/*     35    42 */       XK_H,  NoSymbol,
+/*     36    43 */       XK_J,  NoSymbol,
+/*     37    44 */       XK_K,  NoSymbol,
+/*     38    45 */       XK_L,  NoSymbol,
+/*     39    46 */       XK_semicolon,  XK_colon,
+/*     40    47 */       XK_apostrophe, XK_quotedbl,
+/*     41    48 */       XK_grave,      XK_asciitilde,
+/*     42    49 */       XK_Shift_L,    NoSymbol,
+/*     43    50 */       XK_backslash,  XK_bar,
+/*     44    51 */       XK_Z,  NoSymbol,
+/*     45    52 */       XK_X,  NoSymbol,
+/*     46    53 */       XK_C,  NoSymbol,
+/*     47    54 */       XK_V,  NoSymbol,
+/*     48    55 */       XK_B,  NoSymbol,
+/*     49    56 */       XK_N,  NoSymbol,
+/*     50    57 */       XK_M,  NoSymbol,
+/*     51    58 */       XK_comma,      XK_less,
+/*     52    59 */       XK_period,     XK_greater,
+/*     53    60 */       XK_slash,      XK_question,
+/*     54    61 */       XK_Shift_R,    NoSymbol,
+/*     55    62 */       XK_KP_Multiply,        NoSymbol,
+/*     56    63 */       XK_Alt_L,      XK_Meta_L,
+/*     57    64 */       XK_space,      NoSymbol,
+/*     58    65 */       XK_Caps_Lock,  NoSymbol,
+/*     59    66 */       XK_F1, NoSymbol,
+/*     60    67 */       XK_F2, NoSymbol,
+/*     61    68 */       XK_F3, NoSymbol,
+/*     62    69 */       XK_F4, NoSymbol,
+/*     63    70 */       XK_F5, NoSymbol,
+/*     64    71 */       XK_F6, NoSymbol,
+/*     65    72 */       XK_F7, NoSymbol,
+/*     66    73 */       XK_F8, NoSymbol,
+/*     67    74 */       XK_F9, NoSymbol,
+/*     68    75 */       XK_F10,        NoSymbol,
+/*     69    76 */       XK_Break,      XK_Pause,
+/*     70    77 */       XK_Scroll_Lock,        NoSymbol,
+/*     71    78 */       XK_KP_Home,    XK_KP_7,
+/*     72    79 */       XK_KP_Up,      XK_KP_8,
+/*     73    80 */       XK_KP_Page_Up, XK_KP_9,
+/*     74    81 */       XK_KP_Subtract,        NoSymbol,
+/*     75    82 */       XK_KP_Left,    XK_KP_4,
+/*     76    83 */       XK_KP_5,       NoSymbol,
+/*     77    84 */       XK_KP_Right,   XK_KP_6,
+/*     78    85 */       XK_KP_Add,     NoSymbol,
+/*     79    86 */       XK_KP_End,     XK_KP_1,
+/*     80    87 */       XK_KP_Down,    XK_KP_2,
+/*     81    88 */       XK_KP_Page_Down,       XK_KP_3,
+/*     82    89 */       XK_KP_Insert,  XK_KP_0,
+/*     83    90 */       XK_KP_Delete,  XK_KP_Decimal,
+/*     84    91 */     NoSymbol,        NoSymbol,
+/*     85    92 */     NoSymbol,        NoSymbol,
+/*     86    93 */     NoSymbol,        NoSymbol,
+/*     87    94 */       XK_F11,        NoSymbol,
+/*     88    95 */       XK_F12,        NoSymbol,
+
+/* These are remapped from the extended set (using ExtendMap) */
+
+/*     89    96 */       XK_Control_R,  NoSymbol,
+/*     90    97 */       XK_KP_Enter,   NoSymbol,
+/*     91    98 */       XK_KP_Divide,  NoSymbol,
+/*     92    99 */       XK_Sys_Req,    XK_Print,
+/*     93   100 */       XK_Alt_R,      XK_Meta_R,
+/*     94   101 */       XK_Num_Lock,   NoSymbol,
+/*     95   102 */       XK_Home,       NoSymbol,
+/*     96   103 */       XK_Up,         NoSymbol,
+/*     97   104 */       XK_Page_Up,    NoSymbol,
+/*     98   105 */       XK_Left,       NoSymbol,
+/*     99   106 */       XK_Right,      NoSymbol,
+/*    100   107 */       XK_End,        NoSymbol,
+/*    101   108 */       XK_Down,       NoSymbol,
+/*    102   109 */       XK_Page_Down,  NoSymbol,
+/*    103   110 */       XK_Insert,     NoSymbol,
+/*    104   111 */       XK_Delete,     NoSymbol,
+/*    105   112 */       XK_Super_L,    NoSymbol,
+/*    106   113 */       XK_Super_R,    NoSymbol,
+/*    107   114 */       XK_Menu,       NoSymbol,
+/*    108   115 */       NoSymbol,      NoSymbol,
+/*    109   116 */       NoSymbol,      NoSymbol,
+/*    110   117 */       NoSymbol,      NoSymbol,
+/*    111   118 */       NoSymbol,      NoSymbol,
+/*    112   119 */       NoSymbol,      NoSymbol,
+
+/*    113   120 */      NoSymbol,     NoSymbol,
+/*    114   121 */      NoSymbol,     NoSymbol,
+/*    115   122 */      NoSymbol,     NoSymbol,
+/*    116   123 */      NoSymbol,     NoSymbol,
+/*    117   124 */      NoSymbol,     NoSymbol,
+/*    118   125 */      NoSymbol,     NoSymbol,
+/*    119   126 */      NoSymbol,     NoSymbol,
+/*    120   127 */      NoSymbol,     NoSymbol,
+/*    121   128 */      NoSymbol,     NoSymbol,
+/*    122   129 */      NoSymbol,     NoSymbol,
+/*    123   130 */      NoSymbol,     NoSymbol,
+/*    124   131 */      NoSymbol,     NoSymbol,
+/*    125   132 */      NoSymbol,     NoSymbol,
+/*    126   133 */      NoSymbol,     NoSymbol,
+/*    127   134 */      NoSymbol,     NoSymbol,
+/*    128   135 */      NoSymbol,     NoSymbol,
+/*    129   136 */      NoSymbol,     NoSymbol,
+/*    130   137 */      NoSymbol,     NoSymbol,
+/*    131   138 */      NoSymbol,     NoSymbol,
+/*    132   139 */      NoSymbol,     NoSymbol,
+/*    133   140 */      NoSymbol,     NoSymbol,
+/*    134   141 */      NoSymbol,     NoSymbol,
+/*    135   142 */      NoSymbol,     NoSymbol,
+/*    136   143 */      NoSymbol,     NoSymbol,
+/*    137   144 */      NoSymbol,     NoSymbol,
+/*    138   145 */      NoSymbol,     NoSymbol,
+/*    139   146 */      NoSymbol,     NoSymbol,
+/*    140   147 */      NoSymbol,     NoSymbol,
+/*    141   148 */      NoSymbol,     NoSymbol,
+/*    142   149 */      NoSymbol,     NoSymbol,
+/*    143   150 */      NoSymbol,     NoSymbol,
+/*    144   151 */      NoSymbol,     NoSymbol,
+/*    145   152 */      NoSymbol,     NoSymbol,
+/*    146   153 */      NoSymbol,     NoSymbol,
+/*    147   154 */      NoSymbol,     NoSymbol,
+/*    148   155 */      NoSymbol,     NoSymbol,
+/*    149   156 */      NoSymbol,     NoSymbol,
+/*    150   157 */      NoSymbol,     NoSymbol,
+/*    151   158 */      NoSymbol,     NoSymbol,
+/*    152   159 */      NoSymbol,     NoSymbol,
+/*    153   160 */      NoSymbol,     NoSymbol,
+/*    154   161 */      NoSymbol,     NoSymbol,
+/*    155   162 */      NoSymbol,     NoSymbol,
+/*    156   163 */      NoSymbol,     NoSymbol,
+/*    157   164 */      NoSymbol,     NoSymbol,
+/*    158   165 */      NoSymbol,     NoSymbol,
+/*    159   166 */      NoSymbol,     NoSymbol,
+/*    160   167 */      NoSymbol,     NoSymbol,
+/*    161   168 */      NoSymbol,     NoSymbol,
+/*    162   169 */      NoSymbol,     NoSymbol,
+/*    163   170 */      NoSymbol,     NoSymbol,
+/*    164   171 */      NoSymbol,     NoSymbol,
+/*    165   172 */      NoSymbol,     NoSymbol,
+/*    166   173 */      NoSymbol,     NoSymbol,
+/*    167   174 */      NoSymbol,     NoSymbol,
+/*    168   175 */      NoSymbol,     NoSymbol,
+/*    169   176 */      NoSymbol,     NoSymbol,
+/*    170   177 */      NoSymbol,     NoSymbol,
+/*    171   178 */      NoSymbol,     NoSymbol,
+/*    172   179 */      NoSymbol,     NoSymbol,
+/*    173   180 */      NoSymbol,     NoSymbol,
+/*    174   181 */      NoSymbol,     NoSymbol,
+/*    175   182 */      NoSymbol,     NoSymbol,
+/*    176   183 */      NoSymbol,     NoSymbol,
+/*    177   184 */      NoSymbol,     NoSymbol,
+/*    178   185 */      NoSymbol,     NoSymbol,
+/*    179   186 */      NoSymbol,     NoSymbol,
+/*    180   187 */      NoSymbol,     NoSymbol,
+/*    181   188 */      NoSymbol,     NoSymbol,
+/*    182   189 */      NoSymbol,     NoSymbol,
+/*    183   190 */      NoSymbol,     NoSymbol,
+/*    184   191 */      NoSymbol,     NoSymbol,
+/*    185   192 */      NoSymbol,     NoSymbol,
+/*    186   193 */      NoSymbol,     NoSymbol,
+/*    187   194 */      NoSymbol,     NoSymbol,
+/*    188   195 */      NoSymbol,     NoSymbol,
+/*    189   196 */      NoSymbol,     NoSymbol,
+/*    190   197 */      NoSymbol,     NoSymbol,
+/*    191   198 */      NoSymbol,     NoSymbol,
+/*    192   199 */      NoSymbol,     NoSymbol,
+/*    193   200 */      NoSymbol,     NoSymbol,
+/*    194   201 */      NoSymbol,     NoSymbol,
+};
+
+static void
+EvdevKbdRead (int fd, void *closure)
+{
+    int i, n;
+    struct input_event events[NUM_EVENTS];
+
+    n = read (fd, &events, NUM_EVENTS * sizeof (struct input_event));
+    if (n <= 0)
+      return;
+
+    n /= sizeof (struct input_event);
+
+    for (i = 0; i < n; i++)
+    {
+        if (events[i].type == EV_KEY)
+      	    KdEnqueueKeyboardEvent (events[i].code, !events[i].value);
+    }
+}
+
+static void
+EvdevKbdLoad (void)
+{
+    kdMinScanCode = 0;
+    kdMaxScanCode = 193;
+    kdKeymapWidth = 2;
+    memcpy (kdKeymap, evdevKeymap, sizeof (evdevKeymap));
+}
+
+static int
+EvdevKbdInit (void)
+{
+    int fd, i;
+
+    if (!EvdevInputType)
+        EvdevInputType = KdAllocInputType ();
+
+    if (!kdKeyboard)
+    {
+        for (i = 0; i < NUM_DEFAULT_EVDEV; i++)
+        {
+            fd = open (kdefaultEvdev[i], 2);
+            if (fd >= 0)
+            {
+                kdKeyboard = KdSaveString (kdefaultEvdev[i]);
+                break;
+            }
+	}
+    }
+    else
+    {
+        fd = open (kdKeyboard, O_RDWR);
+        if (fd < 0)
+            return FALSE;
+    }
+
+    if (ioctl (fd, EVIOCGRAB, 1) < 0)
+    {
+        close (fd);
+	return FALSE;
+    }
+
+    if (!KdRegisterFd (EvdevInputType, fd, EvdevKbdRead, NULL))
+        return FALSE;
+
+    kbd_fd = fd;
+    return TRUE;
+}
+
+static void
+EvdevKbdFini (void)
+{
+}
+
+static void
+EvdevKbdLeds (int leds)
+{
+    struct input_event event;
+
+    memset(&event, 0, sizeof(event));
+
+    event.type = EV_LED;
+    event.code = LED_CAPSL;
+    event.value = leds & (1 << 0) ? 1 : 0;
+    write(kbd_fd, (char *) &event, sizeof(event));
+
+    event.type = EV_LED;
+    event.code = LED_NUML;
+    event.value = leds & (1 << 1) ? 1 : 0;
+    write(kbd_fd, (char *) &event, sizeof(event));
+
+    event.type = EV_LED;
+    event.code = LED_SCROLLL;
+    event.value = leds & (1 << 2) ? 1 : 0;
+    write(kbd_fd, (char *) &event, sizeof(event));
+
+    event.type = EV_LED;
+    event.code = LED_COMPOSE;
+    event.value = leds & (1 << 3) ? 1 : 0;
+    write(kbd_fd, (char *) &event, sizeof(event));
+}
+
+static void
+EvdevKbdBell (int volume, int frequency, int duration)
+{
+}
+
 KdKeyboardFuncs LinuxEvdevKeyboardFuncs = {
     EvdevKbdLoad,
     EvdevKbdInit,
@@ -296,4 +659,4 @@ KdKeyboardFuncs LinuxEvdevKeyboardFuncs 
     EvdevKbdFini,
     0,
 };
-#endif
+
diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c
index bb8f79f..acefc8f 100644
--- a/hw/kdrive/src/kdrive.c
+++ b/hw/kdrive/src/kdrive.c
@@ -72,6 +72,7 @@ Bool                kdDontZap;
 Bool		    kdEnabled;
 int		    kdSubpixelOrder;
 int		    kdVirtualTerminal = -1;
+char		    *kdKeyboard = 0;
 Bool		    kdSwitchPending;
 char		    *kdSwitchCmd;
 DDXPointRec	    kdOrigin;
@@ -793,6 +794,14 @@ KdProcessArgument (int argc, char **argv
 	    UseMsg ();
 	return 2;
     }
+    if (!strcmp (argv[i], "-keyboard"))
+    {
+	if ((i+1) < argc)
+	    kdKeyboard = argv[i+1];
+	else
+	    UseMsg ();
+	return 2;
+    }
     if (!strcmp (argv[i], "-rgba"))
     {
 	if ((i+1) < argc)
diff --git a/hw/kdrive/src/kdrive.h b/hw/kdrive/src/kdrive.h
index c371263..8379a19 100644
--- a/hw/kdrive/src/kdrive.h
+++ b/hw/kdrive/src/kdrive.h
@@ -416,6 +416,7 @@ extern Bool		kdEmulateMiddleButton;
 extern Bool		kdDisableZaphod;
 extern Bool		kdDontZap;
 extern int		kdVirtualTerminal;
+extern char		*kdKeyboard;
 extern char		*kdSwitchCmd;
 extern KdOsFuncs	*kdOsFuncs;
 
@@ -769,7 +770,7 @@ void
 ProcessInputEvents (void);
 
 extern KdMouseFuncs	LinuxMouseFuncs;
-extern KdMouseFuncs	LinuxEvdevFuncs;
+extern KdMouseFuncs	LinuxEvdevMouseFuncs;
 extern KdMouseFuncs	Ps2MouseFuncs;
 extern KdMouseFuncs	BusMouseFuncs;
 extern KdMouseFuncs	MsMouseFuncs;
@@ -777,6 +778,7 @@ #ifdef TOUCHSCREEN
 extern KdMouseFuncs	TsFuncs;
 #endif
 extern KdKeyboardFuncs	LinuxKeyboardFuncs;
+extern KdKeyboardFuncs	LinuxEvdevKeyboardFuncs;
 extern KdOsFuncs	LinuxFuncs;
 
 extern KdMouseFuncs	VxWorksMouseFuncs;
diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index 7f1c07f..0a8a2a7 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -1303,6 +1303,7 @@ KdEnqueueKeyboardEvent(unsigned char	sca
 	    xE.u.u.type = KeyPress;
 	xE.u.u.detail = key_code;
 	
+#ifndef XKB
 	switch (KEYCOL1(key_code)) 
 	{
 	case XK_Num_Lock:
@@ -1316,6 +1317,7 @@ KdEnqueueKeyboardEvent(unsigned char	sca
 	    else
 		xE.u.u.type = KeyPress;
 	}
+#endif
 	
 	/*
 	 * Check pressed keys which are already down
-- 
1.4.0