[RFC XI 2.1 - xf86-input-evdev 3/3] Use MTDev for multitouch devices

Chase Douglas chase.douglas at canonical.com
Fri Nov 12 14:35:13 PST 2010


From: Chase Douglas <chase.douglas at ubuntu.com>

MTDev translates all multitouch devices to the slotted evdev protocol.
This provides a clean and uniform interface and reduces message handling
inside the input module and X.

Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
---
 configure.ac    |    3 +++
 src/Makefile.am |    2 +-
 src/evdev.c     |   44 ++++++++++++++++++++++++++++++++++++++++----
 src/evdev.h     |    7 +++++++
 4 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/configure.ac b/configure.ac
index cc9e721..ed87352 100644
--- a/configure.ac
+++ b/configure.ac
@@ -56,6 +56,9 @@ AC_ARG_ENABLE(multitouch,
 
 if test "x$MULTITOUCH" = xyes; then
         AC_DEFINE(MULTITOUCH, 1, [Enable experimental multitouch code])
+
+        # Obtain compiler/linker options for mtdev
+        PKG_CHECK_MODULES(MTDEV, mtdev)
 fi
 
 # Define a configure option for an alternate input module directory
diff --git a/src/Makefile.am b/src/Makefile.am
index a5c89ac..89137bc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,7 +29,7 @@ AM_CFLAGS = $(XORG_CFLAGS) $(CWARNFLAGS)
 AM_CPPFLAGS =-I$(top_srcdir)/include
 
 @DRIVER_NAME at _drv_la_LTLIBRARIES = @DRIVER_NAME at _drv.la
- at DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
+ at DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version $(MTDEV_LIBS)
 @DRIVER_NAME at _drv_ladir = @inputdir@
 
 @DRIVER_NAME at _drv_la_SOURCES = @DRIVER_NAME at .c \
diff --git a/src/evdev.c b/src/evdev.c
index 8b13e9f..a83d4e4 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1065,7 +1065,17 @@ EvdevReadInput(InputInfoPtr pInfo)
 
     while (len == sizeof(ev))
     {
-        len = read(pInfo->fd, &ev, 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
+            len = read(pInfo->fd, &ev, sizeof(ev));
+#else
+            len = read(pInfo->fd, &ev, sizeof(ev));
+#endif
         if (len <= 0)
         {
             if (errno == ENODEV) /* May happen after resume */
@@ -1496,6 +1506,9 @@ EvdevAddAbsClass(DeviceIntPtr device)
 #ifdef HAVE_MASKED_VALUATORS
     num_axes = CountBits((uint8_t *)pEvdev->abs_bitmask, ABS_MT_SLOT);
     num_mt_axes = CountBits((uint8_t *)pEvdev->abs_bitmask, ABS_MAX) - num_axes;
+
+    if (num_mt_axes > 0 && !TestBit(ABS_MT_TRACKING_ID, pEvdev->abs_bitmask))
+        num_mt_axes++;
 #else
     num_axes = EvdevCountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX));
     num_mt_axes = 0;
@@ -1540,7 +1553,8 @@ EvdevAddAbsClass(DeviceIntPtr device)
 
     for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) {
         pEvdev->axis_map[axis] = -1;
-        if (!TestBit(axis, pEvdev->abs_bitmask) || axis == ABS_MT_SLOT)
+        if ((!TestBit(axis, pEvdev->abs_bitmask) || axis == ABS_MT_SLOT) &&
+            axis != ABS_MT_TRACKING_ID)
             continue;
         pEvdev->axis_map[axis] = i;
         i++;
@@ -1565,8 +1579,8 @@ EvdevAddAbsClass(DeviceIntPtr device)
         int mode = pEvdev->flags & EVDEV_TOUCHPAD ?
             XIDependentTouch : XIDirectTouch;
 
-        if (pEvdev->absinfo[ABS_MT_SLOT].maximum > 0)
-            num_touches = pEvdev->absinfo[ABS_MT_SLOT].maximum;
+        if (pEvdev->mtdev->caps.slot.maximum > 0)
+            num_touches = pEvdev->mtdev->caps.slot.maximum;
 
         pEvdev->mt_slot_map = malloc(num_touches * sizeof(int));
         if (!pEvdev->mt_slot_map)
@@ -2061,6 +2075,8 @@ EvdevProc(DeviceIntPtr device, int what)
 #ifdef MULTITOUCH
         free(pEvdev->mt_slot_map);
         free(pEvdev->mtMask);
+        if (pEvdev->mtdev)
+            mtdev_close(pEvdev->mtdev);
 #endif
         EvdevRemoveDevice(pInfo);
         pEvdev->min_maj = 0;
@@ -2489,6 +2505,16 @@ EvdevOpenDevice(InputInfoPtr pInfo)
 
         pEvdev->device = device;
         xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device);
+
+#ifdef MULTITOUCH
+        pEvdev->mtdev = malloc(sizeof(struct mtdev));
+        if (!pEvdev->mtdev)
+        {
+            xf86Msg(X_ERROR, "%s: Couldn't allocate mtdev structure\n",
+                    pInfo->name);
+            return BadAlloc;
+        }
+#endif
     }
 
     if (pInfo->fd < 0)
@@ -2503,6 +2529,16 @@ EvdevOpenDevice(InputInfoPtr pInfo)
         }
     }
 
+#ifdef MULTITOUCH
+    if (mtdev_open(pEvdev->mtdev, pInfo->fd) == 0)
+        pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value;
+    else {
+        free(pEvdev->mtdev);
+        pEvdev->mtdev = NULL;
+        xf86Msg(X_INFO, "%s: Couldn't open mtdev device\n", pInfo->name);
+    }
+#endif
+
     /* Check major/minor of device node to avoid adding duplicate devices. */
     pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
     if (EvdevIsDuplicate(pInfo))
diff --git a/src/evdev.h b/src/evdev.h
index 63c75a3..6bd8fe3 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -39,6 +39,10 @@
 #include <xf86_OSproc.h>
 #include <xkbstr.h>
 
+#ifdef MULTITOUCH
+#include <mtdev.h>
+#endif
+
 #ifndef EV_CNT /* linux 2.6.23 kernels and earlier lack _CNT defines */
 #define EV_CNT (EV_MAX+1)
 #endif
@@ -210,6 +214,9 @@ typedef struct {
     /* Event queue used to defer keyboard/button events until EV_SYN time. */
     int                     num_queue;
     EventQueueRec           queue[EVDEV_MAXQUEUE];
+#ifdef MULTITOUCH
+    struct mtdev            *mtdev;
+#endif
 } EvdevRec, *EvdevPtr;
 
 /* Event posting functions */
-- 
1.7.1



More information about the xorg-devel mailing list