Compare commits

...

45 Commits

Author SHA1 Message Date
Peter Hutterer
5def56d2f4 evdev 2.1.2
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2009-02-02 11:13:10 +10:00
Peter Hutterer
b907c23d00 Protect against zero-sized property values. #19882
X.Org Bug 19882 <http://bugs.freedesktop.org/show_bug.cgi?id=19882>

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 07f40a04df)
2009-02-02 11:12:28 +10:00
Alan Coopersmith
6c975917f8 Add README with pointers to mailing list, bugzilla & git repos
(cherry picked from commit e260993b6a)
2009-02-02 11:12:25 +10:00
Peter Hutterer
ac421e536c Reshuffle property initialization.
We don't need axis calibration, etc. on keyboards, so let's do it
conditionally on actually having axes.

Reported by Simon Thum.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 1906e4d5c1)

Conflicts:

	src/evdev.c
2009-01-22 15:20:05 +11:00
Peter Hutterer
bd55c2f021 Don't print xkb options twice to the log file.
xf86SetStrOption already prints with X_CONFIG anyway, no need to do it again.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 263bf04a9d)
2009-01-22 15:18:45 +11:00
Peter Hutterer
11d506dce6 evdev 2.1.1 2009-01-13 11:36:14 +10:00
Michael Chapman
a34a2cd347 Disable middle mouse button emulation when a middle mouse button event is registered
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 0592d97fbb)
2009-01-13 11:36:14 +10:00
Matt Helsley
78c00bd77f Fix FOO_MAX off-by-one
In linux/input.h each section's (e.g. ABS) FOO_MAX is the maximum FOO
value. Recent kernels define FOO_CNT as the maximum number of FOO there
will ever be. Hence using FOO_MAX to size the bit vectors representing
the capabilities of an evdev device is off by one.

Define FOO_CNT values for use with Linux kernels which lack them. Use
FOO_CNT whenever we need to know the number of bits needed -- usually to
calculate the number of longs needed.

When iterating over the values FOO_MAX still seems appropriate however
the loop test should include FOO_MAX rather than skip it.

Signed-off-by: Matt Helsley <matt.helsley@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 4dfd86b220)

Conflicts:

	src/evdev.c
2009-01-13 11:36:13 +10:00
Matt Helsley
760f1c6bb1 rename NBITS to NLONGS to reflect its actual meaning
NBITS really convers the number of bits passed as its argument
into a number of longs. This is somewhat atypical of many
function-like-macro names. Rename it to NLONGS.

Signed-off-by: Matt Helsley <matt.helsley@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

(cherry-picked from commit d3fd42d864)
Not really required, but it makes cherry-picking
4dfd86b220 easier.
2009-01-13 11:36:13 +10:00
Alan Coopersmith
2db04ba3c3 Remove xorgconfig & xorgcfg from See Also list in man page
(cherry picked from commit 0f0a149067)
2009-01-13 11:36:13 +10:00
Yan Li
363d0bdb9f Fix XkbModel parsing error
Signed-off-by: Yan Li <yan.i.li@intel.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit d170cba0cd)
2009-01-13 11:36:13 +10:00
Peter Hutterer
16a26a1eca Finalize MB emu (and wakeup handlers) before closing the fd.
Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit 2bf6e29b40)
2009-01-13 11:36:13 +10:00
Peter Hutterer
b879ae7351 evdev 2.1 2008-11-18 15:21:01 +10:00
Peter Hutterer
53566b7d4d Store device file's minor/major to avoid duplicate devices.
Devices added that use the same min/maj as an already added device are ignored
by the driver. This way users can have an xorg.conf entry on
/dev/input/by-id/blahblah and not get the same device added by HAL.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit 63af314368)
2008-11-18 15:13:34 +10:00
Fernando Carrijo
29c2765fc3 Fix error message
(cherry picked from commit 4c5c9c111d)
2008-11-11 14:37:45 +10:00
Peter Hutterer
7ef4e2c5e1 evdev 2.1 RC 3
That's it, no more new features. Now it's down to bugfixing only.
2008-11-03 13:47:15 +10:30
Peter Hutterer
dd0eeacc24 Add support for axes swapping.
New option: SwapAxes (boolean)
New property: EVDEV_PROP_SWAP_AXES.

Actual swapping code written by Donnie Berkholz.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit 4826969f23)
2008-11-03 13:46:40 +10:30
Peter Hutterer
67c0ea6c94 Add support for run-time calibration.
Some devices require run-time axis calibration. We can't change the min/max
ranges once we've initialised the valuator structs though, so in-driver
run-time calibration is required.

If the property is set, the driver scales from the calibrated range to the
values reported to the X server (which then may scale to screen coordinates).
If the property is not set (i.e. zero items) no scaling is performed.
(cherry picked from commit 33eb36f266)
2008-11-03 13:46:39 +10:30
Peter Hutterer
6bcbbc0411 Treat BTN_[0-2] as LMR buttons if necessary.
Treat BTN_[0-2] as LMR buttons on devices that do not advertise BTN_LEFT,
BTN_MIDDLE, BTN_RIGHT (e.g. 3Dconnexion SpaceNavigator).

Otherwise, treat BTN_[0+n] as button 5+n. Note: This causes duplicate
mappings for BTN_0 + n and  BTN_SIDE + n.

This also fixes a bug where we could end up with negative button numbers after
trying to map BTN_0.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit 64554e4799)
2008-11-03 13:46:35 +10:30
Peter Hutterer
534a3734d0 Remove obsolete FIXME
xkeyboard-config's maps are perfectly able to cope with evdev now.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit b77f939857)
2008-11-03 13:46:35 +10:30
Peter Hutterer
215c230d5c Flush input after re-opening the fd.
Suggested by Julien Cristau.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit a43ab4999b)
2008-11-03 13:46:33 +10:30
Peter Hutterer
8f96530449 emuMB: add EvdevMBEmuOn and call from EvdevOn to register wakeup handlers.
This got broken in b0737bdbd1, when the
EmuMBPreInit call was removed from EvdevOn. As a result, VT switching away and
back wouldn't restore the wakeup handlers and mouse button presses
disappeared.
(cherry picked from commit af096e8c5d)
2008-11-03 13:46:31 +10:30
Peter Hutterer
4fb97edcd4 Fix axis inversion for absolute coordinates.
If min_x/y was not equal to 0, the inverted calculated range was off and leads
to inaccessible or out-of-range areas.
(cherry picked from commit 12498042fc)
2008-11-03 13:46:25 +10:30
Peter Hutterer
4e86393bc0 emulate MB: fix confusing log message.
If we're forcing MB emulation behaviour as per config, then at least state
whether we're forcing it off or on.

Found by Michel Dänzer.
(cherry picked from commit 0f8fcfccb3)
2008-11-03 13:46:17 +10:30
Peter Hutterer
a64a78791f evdev 2.1 RC 2 2008-10-23 17:16:36 +10:30
Peter Hutterer
09b2a5e87b Silence compiler warning by memsetting the struct properly.
(cherry picked from commit 0ab4c09e50)
2008-10-23 17:15:32 +10:30
Peter Hutterer
fa18a4a38d MB emulation timeout is stored as Time, make the property 32-bit too.
(cherry picked from commit d348eb8ce7)
2008-10-23 17:15:30 +10:30
Peter Hutterer
172523d745 Init ioctl bitmasks to 0, shuts up valgrind too.
(cherry picked from commit 2c1698fa61)
2008-10-23 17:15:28 +10:30
Søren Hauberg
8fb820ffaf Add touchscreen support.
Touchscreens are devices that do not have buttons and only advertise
BTN_TOUCH. Add a new flag to note the device type.

If BTN_TOUCH is detected, change it to BTN_LEFT and process it normally.
(cherry picked from commit 8c39302594)
2008-10-23 17:15:25 +10:30
Julien Cristau
c7893b212d Fix TestBit() on 64bit
Reported by Albert Damen <albrt@gmx.net>
X.Org Bug#18150 <http://bugs.freedesktop.org/show_bug.cgi?id=18150>
(cherry picked from commit f57e8face9)
2008-10-23 17:14:52 +10:30
Peter Hutterer
e9dd721e2d Add option "GrabDevice", don't grab the device by default.
We now have the matching code in the server to set the console to RAW mode and
don't need to grab the devices anymore.

This is an updated version of e8534d47c8, which
was reverted in 6dc4199155.
(cherry picked from commit 4912e2aa7f)
2008-10-23 17:14:49 +10:30
Peter Hutterer
cab104fd9e Don't post keycodes > 255.
If we only have keys > 255 we don't set up a key class rec, so don't post
them. It makes the server unhappy.

Signed-off-by: Julien Cristau <jcristau@debian.org>
(cherry picked from commit 7243116f55)
2008-10-23 17:14:45 +10:30
Peter Hutterer
708eb34599 evdev 2.1 RC 1. 2008-10-14 17:19:58 +10:30
Peter Hutterer
36a687796f Fix "Device reopened after N attempts" message.
(cherry picked from commit 0089d931ac)
2008-10-14 17:18:08 +10:30
Peter Hutterer
26229df106 Don't init draglock, etc. if we don't have the required capabilities.
(cherry picked from commit 0f5a5ac09e)
2008-10-14 17:18:07 +10:30
Peter Hutterer
f4616d87fc 8-bit properties should use 8-bit storage types...
(cherry picked from commit 36d68b006d)
2008-10-14 17:18:07 +10:30
Peter Hutterer
2aa5ca8cdd Don't include the client-side header anymore. xkbstr.h is server SDK.
(cherry picked from commit bb1f421687)
2008-10-14 17:18:07 +10:30
Peter Hutterer
39263dc65d Tidy up evdev.h
This includes shuffling some functions around so we don't need the prototypes
in evdev.h.
(cherry picked from commit 0405f7b17f)
2008-10-14 17:18:07 +10:30
Peter Hutterer
57521e4e60 Rename DragLockInit to DragLockPreInit, remove superfluous "return".
(cherry picked from commit 088e0a175a)
2008-10-14 17:18:07 +10:30
Peter Hutterer
7da1522309 Register property handler from within the modules, not the main evdev file.
(cherry picked from commit cefedeb205)
2008-10-14 17:18:07 +10:30
Peter Hutterer
b4fcb825fc Clean up program flow - don't call PreInit for "modules" on DEVICE_INIT.
Call the PreInit functions for MB Emulation, wheel emu, and draglock during
PreInit, not on DEVICE_INIT. This way, we only parse the options once and
don't overwrite with defaults when coming back from a VT switch.
(cherry picked from commit b0737bdbd1)
2008-10-14 17:18:07 +10:30
Peter Hutterer
7c955ad050 Janitor: clean up xf86Msg use, might as well use X_CONFIG directly.
(cherry picked from commit 5f2c8a2dcd)
2008-10-14 17:18:07 +10:30
Peter Hutterer
4f80c0f2cb Add property support for ReopenAttempts option.
(cherry picked from commit ff783fce65)
2008-10-14 17:18:07 +10:30
Peter Hutterer
5070d64aa8 Document properties in man page.
(cherry picked from commit c638aa4a88)
2008-10-14 17:18:07 +10:30
Peter Hutterer
caacacf057 Document InvertX/Y options.
(cherry picked from commit b46677e346)
2008-10-14 17:18:07 +10:30
9 changed files with 694 additions and 327 deletions

20
README Normal file
View File

@@ -0,0 +1,20 @@
xf86-input-evdev - Generic Linux input driver for the Xorg X server
Please submit bugs & patches to the Xorg bugzilla:
https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
All questions regarding this software should be directed at the
Xorg mailing list:
http://lists.freedesktop.org/mailman/listinfo/xorg
The master development code repository can be found at:
git://anongit.freedesktop.org/git/xorg/driver/xf86-input-evdev
http://cgit.freedesktop.org/xorg/driver/xf86-input-evdev
For more information on the git code manager, see:
http://wiki.x.org/wiki/GitPage

View File

@@ -22,7 +22,7 @@
AC_PREREQ(2.57) AC_PREREQ(2.57)
AC_INIT([xf86-input-evdev], AC_INIT([xf86-input-evdev],
2.0.99, 2.1.2,
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
xf86-input-evdev) xf86-input-evdev)

View File

@@ -31,7 +31,7 @@
/* Middle mouse button emulation */ /* Middle mouse button emulation */
/* BOOL */ /* BOOL */
#define EVDEV_PROP_MIDBUTTON "Evdev Middle Button Emulation" #define EVDEV_PROP_MIDBUTTON "Evdev Middle Button Emulation"
/* CARD16 */ /* CARD32 */
#define EVDEV_PROP_MIDBUTTON_TIMEOUT "Evdev Middle Button Timeout" #define EVDEV_PROP_MIDBUTTON_TIMEOUT "Evdev Middle Button Timeout"
/* Wheel emulation */ /* Wheel emulation */
@@ -54,4 +54,16 @@
/* BOOL, 2 values [x, y], 1 inverts axis */ /* BOOL, 2 values [x, y], 1 inverts axis */
#define EVDEV_PROP_INVERT_AXES "Evdev Axis Inversion" #define EVDEV_PROP_INVERT_AXES "Evdev Axis Inversion"
/* Reopen attempts. */
/* CARD8 */
#define EVDEV_PROP_REOPEN "Evdev Reopen Attempts"
/* Run-time calibration */
/* CARD32, 4 values [minx, maxx, miny, maxy], or no values for unset */
#define EVDEV_PROP_CALIBRATION "Evdev Axis Calibration"
/* Swap x and y axis. */
/* BOOL */
#define EVDEV_PROP_SWAP_AXES "Evdev Axes Swap"
#endif #endif

View File

@@ -11,6 +11,7 @@ evdev \- Generic Linux input driver
.BI " Option \*qDevice\*q \*q" devpath \*q .BI " Option \*qDevice\*q \*q" devpath \*q
.BI " Option \*qEmulate3Buttons\*q \*q" True \*q .BI " Option \*qEmulate3Buttons\*q \*q" True \*q
.BI " Option \*qEmulate3Timeout\*q \*q" 50 \*q .BI " Option \*qEmulate3Timeout\*q \*q" 50 \*q
.BI " Option \*qGrabDevice\*q \*q" False \*q
\ \ ... \ \ ...
.B EndSection .B EndSection
.fi .fi
@@ -52,12 +53,12 @@ The mapping from device node to hardware is system-dependent.
Enable/disable the emulation of the third (middle) mouse button for mice Enable/disable the emulation of the third (middle) mouse button for mice
which only have two physical buttons. The third button is emulated by which only have two physical buttons. The third button is emulated by
pressing both buttons simultaneously. Default: on, until a middle mouse pressing both buttons simultaneously. Default: on, until a middle mouse
button event is registered. button event is registered. Property: "Evdev Middle Button Emulation".
.TP 7 .TP 7
.BI "Option \*qEmulate3Timeout\*q \*q" integer \*q .BI "Option \*qEmulate3Timeout\*q \*q" integer \*q
Sets the timeout (in milliseconds) that the driver waits before deciding Sets the timeout (in milliseconds) that the driver waits before deciding
if two buttons where pressed "simultaneously" when 3 button emulation is if two buttons where pressed "simultaneously" when 3 button emulation is
enabled. Default: 50. enabled. Default: 50. Property: "Evdev Middle Button Timeout".
.TP 7 .TP 7
.BI "Option \*qButtonMapping\*q \*q" string \*q .BI "Option \*qButtonMapping\*q \*q" string \*q
Sets the button mapping for this device. The mapping is a space-separated list Sets the button mapping for this device. The mapping is a space-separated list
@@ -74,12 +75,13 @@ Sets \*qdrag lock buttons\*q that simulate holding a button down, so
that low dexterity people do not have to hold a button down at the that low dexterity people do not have to hold a button down at the
same time they move a mouse cursor. Button numbers occur in pairs, same time they move a mouse cursor. Button numbers occur in pairs,
with the lock button number occurring first, followed by the button with the lock button number occurring first, followed by the button
number that is the target of the lock button. number that is the target of the lock button. Property: "Evdev
Drag Lock Buttons".
.TP 7 .TP 7
.BI "Option \*qDragLockButtons\*q \*q" "M1" \*q .BI "Option \*qDragLockButtons\*q \*q" "M1" \*q
Sets a \*qmaster drag lock button\*q that acts as a \*qMeta Key\*q Sets a \*qmaster drag lock button\*q that acts as a \*qMeta Key\*q
indicating that the next button pressed is to be indicating that the next button pressed is to be
\*qdrag locked\*q. \*qdrag locked\*q. Property: "Evdev Drag Lock Buttons".
.TP 7 .TP 7
.BI "Option \*qEmulateWheel\*q \*q" boolean \*q .BI "Option \*qEmulateWheel\*q \*q" boolean \*q
Enable/disable "wheel" emulation. Wheel emulation means emulating button Enable/disable "wheel" emulation. Wheel emulation means emulating button
@@ -94,7 +96,7 @@ more buttons but no wheel. See the description of the
.BR XAxisMapping , .BR XAxisMapping ,
and and
.B YAxisMapping .B YAxisMapping
options below. Default: off. options below. Default: off. Property "Evdev Wheel Emulation".
.TP 7 .TP 7
.BI "Option \*qEmulateWheelButton\*q \*q" integer \*q .BI "Option \*qEmulateWheelButton\*q \*q" integer \*q
Specifies which button must be held down to enable wheel emulation mode. Specifies which button must be held down to enable wheel emulation mode.
@@ -103,11 +105,12 @@ press/release events as specified for the
.B XAxisMapping .B XAxisMapping
and and
.B YAxisMapping .B YAxisMapping
settings. Default: 4. settings. Default: 4. Property: "Evdev Wheel Emulation Button".
.TP 7 .TP 7
.BI "Option \*qEmulateWheelInertia\*q \*q" integer \*q .BI "Option \*qEmulateWheelInertia\*q \*q" integer \*q
Specifies how far (in pixels) the pointer must move to generate button Specifies how far (in pixels) the pointer must move to generate button
press/release events in wheel emulation mode. Default: 10. press/release events in wheel emulation mode. Default: 10. Property: "Evdev
Wheel Emulation Inertia".
.TP 7 .TP 7
.BI "Option \*qEmulateWheelTimeout\*q \*q" integer \*q .BI "Option \*qEmulateWheelTimeout\*q \*q" integer \*q
Specifies the time in milliseconds the Specifies the time in milliseconds the
@@ -115,7 +118,7 @@ Specifies the time in milliseconds the
must be pressed before wheel emulation is started. If the must be pressed before wheel emulation is started. If the
.BR EmulateWheelButton .BR EmulateWheelButton
is released before this timeout, the original button press/release event is released before this timeout, the original button press/release event
is sent. Default: 200. is sent. Default: 200. Property: "Evdev Wheel Emulation Timeout".
.TP 7 .TP 7
.BI "Option \*qXAxisMapping\*q \*q" "N1 N2" \*q .BI "Option \*qXAxisMapping\*q \*q" "N1 N2" \*q
Specifies which buttons are mapped to motion in the X direction in wheel Specifies which buttons are mapped to motion in the X direction in wheel
@@ -123,7 +126,8 @@ emulation mode. Button number
.I N1 .I N1
is mapped to the negative X axis motion and button number is mapped to the negative X axis motion and button number
.I N2 .I N2
is mapped to the positive X axis motion. Default: no mapping. is mapped to the positive X axis motion. Default: no mapping. Property:
"Evdev Wheel Emulation Axes".
.TP 7 .TP 7
.BI "Option \*qYAxisMapping\*q \*q" "N1 N2" \*q .BI "Option \*qYAxisMapping\*q \*q" "N1 N2" \*q
Specifies which buttons are mapped to motion in the Y direction in wheel Specifies which buttons are mapped to motion in the Y direction in wheel
@@ -131,14 +135,71 @@ emulation mode. Button number
.I N1 .I N1
is mapped to the negative Y axis motion and button number is mapped to the negative Y axis motion and button number
.I N2 .I N2
is mapped to the positive Y axis motion. Default: "4 5" is mapped to the positive Y axis motion. Default: "4 5". Property:
"Evdev Wheel Emulation Axes".
.TP 7 .TP 7
.BI "Option \*qReopenAttempts\*q \*q" integer \*q .BI "Option \*qReopenAttempts\*q \*q" integer \*q
Number of reopen attempts after a read error occurs on the device (e.g. after 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. waking up from suspend). In between each attempt is a 100ms wait. Default: 10.
.TP 7
.BI "Option \*qInvertX\*q \*q" Bool \*q
.TP 7
.BI "Option \*qInvertY\*q \*q" Bool \*q
Invert the given axis. Default: off. Property: "Evdev Axis Inversion".
.TP 7
.BI "Option \*qSwapAxes\*q \*q" Bool \*q
Swap x/y axes. Default: off. Property: "Evdev Axes Swap".
.TP 7
.BI "Option \*qGrabDevice\*q \*q" boolean \*q
Force a grab on the event device. Doing so will ensure that no other driver
can initialise the same device and it will also stop the device from sending
events to /dev/kbd or /dev/input/mice. Events from this device will not be
sent to virtual devices (e.g. rfkill or the Macintosh mouse button emulation).
Default disabled.
.SH SUPPORTED PROPERTIES
The following properties are provided by the
.B evdev
driver.
.TP 7
.BI "Evdev Middle Button Emulation"
1 boolean value (8 bit, 0 or 1).
.TP 7
.BI "Evdev Middle Button Timeout"
1 16-bit positive value.
.TP 7
.BI "Evdev Wheel Emulation"
1 boolean value (8 bit, 0 or 1).
.TP 7
.BI "Evdev Wheel Emulation Axes"
4 8-bit values, order X up, X down, Y up, Y down. 0 disables a value.
.TP 7
.BI "Evdev Wheel Emulation Inertia"
1 16-bit positive value.
.TP 7
.BI "Evdev Wheel Emulation Timeout"
1 16-bit positive value.
.TP 7
.BI "Evdev Wheel Emulation Button"
1 8-bit value, allowed range 0-32, 0 disables the button.
.TP 7
.BI "Evdev Drag Lock Buttons"
8-bit. Either 1 value or pairs of values. Value range 0-32, 0 disables a
value.
.TP 7
.BI "Evdev Axis Inversion"
2 boolean values (8 bit, 0 or 1), order X, Y. 1 inverts the axis.
.BI "Evdev Axis Calibration"
4 32-bit values, order min-x, max-x, min-y, max-y or 0 values to disable
run-time axis calibration. This feature is required for devices that need to
scale to a different coordinate system than originally reported to the X
server, such as touchscreens that require run-time calibration.
.TP 7
.BI "Evdev Axis Swap"
1 boolean values (8 bit, 0 or 1). 1 swaps x/y axes.
.SH AUTHORS .SH AUTHORS
Kristian Høgsberg. Kristian Høgsberg.
.SH "SEE ALSO" .SH "SEE ALSO"
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__), __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__),
README.mouse. README.mouse.

View File

@@ -53,7 +53,7 @@ void EvdevDragLockLockButton(InputInfoPtr pInfo, unsigned int button);
/* Setup and configuration code */ /* Setup and configuration code */
void void
EvdevDragLockInit(InputInfoPtr pInfo) EvdevDragLockPreInit(InputInfoPtr pInfo)
{ {
EvdevPtr pEvdev = (EvdevPtr)pInfo->private; EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
char *option_string = NULL; char *option_string = NULL;
@@ -210,6 +210,74 @@ EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value)
} }
#ifdef HAVE_PROPERTIES #ifdef HAVE_PROPERTIES
/**
* Set the drag lock property.
* If only one value is supplied, then this is used as the meta button.
* If more than one value is supplied, then each value is the drag lock button
* for the pair. 0 disables a pair.
* i.e. to set bt 3 to draglock button 1, supply 0,0,1
*/
int
EvdevDragLockSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (atom == prop_dlock)
{
int i;
if (val->format != 8 || val->type != XA_INTEGER)
return BadMatch;
/* Don't allow changes while a lock is active */
if (pEvdev->dragLock.meta)
{
if (pEvdev->dragLock.meta_state)
return BadAccess;
} else
{
for (i = 0; i < EVDEV_MAXBUTTONS; i++)
if (pEvdev->dragLock.lock_state[i])
return BadValue;
}
if (val->size == 0)
return BadMatch;
else if (val->size == 1)
{
int meta = *((CARD8*)val->data);
if (meta > EVDEV_MAXBUTTONS)
return BadValue;
if (!checkonly)
{
pEvdev->dragLock.meta = meta;
memset(pEvdev->dragLock.lock_pair, 0, sizeof(pEvdev->dragLock.lock_pair));
}
} else
{
CARD8* vals = (CARD8*)val->data;
for (i = 0; i < val->size && i < EVDEV_MAXBUTTONS; i++)
if (vals[i] > EVDEV_MAXBUTTONS)
return BadValue;
if (!checkonly)
{
pEvdev->dragLock.meta = 0;
memset(pEvdev->dragLock.lock_pair, 0, sizeof(pEvdev->dragLock.lock_pair));
for (i = 0; i < val->size && i < EVDEV_MAXBUTTONS; i++)
pEvdev->dragLock.lock_pair[i] = vals[i];
}
}
}
return Success;
}
/** /**
* Initialise property for drag lock buttons setting. * Initialise property for drag lock buttons setting.
*/ */
@@ -246,72 +314,7 @@ EvdevDragLockInitProperty(DeviceIntPtr dev)
XISetDevicePropertyDeletable(dev, prop_dlock, FALSE); XISetDevicePropertyDeletable(dev, prop_dlock, FALSE);
return; XIRegisterPropertyHandler(dev, EvdevDragLockSetProperty, NULL, NULL);
} }
/**
* Set the drag lock property.
* If only one value is supplied, then this is used as the meta button.
* If more than one value is supplied, then each value is the drag lock button
* for the pair. 0 disables a pair.
* i.e. to set bt 3 to draglock button 1, supply 0,0,1
*/
int
EvdevDragLockSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (atom == prop_dlock)
{
int i;
if (val->format != 8 || val->type != XA_INTEGER)
return BadMatch;
/* Don't allow changes while a lock is active */
if (pEvdev->dragLock.meta)
{
if (pEvdev->dragLock.meta_state)
return BadAccess;
} else
{
for (i = 0; i < EVDEV_MAXBUTTONS; i++)
if (pEvdev->dragLock.lock_state[i])
return BadValue;
}
if (val->size == 1)
{
int meta = *((CARD8*)val->data);
if (meta > EVDEV_MAXBUTTONS)
return BadValue;
if (!checkonly)
{
pEvdev->dragLock.meta = meta;
memset(pEvdev->dragLock.lock_pair, 0, sizeof(pEvdev->dragLock.lock_pair));
}
} else
{
CARD8* vals = (CARD8*)val->data;
for (i = 0; i < val->size && i < EVDEV_MAXBUTTONS; i++)
if (vals[i] > EVDEV_MAXBUTTONS)
return BadValue;
if (!checkonly)
{
pEvdev->dragLock.meta = 0;
memset(pEvdev->dragLock.lock_pair, 0, sizeof(pEvdev->dragLock.lock_pair));
for (i = 0; i < val->size && i < EVDEV_MAXBUTTONS; i++)
pEvdev->dragLock.lock_pair[i] = vals[i];
}
}
}
return Success;
}
#endif #endif

View File

@@ -231,6 +231,11 @@ EvdevMBEmuFilterEvent(InputInfoPtr pInfo, int button, BOOL press)
if (!pEvdev->emulateMB.enabled) if (!pEvdev->emulateMB.enabled)
return ret; return ret;
if (button == 2) {
EvdevMBEmuEnable(pInfo, FALSE);
return ret;
}
/* don't care about other buttons */ /* don't care about other buttons */
if (button != 1 && button != 3) if (button != 1 && button != 3)
return ret; return ret;
@@ -311,24 +316,20 @@ EvdevMBEmuPreInit(InputInfoPtr pInfo)
pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options, pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
"Emulate3Buttons", "Emulate3Buttons",
MBEMU_ENABLED); MBEMU_ENABLED);
xf86Msg(X_INFO, "%s: Forcing middle mouse button emulation.\n", xf86Msg(X_INFO, "%s: Forcing middle mouse button emulation %s.\n",
pInfo->name); pInfo->name, (pEvdev->emulateMB.enabled) ? "on" : "off");
} }
pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options, pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options,
"Emulate3Timeout", 50); "Emulate3Timeout", 50);
}
void
EvdevMBEmuOn(InputInfoPtr pInfo)
{
RegisterBlockAndWakeupHandlers (EvdevMBEmuBlockHandler, RegisterBlockAndWakeupHandlers (EvdevMBEmuBlockHandler,
EvdevMBEmuWakeupHandler, EvdevMBEmuWakeupHandler,
(pointer)pInfo); (pointer)pInfo);
#ifdef HAVE_PROPERTIES
XIChangeDeviceProperty(pInfo->dev, prop_mbemu, XA_INTEGER, 8,
PropModeReplace, 1, &pEvdev->emulateMB.enabled,
TRUE);
XIChangeDeviceProperty(pInfo->dev, prop_mbtimeout, XA_INTEGER, 16,
PropModeReplace, 1, &pEvdev->emulateMB.timeout,
TRUE);
#endif
} }
void void
@@ -351,6 +352,32 @@ EvdevMBEmuEnable(InputInfoPtr pInfo, BOOL enable)
#ifdef HAVE_PROPERTIES #ifdef HAVE_PROPERTIES
int
EvdevMBEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (atom == prop_mbemu)
{
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
pEvdev->emulateMB.enabled = *((BOOL*)val->data);
} else if (atom == prop_mbtimeout)
{
if (val->format != 32 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
pEvdev->emulateMB.timeout = *((CARD32*)val->data);
}
return Success;
}
/** /**
* Initialise property for MB emulation on/off. * Initialise property for MB emulation on/off.
*/ */
@@ -376,37 +403,13 @@ EvdevMBEmuInitProperty(DeviceIntPtr dev)
prop_mbtimeout = MakeAtom(EVDEV_PROP_MIDBUTTON_TIMEOUT, prop_mbtimeout = MakeAtom(EVDEV_PROP_MIDBUTTON_TIMEOUT,
strlen(EVDEV_PROP_MIDBUTTON_TIMEOUT), strlen(EVDEV_PROP_MIDBUTTON_TIMEOUT),
TRUE); TRUE);
rc = XIChangeDeviceProperty(dev, prop_mbtimeout, XA_INTEGER, 16, PropModeReplace, 1, rc = XIChangeDeviceProperty(dev, prop_mbtimeout, XA_INTEGER, 32, PropModeReplace, 1,
&pEvdev->emulateMB.timeout, FALSE); &pEvdev->emulateMB.timeout, FALSE);
if (rc != Success) if (rc != Success)
return; return;
XISetDevicePropertyDeletable(dev, prop_mbtimeout, FALSE); XISetDevicePropertyDeletable(dev, prop_mbtimeout, FALSE);
}
int XIRegisterPropertyHandler(dev, EvdevMBEmuSetProperty, NULL, NULL);
EvdevMBEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (atom == prop_mbemu)
{
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
pEvdev->emulateMB.enabled = *((BOOL*)val->data);
} else if (atom == prop_mbtimeout)
{
if (val->format != 16 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
pEvdev->emulateMB.timeout = *((INT16*)val->data);
}
return Success;
} }
#endif #endif

View File

@@ -308,35 +308,111 @@ EvdevWheelEmuPreInit(InputInfoPtr pInfo)
"EmulateWheelInertia: %d, " "EmulateWheelInertia: %d, "
"EmulateWheelTimeout: %d\n", "EmulateWheelTimeout: %d\n",
pInfo->name, pEvdev->emulateWheel.button, inertia, timeout); pInfo->name, pEvdev->emulateWheel.button, inertia, timeout);
#ifdef HAVE_PROPERTIES
XIChangeDeviceProperty(pInfo->dev, prop_wheel_emu, XA_INTEGER, 8,
PropModeReplace, 1, &pEvdev->emulateWheel.enabled, TRUE);
XIChangeDeviceProperty(pInfo->dev, prop_wheel_button, XA_INTEGER, 8,
PropModeReplace, 1, &pEvdev->emulateWheel.button, TRUE);
XIChangeDeviceProperty(pInfo->dev, prop_wheel_inertia, XA_INTEGER, 8,
PropModeReplace, 1, &pEvdev->emulateWheel.inertia, TRUE);
XIChangeDeviceProperty(pInfo->dev, prop_wheel_timeout, XA_INTEGER, 16,
PropModeReplace, 1, &pEvdev->emulateWheel.timeout, TRUE);
val[0] = pEvdev->emulateWheel.X.up_button;
val[1] = pEvdev->emulateWheel.X.down_button;
val[2] = pEvdev->emulateWheel.Y.up_button;
val[3] = pEvdev->emulateWheel.Y.down_button;
XIChangeDeviceProperty(pInfo->dev, prop_wheel_axismap, XA_INTEGER, 8,
PropModeReplace, 4, val, TRUE);
#endif
} }
#ifdef HAVE_PROPERTIES #ifdef HAVE_PROPERTIES
int
EvdevWheelEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (atom == prop_wheel_emu)
{
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
{
pEvdev->emulateWheel.enabled = *((BOOL*)val->data);
/* Don't enable with zero inertia, otherwise we may get stuck in an
* infinite loop */
if (pEvdev->emulateWheel.inertia <= 0)
{
pEvdev->emulateWheel.inertia = 10;
/* We may get here before the property is actually enabled */
if (prop_wheel_inertia)
XIChangeDeviceProperty(dev, prop_wheel_inertia, XA_INTEGER,
16, PropModeReplace, 1,
&pEvdev->emulateWheel.inertia, TRUE);
}
/* Don't enable with negative timeout */
if (pEvdev->emulateWheel.timeout < 0)
{
pEvdev->emulateWheel.timeout = 200;
XIChangeDeviceProperty(dev, prop_wheel_timeout, XA_INTEGER, 16,
PropModeReplace, 1,
&pEvdev->emulateWheel.timeout, TRUE);
}
}
}
else if (atom == prop_wheel_button)
{
int bt;
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
bt = *((CARD8*)val->data);
if (bt < 0 || bt >= EVDEV_MAXBUTTONS)
return BadValue;
if (!checkonly)
pEvdev->emulateWheel.button = bt;
} else if (atom == prop_wheel_axismap)
{
if (val->format != 8 || val->size != 4 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
{
pEvdev->emulateWheel.X.up_button = *((CARD8*)val->data);
pEvdev->emulateWheel.X.down_button = *(((CARD8*)val->data) + 1);
pEvdev->emulateWheel.Y.up_button = *(((CARD8*)val->data) + 2);
pEvdev->emulateWheel.Y.down_button = *(((CARD8*)val->data) + 3);
}
} else if (atom == prop_wheel_inertia)
{
int inertia;
if (val->format != 16 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
inertia = *((CARD16*)val->data);
if (inertia < 0)
return BadValue;
if (!checkonly)
pEvdev->emulateWheel.inertia = inertia;
} else if (atom == prop_wheel_timeout)
{
int timeout;
if (val->format != 16 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
timeout = *((CARD16*)val->data);
if (timeout < 0)
return BadValue;
if (!checkonly)
pEvdev->emulateWheel.timeout = timeout;
}
return Success;
}
void void
EvdevWheelEmuInitProperty(DeviceIntPtr dev) EvdevWheelEmuInitProperty(DeviceIntPtr dev)
{ {
InputInfoPtr pInfo = dev->public.devicePrivate; InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
int rc = TRUE; int rc = TRUE;
INT32 vals[4] = { TRUE, FALSE}; char vals[4];
if (!dev->button) /* don't init prop for keyboards */ if (!dev->button) /* don't init prop for keyboards */
return; return;
@@ -390,96 +466,7 @@ EvdevWheelEmuInitProperty(DeviceIntPtr dev)
return; return;
XISetDevicePropertyDeletable(dev, prop_wheel_button, FALSE); XISetDevicePropertyDeletable(dev, prop_wheel_button, FALSE);
XIRegisterPropertyHandler(dev, EvdevWheelEmuSetProperty, NULL, NULL);
} }
int
EvdevWheelEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (atom == prop_wheel_emu)
{
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
{
pEvdev->emulateWheel.enabled = *((BOOL*)val->data);
/* Don't enable with zero inertia, otherwise we may get stuck in an
* infinite loop */
if (pEvdev->emulateWheel.inertia <= 0)
{
pEvdev->emulateWheel.inertia = 10;
/* We may get here before the property is actually enabled */
if (prop_wheel_inertia)
XIChangeDeviceProperty(dev, prop_wheel_inertia, XA_INTEGER,
16, PropModeReplace, 1,
&pEvdev->emulateWheel.inertia, TRUE);
}
/* Don't enable with negative timeout */
if (pEvdev->emulateWheel.timeout < 0)
{
pEvdev->emulateWheel.timeout = 200;
XIChangeDeviceProperty(dev, prop_wheel_timeout, XA_INTEGER, 16,
PropModeReplace, 1,
&pEvdev->emulateWheel.timeout, TRUE);
}
}
}
else if (atom == prop_wheel_button)
{
int bt = *((CARD8*)val->data);
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (bt < 0 || bt >= EVDEV_MAXBUTTONS)
return BadValue;
if (!checkonly)
pEvdev->emulateWheel.button = bt;
} else if (atom == prop_wheel_axismap)
{
if (val->format != 8 || val->size != 4 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
{
pEvdev->emulateWheel.X.up_button = *((CARD8*)val->data);
pEvdev->emulateWheel.X.down_button = *(((CARD8*)val->data) + 1);
pEvdev->emulateWheel.Y.up_button = *(((CARD8*)val->data) + 2);
pEvdev->emulateWheel.Y.down_button = *(((CARD8*)val->data) + 3);
}
} else if (atom == prop_wheel_inertia)
{
int inertia = *((CARD16*)val->data);
if (val->format != 16 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (inertia < 0)
return BadValue;
if (!checkonly)
pEvdev->emulateWheel.inertia = inertia;
} else if (atom == prop_wheel_timeout)
{
int timeout = *((CARD16*)val->data);
if (val->format != 16 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (timeout < 0)
return BadValue;
if (!checkonly)
pEvdev->emulateWheel.timeout = timeout;
}
return Success;
}
#endif #endif

View File

@@ -32,6 +32,7 @@
#include <X11/keysym.h> #include <X11/keysym.h>
#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@@ -51,6 +52,10 @@
#include <evdev-properties.h> #include <evdev-properties.h>
#endif #endif
#ifndef MAXDEVICES
#include <inputstr.h> /* for MAX_DEVICES */
#define MAXDEVICES MAX_DEVICES
#endif
/* 2.4 compatibility */ /* 2.4 compatibility */
#ifndef EVIOCGRAB #ifndef EVIOCGRAB
@@ -75,6 +80,8 @@
#define EVDEV_ABSOLUTE_EVENTS (1 << 3) #define EVDEV_ABSOLUTE_EVENTS (1 << 3)
#define EVDEV_TOUCHPAD (1 << 4) #define EVDEV_TOUCHPAD (1 << 4)
#define EVDEV_INITIALIZED (1 << 5) /* WheelInit etc. called already? */ #define EVDEV_INITIALIZED (1 << 5) /* WheelInit etc. called already? */
#define EVDEV_TOUCHSCREEN (1 << 6)
#define EVDEV_CALIBRATED (1 << 7) /* run-time calibrated? */
#define MIN_KEYCODE 8 #define MIN_KEYCODE 8
#define GLYPHS_PER_KEY 2 #define GLYPHS_PER_KEY 2
@@ -105,8 +112,93 @@ static void EvdevInitProperty(DeviceIntPtr dev);
static int EvdevSetProperty(DeviceIntPtr dev, Atom atom, static int EvdevSetProperty(DeviceIntPtr dev, Atom atom,
XIPropertyValuePtr val, BOOL checkonly); XIPropertyValuePtr val, BOOL checkonly);
static Atom prop_invert = 0; static Atom prop_invert = 0;
static Atom prop_reopen = 0;
static Atom prop_calibration = 0;
static Atom prop_swap = 0;
#endif #endif
/* All devices the evdev driver has allocated and knows about.
* MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
* cannot be used by evdev, leaving us with a space of 2 at the end. */
static EvdevPtr evdev_devices[MAXDEVICES] = {0};
static int
EvdevGetMajorMinor(InputInfoPtr pInfo)
{
struct stat st;
if (fstat(pInfo->fd, &st) == -1)
{
xf86Msg(X_ERROR, "%s: stat failed (%s). cannot check for duplicates.\n",
pInfo->name, strerror(errno));
return 0;
}
return st.st_rdev;
}
/**
* Return TRUE if one of the devices we know about has the same min/maj
* number.
*/
static BOOL
EvdevIsDuplicate(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = pInfo->private;
EvdevPtr* dev = evdev_devices;
if (pEvdev->min_maj)
{
while(*dev)
{
if ((*dev) != pEvdev &&
(*dev)->min_maj &&
(*dev)->min_maj == pEvdev->min_maj)
return TRUE;
dev++;
}
}
return FALSE;
}
/**
* Add to internal device list.
*/
static void
EvdevAddDevice(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = pInfo->private;
EvdevPtr* dev = evdev_devices;
while(*dev)
dev++;
*dev = pEvdev;
}
/**
* Remove from internal device list.
*/
static void
EvdevRemoveDevice(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = pInfo->private;
EvdevPtr *dev = evdev_devices;
int count = 0;
while(*dev)
{
count++;
if (*dev == pEvdev)
{
memmove(dev, dev + 1,
sizeof(evdev_devices) - (count * sizeof(EvdevPtr)));
break;
}
dev++;
}
}
static void static void
SetXkbOption(InputInfoPtr pInfo, char *name, char **option) SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
@@ -119,7 +211,6 @@ SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
*option = NULL; *option = NULL;
} else { } else {
*option = s; *option = s;
xf86Msg(X_CONFIG, "%s: %s: \"%s\"\n", pInfo->name, name, s);
} }
} }
} }
@@ -144,7 +235,7 @@ static void
PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
{ {
int code = ev->code + MIN_KEYCODE; int code = ev->code + MIN_KEYCODE;
static char warned[KEY_MAX]; static char warned[KEY_CNT];
/* filter repeat events for chording keys */ /* filter repeat events for chording keys */
if (value == 2 && if (value == 2 &&
@@ -156,13 +247,17 @@ PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
ev->code == KEY_SCROLLLOCK)) /* XXX windows keys? */ ev->code == KEY_SCROLLLOCK)) /* XXX windows keys? */
return; return;
if (code > 255 && ev->code < KEY_MAX) { if (code > 255 && ev->code <= KEY_MAX) {
if (!warned[ev->code]) if (!warned[ev->code])
xf86Msg(X_WARNING, "%s: unable to handle keycode %d\n", xf86Msg(X_WARNING, "%s: unable to handle keycode %d\n",
pInfo->name, ev->code); pInfo->name, ev->code);
warned[ev->code] = 1; 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); xf86PostKeyboardEvent(pInfo->dev, code, value);
} }
@@ -184,12 +279,10 @@ EvdevReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
if (pInfo->fd != -1) if (pInfo->fd != -1)
{ {
pEvdev->reopen_left = 0;
if (EvdevCacheCompare(pInfo, TRUE) == Success) if (EvdevCacheCompare(pInfo, TRUE) == Success)
{ {
xf86Msg(X_INFO, "%s: Device reopened after %d attempts.\n", pInfo->name, xf86Msg(X_INFO, "%s: Device reopened after %d attempts.\n", pInfo->name,
pEvdev->reopen_attempts - pEvdev->reopen_left); pEvdev->reopen_attempts - pEvdev->reopen_left + 1);
EvdevOn(pInfo->dev); EvdevOn(pInfo->dev);
} else } else
{ {
@@ -198,7 +291,9 @@ EvdevReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
DisableDevice(pInfo->dev); DisableDevice(pInfo->dev);
close(pInfo->fd); close(pInfo->fd);
pInfo->fd = -1; pInfo->fd = -1;
pEvdev->min_maj = 0; /* don't hog the device */
} }
pEvdev->reopen_left = 0;
return 0; return 0;
} }
@@ -209,6 +304,7 @@ EvdevReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
xf86Msg(X_ERROR, "%s: Failed to reopen device after %d attempts.\n", xf86Msg(X_ERROR, "%s: Failed to reopen device after %d attempts.\n",
pInfo->name, pEvdev->reopen_attempts); pInfo->name, pEvdev->reopen_attempts);
DisableDevice(pInfo->dev); DisableDevice(pInfo->dev);
pEvdev->min_maj = 0; /* don't hog the device */
return 0; return 0;
} }
@@ -220,13 +316,14 @@ EvdevReadInput(InputInfoPtr pInfo)
{ {
struct input_event ev; struct input_event ev;
int len, value; int len, value;
int dx, dy; int dx, dy, tmp;
unsigned int abs; unsigned int abs;
unsigned int button; unsigned int button;
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
dx = 0; dx = 0;
dy = 0; dy = 0;
tmp = 0;
abs = 0; abs = 0;
while (xf86WaitForInput (pInfo->fd, 0) > 0) { while (xf86WaitForInput (pInfo->fd, 0) > 0) {
@@ -313,10 +410,15 @@ EvdevReadInput(InputInfoPtr pInfo)
case BTN_TOOL_MOUSE: case BTN_TOOL_MOUSE:
case BTN_TOOL_LENS: case BTN_TOOL_LENS:
pEvdev->tool = value ? ev.code : 0; pEvdev->tool = value ? ev.code : 0;
break; if (!(pEvdev->flags & EVDEV_TOUCHSCREEN))
break;
/* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
* BTN_LEFT. */
ev.code = BTN_LEFT;
/* Intentional fallthrough! */
default: default:
button = EvdevUtilButtonEventToButtonNumber(ev.code); button = EvdevUtilButtonEventToButtonNumber(pEvdev, ev.code);
/* Handle drag lock */ /* Handle drag lock */
if (EvdevDragLockFilterEvent(pInfo, button, value)) if (EvdevDragLockFilterEvent(pInfo, button, value))
@@ -357,6 +459,11 @@ EvdevReadInput(InputInfoPtr pInfo)
} }
if (dx != 0 || dy != 0) { if (dx != 0 || dy != 0) {
if (pEvdev->swap_axes) {
tmp = dx;
dx = dy;
dy = tmp;
}
if (pEvdev->invert_x) if (pEvdev->invert_x)
dx *= -1; dx *= -1;
if (pEvdev->invert_y) if (pEvdev->invert_y)
@@ -375,18 +482,29 @@ EvdevReadInput(InputInfoPtr pInfo)
*/ */
if (abs && pEvdev->tool) { if (abs && pEvdev->tool) {
int abs_x, abs_y; int abs_x, abs_y;
abs_x = pEvdev->abs_x; abs_x = (pEvdev->swap_axes) ? pEvdev->abs_y : pEvdev->abs_x;
abs_y = pEvdev->abs_y; abs_y = (pEvdev->swap_axes) ? pEvdev->abs_x : pEvdev->abs_y;
if (pEvdev->flags & EVDEV_CALIBRATED)
{
abs_x = xf86ScaleAxis(abs_x,
pEvdev->max_x, pEvdev->min_x,
pEvdev->calibration.max_x, pEvdev->calibration.min_x);
abs_y = xf86ScaleAxis(abs_y,
pEvdev->max_y, pEvdev->min_y,
pEvdev->calibration.max_y, pEvdev->calibration.min_y);
}
if (pEvdev->invert_x) if (pEvdev->invert_x)
abs_x = pEvdev->max_x - abs_x; abs_x = pEvdev->max_x - (abs_x - pEvdev->min_x);
if (pEvdev->invert_y) if (pEvdev->invert_y)
abs_y = pEvdev->max_y - abs_y; abs_y = pEvdev->max_y - (abs_y - pEvdev->min_y);
xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, abs_x, abs_y); xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, abs_x, abs_y);
} }
} }
#define TestBit(bit, array) (array[(bit) / LONG_BITS]) & (1 << ((bit) % LONG_BITS)) #define TestBit(bit, array) (array[(bit) / LONG_BITS]) & (1L << ((bit) % LONG_BITS))
static void static void
EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl) EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
@@ -394,9 +512,6 @@ EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
/* Nothing to do, dix handles all settings */ /* Nothing to do, dix handles all settings */
} }
/* FIXME: this map works with evdev keyboards, but all the xkb maps
* probably don't. The easiest is to remap the event keycodes. */
static KeySym map[] = { static KeySym map[] = {
/* 0x00 */ NoSymbol, NoSymbol, /* 0x00 */ NoSymbol, NoSymbol,
/* 0x01 */ XK_Escape, NoSymbol, /* 0x01 */ XK_Escape, NoSymbol,
@@ -665,6 +780,8 @@ EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
struct input_event ev[ArrayLength(bits)]; struct input_event ev[ArrayLength(bits)];
int i; int i;
memset(ev, 0, sizeof(ev));
pInfo = device->public.devicePrivate; pInfo = device->public.devicePrivate;
for (i = 0; i < ArrayLength(bits); i++) { for (i = 0; i < ArrayLength(bits); i++) {
ev[i].type = EV_LED; ev[i].type = EV_LED;
@@ -736,7 +853,7 @@ EvdevAddKeyClass(DeviceIntPtr device)
SetXkbOption(pInfo, "xkb_rules", &pEvdev->xkb_rules); SetXkbOption(pInfo, "xkb_rules", &pEvdev->xkb_rules);
SetXkbOption(pInfo, "xkb_model", &pEvdev->xkb_model); SetXkbOption(pInfo, "xkb_model", &pEvdev->xkb_model);
if (!pEvdev->xkb_model) if (!pEvdev->xkb_model)
SetXkbOption(pInfo, "XkbModel", &pEvdev->xkb_rules); SetXkbOption(pInfo, "XkbModel", &pEvdev->xkb_model);
SetXkbOption(pInfo, "xkb_layout", &pEvdev->xkb_layout); SetXkbOption(pInfo, "xkb_layout", &pEvdev->xkb_layout);
if (!pEvdev->xkb_layout) if (!pEvdev->xkb_layout)
SetXkbOption(pInfo, "XkbLayout", &pEvdev->xkb_layout); SetXkbOption(pInfo, "XkbLayout", &pEvdev->xkb_layout);
@@ -949,9 +1066,6 @@ EvdevInit(DeviceIntPtr device)
/* We drop the return value, the only time we ever want the handlers to /* We drop the return value, the only time we ever want the handlers to
* unregister is when the device dies. In which case we don't have to * unregister is when the device dies. In which case we don't have to
* unregister anyway */ * unregister anyway */
XIRegisterPropertyHandler(device, EvdevMBEmuSetProperty, NULL, NULL);
XIRegisterPropertyHandler(device, EvdevWheelEmuSetProperty, NULL, NULL);
XIRegisterPropertyHandler(device, EvdevDragLockSetProperty, NULL, NULL);
XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL); XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
EvdevInitProperty(device); EvdevInitProperty(device);
EvdevMBEmuInitProperty(device); EvdevMBEmuInitProperty(device);
@@ -978,7 +1092,7 @@ EvdevOn(DeviceIntPtr device)
pInfo = device->public.devicePrivate; pInfo = device->public.devicePrivate;
pEvdev = pInfo->private; pEvdev = pInfo->private;
if (pInfo->fd != -1 && !pEvdev->kernel24 && if (pInfo->fd != -1 && pEvdev->grabDevice &&
(rc = ioctl(pInfo->fd, EVIOCGRAB, (void *)1))) (rc = ioctl(pInfo->fd, EVIOCGRAB, (void *)1)))
{ {
xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name, xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
@@ -998,14 +1112,17 @@ EvdevOn(DeviceIntPtr device)
pEvdev->reopen_timer = TimerSet(NULL, 0, 100, EvdevReopenTimer, pInfo); pEvdev->reopen_timer = TimerSet(NULL, 0, 100, EvdevReopenTimer, pInfo);
} else } else
{ {
xf86AddEnabledDevice(pInfo); pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
if ((pEvdev->flags & EVDEV_BUTTON_EVENTS) && if (EvdevIsDuplicate(pInfo))
!(pEvdev->flags & EVDEV_INITIALIZED))
{ {
EvdevMBEmuPreInit(pInfo); xf86Msg(X_WARNING, "%s: Refusing to enable duplicate device.\n",
EvdevWheelEmuPreInit(pInfo); pInfo->name);
EvdevDragLockInit(pInfo); return !Success;
} }
xf86FlushInput(pInfo->fd);
xf86AddEnabledDevice(pInfo);
EvdevMBEmuOn(pInfo);
pEvdev->flags |= EVDEV_INITIALIZED; pEvdev->flags |= EVDEV_INITIALIZED;
device->public.on = TRUE; device->public.on = TRUE;
} }
@@ -1032,15 +1149,18 @@ EvdevProc(DeviceIntPtr device, int what)
return EvdevOn(device); return EvdevOn(device);
case DEVICE_OFF: case DEVICE_OFF:
if (pEvdev->flags & EVDEV_INITIALIZED)
EvdevMBEmuFinalize(pInfo);
if (pInfo->fd != -1) if (pInfo->fd != -1)
{ {
if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)0)) if (pEvdev->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name, xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
strerror(errno)); strerror(errno));
xf86RemoveEnabledDevice(pInfo); xf86RemoveEnabledDevice(pInfo);
close(pInfo->fd); close(pInfo->fd);
pInfo->fd = -1; pInfo->fd = -1;
} }
pEvdev->min_maj = 0;
if (pEvdev->flags & EVDEV_INITIALIZED) if (pEvdev->flags & EVDEV_INITIALIZED)
EvdevMBEmuFinalize(pInfo); EvdevMBEmuFinalize(pInfo);
pEvdev->flags &= ~EVDEV_INITIALIZED; pEvdev->flags &= ~EVDEV_INITIALIZED;
@@ -1058,6 +1178,8 @@ EvdevProc(DeviceIntPtr device, int what)
close(pInfo->fd); close(pInfo->fd);
pInfo->fd = -1; pInfo->fd = -1;
} }
EvdevRemoveDevice(pInfo);
pEvdev->min_maj = 0;
break; break;
} }
@@ -1079,12 +1201,12 @@ EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare)
int i; int i;
char name[1024] = {0}; char name[1024] = {0};
long bitmask[NBITS(EV_MAX)] = {0}; long bitmask[NLONGS(EV_CNT)] = {0};
long key_bitmask[NBITS(KEY_MAX)] = {0}; long key_bitmask[NLONGS(KEY_CNT)] = {0};
long rel_bitmask[NBITS(REL_MAX)] = {0}; long rel_bitmask[NLONGS(REL_CNT)] = {0};
long abs_bitmask[NBITS(ABS_MAX)] = {0}; long abs_bitmask[NLONGS(ABS_CNT)] = {0};
long led_bitmask[NBITS(LED_MAX)] = {0}; long led_bitmask[NLONGS(LED_CNT)] = {0};
struct input_absinfo absinfo[ABS_MAX]; struct input_absinfo absinfo[ABS_CNT];
if (ioctl(pInfo->fd, if (ioctl(pInfo->fd,
EVIOCGNAME(sizeof(name) - 1), name) < 0) { EVIOCGNAME(sizeof(name) - 1), name) < 0) {
@@ -1097,7 +1219,7 @@ EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare)
if (ioctl(pInfo->fd, if (ioctl(pInfo->fd,
EVIOCGBIT(0, sizeof(bitmask)), bitmask) < 0) { EVIOCGBIT(0, sizeof(bitmask)), bitmask) < 0) {
xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno)); xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
goto error; goto error;
} }
@@ -1143,7 +1265,7 @@ EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare)
memset(absinfo, 0, sizeof(absinfo)); memset(absinfo, 0, sizeof(absinfo));
for (i = 0; i < ABS_MAX; i++) for (i = ABS_X; i <= ABS_MAX; i++)
{ {
if (TestBit(i, abs_bitmask)) if (TestBit(i, abs_bitmask))
{ {
@@ -1179,21 +1301,23 @@ error:
static int static int
EvdevProbe(InputInfoPtr pInfo) EvdevProbe(InputInfoPtr pInfo)
{ {
long key_bitmask[NBITS(KEY_MAX)]; long key_bitmask[NLONGS(KEY_CNT)] = {0};
long rel_bitmask[NBITS(REL_MAX)]; long rel_bitmask[NLONGS(REL_CNT)] = {0};
long abs_bitmask[NBITS(ABS_MAX)]; long abs_bitmask[NLONGS(ABS_CNT)] = {0};
int i, has_axes, has_keys, num_buttons; int i, has_axes, has_keys, num_buttons;
int kernel24 = 0;
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) { if (pEvdev->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
if (errno == EINVAL) { if (errno == EINVAL) {
/* keyboards are unsafe in 2.4 */ /* keyboards are unsafe in 2.4 */
pEvdev->kernel24 = 1; kernel24 = 1;
pEvdev->grabDevice = 0;
} else { } else {
xf86Msg(X_ERROR, "Grab failed. Device already configured?\n"); xf86Msg(X_ERROR, "Grab failed. Device already configured?\n");
return 1; return 1;
} }
} else { } else if (pEvdev->grabDevice) {
ioctl(pInfo->fd, EVIOCGRAB, (void *)0); ioctl(pInfo->fd, EVIOCGRAB, (void *)0);
} }
@@ -1219,23 +1343,6 @@ EvdevProbe(InputInfoPtr pInfo)
has_keys = FALSE; has_keys = FALSE;
num_buttons = 0; num_buttons = 0;
if (TestBit(REL_X, rel_bitmask) && TestBit(REL_Y, rel_bitmask)) {
xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name);
pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
has_axes = TRUE;
}
if (TestBit(ABS_X, abs_bitmask) && TestBit(ABS_Y, abs_bitmask)) {
xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name);
pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
if (TestBit(BTN_TOUCH, key_bitmask)) {
xf86Msg(X_INFO, "%s: Found absolute touchpad\n", pInfo->name);
pEvdev->flags |= EVDEV_TOUCHPAD;
pEvdev->old_x = pEvdev->old_y = -1;
}
has_axes = TRUE;
}
/* count all buttons */ /* count all buttons */
for (i = BTN_MISC; i < BTN_JOYSTICK; i++) for (i = BTN_MISC; i < BTN_JOYSTICK; i++)
{ {
@@ -1251,6 +1358,29 @@ EvdevProbe(InputInfoPtr pInfo)
num_buttons); num_buttons);
} }
if (TestBit(REL_X, rel_bitmask) && TestBit(REL_Y, rel_bitmask)) {
xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name);
pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
has_axes = TRUE;
}
if (TestBit(ABS_X, abs_bitmask) && TestBit(ABS_Y, abs_bitmask)) {
xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name);
pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
if (TestBit(BTN_TOUCH, key_bitmask)) {
if (num_buttons) {
xf86Msg(X_INFO, "%s: Found absolute touchpad\n", pInfo->name);
pEvdev->flags |= EVDEV_TOUCHPAD;
pEvdev->old_x = pEvdev->old_y = -1;
} else {
xf86Msg(X_INFO, "%s: Found absolute touchscreen\n", pInfo->name);
pEvdev->flags |= EVDEV_TOUCHSCREEN;
pEvdev->flags |= EVDEV_BUTTON_EVENTS;
}
}
has_axes = TRUE;
}
for (i = 0; i < BTN_MISC; i++) for (i = 0; i < BTN_MISC; i++)
if (TestBit(i, key_bitmask)) if (TestBit(i, key_bitmask))
break; break;
@@ -1268,8 +1398,15 @@ EvdevProbe(InputInfoPtr pInfo)
pInfo->type_name = XI_MOUSE; pInfo->type_name = XI_MOUSE;
} }
if (pEvdev->flags & EVDEV_TOUCHSCREEN) {
xf86Msg(X_INFO, "%s: Configuring as touchscreen\n", pInfo->name);
pInfo->type_name = XI_TOUCHSCREEN;
pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
XI86_CONFIGURED;
}
if (has_keys) { if (has_keys) {
if (pEvdev->kernel24) { if (kernel24) {
xf86Msg(X_INFO, "%s: Kernel < 2.6 is too old, ignoring keyboard\n", xf86Msg(X_INFO, "%s: Kernel < 2.6 is too old, ignoring keyboard\n",
pInfo->name); pInfo->name);
} else { } else {
@@ -1293,7 +1430,6 @@ static InputInfoPtr
EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags) EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
{ {
InputInfoPtr pInfo; InputInfoPtr pInfo;
MessageType deviceFrom = X_CONFIG;
const char *device; const char *device;
EvdevPtr pEvdev; EvdevPtr pEvdev;
@@ -1340,7 +1476,7 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
pEvdev->device = device; pEvdev->device = device;
xf86Msg(deviceFrom, "%s: Device: \"%s\"\n", pInfo->name, device); xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device);
do { do {
pInfo->fd = open(device, O_RDWR, 0); pInfo->fd = open(device, O_RDWR, 0);
} while (pInfo->fd < 0 && errno == EINTR); } while (pInfo->fd < 0 && errno == EINTR);
@@ -1351,9 +1487,26 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
return NULL; return NULL;
} }
/* Check major/minor of device node to avoid adding duplicate devices. */
pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
if (EvdevIsDuplicate(pInfo))
{
xf86Msg(X_WARNING, "%s: device file already in use. Ignoring.\n",
pInfo->name);
close(pInfo->fd);
xf86DeleteInput(pInfo, 0);
return NULL;
}
pEvdev->reopen_attempts = xf86SetIntOption(pInfo->options, "ReopenAttempts", 10); pEvdev->reopen_attempts = xf86SetIntOption(pInfo->options, "ReopenAttempts", 10);
pEvdev->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE); pEvdev->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE);
pEvdev->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE); pEvdev->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE);
pEvdev->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE);
/* Grabbing the event device stops in-kernel event forwarding. In other
words, it disables rfkill and the "Macintosh mouse button emulation".
Note that this needs a server that sets the console to RAW mode. */
pEvdev->grabDevice = xf86CheckBoolOption(dev->commonOptions, "GrabDevice", 0);
pEvdev->noXkb = noXkbExtension; /* parse the XKB options during kbd setup */ pEvdev->noXkb = noXkbExtension; /* parse the XKB options during kbd setup */
@@ -1366,6 +1519,14 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
} }
EvdevCacheCompare(pInfo, FALSE); /* cache device data */ EvdevCacheCompare(pInfo, FALSE); /* cache device data */
EvdevAddDevice(pInfo);
if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
{
EvdevMBEmuPreInit(pInfo);
EvdevWheelEmuPreInit(pInfo);
EvdevDragLockPreInit(pInfo);
}
return pInfo; return pInfo;
} }
@@ -1421,7 +1582,7 @@ _X_EXPORT XF86ModuleData evdevModuleData =
* returns 0 on non-button event. * returns 0 on non-button event.
*/ */
unsigned int unsigned int
EvdevUtilButtonEventToButtonNumber(int code) EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code)
{ {
unsigned int button = 0; unsigned int button = 0;
@@ -1438,6 +1599,21 @@ EvdevUtilButtonEventToButtonNumber(int code)
button = 2; button = 2;
break; break;
/* Treat BTN_[0-2] as LMR buttons on devices that do not advertise
BTN_LEFT, BTN_MIDDLE, BTN_RIGHT.
Otherwise, treat BTN_[0+n] as button 5+n.
XXX: This causes duplicate mappings for BTN_0 + n and BTN_SIDE + n
*/
case BTN_0:
button = (TestBit(BTN_LEFT, pEvdev->key_bitmask)) ? 8 : 1;
break;
case BTN_1:
button = (TestBit(BTN_MIDDLE, pEvdev->key_bitmask)) ? 9 : 2;
break;
case BTN_2:
button = (TestBit(BTN_RIGHT, pEvdev->key_bitmask)) ? 10 : 3;
break;
case BTN_SIDE: case BTN_SIDE:
case BTN_EXTRA: case BTN_EXTRA:
case BTN_FORWARD: case BTN_FORWARD:
@@ -1448,8 +1624,12 @@ EvdevUtilButtonEventToButtonNumber(int code)
default: default:
if ((code > BTN_TASK) && (code < KEY_OK)) { if ((code > BTN_TASK) && (code < KEY_OK)) {
if (code < BTN_JOYSTICK) if (code < BTN_JOYSTICK) {
button = (code - BTN_LEFT + 5); if (code < BTN_MOUSE)
button = (code - BTN_0 + 5);
else
button = (code - BTN_LEFT + 5);
}
} }
} }
@@ -1467,19 +1647,54 @@ EvdevInitProperty(DeviceIntPtr dev)
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
int rc; int rc;
BOOL invert[2]; BOOL invert[2];
char reopen;
invert[0] = pEvdev->invert_x; prop_reopen = MakeAtom(EVDEV_PROP_REOPEN, strlen(EVDEV_PROP_REOPEN),
invert[1] = pEvdev->invert_y; TRUE);
prop_invert = MakeAtom(EVDEV_PROP_INVERT_AXES, strlen(EVDEV_PROP_INVERT_AXES), TRUE); reopen = pEvdev->reopen_attempts;
rc = XIChangeDeviceProperty(dev, prop_reopen, XA_INTEGER, 8,
rc = XIChangeDeviceProperty(dev, prop_invert, XA_INTEGER, 8, PropModeReplace, 1, &reopen, FALSE);
PropModeReplace, 2,
invert, FALSE);
if (rc != Success) if (rc != Success)
return; return;
XISetDevicePropertyDeletable(dev, prop_invert, FALSE); XISetDevicePropertyDeletable(dev, prop_reopen, FALSE);
if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_ABSOLUTE_EVENTS))
{
invert[0] = pEvdev->invert_x;
invert[1] = pEvdev->invert_y;
prop_invert = MakeAtom(EVDEV_PROP_INVERT_AXES, strlen(EVDEV_PROP_INVERT_AXES), TRUE);
rc = XIChangeDeviceProperty(dev, prop_invert, XA_INTEGER, 8,
PropModeReplace, 2,
invert, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_invert, FALSE);
prop_calibration = MakeAtom(EVDEV_PROP_CALIBRATION,
strlen(EVDEV_PROP_CALIBRATION), TRUE);
rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER, 32,
PropModeReplace, 0, NULL, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_calibration, FALSE);
prop_swap = MakeAtom(EVDEV_PROP_SWAP_AXES,
strlen(EVDEV_PROP_SWAP_AXES), TRUE);
rc = XIChangeDeviceProperty(dev, prop_swap, XA_INTEGER, 8,
PropModeReplace, 1, &pEvdev->swap_axes, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_swap, FALSE);
}
} }
static int static int
@@ -1501,6 +1716,47 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
pEvdev->invert_x = data[0]; pEvdev->invert_x = data[0];
pEvdev->invert_y = data[1]; pEvdev->invert_y = data[1];
} }
} else if (atom == prop_reopen)
{
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
pEvdev->reopen_attempts = *((CARD8*)val->data);
} else if (atom == prop_calibration)
{
if (val->format != 32 || val->type != XA_INTEGER)
return BadMatch;
if (val->size != 4 && val->size != 0)
return BadMatch;
if (!checkonly)
{
if (val->size == 0)
{
pEvdev->flags &= ~EVDEV_CALIBRATED;
pEvdev->calibration.min_x = 0;
pEvdev->calibration.max_x = 0;
pEvdev->calibration.min_y = 0;
pEvdev->calibration.max_y = 0;
} else if (val->size == 4)
{
CARD32 *vals = (CARD32*)val->data;
pEvdev->flags |= EVDEV_CALIBRATED;
pEvdev->calibration.min_x = vals[0];
pEvdev->calibration.max_x = vals[1];
pEvdev->calibration.min_y = vals[2];
pEvdev->calibration.max_y = vals[3];
}
}
} else if (atom == prop_swap)
{
if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
return BadMatch;
if (!checkonly)
pEvdev->swap_axes = *((BOOL*)val->data);
} }
return Success; return Success;

View File

@@ -31,13 +31,29 @@
#define EVDEV_H #define EVDEV_H
#include <linux/input.h> #include <linux/input.h>
#include <linux/types.h>
#include <xf86Xinput.h> #include <xf86Xinput.h>
#include <xf86_OSproc.h> #include <xf86_OSproc.h>
#if defined(XKB) #ifdef XKB
/* XXX VERY WRONG. this is a client side header. */ #include <xkbstr.h>
#include <X11/extensions/XKBstr.h> #endif
#ifndef EV_CNT /* linux 2.4 kernels and earlier lack _CNT defines */
#define EV_CNT (EV_MAX+1)
#endif
#ifndef KEY_CNT
#define KEY_CNT (KEY_MAX+1)
#endif
#ifndef REL_CNT
#define REL_CNT (REL_MAX+1)
#endif
#ifndef ABS_CNT
#define ABS_CNT (ABS_MAX+1)
#endif
#ifndef LED_CNT
#define LED_CNT (LED_MAX+1)
#endif #endif
#define EVDEV_MAXBUTTONS 32 #define EVDEV_MAXBUTTONS 32
@@ -47,7 +63,9 @@
#endif #endif
#define LONG_BITS (sizeof(long) * 8) #define LONG_BITS (sizeof(long) * 8)
#define NBITS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
/* Number of longs needed to hold the given number of bits */
#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
/* axis specific data for wheel emulation */ /* axis specific data for wheel emulation */
typedef struct { typedef struct {
@@ -58,13 +76,14 @@ typedef struct {
typedef struct { typedef struct {
const char *device; const char *device;
int kernel24; int grabDevice; /* grab the event device? */
int screen; int screen;
int min_x, min_y, max_x, max_y; int min_x, min_y, max_x, max_y;
int abs_x, abs_y, old_x, old_y; int abs_x, abs_y, old_x, old_y;
int flags; int flags;
int tool; int tool;
int buttons; /* number of buttons */ int buttons; /* number of buttons */
BOOL swap_axes;
BOOL invert_x; BOOL invert_x;
BOOL invert_y; BOOL invert_y;
@@ -103,6 +122,13 @@ typedef struct {
Time expires; /* time of expiry */ Time expires; /* time of expiry */
Time timeout; Time timeout;
} emulateWheel; } emulateWheel;
/* run-time calibration */
struct {
int min_x;
int max_x;
int min_y;
int max_y;
} calibration;
unsigned char btnmap[32]; /* config-file specified button mapping */ unsigned char btnmap[32]; /* config-file specified button mapping */
@@ -112,42 +138,41 @@ typedef struct {
/* Cached info from device. */ /* Cached info from device. */
char name[1024]; char name[1024];
long bitmask[NBITS(EV_MAX)]; long bitmask[NLONGS(EV_CNT)];
long key_bitmask[NBITS(KEY_MAX)]; long key_bitmask[NLONGS(KEY_CNT)];
long rel_bitmask[NBITS(REL_MAX)]; long rel_bitmask[NLONGS(REL_CNT)];
long abs_bitmask[NBITS(ABS_MAX)]; long abs_bitmask[NLONGS(ABS_CNT)];
long led_bitmask[NBITS(LED_MAX)]; long led_bitmask[NLONGS(LED_CNT)];
struct input_absinfo absinfo[ABS_MAX]; struct input_absinfo absinfo[ABS_CNT];
/* minor/major number */
dev_t min_maj;
} EvdevRec, *EvdevPtr; } EvdevRec, *EvdevPtr;
unsigned int EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code);
/* Middle Button emulation */ /* Middle Button emulation */
int EvdevMBEmuTimer(InputInfoPtr); int EvdevMBEmuTimer(InputInfoPtr);
BOOL EvdevMBEmuFilterEvent(InputInfoPtr, int, BOOL); BOOL EvdevMBEmuFilterEvent(InputInfoPtr, int, BOOL);
void EvdevMBEmuWakeupHandler(pointer, int, pointer); void EvdevMBEmuWakeupHandler(pointer, int, pointer);
void EvdevMBEmuBlockHandler(pointer, struct timeval**, pointer); void EvdevMBEmuBlockHandler(pointer, struct timeval**, pointer);
void EvdevMBEmuPreInit(InputInfoPtr); void EvdevMBEmuPreInit(InputInfoPtr);
void EvdevMBEmuOn(InputInfoPtr);
void EvdevMBEmuFinalize(InputInfoPtr); void EvdevMBEmuFinalize(InputInfoPtr);
void EvdevMBEmuEnable(InputInfoPtr, BOOL); void EvdevMBEmuEnable(InputInfoPtr, BOOL);
unsigned int EvdevUtilButtonEventToButtonNumber(int code);
#ifdef HAVE_PROPERTIES
void EvdevMBEmuInitProperty(DeviceIntPtr);
int EvdevMBEmuSetProperty(DeviceIntPtr, Atom, XIPropertyValuePtr, BOOL);
void EvdevWheelEmuInitProperty(DeviceIntPtr);
int EvdevWheelEmuSetProperty(DeviceIntPtr, Atom, XIPropertyValuePtr, BOOL);
void EvdevDragLockInitProperty(DeviceIntPtr);
int EvdevDragLockSetProperty(DeviceIntPtr, Atom, XIPropertyValuePtr, BOOL);
#endif
/* Mouse Wheel emulation */ /* Mouse Wheel emulation */
void EvdevWheelEmuPreInit(InputInfoPtr pInfo); void EvdevWheelEmuPreInit(InputInfoPtr pInfo);
BOOL EvdevWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int value); BOOL EvdevWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int value);
BOOL EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv); BOOL EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv);
/* Draglock code */ /* Draglock code */
void EvdevDragLockInit(InputInfoPtr pInfo); void EvdevDragLockPreInit(InputInfoPtr pInfo);
BOOL EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value); BOOL EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value);
#ifdef HAVE_PROPERTIES
void EvdevMBEmuInitProperty(DeviceIntPtr);
void EvdevWheelEmuInitProperty(DeviceIntPtr);
void EvdevDragLockInitProperty(DeviceIntPtr);
#endif
#endif #endif