Compare commits

...

18 Commits

Author SHA1 Message Date
Peter Hutterer
6eab92c7e7 evdev 2.3.3
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2010-04-12 10:57:33 +10:00
Peter Hutterer
0e9990bf3b man: fix man page formatting for option EmulateWheel.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 99505011d1)

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2010-03-11 15:19:22 +10:00
Peter Hutterer
9d2156e5a6 Don't reopen ad infinitum if reopen_attempts is 0.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2010-01-08 13:41:13 +10:00
Peter Hutterer
f7850a4042 evdev 2.3.2
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2009-12-11 13:42:33 +10:00
Peter Hutterer
bd4102af6e Fix up BTN_TOUCH handling for non-button tablets.
BTN_TOOL_* is treated as tool, just like before. BTN_TOUCH on the other hand
may need to be treated as a button left press. This again requires a button
class.

Tested on an HP Touchsmart and a Wacom tablet.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 1b0df04abe)
2009-12-03 09:27:32 +10:00
Peter Hutterer
22e816eb32 Only init the calibration property for absolute devices.
Relative devices can't be calibrated anyway so why bother.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 2ca24a16f0)
2009-12-03 09:27:31 +10:00
David Woodhouse
b6b377fe9a Report initial calibration parameters.
Where an initial calibration is provided through the Calibration option
to the driver, it wasn't being exposed in the 'Evdev Axis Calibration'
property. Remedy that...

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 7b285a802b)
2009-12-03 09:27:28 +10:00
David Woodhouse
3772676fd6 Swap axes before applying touch screen calibration.
When the SwapAxes option is set, the X and Y axes in calibration should
be labelled as the user perceives them -- not as the kernel sends them.

Currently, we apply the X-axis calibration to the X-axis of the input,
and then do the axis swapping so we've actually applied the X-axis
calibration to what the user sees as the Y-axis.

This patch changes the order of the operations, so that the axes are
swapped before the calibration is applied.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit f187badb71)
2009-12-03 09:27:25 +10:00
Peter Hutterer
4f05afd495 evdev 2.3.1
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2009-11-20 11:18:03 +10:00
Bartosz Brachaczek
c6964dd28a Set all valuators for relative motion events (#24737)
We should process all the deltas reported by a relative motion device,
otherwise some devices such as A4Tech X-750F or similar may trigger a
situation when the `v` array contains random values (it isn't
initialized anywhere) and later we process them and in effect the mouse
cursor "jumps" on the screen.
I'm not sure why, but we also must be sure that the `first` and `last`
variables reflect the axis map, otherwise the mouse cursor "jumps" on
the screen when clicking mouse buttons in some rare cases reported by
Bartek Iwaniec on Bugzilla. That's why a simple initialization of the
`v` array with zeros isn't sufficient.

X.Org Bug 24737 <http://bugs.freedesktop.org/show_bug.cgi?id=24737>

Signed-off-by: Bartosz Brachaczek <b.brachaczek@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit c1f16a4f59)
2009-11-20 11:17:44 +10:00
Dmitry Torokhov
175af93bdb Relax checks when reopening devices
When checking whether we are dealing with the same device as before
when we try to reopen it evdev should not require exact match of
entire keymap. Users should be allowed to adjust keymaps to better
match their hardware even after X starts. However we don't expect
changes in [BTN_MISC, KEY_OK) range since these codes are reserved for
mice, joysticks, tablets and so forth, so we will limit the check to
this range.

The same goes for absinfo - limits can change and it should not result
in device being disabled.

Also check the length of the data returned by ioctl and don't try to
compare more than we were given.

[peter: moved the key comparison below the led+abs comparison]

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit a0f7f34dc5)
2009-11-20 11:17:42 +10:00
Peter Hutterer
7c3c7f83d0 Fix drag-lock property handler for multiple draglock buttons.
Parsing of the values was wrong. Given an input of 1 2 3 4, button 1 sets
the lock for button 2 and button 3 sets the lock for button 4.

This also means we need to return BadMatch if the property isn't a multiple
of 2.

Red Hat Bug 524428 <https://bugzilla.redhat.com/show_bug.cgi?id=524428>

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 11669d8279)
2009-11-20 11:17:41 +10:00
Peter Hutterer
aa6399fdb9 evdev 2.3.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2009-10-19 11:40:24 +10:00
Peter Hutterer
1d86f5dec1 Convert IgnoreAbsolute/RelativeAxes options into trinary state.
The Xen Virtual Pointer device exports both absolute and relative axes from
the kernel device. Which coordinates are used is a run-time decision and
depends on the host-specific configuration.
0a3657d2ee broke these devices, and they are
now unusable out-of-the-box as there is no configuration to cover them.

This patch converts the IgnoreAbsoluteAxes and the IgnoreRelativeAxes
configuration options into a trinary state.
1. If unset, configure the device as normal by trying to guess the right
   axis setup.
2. If set to true, ignore the specific axis type completely (except for
   wheel events).
3. If set to false, explicitly 'unignore' the axis type, alwas configuring
   it if it is present on the device. This setting introduces seemingly
   buggy behaviour (see Bug 21832)

1. and 2. replicate the current driver behaviour.
The result of 3. is that is that if a device has absolute axes and the
options set to false, both axes will be initialized (absolute last to get
clipping right). This requires axis labelling priorty to switch from
relative first to absolute first.

Relative events are forwarded into the server through the absolute axes,
the server scales this into the device absolute range and everyone is happy.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2009-10-15 11:36:49 +10:00
Peter Hutterer
fbd86e2530 Fix copy/paste typo in comment. 2009-10-15 10:52:27 +10:00
Peter Hutterer
9ea1f9a695 Fix typo, use uppercase like the other messages
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2009-10-13 18:30:44 +10:00
Oliver McFadden
57b54ee399 evdev: Support the "Calibration" string option.
Originally based on a patch from Daniel Stone, this commit allows for
the calibration factors to be set either from Xorg.conf or via HAL.

Previously the only way was via the properties interface.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2009-10-13 18:30:43 +10:00
Peter Hutterer
f2dc0681fe Finalize the middle button emulation when a read error occurs (#23048)
If a read error occurs, remove the block and wakeup handlers for middle
mouse button emulation. Otherwise, they'll still be around after the device
has been reopened and overwritten with the new ones created by EvdevOn. Once
this happened, future removal of the device can lead to a server crash.

X.Org Bug 23048 <http://bugs.freedesktop.org/show_bug.cgi?id=23048>

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2009-10-10 11:12:42 +10:00
4 changed files with 212 additions and 111 deletions

View File

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

View File

@@ -83,6 +83,7 @@ button event is registered. Property: "Evdev Middle Button Emulation".
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. Property: "Evdev Middle Button Timeout".
.TP 7
.BI "Option \*qEmulateWheel\*q \*q" boolean \*q
Enable/disable "wheel" emulation. Wheel emulation means emulating button
press/release events when the mouse is moved while a specific real button
@@ -138,18 +139,31 @@ Invert the given axis. Default: off. Property: "Evdev Axis Inversion".
.BI "Option \*qIgnoreRelativeAxes\*q \*q" Bool \*q
.TP 7
.BI "Option \*qIgnoreAbsoluteAxes\*q \*q" Bool \*q
Ignore the specified type of axis. Default: off. The X server cannot deal
Ignore the specified type of axis. Default: unset. The X server cannot deal
with devices that have both relative and absolute axes. Evdev tries to guess
wich axes to ignore given the device type and disables absolute axes for
mice and relative axes for tablets, touchscreens and touchpad. These options
allow to forcibly disable an axis type. Mouse wheel axes are exempt and will
work even if relative axes are ignored. No property, this configuration must
be set in the configuration.
.br
If either option is set to False, the driver will not ignore the specified
axes regardless of the presence of other axes. This may trigger buggy
behavior and events from this axis are always forwarded. Users are
discouraged from setting this option.
.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.
.TP 7
.BI "Option \*qCalibration\*q \*q" "min-x max-x min-y max-y" \*q
Calibrates the X and Y axes for devices that need to scale to a different
coordinate system than reported to the X server. This feature is required
for devices that need to scale to a different coordinate system than
originally reported by the kernel (e.g. touchscreens). The scaling to the
custom coordinate system is done in-driver and the X server is unaware of
the transformation. Property: "Evdev Axis Calibration".
.TP 7
.BI "Option \*qSwapAxes\*q \*q" Bool \*q
Swap x/y axes. Default: off. Property: "Evdev Axes Swap".
.TP 7
@@ -178,9 +192,7 @@ driver.
.TP 7
.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.
in-driver axis calibration.
.TP 7
.BI "Evdev Axis Inversion"
2 boolean values (8 bit, 0 or 1), order X, Y. 1 inverts the axis.

View File

@@ -256,7 +256,7 @@ EvdevDragLockSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
pEvdev->dragLock.meta = meta;
memset(pEvdev->dragLock.lock_pair, 0, sizeof(pEvdev->dragLock.lock_pair));
}
} else
} else if ((val->size % 2) == 0)
{
CARD8* vals = (CARD8*)val->data;
@@ -269,10 +269,11 @@ EvdevDragLockSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
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];
for (i = 0; i < val->size && i < EVDEV_MAXBUTTONS; i += 2)
pEvdev->dragLock.lock_pair[vals[i] - 1] = vals[i + 1];
}
}
} else
return BadMatch;
}
return Success;

View File

@@ -89,7 +89,9 @@
#define EVDEV_INITIALIZED (1 << 5) /* WheelInit etc. called already? */
#define EVDEV_TOUCHSCREEN (1 << 6)
#define EVDEV_CALIBRATED (1 << 7) /* run-time calibrated? */
#define EVDEV_TABLET (1 << 8) /* run-time calibrated? */
#define EVDEV_TABLET (1 << 8) /* device looks like a tablet? */
#define EVDEV_UNIGNORE_ABSOLUTE (1 << 9) /* explicitly unignore abs axes */
#define EVDEV_UNIGNORE_RELATIVE (1 << 10) /* explicitly unignore rel axes */
#define MIN_KEYCODE 8
#define GLYPHS_PER_KEY 2
@@ -376,7 +378,7 @@ EvdevReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
pEvdev->reopen_left--;
if (!pEvdev->reopen_left)
if (pEvdev->reopen_left <= 0)
{
xf86Msg(X_ERROR, "%s: Failed to reopen device after %d attempts.\n",
pInfo->name, pEvdev->reopen_attempts);
@@ -438,7 +440,7 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
for (i = 0; i < REL_CNT; i++)
{
int map = pEvdev->axis_map[i];
if (pEvdev->delta[i] && map != -1)
if (map != -1)
{
v[map] = pEvdev->delta[i];
if (map < first)
@@ -462,6 +464,13 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
*/
else if (pEvdev->abs && pEvdev->tool) {
memcpy(v, pEvdev->vals, sizeof(int) * pEvdev->num_vals);
if (pEvdev->swap_axes) {
int tmp = v[0];
v[0] = v[1];
v[1] = tmp;
}
if (pEvdev->flags & EVDEV_CALIBRATED)
{
v[0] = xf86ScaleAxis(v[0],
@@ -474,12 +483,6 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
pEvdev->calibration.max_y, pEvdev->calibration.min_y);
}
if (pEvdev->swap_axes) {
int tmp = v[0];
v[0] = v[1];
v[1] = tmp;
}
if (pEvdev->invert_x)
v[0] = (pEvdev->absinfo[ABS_X].maximum - v[0] +
pEvdev->absinfo[ABS_X].minimum);
@@ -614,7 +617,6 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
return;
switch (ev->code) {
case BTN_TOUCH:
case BTN_TOOL_PEN:
case BTN_TOOL_RUBBER:
case BTN_TOOL_BRUSH:
@@ -624,7 +626,11 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
case BTN_TOOL_MOUSE:
case BTN_TOOL_LENS:
pEvdev->tool = value ? ev->code : 0;
if (!(pEvdev->flags & EVDEV_TOUCHSCREEN))
break;
case BTN_TOUCH:
pEvdev->tool = value ? ev->code : 0;
if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET)))
break;
/* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
* BTN_LEFT. */
@@ -768,6 +774,7 @@ EvdevReadInput(InputInfoPtr pInfo)
{
if (errno == ENODEV) /* May happen after resume */
{
EvdevMBEmuFinalize(pInfo);
xf86RemoveEnabledDevice(pInfo);
close(pInfo->fd);
pInfo->fd = -1;
@@ -1421,6 +1428,17 @@ EvdevInitButtonMapping(InputInfoPtr pInfo)
}
static void
EvdevInitAnyClass(DeviceIntPtr device, EvdevPtr pEvdev)
{
if (pEvdev->flags & EVDEV_RELATIVE_EVENTS &&
EvdevAddRelClass(device) == Success)
xf86Msg(X_INFO, "%s: initialized for relative axes.\n", device->name);
if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS &&
EvdevAddAbsClass(device) == Success)
xf86Msg(X_INFO, "%s: initialized for absolute axes.\n", device->name);
}
static void
EvdevInitAbsClass(DeviceIntPtr device, EvdevPtr pEvdev)
{
@@ -1512,7 +1530,9 @@ EvdevInit(DeviceIntPtr device)
* used and relative axes are ignored.
*/
if (pEvdev->flags & (EVDEV_TOUCHPAD | EVDEV_TOUCHSCREEN | EVDEV_TABLET))
if (pEvdev->flags & (EVDEV_UNIGNORE_RELATIVE | EVDEV_UNIGNORE_ABSOLUTE))
EvdevInitAnyClass(device, pEvdev);
else if (pEvdev->flags & (EVDEV_TOUCHPAD | EVDEV_TOUCHSCREEN | EVDEV_TABLET))
EvdevInitTouchDevice(device, pEvdev);
else if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
EvdevInitRelClass(device, pEvdev);
@@ -1655,6 +1675,7 @@ static int
EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare)
{
EvdevPtr pEvdev = pInfo->private;
size_t len;
int i;
char name[1024] = {0};
@@ -1663,107 +1684,122 @@ EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare)
unsigned long rel_bitmask[NLONGS(REL_CNT)] = {0};
unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0};
unsigned long led_bitmask[NLONGS(LED_CNT)] = {0};
struct input_absinfo absinfo[ABS_CNT];
if (ioctl(pInfo->fd,
EVIOCGNAME(sizeof(name) - 1), name) < 0) {
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)) {
xf86Msg(X_ERROR, "%s: device name changed: %s != %s\n", pInfo->name, pEvdev->name, name);
if (!compare) {
strcpy(pEvdev->name, name);
} else if (strcmp(pEvdev->name, name)) {
xf86Msg(X_ERROR, "%s: device name changed: %s != %s\n",
pInfo->name, pEvdev->name, name);
goto error;
}
if (ioctl(pInfo->fd,
EVIOCGBIT(0, sizeof(bitmask)), bitmask) < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n", pInfo->name, strerror(errno));
len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask);
if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
pInfo->name, strerror(errno));
goto error;
}
if (compare && memcmp(pEvdev->bitmask, bitmask, sizeof(bitmask))) {
if (!compare) {
memcpy(pEvdev->bitmask, bitmask, len);
} else if (memcmp(pEvdev->bitmask, bitmask, len)) {
xf86Msg(X_ERROR, "%s: device bitmask has changed\n", pInfo->name);
goto error;
}
if (ioctl(pInfo->fd,
EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n", pInfo->name, strerror(errno));
len = ioctl(pInfo->fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask);
if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
pInfo->name, strerror(errno));
goto error;
}
if (compare && memcmp(pEvdev->rel_bitmask, rel_bitmask, sizeof(rel_bitmask))) {
if (!compare) {
memcpy(pEvdev->rel_bitmask, rel_bitmask, len);
} else if (memcmp(pEvdev->rel_bitmask, rel_bitmask, len)) {
xf86Msg(X_ERROR, "%s: device rel_bitmask has changed\n", pInfo->name);
goto error;
}
if (ioctl(pInfo->fd,
EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n", pInfo->name, strerror(errno));
len = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
pInfo->name, strerror(errno));
goto error;
}
if (compare && memcmp(pEvdev->abs_bitmask, abs_bitmask, sizeof(abs_bitmask))) {
if (!compare) {
memcpy(pEvdev->abs_bitmask, abs_bitmask, len);
} else if (memcmp(pEvdev->abs_bitmask, abs_bitmask, len)) {
xf86Msg(X_ERROR, "%s: device abs_bitmask has changed\n", pInfo->name);
goto error;
}
if (ioctl(pInfo->fd,
EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n", pInfo->name, strerror(errno));
len = ioctl(pInfo->fd, EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask);
if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
pInfo->name, strerror(errno));
goto error;
}
if (compare && memcmp(pEvdev->key_bitmask, key_bitmask, sizeof(key_bitmask))) {
xf86Msg(X_ERROR, "%s: device key_bitmask has changed\n", pInfo->name);
goto error;
}
if (ioctl(pInfo->fd,
EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask) < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n", pInfo->name, strerror(errno));
goto error;
}
if (compare && memcmp(pEvdev->led_bitmask, led_bitmask, sizeof(led_bitmask))) {
if (!compare) {
memcpy(pEvdev->led_bitmask, led_bitmask, len);
} else if (memcmp(pEvdev->led_bitmask, led_bitmask, len)) {
xf86Msg(X_ERROR, "%s: device led_bitmask has changed\n", pInfo->name);
goto error;
}
memset(absinfo, 0, sizeof(absinfo));
for (i = ABS_X; i <= ABS_MAX; i++)
{
if (TestBit(i, abs_bitmask))
{
if (ioctl(pInfo->fd, EVIOCGABS(i), &absinfo[i]) < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGABS failed: %s\n", pInfo->name, strerror(errno));
/*
* Do not try to validate absinfo data since it is not expected
* to be static, always refresh it in evdev structure.
*/
for (i = ABS_X; i <= ABS_MAX; i++) {
if (TestBit(i, abs_bitmask)) {
len = ioctl(pInfo->fd, EVIOCGABS(i), &pEvdev->absinfo[i]);
if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGABSi(%d) failed: %s\n",
pInfo->name, i, strerror(errno));
goto error;
}
/* ignore current position (value) in comparison (bug #19819) */
absinfo[i].value = pEvdev->absinfo[i].value;
}
}
if (compare && memcmp(pEvdev->absinfo, absinfo, sizeof(absinfo))) {
xf86Msg(X_ERROR, "%s: device absinfo has changed\n", pInfo->name);
len = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask);
if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
pInfo->name, strerror(errno));
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));
if (compare) {
/*
* Keys are special as user can adjust keymap at any time (on
* devices that support EVIOCSKEYCODE. However we do not expect
* buttons reserved for mice/tablets/digitizers and so on to
* appear/disappear so we will check only those in
* [BTN_MISC, KEY_OK) range.
*/
size_t start_word = BTN_MISC / LONG_BITS;
size_t start_byte = start_word * sizeof(unsigned long);
size_t end_word = KEY_OK / LONG_BITS;
size_t end_byte = end_word * sizeof(unsigned long);
if (len >= start_byte &&
memcmp(&pEvdev->key_bitmask[start_word], &key_bitmask[start_word],
min(len, end_byte) - start_byte + 1)) {
xf86Msg(X_ERROR, "%s: device key_bitmask has changed\n", pInfo->name);
goto error;
}
}
/* Copy the data so we have reasonably up-to-date info */
memcpy(pEvdev->key_bitmask, key_bitmask, len);
return Success;
error:
@@ -1776,7 +1812,7 @@ EvdevProbe(InputInfoPtr pInfo)
{
int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll;
int kernel24 = 0;
int ignore_rel, ignore_abs;
int ignore_abs = 0, ignore_rel = 0;
EvdevPtr pEvdev = pInfo->private;
if (pEvdev->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
@@ -1792,8 +1828,26 @@ EvdevProbe(InputInfoPtr pInfo)
ioctl(pInfo->fd, EVIOCGRAB, (void *)0);
}
ignore_rel = xf86SetBoolOption(pInfo->options, "IgnoreRelativeAxes", FALSE);
ignore_abs = xf86SetBoolOption(pInfo->options, "IgnoreAbsoluteAxes", FALSE);
/* Trinary state for ignoring axes:
- unset: do the normal thing.
- TRUE: explicitly ignore them.
- FALSE: unignore axes, use them at all cost if they're present.
*/
if (xf86FindOption(pInfo->options, "IgnoreRelativeAxes"))
{
if (xf86SetBoolOption(pInfo->options, "IgnoreRelativeAxes", FALSE))
ignore_rel = TRUE;
else
pEvdev->flags |= EVDEV_UNIGNORE_RELATIVE;
}
if (xf86FindOption(pInfo->options, "IgnoreAbsoluteAxes"))
{
if (xf86SetBoolOption(pInfo->options, "IgnoreAbsoluteAxes", FALSE))
ignore_abs = TRUE;
else
pEvdev->flags |= EVDEV_UNIGNORE_ABSOLUTE;
}
has_rel_axes = FALSE;
has_abs_axes = FALSE;
@@ -1843,7 +1897,7 @@ EvdevProbe(InputInfoPtr pInfo)
if (!ignore_rel)
{
xf86Msg(X_INFO, "%s: found relative axes\n", pInfo->name);
xf86Msg(X_INFO, "%s: Found relative axes\n", pInfo->name);
pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
if (TestBit(REL_X, pEvdev->rel_bitmask) &&
@@ -1851,7 +1905,7 @@ EvdevProbe(InputInfoPtr pInfo)
xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name);
}
} else {
xf86Msg(X_INFO, "%s: relative axes present but ignored.\n", pInfo->name);
xf86Msg(X_INFO, "%s: Relative axes present but ignored.\n", pInfo->name);
has_rel_axes = FALSE;
}
}
@@ -1865,10 +1919,10 @@ EvdevProbe(InputInfoPtr pInfo)
if (ignore_abs && has_abs_axes)
{
xf86Msg(X_INFO, "%s: absolute axes present but ignored.\n", pInfo->name);
xf86Msg(X_INFO, "%s: Absolute axes present but ignored.\n", pInfo->name);
has_abs_axes = FALSE;
} else if (has_abs_axes) {
xf86Msg(X_INFO, "%s: found absolute axes\n", pInfo->name);
xf86Msg(X_INFO, "%s: Found absolute axes\n", pInfo->name);
pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
if ((TestBit(ABS_X, pEvdev->abs_bitmask) &&
@@ -1878,6 +1932,11 @@ EvdevProbe(InputInfoPtr pInfo)
{
xf86Msg(X_INFO, "%s: Found absolute tablet.\n", pInfo->name);
pEvdev->flags |= EVDEV_TABLET;
if (!pEvdev->num_buttons)
{
pEvdev->num_buttons = 7; /* LMR + scroll wheels */
pEvdev->flags |= EVDEV_BUTTON_EVENTS;
}
} else if (TestBit(ABS_PRESSURE, pEvdev->abs_bitmask) ||
TestBit(BTN_TOUCH, pEvdev->key_bitmask)) {
if (num_buttons || TestBit(BTN_TOOL_FINGER, pEvdev->key_bitmask)) {
@@ -1949,12 +2008,32 @@ EvdevProbe(InputInfoPtr pInfo)
return 0;
}
static void
EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4])
{
EvdevPtr pEvdev = pInfo->private;
if (num_calibration == 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 (num_calibration == 4) {
pEvdev->flags |= EVDEV_CALIBRATED;
pEvdev->calibration.min_x = calibration[0];
pEvdev->calibration.max_x = calibration[1];
pEvdev->calibration.min_y = calibration[2];
pEvdev->calibration.max_y = calibration[3];
}
}
static InputInfoPtr
EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
{
InputInfoPtr pInfo;
const char *device;
const char *device, *str;
int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 };
EvdevPtr pEvdev;
if (!(pInfo = xf86AllocateInput(drv, 0)))
@@ -2027,6 +2106,19 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
pEvdev->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE);
pEvdev->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE);
str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
if (str) {
num_calibration = sscanf(str, "%d %d %d %d",
&calibration[0], &calibration[1],
&calibration[2], &calibration[3]);
if (num_calibration == 4)
EvdevSetCalibration(pInfo, num_calibration, calibration);
else
xf86Msg(X_ERROR,
"%s: Insufficient calibration factors (%d). Ignoring calibration\n",
pInfo->name, num_calibration);
}
/* 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. */
@@ -2318,16 +2410,16 @@ static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms)
int labels_len = 0;
char *misc_label;
if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
{
labels = rel_labels;
labels_len = ArrayLength(rel_labels);
misc_label = AXIS_LABEL_PROP_REL_MISC;
} else if ((pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
{
labels = abs_labels;
labels_len = ArrayLength(abs_labels);
misc_label = AXIS_LABEL_PROP_ABS_MISC;
} else if ((pEvdev->flags & EVDEV_RELATIVE_EVENTS))
{
labels = rel_labels;
labels_len = ArrayLength(rel_labels);
misc_label = AXIS_LABEL_PROP_REL_MISC;
}
memset(atoms, 0, natoms * sizeof(Atom));
@@ -2427,8 +2519,22 @@ EvdevInitProperty(DeviceIntPtr dev)
prop_calibration = MakeAtom(EVDEV_PROP_CALIBRATION,
strlen(EVDEV_PROP_CALIBRATION), TRUE);
rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER, 32,
PropModeReplace, 0, NULL, FALSE);
if (pEvdev->flags & EVDEV_CALIBRATED) {
int calibration[4];
calibration[0] = pEvdev->calibration.min_x;
calibration[1] = pEvdev->calibration.max_x;
calibration[2] = pEvdev->calibration.min_y;
calibration[3] = pEvdev->calibration.max_y;
rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER,
32, PropModeReplace, 4, calibration,
FALSE);
} else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) {
rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER,
32, PropModeReplace, 0, NULL,
FALSE);
}
if (rc != Success)
return;
@@ -2502,25 +2608,7 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
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];
}
}
EvdevSetCalibration(pInfo, val->size, val->data);
} else if (atom == prop_swap)
{
if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)