[PATCH evdev] Don't use mtdev for protocol B devices

Peter Hutterer peter.hutterer at who-t.net
Wed Aug 7 20:41:17 PDT 2013


If a device has ABS_MT_SLOT, mtdev merely reads the events and returns them
to the caller as-is. For this we don't need mtdev, we can just handle those
events ourselves.

This patch switches to the mtdev plumbing layer that takes events and
converts them instead of reading them off the fd.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 58 insertions(+), 19 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index ba2a98c..fc88190 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -53,6 +53,9 @@
 #include <X11/Xatom.h>
 #include <evdev-properties.h>
 #include <xserver-properties.h>
+#ifdef MULTITOUCH
+#include <mtdev-plumbing.h>
+#endif
 
 #ifndef XI_PROP_PRODUCT_ID
 #define XI_PROP_PRODUCT_ID "Device Product ID"
@@ -780,7 +783,7 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev)
     EvdevPtr pEvdev = pInfo->private;
     int map;
 
-    if (!pEvdev->mtdev)
+    if (!pEvdev->mtdev && !EvdevBitIsSet(pEvdev->abs_bitmask, ABS_MT_SLOT))
         return;
 
     if (ev->code == ABS_MT_SLOT) {
@@ -1096,6 +1099,35 @@ EvdevFreeMasks(EvdevPtr pEvdev)
 #endif
 }
 
+static void
+EvdevProcessAllEvents(InputInfoPtr pInfo, struct input_event *ev, int nevents, size_t max_events)
+{
+    EvdevPtr pEvdev = pInfo->private;
+    int i, more_events_left = 0;
+
+    do {
+#ifdef MULTITOUCH
+        if (pEvdev->mtdev) {
+            int nmtevents = 0;
+            for (i = 0; i < nevents; i++)
+                mtdev_put_event(pEvdev->mtdev, &ev[i]);
+
+            while (!mtdev_empty(pEvdev->mtdev) && nmtevents < max_events)
+                mtdev_get_event(pEvdev->mtdev, &ev[nmtevents++]);
+
+            /* mtdev may have converted to more events than we have space for */
+            more_events_left = nmtevents >= max_events && !mtdev_empty(pEvdev->mtdev);
+            nevents = nmtevents;
+        }
+#endif
+
+        for (i = 0; i < nevents; i++)
+            EvdevProcessEvent(pInfo, &ev[i]);
+
+        nevents = 0;
+    } while(more_events_left);
+}
+
 /* just a magic number to reduce the number of reads */
 #define NUM_EVENTS 16
 
@@ -1103,19 +1135,11 @@ static void
 EvdevReadInput(InputInfoPtr pInfo)
 {
     struct input_event ev[NUM_EVENTS];
-    int i, len = sizeof(ev);
+    int len = sizeof(ev);
 
     while (len == sizeof(ev))
     {
-#ifdef MULTITOUCH
-        EvdevPtr pEvdev = pInfo->private;
-
-        if (pEvdev->mtdev)
-            len = mtdev_get(pEvdev->mtdev, pInfo->fd, ev, NUM_EVENTS) *
-                sizeof(struct input_event);
-        else
-#endif
-            len = read(pInfo->fd, &ev, sizeof(ev));
+        len = read(pInfo->fd, &ev, sizeof(ev));
 
         if (len <= 0)
         {
@@ -1134,8 +1158,8 @@ EvdevReadInput(InputInfoPtr pInfo)
             break;
         }
 
-        for (i = 0; i < len/sizeof(ev[0]); i++)
-            EvdevProcessEvent(pInfo, &ev[i]);
+        EvdevProcessAllEvents(pInfo, ev, len/sizeof(ev[0]), NUM_EVENTS);
+
     }
 }
 
@@ -1417,15 +1441,19 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes)
     }
 
 #ifdef MULTITOUCH
-    if (pEvdev->mtdev && num_mt_axes_total > 0)
+    if (num_mt_axes_total > 0)
     {
         int num_touches = 0;
         int mode = pEvdev->flags & EVDEV_TOUCHPAD ?
             XIDependentTouch : XIDirectTouch;
 
-        if (pEvdev->mtdev->caps.slot.maximum > 0)
-            num_touches = pEvdev->mtdev->caps.slot.maximum -
-                          pEvdev->mtdev->caps.slot.minimum + 1;
+        if (pEvdev->mtdev) {
+            if (pEvdev->mtdev->caps.slot.maximum > 0)
+                num_touches = pEvdev->mtdev->caps.slot.maximum -
+                              pEvdev->mtdev->caps.slot.minimum + 1;
+        } else
+            num_touches = pEvdev->absinfo[ABS_MT_SLOT].maximum -
+                          pEvdev->absinfo[ABS_MT_SLOT].minimum + 1;
 
         if (!InitTouchClassDeviceStruct(device, num_touches, mode,
                                         num_mt_axes_total)) {
@@ -1437,10 +1465,11 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes)
         for (i = 0; i < num_slots(pEvdev); i++) {
             for (axis = ABS_MT_TOUCH_MAJOR; axis < ABS_MAX; axis++) {
                 if (pEvdev->abs_axis_map[axis] >= 0) {
+                    int val = pEvdev->mtdev ? 0 : pEvdev->absinfo[axis].value;
                     /* XXX: read initial values from mtdev when it adds support
                      *      for doing so. */
                     valuator_mask_set(pEvdev->last_mt_vals[i],
-                                      pEvdev->abs_axis_map[axis], 0);
+                                      pEvdev->abs_axis_map[axis], val);
                 }
             }
         }
@@ -2400,7 +2429,7 @@ EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4])
 #ifdef MULTITOUCH
 /**
  * Open an mtdev device for this device. mtdev is a bit too generous with
- * memory usage, so only do so for devices with multitouch bits set.
+ * memory usage, so only do so for multitouch protocol A devices.
  *
  * @return FALSE on error, TRUE if mtdev was initiated or the device doesn't
  * need it
@@ -2416,6 +2445,12 @@ EvdevOpenMTDev(InputInfoPtr pInfo)
     if (pEvdev->mtdev) {
         pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value;
         return TRUE;
+    } else if (EvdevBitIsSet(pEvdev->abs_bitmask, ABS_MT_SLOT)) {
+        struct input_absinfo abs;
+        len = ioctl(pInfo->fd, EVIOCGABS(ABS_MT_SLOT), &abs);
+        if (len != -1)
+            pEvdev->cur_slot = abs.value;
+        return TRUE;
     }
 
     if (pInfo->fd < 0) {
@@ -2441,6 +2476,10 @@ EvdevOpenMTDev(InputInfoPtr pInfo)
         return FALSE;
     }
 
+    /* don't need mtdev for protocol B devices */
+    if (EvdevBitIsSet(abs_bitmask, ABS_MT_SLOT))
+        return TRUE;
+
     if (!EvdevBitIsSet(abs_bitmask, ABS_MT_POSITION_X) ||
         !EvdevBitIsSet(abs_bitmask, ABS_MT_POSITION_Y))
         return TRUE;
-- 
1.8.2.1



More information about the xorg-devel mailing list