mirror of
https://github.com/X11Libre/xf86-input-evdev.git
synced 2026-04-14 11:44:16 +00:00
Compare commits
41 Commits
xf86-input
...
xf86-input
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
891bfc56be | ||
|
|
6626ad5cb9 | ||
|
|
ae247ff09c | ||
|
|
46f2b83e01 | ||
|
|
d73a1732c6 | ||
|
|
8c332a8367 | ||
|
|
91e30bb07c | ||
|
|
36d9b9f166 | ||
|
|
69f01976f1 | ||
|
|
32768f8acd | ||
|
|
ed1382866c | ||
|
|
8fe38b2287 | ||
|
|
ef607b6cce | ||
|
|
906a5d6add | ||
|
|
5152d616ca | ||
|
|
2e9a71df5f | ||
|
|
49de32e70f | ||
|
|
f135e07462 | ||
|
|
e926356eb0 | ||
|
|
bd56ab3d72 | ||
|
|
2b30413598 | ||
|
|
52fc8ee846 | ||
|
|
b125b834f4 | ||
|
|
05b20db8db | ||
|
|
43768d59da | ||
|
|
9c524f6963 | ||
|
|
04003a98a9 | ||
|
|
0443fb430f | ||
|
|
998f52010f | ||
|
|
de07c04f5c | ||
|
|
01355b9d4b | ||
|
|
9591dc1f6c | ||
|
|
08ba40b253 | ||
|
|
39dc453691 | ||
|
|
e8887435ac | ||
|
|
b0f6987ee6 | ||
|
|
fec73e1418 | ||
|
|
da112737eb | ||
|
|
d40125ea8c | ||
|
|
42422d8f69 | ||
|
|
15e0091f0b |
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
*.patch
|
||||
ChangeLog
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
man/evdev.4
|
||||
missing
|
||||
.deps
|
||||
.libs
|
||||
*.lo
|
||||
*.la
|
||||
stamp-h1
|
||||
*.bz2
|
||||
*.gz
|
||||
47
ChangeLog
47
ChangeLog
@@ -1,47 +0,0 @@
|
||||
2006-01-09 David Nusinow,,, <set EMAIL_ADDRESS environment variable>
|
||||
|
||||
* man/Makefile.am:
|
||||
* man/evdev.man:
|
||||
Bugzilla #968 <https://bugs.freedesktop.org/show_bug.cgi?id=968>
|
||||
Patch #4301 <https://bugs.freedesktop.org/attachment.cgi?id=4301>
|
||||
Add evdev manpage
|
||||
|
||||
2005-12-20 Kevin E. Martin <kem-at-freedesktop-dot-org>
|
||||
|
||||
* configure.ac:
|
||||
Update package version for X11R7 release.
|
||||
|
||||
2005-12-14 Kevin E. Martin <kem-at-freedesktop-dot-org>
|
||||
|
||||
* configure.ac:
|
||||
Update package version number for final X11R7 release candidate.
|
||||
|
||||
2005-12-06 Kevin E. Martin <kem-at-freedesktop-dot-org>
|
||||
|
||||
* man/Makefile.am:
|
||||
Change *man_SOURCES ==> *man_PRE to fix autotools warnings.
|
||||
|
||||
2005-12-03 Kevin E. Martin <kem-at-freedesktop-dot-org>
|
||||
|
||||
* configure.ac:
|
||||
Update package version number for X11R7 RC3 release.
|
||||
|
||||
2005-12-01 Kevin E. Martin <kem-at-freedesktop-dot-org>
|
||||
|
||||
* configure.ac:
|
||||
Remove extraneous AC_MSG_RESULT.
|
||||
|
||||
2005-11-29 Adam Jackson <ajax@freedesktop.org>
|
||||
|
||||
* configure.ac:
|
||||
Only build dlloader modules by default.
|
||||
|
||||
2005-11-09 Kevin E. Martin <kem-at-freedesktop-dot-org>
|
||||
|
||||
* configure.ac:
|
||||
Update package version number for X11R7 RC2 release.
|
||||
|
||||
2005-11-01 Kevin E. Martin <kem-at-freedesktop-dot-org>
|
||||
|
||||
* configure.ac:
|
||||
Update pkgcheck dependencies to work with separate build roots.
|
||||
12
Makefile.am
12
Makefile.am
@@ -20,3 +20,15 @@
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
SUBDIRS = src man
|
||||
|
||||
EXTRA_DIST = ChangeLog autogen.sh
|
||||
|
||||
MAINTAINERCLEANFILES=ChangeLog
|
||||
|
||||
.PHONY: ChangeLog
|
||||
|
||||
ChangeLog:
|
||||
(GIT_DIR=$(top_srcdir)/.git git-log > .changelog.tmp && mv .changelog.tmp ChangeLog; rm -f .changelog.tmp) || \
|
||||
(touch ChangeLog; echo 'git directory not found: installing possibly empty changelog.' >&2)
|
||||
|
||||
dist-hook: ChangeLog
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([xf86-input-evdev],
|
||||
1.99.2,
|
||||
2.0.8,
|
||||
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
|
||||
xf86-input-evdev)
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ evdev \- Generic Linux input driver
|
||||
.B " Driver \*qevdev\*q"
|
||||
.BI " Option \*qDevice\*q \*q" devpath \*q
|
||||
.BI " Option \*qPath\*q \*q" path \*q
|
||||
.BI " Option \*qEmulate3Buttons\*q \*q" True \*q
|
||||
.BI " Option \*qEmulate3Timeout\*q \*q" 50 \*q
|
||||
\ \ ...
|
||||
.B EndSection
|
||||
.fi
|
||||
@@ -54,6 +56,22 @@ generally be of the form \*q/dev/input/by-path/xyz\*q, where xyz includes the
|
||||
name of the device. The mapping from device node to hardware is
|
||||
system-dependent. This option has precedence over the \*qDevice\*q option but
|
||||
one of \*qPath\*q or \*qDevice\*q must be given.
|
||||
.TP 7
|
||||
.BI "Option \*qEmulate3Buttons\*q \*q" boolean \*q
|
||||
Enable/disable the emulation of the third (middle) mouse button for mice
|
||||
which only have two physical buttons. The third button is emulated by
|
||||
pressing both buttons simultaneously. Default: on, until a middle mouse
|
||||
button event is registered.
|
||||
.TP 7
|
||||
.BI "Option \*qEmulate3Timeout\*q \*q" integer \*q
|
||||
Sets the timeout (in milliseconds) that the driver waits before deciding
|
||||
if two buttons where pressed "simultaneously" when 3 button emulation is
|
||||
enabled. Default: 50.
|
||||
.TP 7
|
||||
.BI "Option \*qReopenAttempts\*q \*q" integer \*q
|
||||
Number of reopen attempts after a read error occurs on the device (e.g. after
|
||||
waking up from suspend). In between each attempt is a 100ms wait. Default: 10.
|
||||
|
||||
.SH AUTHORS
|
||||
Kristian Høgsberg.
|
||||
.SH "SEE ALSO"
|
||||
|
||||
@@ -28,4 +28,6 @@
|
||||
@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
|
||||
@DRIVER_NAME@_drv_ladir = @inputdir@
|
||||
|
||||
@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c
|
||||
@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
|
||||
@DRIVER_NAME@.h \
|
||||
emuMB.c
|
||||
|
||||
334
src/emuMB.c
Normal file
334
src/emuMB.c
Normal file
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
|
||||
* Copyright 1993 by David Dawes <dawes@xfree86.org>
|
||||
* Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
|
||||
* Copyright 1994-2002 by The XFree86 Project, Inc.
|
||||
* Copyright 2002 by Paul Elliott
|
||||
* (Ported from xf86-input-mouse, above copyrights taken from there)
|
||||
* Copyright © 2008 University of South Australia
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of Red Hat
|
||||
* not be used in advertising or publicity pertaining to distribution
|
||||
* of the software without specific, written prior permission. Red
|
||||
* Hat makes no representations about the suitability of this software
|
||||
* for any purpose. It is provided "as is" without express or implied
|
||||
* warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
||||
* NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Middle mouse button emulation code. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <xf86.h>
|
||||
|
||||
#include "evdev.h"
|
||||
|
||||
enum {
|
||||
MBEMU_DISABLED = 0,
|
||||
MBEMU_ENABLED,
|
||||
MBEMU_AUTO
|
||||
};
|
||||
|
||||
/*
|
||||
* Lets create a simple finite-state machine for 3 button emulation:
|
||||
*
|
||||
* We track buttons 1 and 3 (left and right). There are 11 states:
|
||||
* 0 ground - initial state
|
||||
* 1 delayed left - left pressed, waiting for right
|
||||
* 2 delayed right - right pressed, waiting for left
|
||||
* 3 pressed middle - right and left pressed, emulated middle sent
|
||||
* 4 pressed left - left pressed and sent
|
||||
* 5 pressed right - right pressed and sent
|
||||
* 6 released left - left released after emulated middle
|
||||
* 7 released right - right released after emulated middle
|
||||
* 8 repressed left - left pressed after released left
|
||||
* 9 repressed right - right pressed after released right
|
||||
* 10 pressed both - both pressed, not emulating middle
|
||||
*
|
||||
* At each state, we need handlers for the following events
|
||||
* 0: no buttons down
|
||||
* 1: left button down
|
||||
* 2: right button down
|
||||
* 3: both buttons down
|
||||
* 4: emulate3Timeout passed without a button change
|
||||
* Note that button events are not deltas, they are the set of buttons being
|
||||
* pressed now. It's possible (ie, mouse hardware does it) to go from (eg)
|
||||
* left down to right down without anything in between, so all cases must be
|
||||
* handled.
|
||||
*
|
||||
* a handler consists of three values:
|
||||
* 0: action1
|
||||
* 1: action2
|
||||
* 2: new emulation state
|
||||
*
|
||||
* action > 0: ButtonPress
|
||||
* action = 0: nothing
|
||||
* action < 0: ButtonRelease
|
||||
*
|
||||
* The comment preceeding each section is the current emulation state.
|
||||
* The comments to the right are of the form
|
||||
* <button state> (<events>) -> <new emulation state>
|
||||
* which should be read as
|
||||
* If the buttons are in <button state>, generate <events> then go to
|
||||
* <new emulation state>.
|
||||
*/
|
||||
static signed char stateTab[11][5][3] = {
|
||||
/* 0 ground */
|
||||
{
|
||||
{ 0, 0, 0 }, /* nothing -> ground (no change) */
|
||||
{ 0, 0, 1 }, /* left -> delayed left */
|
||||
{ 0, 0, 2 }, /* right -> delayed right */
|
||||
{ 2, 0, 3 }, /* left & right (middle press) -> pressed middle */
|
||||
{ 0, 0, -1 } /* timeout N/A */
|
||||
},
|
||||
/* 1 delayed left */
|
||||
{
|
||||
{ 1, -1, 0 }, /* nothing (left event) -> ground */
|
||||
{ 0, 0, 1 }, /* left -> delayed left (no change) */
|
||||
{ 1, -1, 2 }, /* right (left event) -> delayed right */
|
||||
{ 2, 0, 3 }, /* left & right (middle press) -> pressed middle */
|
||||
{ 1, 0, 4 }, /* timeout (left press) -> pressed left */
|
||||
},
|
||||
/* 2 delayed right */
|
||||
{
|
||||
{ 3, -3, 0 }, /* nothing (right event) -> ground */
|
||||
{ 3, -3, 1 }, /* left (right event) -> delayed left (no change) */
|
||||
{ 0, 0, 2 }, /* right -> delayed right (no change) */
|
||||
{ 2, 0, 3 }, /* left & right (middle press) -> pressed middle */
|
||||
{ 3, 0, 5 }, /* timeout (right press) -> pressed right */
|
||||
},
|
||||
/* 3 pressed middle */
|
||||
{
|
||||
{ -2, 0, 0 }, /* nothing (middle release) -> ground */
|
||||
{ 0, 0, 7 }, /* left -> released right */
|
||||
{ 0, 0, 6 }, /* right -> released left */
|
||||
{ 0, 0, 3 }, /* left & right -> pressed middle (no change) */
|
||||
{ 0, 0, -1 }, /* timeout N/A */
|
||||
},
|
||||
/* 4 pressed left */
|
||||
{
|
||||
{ -1, 0, 0 }, /* nothing (left release) -> ground */
|
||||
{ 0, 0, 4 }, /* left -> pressed left (no change) */
|
||||
{ -1, 0, 2 }, /* right (left release) -> delayed right */
|
||||
{ 3, 0, 10 }, /* left & right (right press) -> pressed both */
|
||||
{ 0, 0, -1 }, /* timeout N/A */
|
||||
},
|
||||
/* 5 pressed right */
|
||||
{
|
||||
{ -3, 0, 0 }, /* nothing (right release) -> ground */
|
||||
{ -3, 0, 1 }, /* left (right release) -> delayed left */
|
||||
{ 0, 0, 5 }, /* right -> pressed right (no change) */
|
||||
{ 1, 0, 10 }, /* left & right (left press) -> pressed both */
|
||||
{ 0, 0, -1 }, /* timeout N/A */
|
||||
},
|
||||
/* 6 released left */
|
||||
{
|
||||
{ -2, 0, 0 }, /* nothing (middle release) -> ground */
|
||||
{ -2, 0, 1 }, /* left (middle release) -> delayed left */
|
||||
{ 0, 0, 6 }, /* right -> released left (no change) */
|
||||
{ 1, 0, 8 }, /* left & right (left press) -> repressed left */
|
||||
{ 0, 0, -1 }, /* timeout N/A */
|
||||
},
|
||||
/* 7 released right */
|
||||
{
|
||||
{ -2, 0, 0 }, /* nothing (middle release) -> ground */
|
||||
{ 0, 0, 7 }, /* left -> released right (no change) */
|
||||
{ -2, 0, 2 }, /* right (middle release) -> delayed right */
|
||||
{ 3, 0, 9 }, /* left & right (right press) -> repressed right */
|
||||
{ 0, 0, -1 }, /* timeout N/A */
|
||||
},
|
||||
/* 8 repressed left */
|
||||
{
|
||||
{ -2, -1, 0 }, /* nothing (middle release, left release) -> ground */
|
||||
{ -2, 0, 4 }, /* left (middle release) -> pressed left */
|
||||
{ -1, 0, 6 }, /* right (left release) -> released left */
|
||||
{ 0, 0, 8 }, /* left & right -> repressed left (no change) */
|
||||
{ 0, 0, -1 }, /* timeout N/A */
|
||||
},
|
||||
/* 9 repressed right */
|
||||
{
|
||||
{ -2, -3, 0 }, /* nothing (middle release, right release) -> ground */
|
||||
{ -3, 0, 7 }, /* left (right release) -> released right */
|
||||
{ -2, 0, 5 }, /* right (middle release) -> pressed right */
|
||||
{ 0, 0, 9 }, /* left & right -> repressed right (no change) */
|
||||
{ 0, 0, -1 }, /* timeout N/A */
|
||||
},
|
||||
/* 10 pressed both */
|
||||
{
|
||||
{ -1, -3, 0 }, /* nothing (left release, right release) -> ground */
|
||||
{ -3, 0, 4 }, /* left (right release) -> pressed left */
|
||||
{ -1, 0, 5 }, /* right (left release) -> pressed right */
|
||||
{ 0, 0, 10 }, /* left & right -> pressed both (no change) */
|
||||
{ 0, 0, -1 }, /* timeout N/A */
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
EvdevMBEmuTimer(InputInfoPtr pInfo)
|
||||
{
|
||||
EvdevPtr pEvdev = pInfo->private;
|
||||
int sigstate;
|
||||
int id;
|
||||
|
||||
sigstate = xf86BlockSIGIO ();
|
||||
|
||||
pEvdev->emulateMB.pending = FALSE;
|
||||
if ((id = stateTab[pEvdev->emulateMB.state][4][0]) != 0) {
|
||||
xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
|
||||
pEvdev->emulateMB.state =
|
||||
stateTab[pEvdev->emulateMB.state][4][2];
|
||||
} else {
|
||||
ErrorF("Got unexpected buttonTimer in state %d\n",
|
||||
pEvdev->emulateMB.state);
|
||||
}
|
||||
|
||||
xf86UnblockSIGIO (sigstate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Emulate a middle button on button press.
|
||||
*
|
||||
* @param code Evdev event code (BTN_LEFT or BTN_RIGHT)
|
||||
* @param press TRUE if press, FALSE if release.
|
||||
*
|
||||
* @return TRUE if event was swallowed by middle mouse button emulation, FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
BOOL
|
||||
EvdevMBEmuFilterEvent(InputInfoPtr pInfo, int code, BOOL press)
|
||||
{
|
||||
EvdevPtr pEvdev = pInfo->private;
|
||||
int id;
|
||||
int *btstate;
|
||||
int ret = FALSE;
|
||||
|
||||
if (!pEvdev->emulateMB.enabled)
|
||||
return ret;
|
||||
|
||||
/* don't care about other buttons */
|
||||
if (code != BTN_LEFT && code != BTN_RIGHT)
|
||||
return ret;
|
||||
|
||||
btstate = &pEvdev->emulateMB.buttonstate;
|
||||
if (press)
|
||||
*btstate |= (code == BTN_LEFT) ? 0x1 : 0x2;
|
||||
else
|
||||
*btstate &= (code == BTN_LEFT) ? ~0x1 : ~0x2;
|
||||
|
||||
if ((id = stateTab[pEvdev->emulateMB.state][*btstate][0]) != 0)
|
||||
{
|
||||
xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
|
||||
ret = TRUE;
|
||||
}
|
||||
if ((id = stateTab[pEvdev->emulateMB.state][*btstate][1]) != 0)
|
||||
{
|
||||
xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
pEvdev->emulateMB.state =
|
||||
stateTab[pEvdev->emulateMB.state][*btstate][2];
|
||||
|
||||
if (stateTab[pEvdev->emulateMB.state][4][0] != 0) {
|
||||
pEvdev->emulateMB.expires = GetTimeInMillis () + pEvdev->emulateMB.timeout;
|
||||
pEvdev->emulateMB.pending = TRUE;
|
||||
ret = TRUE;
|
||||
} else {
|
||||
pEvdev->emulateMB.pending = FALSE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void EvdevMBEmuWakeupHandler(pointer data,
|
||||
int i,
|
||||
pointer LastSelectMask)
|
||||
{
|
||||
InputInfoPtr pInfo = (InputInfoPtr)data;
|
||||
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
|
||||
int ms;
|
||||
|
||||
if (pEvdev->emulateMB.pending)
|
||||
{
|
||||
ms = pEvdev->emulateMB.expires - GetTimeInMillis();
|
||||
if (ms <= 0)
|
||||
EvdevMBEmuTimer(pInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void EvdevMBEmuBlockHandler(pointer data,
|
||||
struct timeval **waitTime,
|
||||
pointer LastSelectMask)
|
||||
{
|
||||
InputInfoPtr pInfo = (InputInfoPtr) data;
|
||||
EvdevPtr pEvdev= (EvdevPtr) pInfo->private;
|
||||
int ms;
|
||||
|
||||
if (pEvdev->emulateMB.pending)
|
||||
{
|
||||
ms = pEvdev->emulateMB.expires - GetTimeInMillis ();
|
||||
if (ms <= 0)
|
||||
ms = 0;
|
||||
AdjustWaitForDelay (waitTime, ms);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EvdevMBEmuPreInit(InputInfoPtr pInfo)
|
||||
{
|
||||
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
|
||||
pEvdev->emulateMB.enabled = MBEMU_AUTO;
|
||||
|
||||
if (xf86FindOption(pInfo->options, "Emulate3Buttons"))
|
||||
{
|
||||
pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
|
||||
"Emulate3Buttons",
|
||||
MBEMU_ENABLED);
|
||||
xf86Msg(X_INFO, "%s: Forcing middle mouse button emulation.\n",
|
||||
pInfo->name);
|
||||
}
|
||||
|
||||
pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options,
|
||||
"Emulate3Timeout", 50);
|
||||
RegisterBlockAndWakeupHandlers (EvdevMBEmuBlockHandler,
|
||||
EvdevMBEmuWakeupHandler,
|
||||
(pointer)pInfo);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
EvdevMBEmuFinalize(InputInfoPtr pInfo)
|
||||
{
|
||||
RemoveBlockAndWakeupHandlers (EvdevMBEmuBlockHandler,
|
||||
EvdevMBEmuWakeupHandler,
|
||||
(pointer)pInfo);
|
||||
|
||||
}
|
||||
|
||||
/* Enable/disable middle mouse button emulation. */
|
||||
void
|
||||
EvdevMBEmuEnable(InputInfoPtr pInfo, BOOL enable)
|
||||
{
|
||||
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
|
||||
if (pEvdev->emulateMB.enabled == MBEMU_AUTO)
|
||||
pEvdev->emulateMB.enabled = enable;
|
||||
}
|
||||
368
src/evdev.c
368
src/evdev.c
@@ -33,7 +33,6 @@
|
||||
#include <X11/XF86keysym.h>
|
||||
#include <X11/extensions/XIproto.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <misc.h>
|
||||
@@ -43,11 +42,9 @@
|
||||
#include <xf86Xinput.h>
|
||||
#include <exevents.h>
|
||||
#include <mipointer.h>
|
||||
#include <xorgVersion.h>
|
||||
|
||||
#if defined(XKB)
|
||||
/* XXX VERY WRONG. this is a client side header. */
|
||||
#include <X11/extensions/XKBstr.h>
|
||||
#endif
|
||||
#include "evdev.h"
|
||||
|
||||
#include <xf86Module.h>
|
||||
|
||||
@@ -76,6 +73,7 @@
|
||||
#define EVDEV_RELATIVE_EVENTS (1 << 2)
|
||||
#define EVDEV_ABSOLUTE_EVENTS (1 << 3)
|
||||
#define EVDEV_TOUCHPAD (1 << 4)
|
||||
#define EVDEV_INITIALIZED (1 << 5) /* WheelInit etc. called already? */
|
||||
|
||||
#define MIN_KEYCODE 8
|
||||
#define GLYPHS_PER_KEY 2
|
||||
@@ -91,25 +89,6 @@
|
||||
#define MODEFLAG 8
|
||||
#define COMPOSEFLAG 16
|
||||
|
||||
typedef struct {
|
||||
int kernel24;
|
||||
int screen;
|
||||
int min_x, min_y, max_x, max_y;
|
||||
int abs_x, abs_y, old_x, old_y;
|
||||
int flags;
|
||||
int tool;
|
||||
|
||||
/* XKB stuff has to be per-device rather than per-driver */
|
||||
int noXkb;
|
||||
#ifdef XKB
|
||||
char *xkb_rules;
|
||||
char *xkb_model;
|
||||
char *xkb_layout;
|
||||
char *xkb_variant;
|
||||
char *xkb_options;
|
||||
XkbComponentNamesRec xkbnames;
|
||||
#endif
|
||||
} EvdevRec, *EvdevPtr;
|
||||
|
||||
static const char *evdevDefaults[] = {
|
||||
"XkbRules", "base",
|
||||
@@ -118,6 +97,9 @@ static const char *evdevDefaults[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static int EvdevOn(DeviceIntPtr);
|
||||
static int EvdevCacheCompare(InputInfoPtr pInfo, Bool compare);
|
||||
|
||||
static void
|
||||
SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
|
||||
{
|
||||
@@ -153,6 +135,9 @@ PostButtonClicks(InputInfoPtr pInfo, int button, int count)
|
||||
static void
|
||||
PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
|
||||
{
|
||||
int code = ev->code + MIN_KEYCODE;
|
||||
static char warned[KEY_MAX];
|
||||
|
||||
/* filter repeat events for chording keys */
|
||||
if (value == 2 &&
|
||||
(ev->code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL ||
|
||||
@@ -163,7 +148,66 @@ PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
|
||||
ev->code == KEY_SCROLLLOCK)) /* XXX windows keys? */
|
||||
return;
|
||||
|
||||
xf86PostKeyboardEvent(pInfo->dev, ev->code + MIN_KEYCODE, value);
|
||||
if (code > 255 && ev->code < KEY_MAX) {
|
||||
if (!warned[ev->code])
|
||||
xf86Msg(X_WARNING, "%s: unable to handle keycode %d\n",
|
||||
pInfo->name, ev->code);
|
||||
warned[ev->code] = 1;
|
||||
}
|
||||
|
||||
/* The X server can't handle keycodes > 255 anyway, just drop them. */
|
||||
if (code > 255)
|
||||
return;
|
||||
|
||||
xf86PostKeyboardEvent(pInfo->dev, code, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Coming back from resume may leave us with a file descriptor that can be
|
||||
* opened but fails on the first read (ENODEV).
|
||||
* In this case, try to open the device until it becomes available or until
|
||||
* the predefined count expires.
|
||||
*/
|
||||
static CARD32
|
||||
EvdevReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
|
||||
{
|
||||
InputInfoPtr pInfo = (InputInfoPtr)arg;
|
||||
EvdevPtr pEvdev = pInfo->private;
|
||||
|
||||
do {
|
||||
pInfo->fd = open(pEvdev->device, O_RDWR, 0);
|
||||
} while (pInfo->fd < 0 && errno == EINTR);
|
||||
|
||||
if (pInfo->fd != -1)
|
||||
{
|
||||
if (EvdevCacheCompare(pInfo, TRUE) == Success)
|
||||
{
|
||||
xf86Msg(X_INFO, "%s: Device reopened after %d attempts.\n", pInfo->name,
|
||||
pEvdev->reopen_attempts - pEvdev->reopen_left + 1);
|
||||
EvdevOn(pInfo->dev);
|
||||
} else
|
||||
{
|
||||
xf86Msg(X_ERROR, "%s: Device has changed - disabling.\n",
|
||||
pInfo->name);
|
||||
DisableDevice(pInfo->dev);
|
||||
close(pInfo->fd);
|
||||
pInfo->fd = -1;
|
||||
}
|
||||
pEvdev->reopen_left = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pEvdev->reopen_left--;
|
||||
|
||||
if (!pEvdev->reopen_left)
|
||||
{
|
||||
xf86Msg(X_ERROR, "%s: Failed to reopen device after %d attempts.\n",
|
||||
pInfo->name, pEvdev->reopen_attempts);
|
||||
DisableDevice(pInfo->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 100; /* come back in 100 ms */
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -184,7 +228,16 @@ EvdevReadInput(InputInfoPtr pInfo)
|
||||
if (len != sizeof ev) {
|
||||
/* The kernel promises that we always only read a complete
|
||||
* event, so len != sizeof ev is an error. */
|
||||
xf86Msg(X_ERROR, "Read error: %s\n", strerror(errno));
|
||||
xf86Msg(X_ERROR, "%s: Read error: %s\n", pInfo->name, strerror(errno));
|
||||
|
||||
if (errno == ENODEV) /* May happen after resume */
|
||||
{
|
||||
xf86RemoveEnabledDevice(pInfo);
|
||||
close(pInfo->fd);
|
||||
pInfo->fd = -1;
|
||||
pEvdev->reopen_left = pEvdev->reopen_attempts;
|
||||
pEvdev->reopen_timer = TimerSet(NULL, 0, 100, EvdevReopenTimer, pInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -241,12 +294,15 @@ EvdevReadInput(InputInfoPtr pInfo)
|
||||
switch (ev.code) {
|
||||
/* swap here, pretend we're an X-conformant device. */
|
||||
case BTN_LEFT:
|
||||
xf86PostButtonEvent(pInfo->dev, 0, 1, value, 0, 0);
|
||||
if (!EvdevMBEmuFilterEvent(pInfo, ev.code, value))
|
||||
xf86PostButtonEvent(pInfo->dev, 0, 1, value, 0, 0);
|
||||
break;
|
||||
case BTN_RIGHT:
|
||||
xf86PostButtonEvent(pInfo->dev, 0, 3, value, 0, 0);
|
||||
if (!EvdevMBEmuFilterEvent(pInfo, ev.code, value))
|
||||
xf86PostButtonEvent(pInfo->dev, 0, 3, value, 0, 0);
|
||||
break;
|
||||
case BTN_MIDDLE:
|
||||
EvdevMBEmuEnable(pInfo, FALSE);
|
||||
xf86PostButtonEvent(pInfo->dev, 0, 2, value, 0, 0);
|
||||
break;
|
||||
|
||||
@@ -272,8 +328,15 @@ EvdevReadInput(InputInfoPtr pInfo)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ev.code > BTN_TASK && ev.code < KEY_OK)
|
||||
if (ev.code > BTN_TASK && ev.code < KEY_OK) {
|
||||
/* Some fancy mice with a lot of buttons generate
|
||||
* button events between BTN_TASK and BTN_JOYSTICK */
|
||||
if (ev.code < BTN_JOYSTICK)
|
||||
xf86PostButtonEvent(pInfo->dev, 0,
|
||||
ev.code - BTN_LEFT + 5,
|
||||
value, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
PostKbdEvent(pInfo, &ev, value);
|
||||
break;
|
||||
@@ -318,7 +381,7 @@ EvdevReadInput(InputInfoPtr pInfo)
|
||||
}
|
||||
}
|
||||
|
||||
#define TestBit(bit, array) (array[(bit) / 8] & (1 << ((bit) % 8)))
|
||||
#define TestBit(bit, array) (array[(bit) / LONG_BITS]) & (1L << ((bit) % LONG_BITS))
|
||||
|
||||
static void
|
||||
EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
|
||||
@@ -726,7 +789,10 @@ EvdevAddAbsClass(DeviceIntPtr device)
|
||||
pEvdev->min_y = absinfo_y.minimum;
|
||||
pEvdev->max_y = absinfo_y.maximum;
|
||||
|
||||
if (!InitValuatorClassDeviceStruct(device, 2, GetMotionHistory,
|
||||
if (!InitValuatorClassDeviceStruct(device, 2,
|
||||
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
|
||||
GetMotionHistory,
|
||||
#endif
|
||||
GetMotionHistorySize(), Absolute))
|
||||
return !Success;
|
||||
|
||||
@@ -756,16 +822,19 @@ EvdevAddRelClass(DeviceIntPtr device)
|
||||
|
||||
pInfo = device->public.devicePrivate;
|
||||
|
||||
if (!InitValuatorClassDeviceStruct(device, 2, GetMotionHistory,
|
||||
if (!InitValuatorClassDeviceStruct(device, 2,
|
||||
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
|
||||
GetMotionHistory,
|
||||
#endif
|
||||
GetMotionHistorySize(), Relative))
|
||||
return !Success;
|
||||
|
||||
/* X valuator */
|
||||
xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1);
|
||||
xf86InitValuatorAxisStruct(device, 0, -1, -1, 1, 0, 1);
|
||||
xf86InitValuatorDefaults(device, 0);
|
||||
|
||||
/* Y valuator */
|
||||
xf86InitValuatorAxisStruct(device, 1, 0, -1, 1, 0, 1);
|
||||
xf86InitValuatorAxisStruct(device, 1, -1, -1, 1, 0, 1);
|
||||
xf86InitValuatorDefaults(device, 1);
|
||||
xf86MotionHistoryAllocate(pInfo);
|
||||
|
||||
@@ -830,6 +899,56 @@ EvdevInit(DeviceIntPtr device)
|
||||
return Success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init all extras (wheel emulation, etc.) and grab the device.
|
||||
*
|
||||
* Coming from a resume, the grab may fail with ENODEV. In this case, we set a
|
||||
* timer to wake up and try to reopen the device later.
|
||||
*/
|
||||
static int
|
||||
EvdevOn(DeviceIntPtr device)
|
||||
{
|
||||
InputInfoPtr pInfo;
|
||||
EvdevPtr pEvdev;
|
||||
int rc = 0;
|
||||
|
||||
pInfo = device->public.devicePrivate;
|
||||
pEvdev = pInfo->private;
|
||||
|
||||
if (pInfo->fd != -1 && !pEvdev->kernel24 &&
|
||||
(rc = ioctl(pInfo->fd, EVIOCGRAB, (void *)1)))
|
||||
{
|
||||
xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
|
||||
strerror(errno));
|
||||
|
||||
/* ENODEV - device has disappeared after resume */
|
||||
if (rc && errno == ENODEV)
|
||||
{
|
||||
close(pInfo->fd);
|
||||
pInfo->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pInfo->fd == -1)
|
||||
{
|
||||
pEvdev->reopen_left = pEvdev->reopen_attempts;
|
||||
pEvdev->reopen_timer = TimerSet(NULL, 0, 100, EvdevReopenTimer, pInfo);
|
||||
} else
|
||||
{
|
||||
xf86AddEnabledDevice(pInfo);
|
||||
if ((pEvdev->flags & EVDEV_BUTTON_EVENTS) &&
|
||||
!(pEvdev->flags & EVDEV_INITIALIZED))
|
||||
{
|
||||
EvdevMBEmuPreInit(pInfo);
|
||||
}
|
||||
pEvdev->flags |= EVDEV_INITIALIZED;
|
||||
device->public.on = TRUE;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
EvdevProc(DeviceIntPtr device, int what)
|
||||
{
|
||||
@@ -845,23 +964,35 @@ EvdevProc(DeviceIntPtr device, int what)
|
||||
return EvdevInit(device);
|
||||
|
||||
case DEVICE_ON:
|
||||
if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)1))
|
||||
xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
|
||||
strerror(errno));
|
||||
xf86AddEnabledDevice(pInfo);
|
||||
device->public.on = TRUE;
|
||||
break;
|
||||
|
||||
return EvdevOn(device);
|
||||
|
||||
case DEVICE_OFF:
|
||||
if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
|
||||
xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
|
||||
strerror(errno));
|
||||
xf86RemoveEnabledDevice(pInfo);
|
||||
if (pInfo->fd != -1)
|
||||
{
|
||||
if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
|
||||
xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
|
||||
strerror(errno));
|
||||
xf86RemoveEnabledDevice(pInfo);
|
||||
close(pInfo->fd);
|
||||
pInfo->fd = -1;
|
||||
}
|
||||
if (pEvdev->flags & EVDEV_INITIALIZED)
|
||||
EvdevMBEmuFinalize(pInfo);
|
||||
pEvdev->flags &= ~EVDEV_INITIALIZED;
|
||||
device->public.on = FALSE;
|
||||
if (pEvdev->reopen_timer)
|
||||
{
|
||||
TimerFree(pEvdev->reopen_timer);
|
||||
pEvdev->reopen_timer = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEVICE_CLOSE:
|
||||
xf86Msg(X_INFO, "%s: Close\n", pInfo->name);
|
||||
if (pInfo->fd != -1) {
|
||||
close(pInfo->fd);
|
||||
pInfo->fd = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -891,19 +1022,134 @@ EvdevConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
/**
|
||||
* Get as much information as we can from the fd and cache it.
|
||||
* If compare is True, then the information retrieved will be compared to the
|
||||
* one already cached. If the information does not match, then this function
|
||||
* returns an error.
|
||||
*
|
||||
* @return Success if the information was cached, or !Success otherwise.
|
||||
*/
|
||||
static int
|
||||
EvdevCacheCompare(InputInfoPtr pInfo, Bool compare)
|
||||
{
|
||||
EvdevPtr pEvdev = pInfo->private;
|
||||
int i;
|
||||
|
||||
char name[1024] = {0};
|
||||
long bitmask[NBITS(EV_MAX)] = {0};
|
||||
long key_bitmask[NBITS(KEY_MAX)] = {0};
|
||||
long rel_bitmask[NBITS(REL_MAX)] = {0};
|
||||
long abs_bitmask[NBITS(ABS_MAX)] = {0};
|
||||
long led_bitmask[NBITS(LED_MAX)] = {0};
|
||||
struct input_absinfo absinfo[ABS_MAX];
|
||||
|
||||
if (ioctl(pInfo->fd,
|
||||
EVIOCGNAME(sizeof(name) - 1), name) < 0) {
|
||||
xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (compare && strcmp(pEvdev->name, name))
|
||||
goto error;
|
||||
|
||||
if (ioctl(pInfo->fd,
|
||||
EVIOCGBIT(0, sizeof(bitmask)), bitmask) < 0) {
|
||||
xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (compare && memcmp(pEvdev->bitmask, bitmask, sizeof(bitmask)))
|
||||
goto error;
|
||||
|
||||
|
||||
if (ioctl(pInfo->fd,
|
||||
EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) < 0) {
|
||||
xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (compare && memcmp(pEvdev->rel_bitmask, rel_bitmask, sizeof(rel_bitmask)))
|
||||
goto error;
|
||||
|
||||
if (ioctl(pInfo->fd,
|
||||
EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) < 0) {
|
||||
xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (compare && memcmp(pEvdev->abs_bitmask, abs_bitmask, sizeof(abs_bitmask)))
|
||||
goto error;
|
||||
|
||||
if (ioctl(pInfo->fd,
|
||||
EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) < 0) {
|
||||
xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (compare && memcmp(pEvdev->key_bitmask, key_bitmask, sizeof(key_bitmask)))
|
||||
goto error;
|
||||
|
||||
if (ioctl(pInfo->fd,
|
||||
EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask) < 0) {
|
||||
xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (compare && memcmp(pEvdev->led_bitmask, led_bitmask, sizeof(led_bitmask)))
|
||||
goto error;
|
||||
|
||||
memset(absinfo, 0, sizeof(absinfo));
|
||||
|
||||
for (i = 0; i < ABS_MAX; i++)
|
||||
{
|
||||
if (TestBit(i, abs_bitmask))
|
||||
{
|
||||
if (ioctl(pInfo->fd, EVIOCGABS(i), &absinfo[i]) < 0) {
|
||||
xf86Msg(X_ERROR, "ioctl EVIOCGABS failed: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (compare && memcmp(pEvdev->absinfo, absinfo, sizeof(absinfo)))
|
||||
goto error;
|
||||
|
||||
/* cache info */
|
||||
if (!compare)
|
||||
{
|
||||
strcpy(pEvdev->name, name);
|
||||
memcpy(pEvdev->bitmask, bitmask, sizeof(bitmask));
|
||||
memcpy(pEvdev->key_bitmask, key_bitmask, sizeof(key_bitmask));
|
||||
memcpy(pEvdev->rel_bitmask, rel_bitmask, sizeof(rel_bitmask));
|
||||
memcpy(pEvdev->abs_bitmask, abs_bitmask, sizeof(abs_bitmask));
|
||||
memcpy(pEvdev->led_bitmask, led_bitmask, sizeof(led_bitmask));
|
||||
memcpy(pEvdev->absinfo, absinfo, sizeof(absinfo));
|
||||
}
|
||||
|
||||
return Success;
|
||||
|
||||
error:
|
||||
return !Success;
|
||||
}
|
||||
|
||||
static int
|
||||
EvdevProbe(InputInfoPtr pInfo)
|
||||
{
|
||||
char key_bitmask[(KEY_MAX + 7) / 8];
|
||||
char rel_bitmask[(REL_MAX + 7) / 8];
|
||||
char abs_bitmask[(ABS_MAX + 7) / 8];
|
||||
long key_bitmask[NBITS(KEY_MAX)];
|
||||
long rel_bitmask[NBITS(REL_MAX)];
|
||||
long abs_bitmask[NBITS(ABS_MAX)];
|
||||
int i, has_axes, has_buttons, has_keys;
|
||||
EvdevPtr pEvdev = pInfo->private;
|
||||
|
||||
if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1) && errno == EINVAL) {
|
||||
/* keyboards are unsafe in 2.4 */
|
||||
pEvdev->kernel24 = 1;
|
||||
if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
|
||||
if (errno == EINVAL) {
|
||||
/* keyboards are unsafe in 2.4 */
|
||||
pEvdev->kernel24 = 1;
|
||||
} else {
|
||||
xf86Msg(X_ERROR, "Grab failed. Device already configured?\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
ioctl(pInfo->fd, EVIOCGRAB, (void *)0);
|
||||
}
|
||||
@@ -1018,10 +1264,6 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
|
||||
pInfo->always_core_feedback = 0;
|
||||
pInfo->conf_idev = dev;
|
||||
|
||||
if (!(pEvdev = xcalloc(sizeof(*pEvdev), 1)))
|
||||
return pInfo;
|
||||
pInfo->private = pEvdev;
|
||||
|
||||
if (!(pEvdev = xcalloc(sizeof(EvdevRec), 1)))
|
||||
return pInfo;
|
||||
|
||||
@@ -1045,12 +1287,13 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
|
||||
xf86DeleteInput(pInfo, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
pEvdev->device = device;
|
||||
|
||||
xf86Msg(deviceFrom, "%s: Device: \"%s\"\n", pInfo->name, device);
|
||||
do {
|
||||
pInfo->fd = open(device, O_RDWR, 0);
|
||||
}
|
||||
while (pInfo->fd < 0 && errno == EINTR);
|
||||
} while (pInfo->fd < 0 && errno == EINTR);
|
||||
|
||||
if (pInfo->fd < 0) {
|
||||
xf86Msg(X_ERROR, "Unable to open evdev device \"%s\".\n", device);
|
||||
@@ -1058,14 +1301,19 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pEvdev->reopen_attempts = xf86SetIntOption(pInfo->options, "ReopenAttempts", 10);
|
||||
|
||||
pEvdev->noXkb = noXkbExtension;
|
||||
/* parse the XKB options during kbd setup */
|
||||
|
||||
if (EvdevProbe(pInfo)) {
|
||||
close(pInfo->fd);
|
||||
xf86DeleteInput(pInfo, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EvdevCacheCompare(pInfo, FALSE); /* cache device data */
|
||||
|
||||
return pInfo;
|
||||
}
|
||||
|
||||
@@ -1100,8 +1348,8 @@ static XF86ModuleVersionInfo EvdevVersionRec =
|
||||
MODULEVENDORSTRING,
|
||||
MODINFOSTRING1,
|
||||
MODINFOSTRING2,
|
||||
0, /* Missing from SDK: XORG_VERSION_CURRENT, */
|
||||
1, 0, 0,
|
||||
XORG_VERSION_CURRENT,
|
||||
PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
|
||||
ABI_CLASS_XINPUT,
|
||||
ABI_XINPUT_VERSION,
|
||||
MOD_CLASS_XINPUT,
|
||||
|
||||
97
src/evdev.h
Normal file
97
src/evdev.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright © 2004-2008 Red Hat, Inc.
|
||||
* Copyright © 2008 University of South Australia
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of Red Hat
|
||||
* not be used in advertising or publicity pertaining to distribution
|
||||
* of the software without specific, written prior permission. Red
|
||||
* Hat makes no representations about the suitability of this software
|
||||
* for any purpose. It is provided "as is" without express or implied
|
||||
* warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
||||
* NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg (krh@redhat.com)
|
||||
* Adam Jackson (ajax@redhat.com)
|
||||
* Peter Hutterer (peter@cs.unisa.edu.au)
|
||||
*/
|
||||
|
||||
#ifndef EVDEV_H
|
||||
#define EVDEV_H
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include <xf86Xinput.h>
|
||||
#include <xf86_OSproc.h>
|
||||
|
||||
#if defined(XKB)
|
||||
/* XXX VERY WRONG. this is a client side header. */
|
||||
#include <X11/extensions/XKBstr.h>
|
||||
#endif
|
||||
|
||||
#define LONG_BITS (sizeof(long) * 8)
|
||||
#define NBITS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
|
||||
|
||||
typedef struct {
|
||||
const char *device;
|
||||
int kernel24;
|
||||
int screen;
|
||||
int min_x, min_y, max_x, max_y;
|
||||
int abs_x, abs_y, old_x, old_y;
|
||||
int flags;
|
||||
int tool;
|
||||
|
||||
/* XKB stuff has to be per-device rather than per-driver */
|
||||
int noXkb;
|
||||
#ifdef XKB
|
||||
char *xkb_rules;
|
||||
char *xkb_model;
|
||||
char *xkb_layout;
|
||||
char *xkb_variant;
|
||||
char *xkb_options;
|
||||
XkbComponentNamesRec xkbnames;
|
||||
#endif
|
||||
/* Middle mouse button emulation */
|
||||
struct {
|
||||
BOOL enabled;
|
||||
BOOL pending; /* timer waiting? */
|
||||
int buttonstate; /* phys. button state */
|
||||
int state; /* state machine (see bt3emu.c) */
|
||||
Time expires; /* time of expiry */
|
||||
Time timeout;
|
||||
} emulateMB;
|
||||
int reopen_attempts; /* max attempts to re-open after read failure */
|
||||
int reopen_left; /* number of attempts left to re-open the device */
|
||||
OsTimerPtr reopen_timer;
|
||||
|
||||
/* Cached info from device. */
|
||||
char name[1024];
|
||||
long bitmask[NBITS(EV_MAX)];
|
||||
long key_bitmask[NBITS(KEY_MAX)];
|
||||
long rel_bitmask[NBITS(REL_MAX)];
|
||||
long abs_bitmask[NBITS(ABS_MAX)];
|
||||
long led_bitmask[NBITS(LED_MAX)];
|
||||
struct input_absinfo absinfo[ABS_MAX];
|
||||
} EvdevRec, *EvdevPtr;
|
||||
|
||||
/* Middle Button emulation */
|
||||
int EvdevMBEmuTimer(InputInfoPtr);
|
||||
BOOL EvdevMBEmuFilterEvent(InputInfoPtr, int, BOOL);
|
||||
void EvdevMBEmuWakeupHandler(pointer, int, pointer);
|
||||
void EvdevMBEmuBlockHandler(pointer, struct timeval**, pointer);
|
||||
void EvdevMBEmuPreInit(InputInfoPtr);
|
||||
void EvdevMBEmuFinalize(InputInfoPtr);
|
||||
void EvdevMBEmuEnable(InputInfoPtr, BOOL);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user