aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2013-08-01 10:43:32 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2013-08-28 10:38:40 +1000
commitcae14787815c452a618c8bd684e2df4892dc93cb (patch)
tree2657b9fe370e84037410d8fd65fb39be2b405f52
parentWrite a SYN_REPORT after the last LED (diff)
downloadxf86-input-evdev-cae14787815c452a618c8bd684e2df4892dc93cb.tar.gz
xf86-input-evdev-cae14787815c452a618c8bd684e2df4892dc93cb.tar.bz2
xf86-input-evdev-cae14787815c452a618c8bd684e2df4892dc93cb.zip
Don't use mtdev for protocol B devices
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@who-t.net>
-rw-r--r--src/evdev.c77
1 files changed, 58 insertions, 19 deletions
diff --git a/src/evdev.c b/src/evdev.c
index 456c7aa..b97b841 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);
+
}
}
@@ -1421,15 +1445,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)) {
@@ -1441,10 +1469,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);
}
}
}
@@ -2404,7 +2433,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
@@ -2420,6 +2449,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) {
@@ -2445,6 +2480,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;