evdev: use mtdev for multitouch devices

mtdev library translates all multitouch based devices to the slotted evdev
protocol. It provides an uniform interface for Weston, which eases mt
implementation when dealing with a big variety of devices.

Weston on drm now directly depends on such library.

Signed-off-by: Tiago Vignatti <tiago.vignatti@intel.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
diff --git a/configure.ac b/configure.ac
index 9467ff7..f60b208 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,7 +73,7 @@
 AM_CONDITIONAL(ENABLE_DRM_COMPOSITOR, test x$enable_drm_compositor = xyes)
 if test x$enable_drm_compositor = xyes; then
   AC_DEFINE([BUILD_DRM_COMPOSITOR], [1], [Build the DRM compositor])
-  PKG_CHECK_MODULES(DRM_COMPOSITOR, [libudev >= 136 libdrm >= 2.4.30 gbm])
+  PKG_CHECK_MODULES(DRM_COMPOSITOR, [libudev >= 136 libdrm >= 2.4.30 gbm mtdev])
 fi
 
 
diff --git a/src/evdev.c b/src/evdev.c
index 530eb6b..9b8d756 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -26,6 +26,7 @@
 #include <linux/input.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <mtdev.h>
 
 #include "compositor.h"
 #include "evdev.h"
@@ -57,6 +58,7 @@
 		int32_t x[MAX_SLOTS];
 		int32_t y[MAX_SLOTS];
 	} mt;
+	struct mtdev *mtdev;
 
 	struct {
 		int dx, dy;
@@ -320,13 +322,14 @@
 		device->type &= ~EVDEV_ABSOLUTE_MOTION;
 	}
 }
+#define NUM_EVENTS 8
 
 static int
 evdev_input_device_data(int fd, uint32_t mask, void *data)
 {
 	struct weston_compositor *ec;
 	struct evdev_input_device *device = data;
-	struct input_event ev[8], *e, *end;
+	struct input_event ev[NUM_EVENTS], *e, *end;
 	int len;
 	uint32_t time = 0;
 
@@ -334,7 +337,11 @@
 	if (!ec->focus)
 		return 1;
 
-	len = read(fd, &ev, sizeof ev);
+	if (device->mtdev)
+		len = mtdev_get(device->mtdev, fd, ev, NUM_EVENTS) *
+		      sizeof (struct input_event);
+	else
+		len = read(fd, &ev, sizeof ev);
 	if (len < 0 || len % sizeof e[0] != 0) {
 		/* FIXME: call device_removed when errno is ENODEV. */;
 		return 1;
@@ -450,18 +457,26 @@
 	device->master = master;
 	device->is_touchpad = 0;
 	device->is_mt = 0;
+	device->mtdev = NULL;
 	device->devnode = strdup(path);
 	device->mt.slot = -1;
 	device->rel.dx = 0;
 	device->rel.dy = 0;
 
-	device->fd = open(path, O_RDONLY);
+	/* if O_NONBLOCK is not set, mtdev_get() blocks */
+	device->fd = open(path, O_RDONLY | O_NONBLOCK);
 	if (device->fd < 0)
 		goto err0;
 
 	if (evdev_configure_device(device) == -1)
 		goto err1;
 
+	if (device->is_mt) {
+		device->mtdev = mtdev_new_open(device->fd);
+		if (!device->mtdev)
+			fprintf(stderr, "mtdev failed to open for %s\n", path);
+	}
+
 	device->source = wl_event_loop_add_fd(ec->input_loop, device->fd,
 					      WL_EVENT_READABLE,
 					      evdev_input_device_data, device);
@@ -511,6 +526,8 @@
 		if (!strcmp(device->devnode, devnode)) {
 			wl_event_source_remove(device->source);
 			wl_list_remove(&device->link);
+			if (device->mtdev)
+				mtdev_close_delete(device->mtdev);
 			close(device->fd);
 			free(device->devnode);
 			free(device);