diff -Nru xserver-xorg-input-keyboard-1.2.2/debian/changelog xserver-xorg-input-keyboard-1.2.2-3ubuntu1/debian/changelog --- xserver-xorg-input-keyboard-1.2.2/debian/changelog 2008-04-05 13:55:09.000000000 -0400 +++ xserver-xorg-input-keyboard-1.2.2-3ubuntu1/debian/changelog 2008-04-05 13:45:39.000000000 -0400 @@ -1,3 +1,10 @@ +xserver-xorg-input-keyboard (1:1.2.2-3ubuntu1-mt1) hardy; urgency=low + + * Multi-threaded input handling in case key events are dropped due to + latencies. + + -- Thomas Jaeger Sat, 05 Apr 2008 13:43:55 -0400 + xserver-xorg-input-keyboard (1:1.2.2-3ubuntu1) hardy; urgency=low * Merge from debian unstable, remaining changes: diff -Nru /tmp/sL2rpZmyuc/xserver-xorg-input-keyboard-1.2.2/src/lnx_kbd.c /tmp/nyt2iM59Ob/xserver-xorg-input-keyboard-1.2.2-3ubuntu1/src/lnx_kbd.c --- xserver-xorg-input-keyboard-1.2.2/src/lnx_kbd.c 2007-08-20 18:38:24.000000000 -0400 +++ xserver-xorg-input-keyboard-1.2.2-3ubuntu1/src/lnx_kbd.c 2008-04-05 13:42:18.000000000 -0400 @@ -31,8 +31,24 @@ #include "atKeynames.h" #include "lnx_kbd.h" +#include + #define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */ +#define EVENT_QUEUE_MAX 256 + +typedef struct { + int kbdtrans; + struct termios kbdtty; + pthread_t thread, thread2; + unsigned char queue[EVENT_QUEUE_MAX]; + unsigned int first, last; + int fd, fdr, fdw; + pthread_mutex_t lock; + pthread_cond_t cond; +} LnxKbdPrivRec, *LnxKbdPrivPtr; + + static KbdProtocolRec protocols[] = { {"standard", PROT_STD }, { NULL, PROT_UNKNOWN_KBD } @@ -43,9 +59,11 @@ static void SoundBell(InputInfoPtr pInfo, int loudness, int pitch, int duration) { + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; if (loudness && pitch) { - ioctl(pInfo->fd, KDMKTONE, + ioctl(priv->fd, KDMKTONE, ((1193190 / pitch) & 0xffff) | (((unsigned long)duration * loudness / 50) << 16)); @@ -56,9 +74,10 @@ SetKbdLeds(InputInfoPtr pInfo, int leds) { int real_leds = 0; + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; #if defined (__sparc__) - KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; if (pKbd->sunKbd) { if (leds & 0x08) real_leds |= XLED1; if (leds & 0x04) real_leds |= XLED3; @@ -78,15 +97,17 @@ if (leds & XLED4) real_leds |= LED_SCR; #endif #endif - ioctl(pInfo->fd, KDSETLED, real_leds); + ioctl(priv->fd, KDSETLED, real_leds); } static int GetKbdLeds(InputInfoPtr pInfo) { int real_leds, leds = 0; + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; - ioctl(pInfo->fd, KDGETLED, &real_leds); + ioctl(priv->fd, KDGETLED, &real_leds); if (real_leds & LED_CAP) leds |= XLED1; if (real_leds & LED_NUM) leds |= XLED2; @@ -240,11 +261,6 @@ #endif /* __alpha__ || __i386__ || __ia64__ */ } -typedef struct { - int kbdtrans; - struct termios kbdtty; -} LnxKbdPrivRec, *LnxKbdPrivPtr; - static int KbdInit(InputInfoPtr pInfo, int what) { @@ -252,8 +268,8 @@ LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; if (pKbd->isConsole) { - ioctl (pInfo->fd, KDGKBMODE, &(priv->kbdtrans)); - tcgetattr (pInfo->fd, &(priv->kbdtty)); + ioctl (priv->fd, KDGKBMODE, &(priv->kbdtrans)); + tcgetattr (priv->fd, &(priv->kbdtty)); } if (!pKbd->CustomKeycodes) { pKbd->RemapScanCode = ATScancode; @@ -271,9 +287,9 @@ if (pKbd->isConsole) { if (pKbd->CustomKeycodes) - ioctl(pInfo->fd, KDSKBMODE, K_MEDIUMRAW); + ioctl(priv->fd, KDSKBMODE, K_MEDIUMRAW); else - ioctl(pInfo->fd, KDSKBMODE, K_RAW); + ioctl(priv->fd, KDSKBMODE, K_RAW); nTty = priv->kbdtty; nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); @@ -284,7 +300,7 @@ nTty.c_cc[VMIN]=1; cfsetispeed(&nTty, 9600); cfsetospeed(&nTty, 9600); - tcsetattr(pInfo->fd, TCSANOW, &nTty); + tcsetattr(priv->fd, TCSANOW, &nTty); } return Success; } @@ -296,8 +312,8 @@ LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; if (pKbd->isConsole) { - ioctl(pInfo->fd, KDSKBMODE, priv->kbdtrans); - tcsetattr(pInfo->fd, TCSANOW, &(priv->kbdtty)); + ioctl(priv->fd, KDSKBMODE, priv->kbdtrans); + tcsetattr(priv->fd, TCSANOW, &(priv->kbdtty)); } return Success; } @@ -379,26 +395,71 @@ return FALSE; } -static void -stdReadInput(InputInfoPtr pInfo) +static void* +notifyX(void *data) { + InputInfoPtr pInfo = (InputInfoPtr) data; KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; + pthread_mutex_t lock; + pthread_mutex_init(&lock, NULL); + pthread_mutex_lock(&lock); + while (1) { + pthread_cond_wait(&priv->cond, &lock); + write(priv->fdw, "x", 1); + } +} + +static void* +queueInput(void *data) +{ + InputInfoPtr pInfo = (InputInfoPtr) data; + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; unsigned char rBuf[64]; int nBytes, i; - if ((nBytes = read( pInfo->fd, (char *)rBuf, sizeof(rBuf))) > 0) { - for (i = 0; i < nBytes; i++) - pKbd->PostEvent(pInfo, rBuf[i] & 0x7f, - rBuf[i] & 0x80 ? FALSE : TRUE); - } + while (1) { + nBytes = read( priv->fd, (char *)rBuf, sizeof(rBuf)); + if (nBytes > 0) { + pthread_mutex_lock(&priv->lock); + for (i = 0; i < nBytes; i++) { + xf86Msg(X_INFO,"queueing key %d (%s)\n",rBuf[i] & 0x7f, rBuf[i] & 0x80 ? "up": "down"); + // TODO Handle overflow + priv->queue[priv->last] = rBuf[i]; + priv->last = (priv->last + 1) % EVENT_QUEUE_MAX; + } + pthread_cond_signal(&priv->cond); + pthread_mutex_unlock(&priv->lock); + } + } +} + +static void +stdReadInput(InputInfoPtr pInfo) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; + char dummy; + read(priv->fdr, &dummy, 1); + pthread_mutex_lock(&priv->lock); + while (priv->first != priv->last) { + unsigned int key = priv->queue[priv->first]; + priv->first = (priv->first + 1) % EVENT_QUEUE_MAX; + xf86Msg(X_INFO,"processing key %d (%s)\n",key & 0x7f, key & 0x80 ? "up": "down"); + pKbd->PostEvent(pInfo, key & 0x7f, key & 0x80 ? FALSE : TRUE); + } + pthread_mutex_unlock(&priv->lock); } static Bool OpenKeyboard(InputInfoPtr pInfo) { KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; int i; KbdProtocolId prot = PROT_UNKNOWN_KBD; char *s; + int fds[2]; s = xf86SetStrOption(pInfo->options, "Protocol", NULL); for (i = 0; protocols[i].name; i++) { @@ -424,9 +485,10 @@ s = xf86SetStrOption(pInfo->options, "Device", NULL); if (s == NULL) { pInfo->fd = xf86Info.consoleFd; + fcntl(pInfo->fd, F_SETFL, 0); pKbd->isConsole = TRUE; } else { - pInfo->fd = open(s, O_RDONLY | O_NONBLOCK | O_EXCL); + pInfo->fd = open(s, O_RDONLY | O_EXCL); if (pInfo->fd == -1) { xf86Msg(X_ERROR, "%s: cannot open \"%s\"\n", pInfo->name, s); xfree(s); @@ -439,6 +501,23 @@ if (pKbd->isConsole) pKbd->vtSwitchSupported = TRUE; + + pipe(fds); + priv->fdr = fds[0]; + priv->fdw = fds[1]; + priv->fd = pInfo->fd; + pInfo->fd = priv->fdr; + fcntl(priv->fdr, F_SETFL, O_NONBLOCK); + + // TODO error on failure + priv->first = 0; + priv->last = 0; + pthread_mutex_init(&priv->lock, NULL); + pthread_cond_init(&priv->cond, NULL); + pthread_create(&priv->thread2, NULL, ¬ifyX, pInfo); + pthread_create(&priv->thread, NULL, &queueInput, pInfo); + // TODO destroy stuff in the end + return TRUE; } diff -Nru /tmp/sL2rpZmyuc/xserver-xorg-input-keyboard-1.2.2/src/Makefile.am /tmp/nyt2iM59Ob/xserver-xorg-input-keyboard-1.2.2-3ubuntu1/src/Makefile.am --- xserver-xorg-input-keyboard-1.2.2/src/Makefile.am 2007-08-20 18:38:24.000000000 -0400 +++ xserver-xorg-input-keyboard-1.2.2-3ubuntu1/src/Makefile.am 2008-04-05 13:42:18.000000000 -0400 @@ -21,6 +21,7 @@ driverdir = @inputdir@ driver_LTLIBRARIES = kbd_drv.la kbd_drv_la_LDFLAGS = -avoid-version -module +kbd_drv_la_CFLAGS = -ggdb kbd_drv_la_SOURCES = kbd.c xf86OSKbd.h xf86Keymap.h BSD_SRCS = bsd_KbdMap.c bsd_kbd.c bsd_kbd.h at_scancode.c @@ -39,6 +40,8 @@ if LINUX kbd_drv_la_SOURCES += $(LINUX_SRCS) +kbd_drv_la_LDFLAGS += -pthread -lpthread -shared +kbd_drv_la_CFLAGS += -pthread endif if SCO