From cae14787815c452a618c8bd684e2df4892dc93cb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 1 Aug 2013 10:43:32 +1000 Subject: 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 --- src/evdev.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file 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 #include #include +#ifdef MULTITOUCH +#include +#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; -- cgit v1.2.3