[PATCH] Evdev input on Xglx

Tiago Vignatti tv02 at c3sl.ufpr.br
Tue Apr 11 11:33:12 PDT 2006


This one adds the evdev input on Xglx. I don't know if it is a "feature
bloat", but it really helps to make nested multiseat systems with 3D and xv 
support.

-- 
Tiago Vignatti
C3SL - Centro de Computação Científica e Software Livre
www.c3sl.ufpr.br
-------------- next part --------------
diff -u --exclude=Makefile --exclude='*.Plo' --exclude='*.in' --recursive --new-file xgl.orig/glx/evdev.c xgl/glx/evdev.c
--- xgl.orig/glx/evdev.c	1969-12-31 21:00:00.000000000 -0300
+++ xgl/glx/evdev.c	2006-04-10 18:26:52.000000000 -0300
@@ -0,0 +1,341 @@
+#include "evdev.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "os.h"
+#include "mipointer.h"
+#include "mi.h"
+
+CARD32          lastEventTime = 0;
+
+extern char    *xglKbdEvdevFile;
+extern char    *xglPtrEvdevFile;
+
+int             kbd_fd,
+                ptr_fd;
+
+int             EventToXserver[] = {
+    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, 84, 85, 86, 87,
+    88, 203, 90, 91, 92, 93, 94, 126,
+    100, 101, 104, 99, 105, 101, 89, 90,
+    91, 92, 94, 95, 96, 97, 98, 99,
+    112, 113, 114, 115, 214, 117, 118, 102,
+    120, 126, 122, 123, 124, 125, 126, 127,
+    128, 129, 130, 131, 132, 133, 134, 135,
+    136, 137, 138, 109, 140, 141, 215, 219,
+    144, 145, 146, 147, 148, 149, 150, 151,
+    152, 153, 154, 155, 156, 157, 158, 159,
+    160, 161, 162, 163, 164, 165, 166, 167,
+    168, 169, 170, 171, 172, 173, 174, 175,
+    176, 177, 178, 179, 180, 181, 182, 183,
+    184, 185, 186, 187, 188, 189, 190, 191,
+    192, 193, 194, 195, 196, 197, 198, 199,
+    200, 201, 202, 203, 204, 205, 206, 207,
+    208, 209, 210, 211, 212, 213, 214, 215,
+    216, 217, 218, 219, 220, 221, 222, 223,
+    224, 225, 226, 227, 228, 229, 230, 231,
+    232, 233, 234, 235, 236, 237, 238, 239,
+    240, 241, 242, 243, 244, 245, 246, 247,
+    248
+};
+
+void
+xglCollectEvdevEvents()
+{
+    xEvent          x;
+
+    int             i;
+    struct input_event ie;
+
+    while (EvdevCheckIfEvent(&ie)) {
+	switch (ie.type) {
+	case EV_REL:
+	    switch (ie.code) {
+	    case REL_X:
+		miPointerDeltaCursor(ie.value, 0, lastEventTime =
+				     GetTimeInMillis());
+		break;
+
+	    case REL_Y:
+		miPointerDeltaCursor(0, ie.value, lastEventTime =
+				     GetTimeInMillis());
+		break;
+	    case REL_WHEEL:
+		if (ie.value > 0)
+		    x.u.u.detail = 4;
+		else {
+		    x.u.u.detail = 5;
+		    ie.value *= -1;
+		}
+
+		for (i = 0; i < ie.value; i++) {
+		    x.u.u.type = ButtonPress;
+		    mieqEnqueue(&x);
+		    x.u.u.type = ButtonRelease;
+		    mieqEnqueue(&x);
+		}
+		break;
+	    case REL_HWHEEL:
+		if (ie.value > 0)
+		    x.u.u.detail = 6;
+		else {
+		    x.u.u.detail = 7;
+		    ie.value *= -1;
+		}
+
+		for (i = 0; i < ie.value; i++) {
+		    x.u.u.type = ButtonPress;
+		    mieqEnqueue(&x);
+		    x.u.u.type = ButtonRelease;
+		    mieqEnqueue(&x);
+		}
+		break;
+	    }
+	    break;
+
+	case EV_ABS:
+	    break;
+
+	case EV_KEY:
+	    if (ie.code >= BTN_MOUSE && ie.type < BTN_JOYSTICK) {
+		x.u.u.type = ie.value ? ButtonPress : ButtonRelease;
+		switch (ie.code) {
+		case BTN_LEFT:
+		    x.u.u.detail = 1;
+		    break;
+		case BTN_MIDDLE:
+		    x.u.u.detail = 2;
+		    break;
+		case BTN_RIGHT:
+		    x.u.u.detail = 3;
+		    break;
+		default:
+		    x.u.u.detail = 2;
+		    break;
+		}
+		x.u.keyButtonPointer.time = lastEventTime =
+		    GetTimeInMillis();
+		mieqEnqueue(&x);
+		break;
+	    } else {
+		x.u.u.type = ie.value ? KeyPress : KeyRelease;
+		x.u.u.detail = EventToXserver[ie.code] + 8;	/* FIXME:"8" 
+								 * means
+								 * the
+								 * MIN_KEYCODE 
+								 */
+		x.u.keyButtonPointer.time = lastEventTime =
+		    GetTimeInMillis();
+		mieqEnqueue(&x);
+	    }
+
+	case EV_SYN:
+	    break;
+	}
+    }
+}
+
+static int
+xglBlockSIGIO(void)
+{
+    sigset_t        set,
+                    old;
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGIO);
+    sigprocmask(SIG_BLOCK, &set, &old);
+    return sigismember(&old, SIGIO);
+}
+
+static void
+xglUnblockSIGIO(int wasset)
+{
+    sigset_t        set;
+
+    if (!wasset) {
+	sigemptyset(&set);
+	sigaddset(&set, SIGIO);
+	sigprocmask(SIG_UNBLOCK, &set, NULL);
+    }
+}
+
+void
+xglSIGIO(int sig)
+{
+    int             wasset = xglBlockSIGIO();
+    xglCollectEvdevEvents();
+    xglUnblockSIGIO(wasset);
+}
+
+#define BITS_PER_LONG          (sizeof(long) * 8)
+#define BIT(x)                 (1UL<<((x)%BITS_PER_LONG))
+
+#define EVIOCGMASK             _IOR('E', 0x91, unsigned long *)	/* Get our 
+								 * input
+								 * mask */
+#define EVIOCSMASK             _IOW('E', 0x92, unsigned long)	/* Set our 
+								 * input
+								 * mask */
+#define EVIOCGDMASK            _IOR('E', 0x93, unsigned long *)	/* Get
+								 * device
+								 * input
+								 * mask */
+#define EVIOCSDMASK            _IOW('E', 0x94, unsigned long)	/* Set
+								 * device
+								 * input
+								 * mask */
+
+void
+xglOpenEvdevInput()
+{
+    static int      already_open = 0;
+    struct sigaction sa;
+    struct sigaction osa;
+
+    if (already_open)
+	return;
+
+    kbd_fd = open(xglKbdEvdevFile, O_RDWR | O_NONBLOCK);
+    if (kbd_fd == -1)
+	FatalError("Unable to open keyboard device %s.\n",
+		   xglKbdEvdevFile);
+
+    ptr_fd = open(xglPtrEvdevFile, O_RDONLY | O_NONBLOCK);
+    if (ptr_fd == -1)
+	FatalError("Unable to open pointer device %s.\n", xglPtrEvdevFile);
+
+    /*
+     * Register the fd to receive SIGIO signals 
+     */
+    if (fcntl(kbd_fd, F_SETFL, fcntl(kbd_fd, F_GETFL) | O_ASYNC) == -1)
+	fprintf(stderr, "fcntl(%d, O_ASYNC): %s\n", kbd_fd,
+		strerror(errno));
+    if (fcntl(kbd_fd, F_SETOWN, getpid()) == -1)
+	fprintf(stderr, "fcntl(%d, F_SETOWN): %s\n", kbd_fd,
+		strerror(errno));
+
+    /*
+     * Register the fd to receive SIGIO signals 
+     */
+    if (fcntl(ptr_fd, F_SETFL, fcntl(ptr_fd, F_GETFL) | O_ASYNC) == -1)
+	fprintf(stderr, "fcntl(%d, O_ASYNC): %s\n", ptr_fd,
+		strerror(errno));
+    if (fcntl(ptr_fd, F_SETOWN, getpid()) == -1)
+	fprintf(stderr, "fcntl(%d, F_SETOWN): %s\n", ptr_fd,
+		strerror(errno));
+
+    sigemptyset(&sa.sa_mask);
+    sigaddset(&sa.sa_mask, SIGIO);
+    sa.sa_flags = 0;
+    sa.sa_handler = xglSIGIO;
+    sigaction(SIGIO, &sa, &osa);
+
+    already_open = 1;
+}
+
+static int      grabbed = 0;
+
+void
+xglEvdevGrabKeyboard()
+{
+    unsigned long   mask;
+
+    if (grabbed)
+	return;
+
+    if (ioctl(kbd_fd, EVIOCGMASK, &mask) < 0) {
+	ErrorF
+	    ("unable to use input device masking '%s', trying grabbing.\n",
+	     strerror(errno));
+	if (ioctl(kbd_fd, EVIOCGRAB, 1) < 0) {
+	    ErrorF("unable to grab device '%s', you may have problems.\n",
+		   strerror(errno));
+	}
+	return;
+    }
+
+    mask |= BIT(2);
+    ioctl(kbd_fd, EVIOCSMASK, mask);
+    ioctl(kbd_fd, EVIOCGDMASK, &mask);
+    mask &= ~BIT(0);
+    mask |= BIT(2);
+    ioctl(kbd_fd, EVIOCSDMASK, mask);
+}
+
+
+void
+xglEvdevUngrabKeyboard()
+{
+    if (!grabbed)
+	return;
+
+    unsigned long   mask;
+    if (ioctl(kbd_fd, EVIOCGDMASK, &mask) >= 0) {
+	mask |= BIT(0);
+	ioctl(kbd_fd, EVIOCSDMASK, mask);
+    }
+}
+
+int
+EvdevCheckIfEvent(struct input_event *ie)
+{
+    int             result,
+                    nread;
+
+    nread = read(kbd_fd, ie, sizeof(struct input_event));
+
+    if (nread <= 0)
+	nread = read(ptr_fd, ie, sizeof(struct input_event));
+
+    if (nread <= 0)
+	result = 0;
+    else
+	result = 1;
+
+    return result;
+}
+
+
+int
+EvdevSetLeds(long int leds)
+{
+    struct input_event event;
+    int             i;
+
+    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));
+}
diff -u --exclude=Makefile --exclude='*.Plo' --exclude='*.in' --recursive --new-file xgl.orig/glx/evdev.h xgl/glx/evdev.h
--- xgl.orig/glx/evdev.h	1969-12-31 21:00:00.000000000 -0300
+++ xgl/glx/evdev.h	2006-04-10 18:25:25.000000000 -0300
@@ -0,0 +1,17 @@
+#ifndef XGLEVDEV_H
+#define XGLEVDEV_H
+
+#include <linux/input.h>
+
+extern void     xglOpenEvdevInput();
+
+extern void     xglEvdevGrabKeyboard();
+extern void     xglEvdevUngrabKeyboard();
+
+extern int      EvdevCheckIfEvent(struct input_event *ie);
+
+extern int      EvdevSetLeds(long int leds);
+
+extern int      EventToXserver[];
+
+#endif				/* XGLEVDEV_H */
diff -u --exclude=Makefile --exclude='*.Plo' --exclude='*.in' --recursive --new-file xgl.orig/glx/Makefile.am xgl/glx/Makefile.am
--- xgl.orig/glx/Makefile.am	2006-04-10 17:57:21.000000000 -0300
+++ xgl/glx/Makefile.am	2006-04-10 17:58:56.000000000 -0300
@@ -25,7 +25,9 @@
 libxglx_la_SOURCES = \
 	xglx.h	     \
 	xglx.c	     \
-	xglxorg.c
+	xglxorg.c    \
+	evdev.h	     \
+	evdev.c
 
 # Xglx_DEPENDENCIES = @XGLX_LIBS@
 # Xglx_LDFLAGS	  = -export-dynamic
diff -u --exclude=Makefile --exclude='*.Plo' --exclude='*.in' --recursive --new-file xgl.orig/glx/xglx.c xgl/glx/xglx.c
--- xgl.orig/glx/xglx.c	2006-04-10 17:57:21.000000000 -0300
+++ xgl/glx/xglx.c	2006-04-11 15:14:35.000000000 -0300
@@ -55,6 +55,8 @@
 #include <X11/extensions/XKBconfig.h>
 #include <X11/extensions/XKBrules.h>
 
+#include "evdev.h"
+
 extern Bool
 XkbQueryExtension (Display *dpy,
 		   int     *opcodeReturn,
@@ -136,12 +138,17 @@
 static Bool	 softCursor    = FALSE;
 static Bool	 fullscreen    = TRUE;
 static Bool	 xDpms         = FALSE;
+static Bool	 useEvdev      = FALSE;
 
 static Bool randrExtension = FALSE;
 static int  randrEvent, randrError;
 
 static glitz_drawable_format_t *xglxScreenFormat = 0;
 
+/* evdev default file for keyboard and pointer */
+char *xglKbdEvdevFile = "/dev/input/event0";
+char *xglPtrEvdevFile = "/dev/input/event1";
+
 static Bool
 xglxAllocatePrivates (ScreenPtr pScreen)
 {
@@ -978,6 +985,8 @@
 
     while (XCheckIfEvent (xdisplay, &X, xglxNotExposurePredicate, NULL))
     {
+	if (useEvdev) ;
+	else {
 	switch (X.type) {
 	case KeyPress:
 	    x.u.u.type = KeyPress;
@@ -1029,6 +1038,7 @@
 	default:
 	    break;
 	}
+	} /* useEvdev patch*/
     }
 }
 
@@ -1049,6 +1059,11 @@
     XKeyboardControl values;
     int		     i;
 
+    if (useEvdev) 
+	/* TODO: handle other control stuff: click, bell, autoRepeat */
+	EvdevSetLeds (ctrl->leds);
+    else {
+
     valueMask = KBKeyClickPercent | KBBellPercent | KBBellPitch |
 	KBBellDuration | KBAutoRepeatMode;
 
@@ -1071,6 +1086,7 @@
 
 	XChangeKeyboardControl (xdisplay, valueMask, &values);
     }
+    }
 }
 
 static int
@@ -1247,10 +1263,14 @@
 
     } break;
     case DEVICE_ON:
+	if (useEvdev)
+	    xglEvdevGrabKeyboard ();	     
 	pDev->on = TRUE;
 	break;
     case DEVICE_OFF:
     case DEVICE_CLOSE:
+	if (useEvdev)
+	    xglEvdevUngrabKeyboard ();
 	pDev->on = FALSE;
 	break;
     }
@@ -1317,6 +1337,9 @@
 {
     DeviceIntPtr pKeyboard, pPointer;
 
+    if (useEvdev) 
+	xglOpenEvdevInput();
+
     pPointer  = AddInputDevice (xglxPointerProc, TRUE);
     pKeyboard = AddInputDevice (xglxKeybdProc, TRUE);
 
@@ -1341,6 +1364,10 @@
     ErrorF ("-fullscreen            run fullscreen\n");
     ErrorF ("-display string        display name of the real server\n");
     ErrorF ("-softcursor            force software cursor\n");
+    ErrorF ("-kbd file              evdev file to read keyboard events\n");
+    ErrorF ("-ptr file              evdev file to read pointer events\n");
+    ErrorF ("                       (if -kbd or -ptr is not set, Xglx will\n");
+    ErrorF ("                       read from xorg input)\n");
 
     if (!xDisplayName)
 	xglxUseXorgMsg ();
@@ -1424,6 +1451,24 @@
 	return xglxProcessXorgArgument (argc, argv, i);
     }
 
+    if (!strcmp(argv[i], "-kbd")) 
+    {
+	if (++i < argc) {
+	    xglKbdEvdevFile = argv[i];
+	    useEvdev = TRUE;
+	    return 2;
+        }
+	return 0;
+    }
+    if (!strcmp(argv[i], "-ptr")) {
+	if (++i < argc) {
+            xglPtrEvdevFile = argv[i];
+	    useEvdev = TRUE;
+            return 2;
+	}
+	return 0;
+    }
+
     return 0;
 }
 


More information about the xorg mailing list