Compare commits

...

4 Commits

Author SHA1 Message Date
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
3 changed files with 78 additions and 61 deletions

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.3.0, 2.3.1,
[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

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

View File

@@ -440,7 +440,7 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
for (i = 0; i < REL_CNT; i++) for (i = 0; i < REL_CNT; i++)
{ {
int map = pEvdev->axis_map[i]; int map = pEvdev->axis_map[i];
if (pEvdev->delta[i] && map != -1) if (map != -1)
{ {
v[map] = pEvdev->delta[i]; v[map] = pEvdev->delta[i];
if (map < first) if (map < first)
@@ -1671,6 +1671,7 @@ static int
EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare) EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare)
{ {
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
size_t len;
int i; int i;
char name[1024] = {0}; char name[1024] = {0};
@@ -1679,107 +1680,122 @@ EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare)
unsigned long rel_bitmask[NLONGS(REL_CNT)] = {0}; unsigned long rel_bitmask[NLONGS(REL_CNT)] = {0};
unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0}; unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0};
unsigned long led_bitmask[NLONGS(LED_CNT)] = {0}; unsigned long led_bitmask[NLONGS(LED_CNT)] = {0};
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) {
xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno)); xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
goto error; goto error;
} }
if (compare && strcmp(pEvdev->name, name)) { if (!compare) {
xf86Msg(X_ERROR, "%s: device name changed: %s != %s\n", pInfo->name, pEvdev->name, name); 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; goto error;
} }
if (ioctl(pInfo->fd, len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask);
EVIOCGBIT(0, sizeof(bitmask)), bitmask) < 0) { if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n", pInfo->name, strerror(errno)); xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
pInfo->name, strerror(errno));
goto error; 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); xf86Msg(X_ERROR, "%s: device bitmask has changed\n", pInfo->name);
goto error; goto error;
} }
len = ioctl(pInfo->fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask);
if (ioctl(pInfo->fd, if (len < 0) {
EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) < 0) { xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n", pInfo->name, strerror(errno)); pInfo->name, strerror(errno));
goto error; 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); xf86Msg(X_ERROR, "%s: device rel_bitmask has changed\n", pInfo->name);
goto error; goto error;
} }
if (ioctl(pInfo->fd, len = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) < 0) { if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n", pInfo->name, strerror(errno)); xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
pInfo->name, strerror(errno));
goto error; 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); xf86Msg(X_ERROR, "%s: device abs_bitmask has changed\n", pInfo->name);
goto error; goto error;
} }
if (ioctl(pInfo->fd, len = ioctl(pInfo->fd, EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask);
EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) < 0) { if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n", pInfo->name, strerror(errno)); xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
pInfo->name, strerror(errno));
goto error; goto error;
} }
if (compare && memcmp(pEvdev->key_bitmask, key_bitmask, sizeof(key_bitmask))) { if (!compare) {
xf86Msg(X_ERROR, "%s: device key_bitmask has changed\n", pInfo->name); memcpy(pEvdev->led_bitmask, led_bitmask, len);
goto error; } else if (memcmp(pEvdev->led_bitmask, led_bitmask, len)) {
}
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))) {
xf86Msg(X_ERROR, "%s: device led_bitmask has changed\n", pInfo->name); xf86Msg(X_ERROR, "%s: device led_bitmask has changed\n", pInfo->name);
goto error; goto error;
} }
memset(absinfo, 0, sizeof(absinfo)); /*
* Do not try to validate absinfo data since it is not expected
for (i = ABS_X; i <= ABS_MAX; i++) * to be static, always refresh it in evdev structure.
{ */
if (TestBit(i, abs_bitmask)) for (i = ABS_X; i <= ABS_MAX; i++) {
{ if (TestBit(i, abs_bitmask)) {
if (ioctl(pInfo->fd, EVIOCGABS(i), &absinfo[i]) < 0) { len = ioctl(pInfo->fd, EVIOCGABS(i), &pEvdev->absinfo[i]);
xf86Msg(X_ERROR, "%s: ioctl EVIOCGABS failed: %s\n", pInfo->name, strerror(errno)); if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGABSi(%d) failed: %s\n",
pInfo->name, i, strerror(errno));
goto error; 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))) { len = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask);
xf86Msg(X_ERROR, "%s: device absinfo has changed\n", pInfo->name); if (len < 0) {
xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
pInfo->name, strerror(errno));
goto error; goto error;
} }
/* cache info */ if (compare) {
if (!compare) /*
{ * Keys are special as user can adjust keymap at any time (on
strcpy(pEvdev->name, name); * devices that support EVIOCSKEYCODE. However we do not expect
memcpy(pEvdev->bitmask, bitmask, sizeof(bitmask)); * buttons reserved for mice/tablets/digitizers and so on to
memcpy(pEvdev->key_bitmask, key_bitmask, sizeof(key_bitmask)); * appear/disappear so we will check only those in
memcpy(pEvdev->rel_bitmask, rel_bitmask, sizeof(rel_bitmask)); * [BTN_MISC, KEY_OK) range.
memcpy(pEvdev->abs_bitmask, abs_bitmask, sizeof(abs_bitmask)); */
memcpy(pEvdev->led_bitmask, led_bitmask, sizeof(led_bitmask)); size_t start_word = BTN_MISC / LONG_BITS;
memcpy(pEvdev->absinfo, absinfo, sizeof(absinfo)); 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; return Success;
error: error: