From: Andreas S. <an...@sc...> - 2002-11-11 17:56:39
|
This patch (written by Zephaniah E. Hull <wa...@de...>) adds an event interface to X. this is just for mice at the moment, but he works on keyboards right now. It uses the Mouse name as seen in /proc/bus/input/devices in the Name filed. the XF86Config section looks like this, then: Section "InputDevice" Identifier "Mouse1" Driver "mouse" Option "Protocol" "evdev" Option "Device" "A4Tech USB Optical Mouse" Option "Buttons" "9" Option "ZAxisMapping" "6 7 8 9" EndSection I am using it right now on my multi-Xserver machine. diff -ur build-tree/xc/programs/Xserver/hw/xfree86/os-support/linux/Imakefile build-tree.mine/xc/programs/Xserver/hw/xfree86/os-support/linux/Imakefile --- xc/programs/Xserver/hw/xfree86/os-support/linux/Imakefile 2000-11-16 14:45:03.000000000 -0500 +++ xc/programs/Xserver/hw/xfree86/os-support/linux/Imakefile 2002-11-09 06:06:23.000000000 -0500 @@ -50,7 +50,8 @@ $(AXP_OBJ) lnx_kmod.o lnx_agp.o INCLUDES = -I$(XF86COMSRC) -I$(XF86OSSRC) -I. -I$(SERVERSRC)/include \ - -I$(XINCLUDESRC) -I$(EXTINCSRC) -I$(XF86OSSRC)/shared + -I$(XINCLUDESRC) -I$(EXTINCSRC) -I$(XF86OSSRC)/shared \ + -I$(SERVERSRC)/mi RESDEFINES = -DUSESTDRES diff -ur build-tree/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_mouse.c build-tree.mine/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_mouse.c --- xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_mouse.c 1999-05-17 09:17:18.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_mouse.c 2002-11-09 11:21:23.000000000 -0500 @@ -6,8 +6,24 @@ #include "X.h" #include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" #include "xf86Xinput.h" #include "xf86OSmouse.h" +#include "mipointer.h" +#include <linux/input.h> + +#define BITS_PER_LONG (sizeof(long) * 8) +#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) +#define OFF(x) ((x)%BITS_PER_LONG) +#define LONG(x) ((x)/BITS_PER_LONG) +#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) + +/* Names of protocols that are handled internally here. */ +static const char *internalNames[] = { + "evdev", + NULL +}; static int SupportedInterfaces(void) @@ -15,6 +31,260 @@ return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO; } +static const char ** +BuiltinNames(void) +{ + return internalNames; +} + +static Bool +CheckProtocol(const char *protocol) +{ + int i; + + for (i = 0; internalNames[i]; i++) + if (xf86NameCmp(protocol, internalNames[i]) == 0) + return TRUE; + return FALSE; +} + +typedef struct _evdevMseRec { + int packetSize; + int buttons; +} evdevMseRec, *evdevMsePtr; + +static int +evdevFindMouse (const char *want) +{ + char dev[20]; + char name[256] = ""; + int fd, i; + + i = 0; + while (1) { + snprintf(dev, sizeof(dev), "/dev/input/event%d", i++); + SYSCALL(fd = open (dev, O_RDWR | O_NONBLOCK)); + if (fd == -1) + return -1; + ioctl(fd, EVIOCGNAME(sizeof(name)), name); + if (xf86NameCmp(name, want) == 0) { + return fd; + } + close(fd); + } + return -1; +} + +static void +evdevReadInput(InputInfoPtr pInfo) +{ + MouseDevPtr pMse; + evdevMsePtr evdevMse; + struct input_event *ev; + int n, bit; + + pMse = pInfo->private; + ev = (struct input_event *) pMse->buffer; + evdevMse = pMse->mousePriv; + + if (pInfo->fd == -1) + return; + + do { + int dx = 0, dy = 0, dz = 0, dw = 0; + n = read(pInfo->fd, pMse->buffer, sizeof(struct input_event)); + if (n == -1) { + xf86Msg(X_ERROR, "%s: Error in reading! (%s) Disabiling.\n", + pInfo->name, strerror(errno)); + RemoveEnabledDevice(pInfo->fd); + xf86RemoveSIGIOHandler(pInfo->fd); + close (pInfo->fd); + pMse->device->public.on = FALSE; + pInfo->fd = -1; + return; + } + if (n != sizeof(struct input_event)) { + xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n", pInfo->name, n); + return; + } + + switch (ev->type) { + case EV_REL: + switch (ev->code) { + case REL_X: + dx += ev->value; + break; + case REL_Y: + dy += ev->value; + break; + case REL_Z: + case REL_WHEEL: + dz -= ev->value; + break; + case REL_HWHEEL: + dw -= ev->value; + break; + } + break; + case EV_KEY: + if ((ev->code < BTN_MOUSE) || (ev->code >= BTN_JOYSTICK)) + break; + switch (ev->code) { + case BTN_RIGHT: bit = 1 << 0; break; /* 1 */ + case BTN_MIDDLE: bit = 1 << 1; break; /* 2 */ + case BTN_LEFT: bit = 1 << 2; break; /* 3 */ + default: bit = 1 << (ev->code - BTN_MOUSE); break; + } + evdevMse->buttons &= ~bit; + if (ev->value) + evdevMse->buttons |= bit; + break; + } + + pMse->PostEvent(pInfo, evdevMse->buttons, dx, dy, dz, dw); + } while (xf86WaitForInput(pInfo->fd, 0)); + + return; +} + +static void +evdevSigioReadInput (int fd, void *closure) +{ + evdevReadInput ((InputInfoPtr) closure); +} + +static int +evdevMouseProc(DeviceIntPtr pPointer, int what) +{ + InputInfoPtr pInfo; + MouseDevPtr pMse; + evdevMsePtr evdevMse; + unsigned char map[MSE_MAXBUTTONS + 1]; + char *dev; + int i, blocked; + + pInfo = pPointer->public.devicePrivate; + pMse = pInfo->private; + pMse->device = pPointer; + evdevMse = pMse->mousePriv; + + switch (what) { + case DEVICE_INIT: + pPointer->public.on = FALSE; + + for (i = 0; i < MSE_MAXBUTTONS; ++i) + map[i + 1] = i + 1; + + InitPointerDeviceStruct((DevicePtr)pPointer, map, + min(pMse->buttons, MSE_MAXBUTTONS), + miPointerGetMotionEvents, pMse->Ctrl, + miPointerGetMotionBufferSize()); + + /* X valuator */ + xf86InitValuatorAxisStruct(pPointer, 0, 0, -1, 1, 0, 1); + xf86InitValuatorDefaults(pPointer, 0); + /* Y valuator */ + xf86InitValuatorAxisStruct(pPointer, 1, 0, -1, 1, 0, 1); + xf86InitValuatorDefaults(pPointer, 1); + xf86MotionHistoryAllocate(pInfo); + break; + + case DEVICE_ON: + dev = xf86SetStrOption (pInfo->options, "Device", NULL); + if ((pInfo->fd = evdevFindMouse (dev)) == -1) { + xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); + return BadRequest; + } + + xf86FlushInput(pInfo->fd); + if (!xf86InstallSIGIOHandler (pInfo->fd, evdevSigioReadInput, pInfo)) + AddEnabledDevice(pInfo->fd); + pMse->lastButtons = 0; + pMse->emulateState = 0; + evdevMse->buttons = 0; + pPointer->public.on = TRUE; + /* + * send button up events for sanity. If no button down is pending + * xf86PostButtonEvent() will discard them. So we are on the safe side. + */ + blocked = xf86BlockSIGIO (); + for (i = 1; i <= 5; i++) + xf86PostButtonEvent(pPointer,0,i,0,0,0); + xf86UnblockSIGIO (blocked); + break; + + case DEVICE_OFF: + case DEVICE_CLOSE: + if (pInfo->fd != -1) { + RemoveEnabledDevice(pInfo->fd); + xf86RemoveSIGIOHandler(pInfo->fd); + close (pInfo->fd); + pInfo->fd = -1; + } + pPointer->public.on = FALSE; + usleep(300000); + break; + } + return Success; +} + + +/* This function is called when the protocol is "evdev". */ +static Bool +evdevPreInit(InputInfoPtr pInfo, const char *protocol, int flags) +{ + unsigned long evtype_bits[NBITS(KEY_MAX)]; + unsigned long evkey_bits[NBITS(KEY_MAX)]; + MouseDevPtr pMse = pInfo->private; + char *dev; + int i, j; + + pMse->protocol = protocol; + xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol); + + /* Collect the options, and process the common options. */ + xf86CollectInputOptions(pInfo, NULL, NULL); + xf86ProcessCommonOptions(pInfo, pInfo->options); + + dev = xf86SetStrOption (pInfo->options, "Device", NULL); + if ((pInfo->fd = evdevFindMouse (dev)) == -1) + return FALSE; /* FIXME: Print a message or something too? */ + + ioctl(pInfo->fd, EVIOCGBIT(0, EV_MAX), evtype_bits); + if (test_bit(EV_KEY, evtype_bits)) { + ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, EV_MAX), evkey_bits); + i = BTN_LEFT; + pMse->buttons = 0; + for (i = BTN_LEFT, j = 0; i <= BTN_BACK; i++) + if (test_bit(i, evkey_bits)) + pMse->buttons++; + } + + close(pInfo->fd); + pInfo->fd = -1; + + if (sizeof(struct input_event) <= sizeof(pMse->protoBuf)) + pMse->buffer = pMse->protoBuf; + else + pMse->buffer = xalloc(sizeof(struct input_event)); + pMse->mousePriv = xalloc(sizeof(evdevMseRec));; + if ((pMse->buffer == NULL) || (pMse->mousePriv == NULL)) { + xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name); + xfree(pMse); + return FALSE; + } + + pMse->CommonOptions(pInfo); + + /* Setup the local procs. */ + pInfo->device_control = evdevMouseProc; + pInfo->read_input = evdevReadInput; + + pInfo->flags |= XI86_CONFIGURED; + + return TRUE; +} + OSMouseInfoPtr xf86OSMouseInit(int flags) { @@ -24,6 +294,9 @@ if (!p) return NULL; p->SupportedInterfaces = SupportedInterfaces; + p->CheckProtocol = CheckProtocol; + p->BuiltinNames = BuiltinNames; + p->PreInit = evdevPreInit; return p; } |