From 683a55e504f4fc2d1c847c54986439a0c61b2f20 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 25 Oct 2011 09:59:50 +1000 Subject: Use a new "Virtual Device" boolean property to mark virtual devices Use udev to check for the device's sysfs path, if it contains LNXSYSTM it's a kernel-emulated device. This property can then be used to determine if there are any real devices connected, allowing the desktop environment to e.g. turn off the touchpad whenever there's a mouse attached. Signed-off-by: Peter Hutterer --- src/evdev.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 428d3c1..5e65e35 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -56,6 +57,10 @@ #define XI_PROP_PRODUCT_ID "Device Product ID" #endif +#ifndef XI_PROP_VIRTUAL_DEVICE +#define XI_PROP_VIRTUAL_DEVICE "Virtual Device" +#endif + /* removed from server, purge when dropping support for server 1.10 */ #define XI86_SEND_DRAG_EVENTS 0x08 @@ -119,6 +124,7 @@ static Atom prop_swap; static Atom prop_axis_label; static Atom prop_btn_label; static Atom prop_device; +static Atom prop_virtual; /* All devices the evdev driver has allocated and knows about. * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK) @@ -277,6 +283,39 @@ SetXkbOption(InputInfoPtr pInfo, char *name, char **option) } } +static BOOL +EvdevDeviceIsVirtual(const char* devicenode) +{ + struct udev *udev = NULL; + struct udev_device *device = NULL; + struct stat st; + int rc = FALSE; + const char *devpath; + + udev = udev_new(); + if (!udev) + goto out; + + stat(devicenode, &st); + device = udev_device_new_from_devnum(udev, 'c', st.st_rdev); + + if (!device) + goto out; + + + devpath = udev_device_get_devpath(device); + if (!devpath) + goto out; + + if (strstr(devpath, "LNXSYSTM")) + rc = TRUE; + +out: + udev_device_unref(device); + udev_unref(udev); + return rc; +} + #ifndef HAVE_SMOOTH_SCROLLING static int wheel_up_button = 4; static int wheel_down_button = 5; @@ -2317,6 +2356,17 @@ EvdevInitProperty(DeviceIntPtr dev) if (rc != Success) return; + if (EvdevDeviceIsVirtual(pEvdev->device)) + { + BOOL virtual = 1; + prop_virtual = MakeAtom(XI_PROP_VIRTUAL_DEVICE, + strlen(XI_PROP_VIRTUAL_DEVICE), TRUE); + rc = XIChangeDeviceProperty(dev, prop_virtual, XA_INTEGER, 8, + PropModeReplace, 1, &virtual, FALSE); + XISetDevicePropertyDeletable(dev, prop_virtual, FALSE); + } + + XISetDevicePropertyDeletable(dev, prop_device, FALSE); if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_ABSOLUTE_EVENTS)) @@ -2426,7 +2476,8 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, if (!checkonly) pEvdev->swap_axes = *((BOOL*)val->data); } else if (atom == prop_axis_label || atom == prop_btn_label || - atom == prop_product_id || atom == prop_device) + atom == prop_product_id || atom == prop_device || + atom == prop_virtual) return BadAccess; /* Read-only properties */ return Success; -- cgit v1.2.3 From e18abd0049421a98e61c15c2d56cfe2821cf4739 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Mon, 8 Nov 2010 11:08:01 -0500 Subject: Add experimental XI 2.1 multitouch support This multitouch addition only supports slotted MT evdev protocol devices. Support must be enabled at configure time using --enable-multitouch. Signed-off-by: Chase Douglas Amendments: XI_TouchMotion -> XI_TouchUpdate, rename mtMask to mt_mask Signed-off-by: Peter Hutterer --- src/evdev.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 203 insertions(+), 14 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 5e65e35..16f7339 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -85,6 +85,14 @@ #define MODEFLAG 8 #define COMPOSEFLAG 16 +#ifndef ABS_MT_SLOT +#define ABS_MT_SLOT 0x2f +#endif + +#ifndef ABS_MT_TRACKING_ID +#define ABS_MT_TRACKING_ID 0x39 +#endif + static char *evdevDefaults[] = { "XkbRules", "evdev", "XkbModel", "evdev", @@ -352,7 +360,7 @@ EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) if ((pQueue = EvdevNextInQueue(pInfo))) { pQueue->type = EV_QUEUE_KEY; - pQueue->key = code; + pQueue->detail.key = code; pQueue->val = value; } } @@ -365,7 +373,7 @@ EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value) if ((pQueue = EvdevNextInQueue(pInfo))) { pQueue->type = EV_QUEUE_BTN; - pQueue->key = button; + pQueue->detail.key = button; pQueue->val = value; } } @@ -377,11 +385,27 @@ EvdevQueueProximityEvent(InputInfoPtr pInfo, int value) if ((pQueue = EvdevNextInQueue(pInfo))) { pQueue->type = EV_QUEUE_PROXIMITY; - pQueue->key = 0; + pQueue->detail.key = 0; pQueue->val = value; } } +#ifdef MULTITOUCH +void +EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ValuatorMask *mask, + uint16_t evtype) +{ + EventQueuePtr pQueue; + if ((pQueue = EvdevNextInQueue(pInfo))) + { + pQueue->type = EV_QUEUE_TOUCH; + pQueue->detail.touch = touch; + valuator_mask_copy(pQueue->touchMask, mask); + pQueue->val = evtype; + } +} +#endif + /** * Post button event right here, right now. * Interface for MB emulation since these need to post immediately. @@ -675,6 +699,53 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev) } } +#ifdef MULTITOUCH +static void +EvdevProcessTouch(InputInfoPtr pInfo) +{ + EvdevPtr pEvdev = pInfo->private; + + if (pEvdev->cur_slot < 0 || !pEvdev->mt_mask) + return; + + if (pEvdev->close_slot) { + EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, + XI_TouchEnd); + pEvdev->close_slot = 0; + } else { + EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, + pEvdev->open_slot ? XI_TouchBegin : + XI_TouchUpdate); + pEvdev->open_slot = 0; + } + + valuator_mask_zero(pEvdev->mt_mask); +} + +static void +EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev) +{ + EvdevPtr pEvdev = pInfo->private; + int map; + + if (ev->code == ABS_MT_SLOT) { + EvdevProcessTouch(pInfo); + pEvdev->cur_slot = ev->value; + } else if (ev->code == ABS_MT_TRACKING_ID) { + if (ev->value >= 0) + pEvdev->open_slot = 1; + else + pEvdev->close_slot = 1; + } else { + map = pEvdev->axis_map[ev->code] - pEvdev->num_vals; + valuator_mask_set(pEvdev->mt_mask, map, ev->value); + } +} +#else +#define EvdevProcessTouch(pInfo) +#define EvdevProcessTouchEvent(pInfo, ev) +#endif /* MULTITOUCH */ + /** * Take the absolute motion input event and process it accordingly. */ @@ -698,9 +769,13 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev) if (EvdevWheelEmuFilterMotion(pInfo, ev)) return; - map = pEvdev->axis_map[ev->code]; - valuator_mask_set(pEvdev->vals, map, value); - pEvdev->abs_queued = 1; + if (ev->code >= ABS_MT_SLOT) + EvdevProcessTouchEvent(pInfo, ev); + else { + map = pEvdev->axis_map[ev->code]; + valuator_mask_set(pEvdev->vals, map, value); + pEvdev->abs_queued = 1; + } } /** @@ -796,6 +871,9 @@ EvdevPostProximityEvents(InputInfoPtr pInfo, int which, int num_v, int first_v, switch (pEvdev->queue[i].type) { case EV_QUEUE_KEY: case EV_QUEUE_BTN: +#ifdef MULTITOUCH + case EV_QUEUE_TOUCH: +#endif break; case EV_QUEUE_PROXIMITY: if (pEvdev->queue[i].val == which) @@ -818,26 +896,33 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v, for (i = 0; i < pEvdev->num_queue; i++) { switch (pEvdev->queue[i].type) { case EV_QUEUE_KEY: - xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].key, + xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].detail.key, pEvdev->queue[i].val); break; case EV_QUEUE_BTN: if (Evdev3BEmuFilterEvent(pInfo, - pEvdev->queue[i].key, + pEvdev->queue[i].detail.key, pEvdev->queue[i].val)) break; if (pEvdev->abs_queued && pEvdev->in_proximity) { - xf86PostButtonEventP(pInfo->dev, Absolute, pEvdev->queue[i].key, + xf86PostButtonEventP(pInfo->dev, Absolute, pEvdev->queue[i].detail.key, pEvdev->queue[i].val, first_v, num_v, v + first_v); } else - xf86PostButtonEvent(pInfo->dev, Relative, pEvdev->queue[i].key, + xf86PostButtonEvent(pInfo->dev, Relative, pEvdev->queue[i].detail.key, pEvdev->queue[i].val, 0, 0); break; case EV_QUEUE_PROXIMITY: break; +#ifdef MULTITOUCH + case EV_QUEUE_TOUCH: + xf86PostTouchEvent(pInfo->dev, pEvdev->queue[i].detail.touch, + pEvdev->queue[i].val, 0, + pEvdev->queue[i].touchMask); + break; +#endif } } } @@ -856,6 +941,7 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevProcessProximityState(pInfo); EvdevProcessValuators(pInfo); + EvdevProcessTouch(pInfo); EvdevPostProximityEvents(pInfo, TRUE, num_v, first_v, v); EvdevPostRelativeMotionEvents(pInfo, num_v, first_v, v); @@ -1014,6 +1100,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) InputInfoPtr pInfo; EvdevPtr pEvdev; int num_axes, axis, i = 0; + int num_mt_axes = 0; Atom *atoms; pInfo = device->public.devicePrivate; @@ -1026,11 +1113,36 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) if (num_axes < 1) goto out; +#ifdef MULTITOUCH + for (axis = ABS_MT_SLOT; axis < ABS_MAX; axis++) + { + if (EvdevBitIsSet(pEvdev->abs_bitmask, axis)) + { + if(axis != ABS_MT_SLOT && axis != ABS_MT_TRACKING_ID) + num_mt_axes++; + num_axes--; + } + } +#endif + if (num_axes > MAX_VALUATORS) { xf86IDrvMsg(pInfo, X_WARNING, "found %d axes, limiting to %d.\n", num_axes, MAX_VALUATORS); num_axes = MAX_VALUATORS; } +#ifdef MULTITOUCH + if (num_mt_axes > MAX_VALUATORS) { + xf86Msg(X_WARNING, "%s: found %d MT axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS); + num_mt_axes = MAX_VALUATORS; + } +#endif + + if (num_axes < 1 && num_mt_axes < 1) { + xf86Msg(X_WARNING, "%s: no absolute or touch axes found.\n", + device->name); + return !Success; + } + pEvdev->num_vals = num_axes; if (num_axes > 0) { pEvdev->vals = valuator_mask_new(num_axes); @@ -1040,17 +1152,39 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) goto out; } } - atoms = malloc(pEvdev->num_vals * sizeof(Atom)); +#ifdef MULTITOUCH + if (num_mt_axes > 0) { + pEvdev->mt_mask = valuator_mask_new(num_mt_axes); + if (!pEvdev->mt_mask) { + xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n", + device->name); + goto out; + } + for (i = 0; i < EVDEV_MAXQUEUE; i++) { + pEvdev->queue[i].touchMask = + valuator_mask_new(num_mt_axes); + if (!pEvdev->queue[i].touchMask) { + xf86Msg(X_ERROR, "%s: failed to allocate MT valuator masks for " + "evdev event queue.\n", device->name); + goto out; + } + } + } +#endif + atoms = malloc((pEvdev->num_vals + num_mt_axes) * sizeof(Atom)); + + i = 0; for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) { pEvdev->axis_map[axis] = -1; - if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis)) + if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis) || + axis == ABS_MT_SLOT || axis == ABS_MT_TRACKING_ID) continue; pEvdev->axis_map[axis] = i; i++; } - EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms); + EvdevInitAxesLabels(pEvdev, pEvdev->num_vals + num_mt_axes, atoms); if (!InitValuatorClassDeviceStruct(device, num_axes, atoms, GetMotionHistorySize(), Absolute)) { @@ -1058,7 +1192,26 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) goto out; } - for (axis = ABS_X; axis <= ABS_MAX; axis++) { +#ifdef MULTITOUCH + if (num_mt_axes > 0) + { + int num_touches = 10; + 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 (!InitTouchClassDeviceStruct(device, num_touches, mode, + num_mt_axes)) { + xf86Msg(X_ERROR, "%s: failed to initialize touch class device.\n", + device->name); + goto out; + } + } +#endif + + for (axis = ABS_X; axis < ABS_MT_SLOT; axis++) { int axnum = pEvdev->axis_map[axis]; int resolution = 10000; @@ -1079,6 +1232,25 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) xf86InitValuatorDefaults(device, axnum); } +#ifdef MULTITOUCH + for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) { + int axnum = pEvdev->axis_map[axis] - pEvdev->num_vals; + int resolution = 10000; + + if (axnum < 0) + continue; + + if (pEvdev->absinfo[axis].resolution) + resolution = pEvdev->absinfo[axis].resolution * 1000; + + xf86InitTouchValuatorAxisStruct(device, axnum, + atoms[axnum + pEvdev->num_vals], + pEvdev->absinfo[axis].minimum, + pEvdev->absinfo[axis].maximum, + pEvdev->absinfo[axis].resolution); + } +#endif + free(atoms); for (i = 0; i < ArrayLength(proximity_bits); i++) @@ -1129,6 +1301,11 @@ out: valuator_mask_free(&pEvdev->vals); valuator_mask_free(&pEvdev->old_vals); valuator_mask_free(&pEvdev->prox); +#ifdef MULTITOUCH + valuator_mask_free(&pEvdev->mt_mask); + for (i = 0; i < EVDEV_MAXQUEUE; i++) + valuator_mask_free(&pEvdev->queue[i].touchMask); +#endif return !Success; } @@ -1462,6 +1639,9 @@ EvdevProc(DeviceIntPtr device, int what) { InputInfoPtr pInfo; EvdevPtr pEvdev; +#ifdef MULTITOUCH + int i; +#endif pInfo = device->public.devicePrivate; pEvdev = pInfo->private; @@ -1501,6 +1681,11 @@ EvdevProc(DeviceIntPtr device, int what) valuator_mask_free(&pEvdev->vals); valuator_mask_free(&pEvdev->old_vals); valuator_mask_free(&pEvdev->prox); +#ifdef MULTITOUCH + valuator_mask_free(&pEvdev->mt_mask); + for (i = 0; i < EVDEV_MAXQUEUE; i++) + valuator_mask_free(&pEvdev->queue[i].touchMask); +#endif EvdevRemoveDevice(pInfo); pEvdev->min_maj = 0; break; @@ -1959,6 +2144,10 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) if (rc != Success) goto error; +#ifdef MULTITOUCH + pEvdev->cur_slot = -1; +#endif + /* * We initialize pEvdev->in_proximity to 1 so that device that doesn't use * proximity will still report events. -- cgit v1.2.3 From c9a2b4e9ce9b15e57241184df78c72ec8f6a4705 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Mon, 8 Nov 2010 14:35:02 -0500 Subject: Use MTDev for multitouch devices 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 --- src/evdev.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 16f7339..48bfaea 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -998,7 +998,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 */ @@ -1199,8 +1209,8 @@ EvdevAddAbsValuatorClass(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; if (!InitTouchClassDeviceStruct(device, num_touches, mode, num_mt_axes)) { @@ -1685,6 +1695,8 @@ EvdevProc(DeviceIntPtr device, int what) valuator_mask_free(&pEvdev->mt_mask); for (i = 0; i < EVDEV_MAXQUEUE; i++) valuator_mask_free(&pEvdev->queue[i].touchMask); + if (pEvdev->mtdev) + mtdev_close(pEvdev->mtdev); #endif EvdevRemoveDevice(pInfo); pEvdev->min_maj = 0; @@ -2084,6 +2096,16 @@ EvdevOpenDevice(InputInfoPtr pInfo) pEvdev->device = device; xf86IDrvMsg(pInfo, X_CONFIG, "Device: \"%s\"\n", 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) @@ -2098,6 +2120,17 @@ 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_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name); + return FALSE; + } +#endif + /* Check major/minor of device node to avoid adding duplicate devices. */ pEvdev->min_maj = EvdevGetMajorMinor(pInfo); if (EvdevIsDuplicate(pInfo)) -- cgit v1.2.3 From 907b7cad3fd892ca3349cd18e9ccdc5659027b40 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Thu, 2 Dec 2010 18:01:41 -0500 Subject: Ensure touchpad events are always processed with MT Without this change, an MT touchpad in relative mode could end a touch while not resetting the oldMask used to calculate relative values. This fix allows a Magic Trackpad to behave as a relative mode device again. Signed-off-by: Chase Douglas --- src/evdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 48bfaea..d32427c 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -774,8 +774,9 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev) else { map = pEvdev->axis_map[ev->code]; valuator_mask_set(pEvdev->vals, map, value); - pEvdev->abs_queued = 1; } + + pEvdev->abs_queued = 1; } /** -- cgit v1.2.3 From c1b89bda12c1897120bace941625cfa27e547458 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 25 Oct 2011 14:52:26 +1000 Subject: Remove duplicate line Signed-off-by: Peter Hutterer --- src/evdev.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index d32427c..9e3cc4e 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1006,10 +1006,9 @@ EvdevReadInput(InputInfoPtr pInfo) 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 + len = read(pInfo->fd, &ev, sizeof(ev)); + if (len <= 0) { if (errno == ENODEV) /* May happen after resume */ -- cgit v1.2.3 From 91d90a79593369ba1079d06a75f09ceaa9143768 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 25 Oct 2011 14:55:47 +1000 Subject: Use mtdev API to allocate/free mtdev structs Signed-off-by: Peter Hutterer --- src/evdev.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 9e3cc4e..ce7cb7f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -2096,16 +2096,6 @@ EvdevOpenDevice(InputInfoPtr pInfo) pEvdev->device = device; xf86IDrvMsg(pInfo, X_CONFIG, "Device: \"%s\"\n", 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) @@ -2121,11 +2111,10 @@ EvdevOpenDevice(InputInfoPtr pInfo) } #ifdef MULTITOUCH - if (mtdev_open(pEvdev->mtdev, pInfo->fd) == 0) + pEvdev->mtdev = mtdev_new_open(pInfo->fd); + if (pEvdev->mtdev) pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value; else { - free(pEvdev->mtdev); - pEvdev->mtdev = NULL; xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name); return FALSE; } @@ -2137,6 +2126,10 @@ EvdevOpenDevice(InputInfoPtr pInfo) { xf86IDrvMsg(pInfo, X_WARNING, "device file is duplicate. Ignoring.\n"); close(pInfo->fd); +#ifdef MULTITOUCH + mtdev_close_delete(pEvdev->mtdev); + pEvdev->mtdev = NULL; +#endif return BadMatch; } -- cgit v1.2.3 From fabee66bcc7260ec50c3091be3f9b503eea65e61 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 25 Oct 2011 15:06:38 +1000 Subject: 0 is the value for "unknown/unlimited" number of touches Signed-off-by: Peter Hutterer --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index ce7cb7f..8108969 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1205,7 +1205,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) #ifdef MULTITOUCH if (num_mt_axes > 0) { - int num_touches = 10; + int num_touches = 0; int mode = pEvdev->flags & EVDEV_TOUCHPAD ? XIDependentTouch : XIDirectTouch; -- cgit v1.2.3 From fc4f98153c2608389d87e37316036a31fb1021e7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Oct 2011 09:59:34 +1000 Subject: MT axes are counted separately, make sure they're initialized too. Signed-off-by: Peter Hutterer --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 8108969..366de37 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1196,7 +1196,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) EvdevInitAxesLabels(pEvdev, pEvdev->num_vals + num_mt_axes, atoms); - if (!InitValuatorClassDeviceStruct(device, num_axes, atoms, + if (!InitValuatorClassDeviceStruct(device, num_axes + num_mt_axes, atoms, GetMotionHistorySize(), Absolute)) { xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize valuator class device.\n"); goto out; -- cgit v1.2.3 From 6127923fe0d50cb9b9ac4ae0a3876ba6f180137c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Oct 2011 10:51:16 +1000 Subject: When resetting the queue, don't reset the touchMask Otherwise we segfault after the first SYN event Signed-off-by: Peter Hutterer --- src/evdev.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 366de37..4291343 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -935,6 +935,7 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v, static void EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) { + int i; int num_v = 0, first_v = 0; int v[MAX_VALUATORS] = {}; EvdevPtr pEvdev = pInfo->private; @@ -951,7 +952,15 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevPostProximityEvents(pInfo, FALSE, num_v, first_v, v); memset(pEvdev->delta, 0, sizeof(pEvdev->delta)); - memset(pEvdev->queue, 0, sizeof(pEvdev->queue)); + for (i = 0; i < ArrayLength(pEvdev->queue); i++) + { + EventQueuePtr queue = &pEvdev->queue[i]; + queue->detail.key = 0; + queue->type = 0; + queue->val = 0; + /* don't reset the touchMask */ + } + if (pEvdev->vals) valuator_mask_zero(pEvdev->vals); pEvdev->num_queue = 0; -- cgit v1.2.3 From 239e972be1f2c6a984dd6c5aecce710d0b866257 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Oct 2011 11:14:04 +1000 Subject: Simplify a condition, only the event type differs here Signed-off-by: Peter Hutterer --- src/evdev.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 4291343..97da9c8 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -704,20 +704,23 @@ static void EvdevProcessTouch(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; + int type; if (pEvdev->cur_slot < 0 || !pEvdev->mt_mask) return; - if (pEvdev->close_slot) { - EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, - XI_TouchEnd); - pEvdev->close_slot = 0; - } else { - EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, - pEvdev->open_slot ? XI_TouchBegin : - XI_TouchUpdate); - pEvdev->open_slot = 0; - } + if (pEvdev->close_slot) + type = XI_TouchEnd; + else if (pEvdev->open_slot) + type = XI_TouchBegin; + else + type = XI_TouchUpdate; + + + EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, type); + + pEvdev->close_slot = 0; + pEvdev->open_slot = 0; valuator_mask_zero(pEvdev->mt_mask); } -- cgit v1.2.3 From 9411749f76c31a8054ded62a6fb767c8135b4d4e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Oct 2011 13:09:30 +1000 Subject: Replace open_slot/close_slot with a SlotState enum Signed-off-by: Peter Hutterer --- src/evdev.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 97da9c8..b55a0aa 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -709,9 +709,9 @@ EvdevProcessTouch(InputInfoPtr pInfo) if (pEvdev->cur_slot < 0 || !pEvdev->mt_mask) return; - if (pEvdev->close_slot) + if (pEvdev->slot_state == SLOTSTATE_CLOSE) type = XI_TouchEnd; - else if (pEvdev->open_slot) + else if (pEvdev->slot_state == SLOTSTATE_OPEN) type = XI_TouchBegin; else type = XI_TouchUpdate; @@ -719,8 +719,7 @@ EvdevProcessTouch(InputInfoPtr pInfo) EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, type); - pEvdev->close_slot = 0; - pEvdev->open_slot = 0; + pEvdev->slot_state = SLOTSTATE_EMPTY; valuator_mask_zero(pEvdev->mt_mask); } @@ -736,9 +735,9 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev) pEvdev->cur_slot = ev->value; } else if (ev->code == ABS_MT_TRACKING_ID) { if (ev->value >= 0) - pEvdev->open_slot = 1; + pEvdev->slot_state = SLOTSTATE_OPEN; else - pEvdev->close_slot = 1; + pEvdev->slot_state = SLOTSTATE_CLOSE; } else { map = pEvdev->axis_map[ev->code] - pEvdev->num_vals; valuator_mask_set(pEvdev->mt_mask, map, ev->value); -- cgit v1.2.3 From 2ce305129ca94394096f4d697d51eb120de2940b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Oct 2011 13:21:18 +1000 Subject: Skip event posting for empty slots. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ABS_MT_SLOT comes before any other events. The following order of events is common for protocol B devices (and mtdev): ... EV_SYN ABS_MT_SLOT → posting here means we miss on the position information ABS_MT_POSITION_X ABS_MT_POSITION_Y ABS_MT_SLOT ABS_MT_POSITION_X ABS_MT_POSITION_Y EV_SYN Store the stot state as SLOT_EMPTY after posting an event (i.e. EV_SYN and ABS_MT_SLOT) and then don't post until the next slot/syn event. Signed-off-by: Peter Hutterer --- src/evdev.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index b55a0aa..13b1e10 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -709,6 +709,10 @@ EvdevProcessTouch(InputInfoPtr pInfo) if (pEvdev->cur_slot < 0 || !pEvdev->mt_mask) return; + /* If the ABS_MT_SLOT is the first event we get after EV_SYN, skip this */ + if (pEvdev->slot_state == SLOTSTATE_EMPTY) + return; + if (pEvdev->slot_state == SLOTSTATE_CLOSE) type = XI_TouchEnd; else if (pEvdev->slot_state == SLOTSTATE_OPEN) @@ -733,14 +737,19 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev) if (ev->code == ABS_MT_SLOT) { EvdevProcessTouch(pInfo); pEvdev->cur_slot = ev->value; - } else if (ev->code == ABS_MT_TRACKING_ID) { + } else + { + if (pEvdev->slot_state == SLOTSTATE_EMPTY) + pEvdev->slot_state = SLOTSTATE_UPDATE; + if (ev->code == ABS_MT_TRACKING_ID) { if (ev->value >= 0) pEvdev->slot_state = SLOTSTATE_OPEN; else pEvdev->slot_state = SLOTSTATE_CLOSE; - } else { - map = pEvdev->axis_map[ev->code] - pEvdev->num_vals; - valuator_mask_set(pEvdev->mt_mask, map, ev->value); + } else { + map = pEvdev->axis_map[ev->code] - pEvdev->num_vals; + valuator_mask_set(pEvdev->mt_mask, map, ev->value); + } } } #else -- cgit v1.2.3 From 5e9b027807cc205dc9c4efbb8360ac4b20317682 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 31 Oct 2011 08:58:18 +1000 Subject: Replace 0/1 button values with enums BUTTON_PRESS is much harder to confuse with a button number than a simple 1. Signed-off-by: Peter Hutterer --- src/evdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 13b1e10..4bb55f5 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -411,9 +411,10 @@ EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ValuatorMask *mask, * Interface for MB emulation since these need to post immediately. */ void -EvdevPostButtonEvent(InputInfoPtr pInfo, int button, int value) +EvdevPostButtonEvent(InputInfoPtr pInfo, int button, enum ButtonAction act) { - xf86PostButtonEvent(pInfo->dev, Relative, button, value, 0, 0); + xf86PostButtonEvent(pInfo->dev, Relative, button, + (act == BUTTON_PRESS) ? 1 : 0, 0, 0); } void -- cgit v1.2.3 From 3175a2a96d448a0b2584a58ab3d05fbebb11fab1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 2 Nov 2011 09:53:34 +1000 Subject: Print to the log if we find multitouch axes. No real effect on the code, but it helps to have that line in the log when searching for driver issues. Signed-off-by: Peter Hutterer --- src/evdev.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 4bb55f5..f88074b 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1866,6 +1866,7 @@ EvdevProbe(InputInfoPtr pInfo) { int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll; int has_lmr; /* left middle right */ + int has_mt; /* multitouch */ int ignore_abs = 0, ignore_rel = 0; EvdevPtr pEvdev = pInfo->private; int rc = 1; @@ -1899,6 +1900,7 @@ EvdevProbe(InputInfoPtr pInfo) has_keys = FALSE; has_scroll = FALSE; has_lmr = FALSE; + has_mt = FALSE; num_buttons = 0; /* count all buttons */ @@ -1966,6 +1968,15 @@ EvdevProbe(InputInfoPtr pInfo) } } +#ifdef MULTITOUCH + for (i = ABS_MT_SLOT; i < ABS_MAX; i++) { + if (EvdevBitIsSet(pEvdev->abs_bitmask, i)) { + has_mt = TRUE; + break; + } + } +#endif + if (ignore_abs && has_abs_axes) { xf86IDrvMsg(pInfo, X_INFO, "Absolute axes present but ignored.\n"); @@ -1974,6 +1985,9 @@ EvdevProbe(InputInfoPtr pInfo) xf86IDrvMsg(pInfo, X_PROBED, "Found absolute axes\n"); pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS; + if (has_mt) + xf86IDrvMsg(pInfo, X_PROBED, "Found absolute multitouch axes\n"); + if ((EvdevBitIsSet(pEvdev->abs_bitmask, ABS_X) && EvdevBitIsSet(pEvdev->abs_bitmask, ABS_Y))) { xf86IDrvMsg(pInfo, X_PROBED, "Found x and y absolute axes\n"); -- cgit v1.2.3 From cf93a21df1dd66118d3a1f5a0769d48f317de749 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Tue, 29 Nov 2011 18:02:58 -0800 Subject: Don't send pointer events for multitouch touchscreen devices Pointer events will be emulated by the server. Signed-off-by: Chase Douglas --- src/evdev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index f88074b..760f3ce 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -781,14 +781,14 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev) if (EvdevWheelEmuFilterMotion(pInfo, ev)) return; - if (ev->code >= ABS_MT_SLOT) + if (ev->code >= ABS_MT_SLOT) { EvdevProcessTouchEvent(pInfo, ev); - else { + pEvdev->abs_queued = 1; + } else if (!pEvdev->mt_mask) { map = pEvdev->axis_map[ev->code]; valuator_mask_set(pEvdev->vals, map, value); + pEvdev->abs_queued = 1; } - - pEvdev->abs_queued = 1; } /** @@ -823,7 +823,8 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev) * BTN_TOUCH as the proximity notifier */ if (!pEvdev->use_proximity) pEvdev->in_proximity = value ? ev->code : 0; - if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET))) + if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET)) || + pEvdev->mt_mask) break; /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as * BTN_LEFT. */ -- cgit v1.2.3 From fed454192ddc4ad94226040c657deb6abea3df88 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 15 Dec 2011 08:55:32 +1000 Subject: Use xf86InitValuatorAxisStruct, the touch-specific version was dropped Signed-off-by: Peter Hutterer --- src/evdev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 760f3ce..8adfefd 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1275,11 +1275,12 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) if (pEvdev->absinfo[axis].resolution) resolution = pEvdev->absinfo[axis].resolution * 1000; - xf86InitTouchValuatorAxisStruct(device, axnum, - atoms[axnum + pEvdev->num_vals], - pEvdev->absinfo[axis].minimum, - pEvdev->absinfo[axis].maximum, - pEvdev->absinfo[axis].resolution); + xf86InitValuatorAxisStruct(device, axnum, + atoms[axnum + pEvdev->num_vals], + pEvdev->absinfo[axis].minimum, + pEvdev->absinfo[axis].maximum, + resolution, 0, resolution, + Absolute); } #endif -- cgit v1.2.3 From f3c628acc4f7399325756590cdc72e769341243c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 20 Dec 2011 10:56:22 +1000 Subject: Map ABS_MT_POSITION_X/Y into ABS_X/Y MT axes are the same as traditional axes, so one into the other so we get x/y coordinates regardless wich axes it comes from. Signed-off-by: Peter Hutterer --- src/evdev.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 8adfefd..9a5608b 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -748,7 +748,12 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev) else pEvdev->slot_state = SLOTSTATE_CLOSE; } else { - map = pEvdev->axis_map[ev->code] - pEvdev->num_vals; + if (ev->code == ABS_MT_POSITION_X) + map = pEvdev->axis_map[ABS_X]; + else if (ev->code == ABS_MT_POSITION_Y) + map = pEvdev->axis_map[ABS_Y]; + else + map = pEvdev->axis_map[ev->code] - pEvdev->num_vals; valuator_mask_set(pEvdev->mt_mask, map, ev->value); } } -- cgit v1.2.3 From 191660189a01b9c96bb4c0fa1a2e5008ae666238 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 20 Dec 2011 14:14:16 +1000 Subject: Add is_blacklisted_axis() helper The kernel exports a bunch of information as axis that shouldn't be an axis and we don't treat it as axis in the server. Add this helper instead of checking for the axis codes manually. No function change. Signed-off-by: Peter Hutterer --- src/evdev.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 9a5608b..00c9935 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1131,6 +1131,23 @@ EvdevAddKeyClass(DeviceIntPtr device) return Success; } +/** + * return TRUE if the axis is not one we should count as true axis + */ +static int +is_blacklisted_axis(int axis) +{ + switch(axis) + { + case ABS_MT_SLOT: + case ABS_MT_TRACKING_ID: + return TRUE; + default: + return FALSE; + } +} + + static int EvdevAddAbsValuatorClass(DeviceIntPtr device) { @@ -1155,7 +1172,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) { if (EvdevBitIsSet(pEvdev->abs_bitmask, axis)) { - if(axis != ABS_MT_SLOT && axis != ABS_MT_TRACKING_ID) + if (!is_blacklisted_axis(axis)) num_mt_axes++; num_axes--; } @@ -1215,7 +1232,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) { pEvdev->axis_map[axis] = -1; if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis) || - axis == ABS_MT_SLOT || axis == ABS_MT_TRACKING_ID) + is_blacklisted_axis(axis)) continue; pEvdev->axis_map[axis] = i; i++; -- cgit v1.2.3 From e99ab2314f712df8dd705b16008755f8b3095707 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 20 Dec 2011 15:08:06 +1000 Subject: Don't count legacy and MT axes twice The kernel exports both ABS_X and ABS_MT_POSITION_X (and a couple others) for a multi-touch capable device. For such devices, only count the axis once since we submit ABS_MT_POSITION_X through ABS_X. Signed-off-by: Peter Hutterer --- src/evdev.c | 107 +++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 80 insertions(+), 27 deletions(-) (limited to 'src/evdev.c') diff --git a/src/evdev.c b/src/evdev.c index 00c9935..aef1d6e 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -748,12 +748,7 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev) else pEvdev->slot_state = SLOTSTATE_CLOSE; } else { - if (ev->code == ABS_MT_POSITION_X) - map = pEvdev->axis_map[ABS_X]; - else if (ev->code == ABS_MT_POSITION_Y) - map = pEvdev->axis_map[ABS_Y]; - else - map = pEvdev->axis_map[ev->code] - pEvdev->num_vals; + map = pEvdev->axis_map[ev->code]; valuator_mask_set(pEvdev->mt_mask, map, ev->value); } } @@ -1131,6 +1126,24 @@ EvdevAddKeyClass(DeviceIntPtr device) return Success; } +/* MT axes are counted twice - once as ABS_X (which the kernel keeps for + * backwards compatibility), once as ABS_MT_POSITION_X. So we need to keep a + * mapping of those axes to make sure we only count them once + */ +struct mt_axis_mappings { + int mt_code; + int code; + Bool needs_mapping; /* TRUE if both code and mt_code are present */ + int mapping; /* Logical mapping of 'code' axis */ +}; + +static struct mt_axis_mappings mt_axis_mappings[] = { + {ABS_MT_POSITION_X, ABS_X}, + {ABS_MT_POSITION_Y, ABS_Y}, + {ABS_MT_PRESSURE, ABS_PRESSURE}, + {ABS_MT_DISTANCE, ABS_DISTANCE}, +}; + /** * return TRUE if the axis is not one we should count as true axis */ @@ -1154,7 +1167,9 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) InputInfoPtr pInfo; EvdevPtr pEvdev; int num_axes, axis, i = 0; - int num_mt_axes = 0; + int num_mt_axes = 0, /* number of MT-only axes */ + num_mt_axes_total = 0; /* total number of MT axes, including + double-counted ones, excluding blacklisted */ Atom *atoms; pInfo = device->public.devicePrivate; @@ -1172,26 +1187,35 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) { if (EvdevBitIsSet(pEvdev->abs_bitmask, axis)) { + int j; + Bool skip = FALSE; + + for (j = 0; j < ArrayLength(mt_axis_mappings); j++) + { + if (mt_axis_mappings[j].mt_code == axis && + BitIsOn(pEvdev->abs_bitmask, mt_axis_mappings[j].code)) + { + mt_axis_mappings[j].needs_mapping = TRUE; + skip = TRUE; + } + } + if (!is_blacklisted_axis(axis)) - num_mt_axes++; + { + num_mt_axes_total++; + if (!skip) + num_mt_axes++; + } num_axes--; } } #endif - - if (num_axes > MAX_VALUATORS) { + if (num_axes + num_mt_axes > MAX_VALUATORS) { xf86IDrvMsg(pInfo, X_WARNING, "found %d axes, limiting to %d.\n", num_axes, MAX_VALUATORS); num_axes = MAX_VALUATORS; } -#ifdef MULTITOUCH - if (num_mt_axes > MAX_VALUATORS) { - xf86Msg(X_WARNING, "%s: found %d MT axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS); - num_mt_axes = MAX_VALUATORS; - } -#endif - - if (num_axes < 1 && num_mt_axes < 1) { + if (num_axes < 1 && num_mt_axes_total < 1) { xf86Msg(X_WARNING, "%s: no absolute or touch axes found.\n", device->name); return !Success; @@ -1207,8 +1231,8 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) } } #ifdef MULTITOUCH - if (num_mt_axes > 0) { - pEvdev->mt_mask = valuator_mask_new(num_mt_axes); + if (num_mt_axes_total > 0) { + pEvdev->mt_mask = valuator_mask_new(num_mt_axes_total); if (!pEvdev->mt_mask) { xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n", device->name); @@ -1217,7 +1241,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) for (i = 0; i < EVDEV_MAXQUEUE; i++) { pEvdev->queue[i].touchMask = - valuator_mask_new(num_mt_axes); + valuator_mask_new(num_mt_axes_total); if (!pEvdev->queue[i].touchMask) { xf86Msg(X_ERROR, "%s: failed to allocate MT valuator masks for " "evdev event queue.\n", device->name); @@ -1230,12 +1254,27 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) i = 0; for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) { + int j; + int mapping; pEvdev->axis_map[axis] = -1; if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis) || is_blacklisted_axis(axis)) continue; - pEvdev->axis_map[axis] = i; - i++; + + mapping = i; + + for (j = 0; j < ArrayLength(mt_axis_mappings); j++) + { + if (mt_axis_mappings[j].code == axis) + mt_axis_mappings[j].mapping = mapping; + else if (mt_axis_mappings[j].mt_code == axis && + mt_axis_mappings[j].needs_mapping) + mapping = mt_axis_mappings[j].mapping; + } + + pEvdev->axis_map[axis] = mapping; + if (mapping == i) + i++; } EvdevInitAxesLabels(pEvdev, pEvdev->num_vals + num_mt_axes, atoms); @@ -1247,7 +1286,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) } #ifdef MULTITOUCH - if (num_mt_axes > 0) + if (num_mt_axes_total > 0) { int num_touches = 0; int mode = pEvdev->flags & EVDEV_TOUCHPAD ? @@ -1257,7 +1296,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) num_touches = pEvdev->mtdev->caps.slot.maximum; if (!InitTouchClassDeviceStruct(device, num_touches, mode, - num_mt_axes)) { + num_mt_axes_total)) { xf86Msg(X_ERROR, "%s: failed to initialize touch class device.\n", device->name); goto out; @@ -1288,17 +1327,31 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) #ifdef MULTITOUCH for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) { - int axnum = pEvdev->axis_map[axis] - pEvdev->num_vals; + int axnum = pEvdev->axis_map[axis]; int resolution = 10000; + int j; + BOOL skip = FALSE; if (axnum < 0) continue; + for (j = 0; j < ArrayLength(mt_axis_mappings); j++) + if (mt_axis_mappings[j].mt_code == axis && + mt_axis_mappings[j].needs_mapping) + { + skip = TRUE; + break; + } + + /* MT axis is mapped, don't set up twice */ + if (skip) + continue; + if (pEvdev->absinfo[axis].resolution) resolution = pEvdev->absinfo[axis].resolution * 1000; xf86InitValuatorAxisStruct(device, axnum, - atoms[axnum + pEvdev->num_vals], + atoms[axnum], pEvdev->absinfo[axis].minimum, pEvdev->absinfo[axis].maximum, resolution, 0, resolution, -- cgit v1.2.3