xserver-xorg-input-synaptics: Changes to 'ubuntu+1'
debian/changelog | 9
debian/control | 5
debian/patches/127_multitouch.patch | 745 ++++++++++++++++++++++++++++++++++++
debian/patches/series | 1
4 files changed, 756 insertions(+), 4 deletions(-)
New commits:
commit 906dfcfdb5954360c69d2f713ff4462a4326e679
Author: Chase Douglas <chase.douglas@canonical.com>
Date: Thu Jan 19 16:39:39 2012 -0800
releasing version 1.5.0+git20120101-1ubuntu1
diff --git a/debian/changelog b/debian/changelog
index f3e3b4a..bfebd76 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,11 +1,11 @@
-xserver-xorg-input-synaptics (1.5.0+git20120101-1ubuntu1) UNRELEASED; urgency=low
+xserver-xorg-input-synaptics (1.5.0+git20120101-1ubuntu1) precise; urgency=low
* Add multitouch support
- Add 127_multitouch.patch
* Bump Build-Depends for x11proto-input-dev to 2.1.99.5
* Remove obsolete dependencies on utouch-grail and old xserver-xorg-core
- -- Chase Douglas <chase.douglas@ubuntu.com> Thu, 19 Jan 2012 16:38:25 -0800
+ -- Chase Douglas <chase.douglas@ubuntu.com> Thu, 19 Jan 2012 16:39:31 -0800
xserver-xorg-input-synaptics (1.5.0+git20120101-1ubuntu1~nomt3) precise; urgency=low
commit 6638c4485fdcfed12f646992cb120355623c7531
Author: Chase Douglas <chase.douglas@canonical.com>
Date: Thu Jan 19 16:38:46 2012 -0800
Remove obsolete dependencies on utouch-grail and old xserver-xorg-core
diff --git a/debian/changelog b/debian/changelog
index 46f068b..f3e3b4a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -3,8 +3,9 @@ xserver-xorg-input-synaptics (1.5.0+git20120101-1ubuntu1) UNRELEASED; urgency=lo
* Add multitouch support
- Add 127_multitouch.patch
* Bump Build-Depends for x11proto-input-dev to 2.1.99.5
+ * Remove obsolete dependencies on utouch-grail and old xserver-xorg-core
- -- Chase Douglas <chase.douglas@ubuntu.com> Thu, 19 Jan 2012 16:35:19 -0800
+ -- Chase Douglas <chase.douglas@ubuntu.com> Thu, 19 Jan 2012 16:38:25 -0800
xserver-xorg-input-synaptics (1.5.0+git20120101-1ubuntu1~nomt3) precise; urgency=low
diff --git a/debian/control b/debian/control
index db9e29c..2355490 100644
--- a/debian/control
+++ b/debian/control
@@ -17,7 +17,6 @@ Build-Depends:
xutils-dev (>= 1:7.5+4),
x11proto-input-dev (>= 2.1.99.5),
libmtdev-dev,
- libutouch-grail-dev
Build-Conflicts:
libxtst-dev
Standards-Version: 3.9.2
@@ -31,8 +30,6 @@ Depends:
${shlibs:Depends},
${xinpdriver:Depends},
${misc:Depends},
- libutouch-grail1 (>= 1.0.19),
- xserver-xorg-core (>= 2:1.9.99.902-2ubuntu1)
Conflicts: xorg-driver-synaptics
Replaces: xorg-driver-synaptics
Provides: ${xinpdriver:Provides}, xorg-driver-synaptics
commit 034f46c4aa1cbd4d3a35626bcfaf5bca4a058d6d
Author: Chase Douglas <chase.douglas@canonical.com>
Date: Thu Jan 19 16:37:05 2012 -0800
Bump Build-Depends for x11proto-input-dev to 2.1.99.5
diff --git a/debian/changelog b/debian/changelog
index ab5fc0e..46f068b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,8 +2,9 @@ xserver-xorg-input-synaptics (1.5.0+git20120101-1ubuntu1) UNRELEASED; urgency=lo
* Add multitouch support
- Add 127_multitouch.patch
+ * Bump Build-Depends for x11proto-input-dev to 2.1.99.5
- -- Chase Douglas <chase.douglas@ubuntu.com> Thu, 19 Jan 2012 16:32:52 -0800
+ -- Chase Douglas <chase.douglas@ubuntu.com> Thu, 19 Jan 2012 16:35:19 -0800
xserver-xorg-input-synaptics (1.5.0+git20120101-1ubuntu1~nomt3) precise; urgency=low
diff --git a/debian/control b/debian/control
index 90a2f80..db9e29c 100644
--- a/debian/control
+++ b/debian/control
@@ -15,7 +15,7 @@ Build-Depends:
pkg-config,
quilt,
xutils-dev (>= 1:7.5+4),
- x11proto-input-dev (>= 2.0.1-1ubuntu1),
+ x11proto-input-dev (>= 2.1.99.5),
libmtdev-dev,
libutouch-grail-dev
Build-Conflicts:
commit b1e0f380abc08700f14b157ef74e8dae8874af1b
Author: Chase Douglas <chase.douglas@canonical.com>
Date: Thu Jan 19 16:33:36 2012 -0800
Add multitouch support
* Add multitouch support
- Add 127_multitouch.patch
diff --git a/debian/changelog b/debian/changelog
index d792baf..ab5fc0e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+xserver-xorg-input-synaptics (1.5.0+git20120101-1ubuntu1) UNRELEASED; urgency=low
+
+ * Add multitouch support
+ - Add 127_multitouch.patch
+
+ -- Chase Douglas <chase.douglas@ubuntu.com> Thu, 19 Jan 2012 16:32:52 -0800
+
xserver-xorg-input-synaptics (1.5.0+git20120101-1ubuntu1~nomt3) precise; urgency=low
* Fix default speed due to change in motion estimation
diff --git a/debian/patches/127_multitouch.patch b/debian/patches/127_multitouch.patch
new file mode 100644
index 0000000..ca19332
--- /dev/null
+++ b/debian/patches/127_multitouch.patch
@@ -0,0 +1,745 @@
+diff --git a/configure.ac b/configure.ac
+index bb95403..166a4f8 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -64,6 +64,11 @@ AC_SUBST([sdkdir])
+ DRIVER_NAME=synaptics
+ AC_SUBST([DRIVER_NAME])
+
++PKG_CHECK_MODULES(XI22, [inputproto >= 2.1.99.3] [xorg-server >= 1.11.3], HAVE_XI22="yes", HAVE_XI22="no")
++if test "x$HAVE_XI22" = xyes; then
++ AC_DEFINE(HAVE_MULTITOUCH, 1, [XI2.2 available])
++fi
++
+ # -----------------------------------------------------------------------------
+ # Configuration options
+ # -----------------------------------------------------------------------------
+@@ -116,6 +121,14 @@ case "${host}" in
+ esac
+ if test "x$BUILD_EVENTCOMM" = xyes; then
+ AC_DEFINE(BUILD_EVENTCOMM, 1, [Optional backend eventcomm enabled])
++
++ if test "x$HAVE_XI22" = xyes; then
++ # Obtain compiler/linker options for mtdev
++ PKG_CHECK_MODULES(MTDEV, mtdev, HAVE_MTDEV="yes", HAVE_MTDEV="no")
++ fi
++ if test "x$HAVE_XI22" = xyes && test "x$HAVE_MTDEV" = xyes; then
++ AC_DEFINE(HAVE_MTDEV, 1, [MTDev available])
++ fi
+ fi
+ if test "x$BUILD_PSMCOMM" = xyes; then
+ AC_DEFINE(BUILD_PSMCOMM, 1, [Optional backend psmcomm enabled])
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 5e04670..a6715e6 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -44,6 +44,8 @@ endif
+ if BUILD_EVENTCOMM
+ @DRIVER_NAME@_drv_la_SOURCES += \
+ eventcomm.c eventcomm.h
++@DRIVER_NAME@_drv_la_LIBADD = \
++ $(MTDEV_LIBS)
+ endif
+
+ if BUILD_PSMCOMM
+diff --git a/src/eventcomm.c b/src/eventcomm.c
+index 00dc532..05ff02b 100644
+--- a/src/eventcomm.c
++++ b/src/eventcomm.c
+@@ -41,6 +41,9 @@
+ #include "synaptics.h"
+ #include "synapticsstr.h"
+ #include <xf86.h>
++#ifdef HAVE_MTDEV
++#include <mtdev.h>
++#endif
+
+
+ #define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
+@@ -62,19 +65,133 @@ struct eventcomm_proto_data
+ * exists for readability of the code.
+ */
+ BOOL need_grab;
++#ifdef HAVE_MTDEV
++ struct mtdev *mtdev;
++ int axis_map[MT_ABS_SIZE];
++ int cur_slot;
++ enum
++ {
++ SLOTSTATE_OPEN = 0,
++ SLOTSTATE_CLOSE,
++ SLOTSTATE_UPDATE,
++ SLOTSTATE_EMPTY,
++ } slot_state;
++ ValuatorMask *mt_mask;
++ ValuatorMask **last_mt_vals;
++#endif
+ };
+
+-static Bool
+-EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters *para)
++#ifdef HAVE_MTDEV
++static int
++num_slots(const struct eventcomm_proto_data *proto_data)
++{
++ int value = proto_data->mtdev->caps.slot.maximum -
++ proto_data->mtdev->caps.slot.minimum + 1;
++
++ /* If we don't know how many slots there are, assume at least 10 */
++ return value > 1 ? value : 10;
++}
++
++static int
++last_mt_vals_slot(const struct eventcomm_proto_data *proto_data)
++{
++ int value = proto_data->cur_slot - proto_data->mtdev->caps.slot.minimum;
++
++ return value < num_slots(proto_data) ? value : -1;
++}
++
++static void
++UninitializeTouch(InputInfoPtr pInfo)
+ {
+ SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
+ struct eventcomm_proto_data *proto_data = (struct eventcomm_proto_data*)priv->proto_data;
+
+- if (!proto_data) {
+- proto_data = calloc(1, sizeof(struct eventcomm_proto_data));
+- priv->proto_data = proto_data;
++ if (!proto_data->mtdev)
++ return;
++
++ valuator_mask_free(&proto_data->mt_mask);
++ if (proto_data->last_mt_vals)
++ {
++ int i;
++
++ for (i = 0; i < num_slots(proto_data); i++)
++ valuator_mask_free(&proto_data->last_mt_vals[i]);
++ free(proto_data->last_mt_vals);
++ proto_data->last_mt_vals = NULL;
++ }
++
++ mtdev_close(proto_data->mtdev);
++ proto_data->mtdev = NULL;
++}
++
++static void
++InitializeTouch(InputInfoPtr pInfo)
++{
++ SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
++ struct eventcomm_proto_data *proto_data = (struct eventcomm_proto_data*)priv->proto_data;
++ int i;
++
++ proto_data->mtdev = mtdev_new_open(pInfo->fd);
++ if (!proto_data->mtdev)
++ {
++ xf86IDrvMsg(pInfo, X_WARNING,
++ "failed to create mtdev instance, ignoring touch events\n");
++ return;
++ }
++
++ proto_data->cur_slot = proto_data->mtdev->caps.slot.value;
++
++ /* Axes 0-4 are for X, Y, and scrolling. num_mt_axes does not include X and
++ * Y. */
++ proto_data->mt_mask = valuator_mask_new(4 + priv->num_mt_axes);
++ if (!proto_data->mt_mask)
++ {
++ xf86IDrvMsg(pInfo, X_WARNING,
++ "failed to create MT valuator mask, ignoring touch "
++ "events\n");
++ UninitializeTouch(pInfo);
++ return;
++ }
++
++ proto_data->last_mt_vals = calloc(num_slots(proto_data),
++ sizeof(ValuatorMask *));
++ if (!proto_data->last_mt_vals)
++ {
++ xf86IDrvMsg(pInfo, X_WARNING,
++ "failed to allocate MT last values mask array\n");
++ UninitializeTouch(pInfo);
++ return;
+ }
+
++ for (i = 0; i < num_slots(proto_data); i++)
++ {
++ int j;
++
++ proto_data->last_mt_vals[i] = valuator_mask_new(4 + priv->num_mt_axes);
++ if (!proto_data->last_mt_vals[i])
++ {
++ xf86IDrvMsg(pInfo, X_WARNING,
++ "failed to allocate MT last values mask\n");
++ UninitializeTouch(pInfo);
++ return;
++ }
++
++ /* Axes 0-4 are for X, Y, and scrolling. num_mt_axes does not include X
++ * and Y. */
++ valuator_mask_set(proto_data->last_mt_vals[i], 0, 0);
++ valuator_mask_set(proto_data->last_mt_vals[i], 1, 0);
++ for (j = 4; j < priv->num_mt_axes; j++)
++ valuator_mask_set(proto_data->last_mt_vals[i], j, 0);
++ }
++}
++#endif
++
++static Bool
++EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters *para)
++{
++ SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
++ struct eventcomm_proto_data *proto_data = (struct eventcomm_proto_data*)priv->proto_data;
++
+ if (para->grab_event_device) {
+ /* Try to grab the event device so that data don't leak to /dev/input/mice */
+ int ret;
+@@ -88,9 +205,23 @@ EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters *para)
+
+ proto_data->need_grab = FALSE;
+
++#ifdef HAVE_MTDEV
++ InitializeTouch(pInfo);
++#endif
++
+ return TRUE;
+ }
+
++static Bool
++EventDeviceOffHook(InputInfoPtr pInfo)
++{
++#ifdef HAVE_MTDEV
++ UninitializeTouch(pInfo);
++#endif
++
++ return Success;
++}
++
+ /**
+ * Test if the device on the file descriptior is recognized as touchpad
+ * device. Required bits for touchpad recognition are:
+@@ -353,10 +484,20 @@ EventQueryHardware(InputInfoPtr pInfo)
+ static Bool
+ SynapticsReadEvent(InputInfoPtr pInfo, struct input_event *ev)
+ {
++#ifdef HAVE_MTDEV
++ SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
++ struct eventcomm_proto_data *proto_data = priv->proto_data;
++#endif
+ int rc = TRUE;
+ ssize_t len;
+
+- len = read(pInfo->fd, ev, sizeof(*ev));
++#ifdef HAVE_MTDEV
++ if (proto_data->mtdev)
++ len = mtdev_get(proto_data->mtdev, pInfo->fd, ev, 1) *
++ sizeof(struct input_event);
++ else
++#endif
++ len = read(pInfo->fd, ev, sizeof(*ev));
+ if (len <= 0)
+ {
+ /* We use X_NONE here because it doesn't alloc */
+@@ -370,6 +511,87 @@ SynapticsReadEvent(InputInfoPtr pInfo, struct input_event *ev)
+ return rc;
+ }
+
++static void
++EventProcessTouch(InputInfoPtr pInfo)
++{
++#ifdef HAVE_MTDEV
++ SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
++ struct eventcomm_proto_data *proto_data = priv->proto_data;
++ int type;
++
++ if (proto_data->cur_slot < 0 || !priv->has_touch)
++ return;
++
++ /* If the ABS_MT_SLOT is the first event we get after EV_SYN, skip this */
++ if (proto_data->slot_state == SLOTSTATE_EMPTY)
++ return;
++
++ switch (proto_data->slot_state)
++ {
++ case SLOTSTATE_CLOSE:
++ type = XI_TouchEnd;
++ break;
++ case SLOTSTATE_OPEN:
++ type = XI_TouchBegin;
++ break;
++ default:
++ type = XI_TouchUpdate;
++ break;
++ }
++
++ xf86PostTouchEvent(pInfo->dev, proto_data->cur_slot, type, 0,
++ proto_data->mt_mask);
++
++ proto_data->slot_state = SLOTSTATE_EMPTY;
++ valuator_mask_zero(proto_data->mt_mask);
++#endif
++}
++
++static void
++EventProcessTouchEvent(InputInfoPtr pInfo, struct CommData *comm,
++ struct input_event *ev)
++{
++#ifdef HAVE_MTDEV
++ SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
++ struct eventcomm_proto_data *proto_data = priv->proto_data;
++
++ if (ev->code == ABS_MT_SLOT)
++ {
++ EventProcessTouch(pInfo);
++ proto_data->cur_slot = ev->value;
++ } else
++ {
++ int slot_index = last_mt_vals_slot(proto_data);
++
++ if (proto_data->slot_state == SLOTSTATE_EMPTY)
++ proto_data->slot_state = SLOTSTATE_UPDATE;
++ if (ev->code == ABS_MT_TRACKING_ID)
++ {
++ if (ev->value >= 0)
++ {
++ proto_data->slot_state = SLOTSTATE_OPEN;
++
++ if (slot_index >= 0)
++ valuator_mask_copy(proto_data->mt_mask,
++ proto_data->last_mt_vals[slot_index]);
++ else
++ xf86IDrvMsg(pInfo, X_WARNING,
++ "Attempted to copy values from out-of-range "
++ "slot, touch events may be incorrect.\n");
++ } else
++ proto_data->slot_state = SLOTSTATE_CLOSE;
++ } else
++ {
++ int map = proto_data->axis_map[ev->code - ABS_MT_TOUCH_MAJOR];
++ valuator_mask_set(proto_data->mt_mask, map, ev->value);
++ if (slot_index >= 0)
++ valuator_mask_set(proto_data->last_mt_vals[slot_index], map,
++ ev->value);
++ }
++ }
++#endif
++}
++
+ /**
+ * Count the number of fingers based on the CommData information.
+ * The CommData struct contains the event information based on previous
+@@ -408,6 +630,7 @@ EventReadHwState(InputInfoPtr pInfo,
+ case EV_SYN:
+ switch (ev.code) {
+ case SYN_REPORT:
++ EventProcessTouch(pInfo);
+ hw->numFingers = count_fingers(comm);
+ hw->millis = 1000 * ev.time.tv_sec + ev.time.tv_usec / 1000;
+ *hwRet = *hw;
+@@ -472,20 +695,23 @@ EventReadHwState(InputInfoPtr pInfo,
+ }
+ break;
+ case EV_ABS:
+- switch (ev.code) {
+- case ABS_X:
+- hw->x = ev.value;
+- break;
+- case ABS_Y:
+- hw->y = ev.value;
+- break;
+- case ABS_PRESSURE:
+- hw->z = ev.value;
+- break;
+- case ABS_TOOL_WIDTH:
+- hw->fingerWidth = ev.value;
+- break;
+- }
++ if (ev.code < ABS_MT_SLOT) {
++ switch (ev.code) {
++ case ABS_X:
++ hw->x = ev.value;
++ break;
++ case ABS_Y:
++ hw->y = ev.value;
++ break;
++ case ABS_PRESSURE:
++ hw->z = ev.value;
++ break;
++ case ABS_TOOL_WIDTH:
++ hw->fingerWidth = ev.value;
++ break;
++ }
++ } else
++ EventProcessTouchEvent(pInfo, comm, &ev);
+ break;
+ }
+ }
+@@ -497,6 +723,120 @@ static int EventDevOnly(const struct dirent *dir) {
+ return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0;
+ }
+
++#ifdef HAVE_MTDEV
++static void
++event_query_touch(InputInfoPtr pInfo)
++{
++ SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
++ struct eventcomm_proto_data *proto_data = priv->proto_data;
++ struct mtdev *mtdev;
++ int i;
++
++ priv->num_touches = 0;
++ priv->num_mt_axes = 0;
++
++ mtdev = mtdev_new_open(pInfo->fd);
++ if (!mtdev)
++ {
++ xf86IDrvMsg(pInfo, X_WARNING,
++ "failed to open mtdev when querying touch capabilities\n");
++ return;
++ }
++
++ for (i = 0; i < MT_ABS_SIZE; i++)
++ {
++ if (mtdev->caps.has_abs[i])
++ {
++ switch (i)
++ {
++ /* X and Y axis info is handed by synaptics already */
++ case ABS_MT_POSITION_X - ABS_MT_TOUCH_MAJOR:
++ case ABS_MT_POSITION_Y - ABS_MT_TOUCH_MAJOR:
++ /* Skip tracking ID info */
++ case ABS_MT_TRACKING_ID - ABS_MT_TOUCH_MAJOR:
++ break;
++ default:
++ priv->num_mt_axes++;
++ break;
++ }
++ priv->has_touch = TRUE;
++ }
++ }
++
++ if (priv->has_touch)
++ {
++ int axnum;
++ static const char *labels[] =
++ {
++ AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR,
++ AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR,
++ AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR,
++ AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR,
++ AXIS_LABEL_PROP_ABS_MT_ORIENTATION,
++ AXIS_LABEL_PROP_ABS_MT_POSITION_X,
++ AXIS_LABEL_PROP_ABS_MT_POSITION_Y,
++ AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE,
++ AXIS_LABEL_PROP_ABS_MT_BLOB_ID,
++ AXIS_LABEL_PROP_ABS_MT_TRACKING_ID,
++ AXIS_LABEL_PROP_ABS_MT_PRESSURE,
++ };
++
++ if (mtdev->caps.slot.maximum > 0)
++ priv->num_touches = mtdev->caps.slot.maximum -
++ mtdev->caps.slot.minimum + 1;
++
++ priv->touch_axes = malloc(priv->num_mt_axes *
++ sizeof(SynapticsTouchAxisRec));
++ if (!priv->touch_axes)
++ {
++ priv->has_touch = FALSE;
++ goto out;
++ }
++
++ axnum = 0;
++ for (i = 0; i < MT_ABS_SIZE; i++)
++ {
++ if (mtdev->caps.has_abs[i])
++ {
++ switch (i)
++ {
++ /* X and Y axis info is handed by synaptics already, we just
++ * need to map the evdev codes to the valuator numbers */
++ case ABS_MT_POSITION_X - ABS_MT_TOUCH_MAJOR:
++ proto_data->axis_map[i] = 0;
++ break;
++
++ case ABS_MT_POSITION_Y - ABS_MT_TOUCH_MAJOR:
++ proto_data->axis_map[i] = 1;
++ break;
++
++ /* Skip tracking ID info */
++ case ABS_MT_TRACKING_ID - ABS_MT_TOUCH_MAJOR:
++ break;
++
++ default:
++ priv->touch_axes[axnum].label = labels[i];
++ priv->touch_axes[axnum].min =
++ mtdev->caps.abs[i].minimum;
++ priv->touch_axes[axnum].max =
++ mtdev->caps.abs[i].maximum;
++ /* Kernel provides units/mm, X wants units/m */
++ priv->touch_axes[axnum].res =
++ mtdev->caps.abs[i].resolution * 1000;
++ /* Valuators 0-3 are used for X, Y, and scrolling */
++ proto_data->axis_map[i] = 4 + axnum;
++ axnum++;
++ break;
++ }
++ }
++ }
++ }
++
++out:
++ mtdev_close(mtdev);
++}
++#endif
++
+ /**
+ * Probe the open device for dimensions.
+ */
+@@ -505,9 +845,26 @@ EventReadDevDimensions(InputInfoPtr pInfo)
+ {
+ SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
+ struct eventcomm_proto_data *proto_data = priv->proto_data;
++#ifdef HAVE_MTDEV
++ int i;
++#endif
++
++ proto_data = calloc(1, sizeof(struct eventcomm_proto_data));
++ priv->proto_data = proto_data;
++
++#ifdef HAVE_MTDEV
++ for (i = 0; i < MT_ABS_SIZE; i++)
++ proto_data->axis_map[i] = -1;
++ proto_data->cur_slot = -1;
++#endif
+
+ if (event_query_is_touchpad(pInfo->fd, (proto_data) ? proto_data->need_grab : TRUE))
+- event_query_axis_ranges(pInfo);
++ {
++ event_query_axis_ranges(pInfo);
++#ifdef HAVE_MTDEV
++ event_query_touch(pInfo);
++#endif
++ }
+ event_query_model(pInfo->fd, &priv->model, &priv->id_vendor, &priv->id_product);
+
+ xf86IDrvMsg(pInfo, X_PROBED, "Vendor %#hx Product %#hx\n",
+@@ -584,7 +941,7 @@ EventAutoDevProbe(InputInfoPtr pInfo, const char *device)
+
+ struct SynapticsProtocolOperations event_proto_operations = {
+ EventDeviceOnHook,
+- NULL,
++ EventDeviceOffHook,
+ EventQueryHardware,
+ EventReadHwState,
+ EventAutoDevProbe,
+diff --git a/src/synaptics.c b/src/synaptics.c
+index b1f2cf2..34915a2 100644
+--- a/src/synaptics.c
++++ b/src/synaptics.c
+@@ -937,8 +937,13 @@ DeviceClose(DeviceIntPtr dev)
+ return RetValue;
+ }
+
+-static void InitAxesLabels(Atom *labels, int nlabels)
++static void InitAxesLabels(Atom *labels, int nlabels,
++ const SynapticsPrivate *priv)
+ {
++#ifdef HAVE_MULTITOUCH
++ int i;
++#endif
++
+ memset(labels, 0, nlabels * sizeof(Atom));
+ switch(nlabels)
+ {
+@@ -950,11 +955,20 @@ static void InitAxesLabels(Atom *labels, int nlabels)
+ labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
+ #endif
+ case 2:
+- labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
++ labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
+ case 1:
+- labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
++ labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
+ break;
+ }
++
++#ifdef HAVE_MULTITOUCH
++ for (i = 0; i < priv->num_mt_axes; i++)
++ {
++ SynapticsTouchAxisRec *axis = &priv->touch_axes[i];
++ int axnum = nlabels - priv->num_mt_axes + i;
++ labels[axnum] = XIGetKnownProperty(axis->label);
++ }
++#endif
+ }
+
+ static void InitButtonLabels(Atom *labels, int nlabels)
+@@ -993,14 +1007,25 @@ DeviceInit(DeviceIntPtr dev)
+ int min, max;
+ int num_axes = 2;
+ Atom btn_labels[SYN_MAX_BUTTONS] = { 0 };
+- Atom axes_labels[4] = { 0 };
++ Atom *axes_labels;
+ DeviceVelocityPtr pVel;
+
+ #ifdef HAVE_SMOOTH_SCROLL
+ num_axes += 2;
+ #endif
+
+- InitAxesLabels(axes_labels, num_axes);
++#ifdef HAVE_MULTITOUCH
++ num_axes += priv->num_mt_axes;
++#endif
++
++ axes_labels = calloc(num_axes, sizeof(Atom));
++ if (!axes_labels)
++ {
++ xf86IDrvMsg(pInfo, X_ERROR, "failed to allocate axis labels\n");
++ return !Success;
++ }
++
++ InitAxesLabels(axes_labels, num_axes, priv);
+ InitButtonLabels(btn_labels, SYN_MAX_BUTTONS);
+
+ DBG(3, "Synaptics DeviceInit called\n");
+@@ -1106,7 +1131,10 @@ DeviceInit(DeviceIntPtr dev)
+ priv->scroll_axis_vert = 3;
+ priv->scroll_events_mask = valuator_mask_new(MAX_VALUATORS);
+ if (!priv->scroll_events_mask)
++ {
++ free(axes_labels);
+ return !Success;
++ }
+
+ SetScrollValuator(dev, priv->scroll_axis_horiz, SCROLL_TYPE_HORIZONTAL,
+ priv->synpara.scroll_dist_horiz, 0);
+@@ -1114,6 +1142,43 @@ DeviceInit(DeviceIntPtr dev)
+ priv->synpara.scroll_dist_vert, 0);
+ #endif
+
++#ifdef HAVE_MULTITOUCH
++ if (priv->has_touch)
++ {
++ if (!InitTouchClassDeviceStruct(dev, priv->num_touches,
++ XIDependentTouch, priv->num_mt_axes))
++ {
++ xf86IDrvMsg(pInfo, X_ERROR,
++ "failed to initialize touch class device\n");
++ priv->has_touch = 0;
++ goto no_touch;
++ }
++
++ for (i = 0; i < priv->num_mt_axes; i++)
++ {
++ SynapticsTouchAxisRec *axis = &priv->touch_axes[i];
++ int axnum = num_axes - priv->num_mt_axes + i;
++ Atom atom = axes_labels[axnum];
++
++ if (!xf86InitValuatorAxisStruct(dev, axnum, axes_labels[axnum],
++ axis->min, axis->max, axis->res, 0,
++ axis->res, Absolute))
++ {
++ xf86IDrvMsg(pInfo, X_WARNING,
++ "failed to initialize axis %s, skipping\n",
++ axis->label);
++ continue;
++ }
++
++ xf86InitValuatorDefaults(dev, axnum);
++ }
++ }
++
++no_touch:
++#endif
++
++ free(axes_labels);
++
+ if (!alloc_shm_data(pInfo))
+ return !Success;
+
+diff --git a/src/synapticsstr.h b/src/synapticsstr.h
+index d74ebcd..d3b8607 100644
+--- a/src/synapticsstr.h
++++ b/src/synapticsstr.h
+@@ -56,6 +56,14 @@ typedef struct _SynapticsMoveHist
+ CARD32 millis;
+ } SynapticsMoveHistRec;
+
++typedef struct _SynapticsTouchAxis
++{
++ const char *label;
++ int min;
++ int max;
++ int res;
++} SynapticsTouchAxisRec;
++
+ enum FingerState { /* Note! The order matters. Compared with < operator. */
+ FS_BLOCKED = -1,
+ FS_UNTOUCHED = 0, /* this is 0 so it's the initialized value. */
+@@ -265,6 +273,13 @@ typedef struct _SynapticsPrivateRec
+ int scroll_axis_vert; /* Vertical smooth-scrolling axis */
+ ValuatorMask *scroll_events_mask; /* ValuatorMask for smooth-scrolling */
+ #endif
++
++#ifdef HAVE_MULTITOUCH
++ Bool has_touch; /* Device has multitouch capabilities */
++ int num_touches; /* Number of touches supported */
++ int num_mt_axes; /* Number of multitouch axes other than X, Y */
++ SynapticsTouchAxisRec *touch_axes; /* Touch axis information other than X, Y */
++#endif
+ } SynapticsPrivate;
+
+ #endif /* _SYNAPTICSSTR_H_ */
+diff --git a/test/Makefile.am b/test/Makefile.am
+index 5dd8cdb..87de1ec 100644
+--- a/test/Makefile.am
++++ b/test/Makefile.am
+@@ -9,6 +9,8 @@ noinst_PROGRAMS = eventcomm-test
+ eventcomm_test_SOURCES = eventcomm-test.c\
+ $(top_srcdir)/src/eventcomm.c \
+ $(fake_syms)
++
++eventcomm_test_LDADD = $(MTDEV_LIBS)
+ endif
+
+ TESTS = $(noinst_PROGRAMS)
+diff --git a/test/fake-symbols.c b/test/fake-symbols.c
+index 71c3bc5..361243c 100644
+--- a/test/fake-symbols.c
++++ b/test/fake-symbols.c
+@@ -450,3 +450,34 @@ Bool QueueWorkProc (
+ {
+ return FALSE;
+ }
++
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
++_X_EXPORT ValuatorMask *valuator_mask_new(int num_valuators)
++{
++ return NULL;
++}
++
++_X_EXPORT void valuator_mask_free(ValuatorMask **mask)
++{
++}
++
++_X_EXPORT void valuator_mask_set(ValuatorMask *mask, int valuator, int data)
++{
++}
++
++_X_EXPORT void valuator_mask_zero(ValuatorMask *mask)
++{
++}
++
++_X_EXPORT void valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src)
++{
++}
++#endif
++
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 16
++_X_EXPORT void xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid,
++ uint16_t type, uint32_t flags,
++ const ValuatorMask *mask)
++{
++}
++#endif
diff --git a/debian/patches/series b/debian/patches/series
index 87644a2..5793129 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -17,3 +17,4 @@
124_syndaemon_events.patch
125_option_rec_revert.patch
126_default_speed.patch
+127_multitouch.patch
Reply to: