[PATCH libinput] evdev: allow weird multitouch device without slots

Leonid Borisenko leo.borisenko at gmail.com
Mon Aug 18 20:29:40 PDT 2014


HID device 'USB HID v1.11 Mouse' provided by Microsoft Wireless Optical
Desktop® 2.20 (connected to USB and identified as vendor 0x45e, product
0xe3, version 0x111) is reported as supporting EV_ABS event with ABS_MT_SLOT
code, but nevertheless libevdev_get_num_slots returns -1.

Furthermore, all connected devices (mouse and keyboard) don't produce any
EV_ABS events for that HID Mouse device in tests with evtest.

Before this fix mouse didn't work in Weston (but worked in X.Org).

As partially explained by LKML message [1] (Message-Id [2]):

    The root of the problem comes from hid-input, which maps unknown axis
    to ABS_MISC. However, when an event code is already in use, hid-input
    uses the one after, leading to uses of ABS_MISC + N, where N is the
    number of unknown axis.

    We are encountering a problem with the multitouch protocol here because
    if a device has more than 7 unknown axis (which is the case for the PS3
    Sixaxis controller), then the unknown axis get maps to ABS_MT_SLOT and
    beyond.

[1] https://lkml.org/lkml/2013/11/20/515
[2] 1384983141-31019-1-git-send-email-benjamin.tissoires at redhat.com

Signed-off-by: Leonid Borisenko <leo.borisenko at gmail.com>
---
 src/evdev.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index a125510..d6a14b7 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -144,7 +144,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
 		pointer_notify_motion(base, time, motion.dx, motion.dy);
 		break;
 	case EVDEV_ABSOLUTE_MT_DOWN:
-		if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
+		if (slot == -1 || !(device->seat_caps & EVDEV_DEVICE_TOUCH))
 			break;
 
 		if (device->mt.slots[slot].seat_slot != -1) {
@@ -167,7 +167,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
 		touch_notify_touch_down(base, time, slot, seat_slot, x, y);
 		break;
 	case EVDEV_ABSOLUTE_MT_MOTION:
-		if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
+		if (slot == -1 || !(device->seat_caps & EVDEV_DEVICE_TOUCH))
 			break;
 
 		seat_slot = device->mt.slots[slot].seat_slot;
@@ -180,7 +180,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
 		touch_notify_touch_motion(base, time, slot, seat_slot, x, y);
 		break;
 	case EVDEV_ABSOLUTE_MT_UP:
-		if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
+		if (slot == -1 || !(device->seat_caps & EVDEV_DEVICE_TOUCH))
 			break;
 
 		seat_slot = device->mt.slots[slot].seat_slot;
@@ -680,6 +680,16 @@ evdev_configure_device(struct evdev_device *device)
 				active_slot = libevdev_get_current_slot(evdev);
 			}
 
+			if (num_slots <= 0) {
+				log_bug_kernel(libinput,
+					       "multitouch input device %s "
+					       "has %s slots\n",
+					       device->devnode,
+					       num_slots == 0 ? "0" : "no");
+				num_slots = 0;
+				active_slot = -1;
+			}
+
 			slots = calloc(num_slots, sizeof(struct mt_slot));
 			if (!slots)
 				return -1;
-- 
2.1.0.rc1



More information about the wayland-devel mailing list