summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac3
-rw-r--r--src/Makefile.am2
-rw-r--r--src/evdev.c253
-rw-r--r--src/evdev.h16
4 files changed, 135 insertions, 139 deletions
diff --git a/configure.ac b/configure.ac
index 07cd64e..34dbbd0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,6 +47,9 @@ XORG_DEFAULT_OPTIONS
# Obtain compiler/linker options from server and required extensions
PKG_CHECK_MODULES(XORG, xorg-server xproto inputproto)
+# Obtain compiler/linker options for mtdev
+PKG_CHECK_MODULES(MTDEV, mtdev)
+
# Define a configure option for an alternate input module directory
AC_ARG_WITH(xorg-module-dir,
AC_HELP_STRING([--with-xorg-module-dir=DIR],
diff --git a/src/Makefile.am b/src/Makefile.am
index a5c89ac..89137bc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,7 +29,7 @@ AM_CFLAGS = $(XORG_CFLAGS) $(CWARNFLAGS)
AM_CPPFLAGS =-I$(top_srcdir)/include
@DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
-@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
+@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version $(MTDEV_LIBS)
@DRIVER_NAME@_drv_ladir = @inputdir@
@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
diff --git a/src/evdev.c b/src/evdev.c
index 7a72de8..dd90091 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -98,30 +98,6 @@ static char *evdevDefaults[] = {
NULL
};
-static int abs_mt_axis_map[] = {
- ABS_MT_POSITION_X,
- ABS_MT_POSITION_Y,
- ABS_MT_TOUCH_MAJOR,
- ABS_MT_TOUCH_MINOR,
- ABS_MT_WIDTH_MAJOR,
- ABS_MT_WIDTH_MINOR,
- ABS_MT_ORIENTATION,
- ABS_MT_TRACKING_ID,
- ABS_MT_TOOL_TYPE,
-};
-static inline int mt_axis_to_evdev(int axis)
-{
- int i;
-
- for (i = 0; i < ArrayLength(abs_mt_axis_map); i++)
- if (abs_mt_axis_map[i] == axis)
- return i;
-
- return -1;
-}
-#define mt_cached_axis(_evdev, _axis) \
- (_evdev->mt_tp_axes[mt_axis_to_evdev(_axis)])
-
static int EvdevOn(DeviceIntPtr);
static int EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare);
static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
@@ -561,6 +537,54 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
}
}
+static void
+EvdevProcessSlot(InputInfoPtr pInfo)
+{
+ EvdevPtr pEvdev = pInfo->private;
+ int slot = pEvdev->mt_cur_slot;
+
+ if (slot >= 0 && pEvdev->mt_ids[slot] >= 0)
+ {
+ if (BitIsOn(pEvdev->mt_axismask, MT_AXIS(ABS_MT_TRACKING_ID)) &&
+ pEvdev->mt_slot[MT_AXIS(ABS_MT_TRACKING_ID)] < 0) {
+ xf86FiniTouchPoint(pInfo->dev, pEvdev->mt_ids[slot]);
+ pEvdev->mt_ids[slot] = -1;
+
+ memset(pEvdev->mt_axismask, 0, sizeof(pEvdev->mt_axismask));
+ }
+ else {
+ int mask = 0;
+
+ if (BitIsOn(pEvdev->mt_axismask, MT_AXIS(ABS_MT_POSITION_X)))
+ mask |= XITouchXMask;
+ if (BitIsOn(pEvdev->mt_axismask, MT_AXIS(ABS_MT_POSITION_Y)))
+ mask |= XITouchYMask;
+ if (BitIsOn(pEvdev->mt_axismask, MT_AXIS(ABS_MT_TOUCH_MAJOR)) ||
+ BitIsOn(pEvdev->mt_axismask, MT_AXIS(ABS_MT_TOUCH_MINOR)))
+ mask |= XITouchTouchSizeMask;
+ if (BitIsOn(pEvdev->mt_axismask, MT_AXIS(ABS_MT_WIDTH_MAJOR)) ||
+ BitIsOn(pEvdev->mt_axismask, MT_AXIS(ABS_MT_WIDTH_MINOR)))
+ mask |= XITouchToolSizeMask;
+ if (BitIsOn(pEvdev->mt_axismask, MT_AXIS(ABS_MT_ORIENTATION)))
+ mask |= XITouchOrientationMask;
+
+ xf86PostTouchMotion(pInfo->dev,
+ pEvdev->mt_ids[slot],
+ pEvdev->mt_slot[MT_AXIS(ABS_MT_TOOL_TYPE)],
+ mask,
+ pEvdev->mt_slot[MT_AXIS(ABS_MT_POSITION_X)],
+ pEvdev->mt_slot[MT_AXIS(ABS_MT_POSITION_Y)],
+ pEvdev->mt_slot[MT_AXIS(ABS_MT_TOUCH_MAJOR)],
+ pEvdev->mt_slot[MT_AXIS(ABS_MT_TOUCH_MINOR)],
+ pEvdev->mt_slot[MT_AXIS(ABS_MT_WIDTH_MAJOR)],
+ pEvdev->mt_slot[MT_AXIS(ABS_MT_WIDTH_MINOR)],
+ pEvdev->mt_slot[MT_AXIS(ABS_MT_ORIENTATION)]);
+
+ memset(pEvdev->mt_axismask, 0, sizeof(pEvdev->mt_axismask));
+ }
+ }
+}
+
/**
* Take the absolute motion input event and process it accordingly.
*/
@@ -575,15 +599,31 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
/* Process multitouch events first, since they don't interfere
* with abs/rel. */
- if (ev->code >= ABS_MT_TOUCH_MAJOR && ev->code <= ABS_MT_TRACKING_ID)
+ if (ev->code == ABS_MT_SLOT)
{
- int axis = mt_axis_to_evdev(ev->code);
-
- if (axis == -1 || !(pEvdev->flags & EVDEV_MULTITOUCH))
- return;
+ /* Process current touch first */
+ EvdevProcessSlot(pInfo);
- pEvdev->mt_tp_axes[axis] = value;
- SetBitLong(ev->code, pEvdev->mt_tp_axismask);
+ /* Process new slot */
+ if (ev->value >= pEvdev->mt_num_slots)
+ {
+ pEvdev->mt_cur_slot = -1;
+ xf86Msg(X_WARNING, "%s: No more slots for touch %d, dropping\n",
+ pInfo->name, value);
+ } else
+ pEvdev->mt_cur_slot = ev->value;
+ return;
+ }
+ if (ev->code >= ABS_MT_TOUCH_MAJOR && ev->code <= ABS_MT_PRESSURE)
+ {
+ if ((pEvdev->flags & EVDEV_MULTITOUCH) && pEvdev->mt_cur_slot >= 0)
+ {
+ unsigned int slot = pEvdev->mt_cur_slot;
+ pEvdev->mt_slot[MT_AXIS(ev->code)] = value;
+ if (ev->code == ABS_MT_TRACKING_ID && ev->value >= 0)
+ pEvdev->mt_ids[slot] = value;
+ SetBit(pEvdev->mt_axismask, MT_AXIS(ev->code));
+ }
return;
}
@@ -715,40 +755,6 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v,
}
/**
- * If a touchpoint hasn't appeared between EV_SYN::SYN_REPORT pairs, it means
- * that it's gone; ABS_MT_TRACKING_ID is always guaranteed to appear
- * if a touchpoint is live, even if it hasn't moved.
- */
-static void
-EvdevGCTouchPoints(InputInfoPtr pInfo)
-{
- EvdevPtr pEvdev = pInfo->private;
- int i, j;
-
- if (!(pEvdev->flags & EVDEV_MULTITOUCH))
- return;
-
- for (i = 0; i < pEvdev->mt_max_tps; i++)
- {
- if (!pEvdev->mt_all_tps[i])
- continue;
-
- for (j = 0; j < pEvdev->mt_max_tps; j++)
- if (pEvdev->mt_active_tps[j] == pEvdev->mt_all_tps[i])
- break;
- if (j == pEvdev->mt_max_tps)
- {
- xf86FiniTouchPoint(pInfo->dev, pEvdev->mt_all_tps[i]);
- pEvdev->mt_all_tps[i] = 0;
- }
- }
-
- memcpy(pEvdev->mt_all_tps, pEvdev->mt_active_tps,
- pEvdev->mt_max_tps * sizeof(int));
- memset(pEvdev->mt_active_tps, 0, pEvdev->mt_max_tps * sizeof(int));
-}
-
-/**
* Take the synchronization input event and process it accordingly; the motion
* notify events are sent first, then any button/key press/release events.
*/
@@ -757,66 +763,21 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
{
int num_v = 0, first_v = 0;
int v[MAX_VALUATORS] = {};
- int i;
EvdevPtr pEvdev = pInfo->private;
- /* This means we've finished receiving all the events for a given
- * touchpoint; collate them, update the valuators, and bail. */
- if (ev->code == SYN_MT_REPORT) {
- int id = mt_cached_axis(pEvdev, ABS_MT_TRACKING_ID);
- int mask = 0;
+ EvdevProcessSlot(pInfo);
- if (id == -1 || !(pEvdev->flags & EVDEV_MULTITOUCH))
- return;
+ EvdevProcessValuators(pInfo, v, &num_v, &first_v);
- for (i = 0; i < pEvdev->mt_max_tps; i++) {
- if (pEvdev->mt_active_tps[i] == 0) {
- pEvdev->mt_active_tps[i] = id;
- break;
- }
- }
+ EvdevPostRelativeMotionEvents(pInfo, num_v, first_v, v);
+ EvdevPostAbsoluteMotionEvents(pInfo, num_v, first_v, v);
+ EvdevPostQueuedEvents(pInfo, num_v, first_v, v);
- if (TestBit(ABS_MT_POSITION_X, pEvdev->mt_tp_axismask))
- mask |= XITouchXMask;
- if (TestBit(ABS_MT_POSITION_Y, pEvdev->mt_tp_axismask))
- mask |= XITouchYMask;
- if (TestBit(ABS_MT_TOUCH_MAJOR, pEvdev->mt_tp_axismask) ||
- TestBit(ABS_MT_TOUCH_MINOR, pEvdev->mt_tp_axismask))
- mask |= XITouchTouchSizeMask;
- if (TestBit(ABS_MT_WIDTH_MAJOR, pEvdev->mt_tp_axismask) ||
- TestBit(ABS_MT_WIDTH_MINOR, pEvdev->mt_tp_axismask))
- mask |= XITouchToolSizeMask;
- if (TestBit(ABS_MT_ORIENTATION, pEvdev->mt_tp_axismask))
- mask |= XITouchOrientationMask;
-
- xf86PostTouchMotion(pInfo->dev, id,
- mt_cached_axis(pEvdev, ABS_MT_TOOL_TYPE),
- mask,
- mt_cached_axis(pEvdev, ABS_MT_POSITION_X),
- mt_cached_axis(pEvdev, ABS_MT_POSITION_Y),
- mt_cached_axis(pEvdev, ABS_MT_TOUCH_MAJOR),
- mt_cached_axis(pEvdev, ABS_MT_TOUCH_MINOR),
- mt_cached_axis(pEvdev, ABS_MT_WIDTH_MAJOR),
- mt_cached_axis(pEvdev, ABS_MT_WIDTH_MINOR),
- mt_cached_axis(pEvdev, ABS_MT_ORIENTATION));
-
- memset(pEvdev->mt_tp_axes, 0, pEvdev->mt_max_tps * sizeof(int));
- memset(pEvdev->mt_tp_axismask, 0, sizeof(pEvdev->mt_tp_axismask));
- } else if (ev->code == SYN_REPORT) {
- EvdevGCTouchPoints(pInfo);
-
- EvdevProcessValuators(pInfo, v, &num_v, &first_v);
-
- EvdevPostRelativeMotionEvents(pInfo, num_v, first_v, v);
- EvdevPostAbsoluteMotionEvents(pInfo, num_v, first_v, v);
- EvdevPostQueuedEvents(pInfo, num_v, first_v, v);
-
- memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
- memset(pEvdev->queue, 0, sizeof(pEvdev->queue));
- pEvdev->num_queue = 0;
- pEvdev->abs = 0;
- pEvdev->rel = 0;
- }
+ memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
+ memset(pEvdev->queue, 0, sizeof(pEvdev->queue));
+ pEvdev->num_queue = 0;
+ pEvdev->abs = 0;
+ pEvdev->rel = 0;
}
/**
@@ -853,11 +814,16 @@ static void
EvdevReadInput(InputInfoPtr pInfo)
{
struct input_event ev[NUM_EVENTS];
+ EvdevPtr pEvdev = pInfo->private;
int i, len = sizeof(ev);
while (len == sizeof(ev))
{
- len = read(pInfo->fd, &ev, sizeof(ev));
+ 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));
if (len <= 0)
{
@@ -1304,7 +1270,7 @@ EvdevAddAbsClass(DeviceIntPtr device)
if (!TestBit(axis, pEvdev->abs_bitmask))
continue;
if ((pEvdev->flags & EVDEV_MULTITOUCH) &&
- axis >= ABS_MT_TOUCH_MAJOR && axis <= ABS_MT_TRACKING_ID)
+ axis >= ABS_MT_SLOT && axis <= ABS_MT_PRESSURE)
continue;
pEvdev->axis_map[axis] = i;
i++;
@@ -1581,7 +1547,7 @@ EvdevInitMTClass(DeviceIntPtr device, EvdevPtr pEvdev)
max_touch_width = -1;
}
- ret = InitTouchClassDeviceStruct(device, pEvdev->mt_max_tps, Absolute,
+ ret = InitTouchClassDeviceStruct(device, pEvdev->mt_num_slots, Absolute,
Relative, min_x, max_x, min_y, max_y,
min_touch_width, max_touch_width);
if (ret == TRUE) {
@@ -1591,8 +1557,7 @@ EvdevInitMTClass(DeviceIntPtr device, EvdevPtr pEvdev)
device->name);
}
- memset(pEvdev->mt_tp_axes, 0, pEvdev->mt_max_tps * sizeof(int));
- memset(pEvdev->mt_tp_axismask, 0, sizeof(pEvdev->mt_tp_axismask));
+ memset(pEvdev->mt_axismask, 0, sizeof(pEvdev->mt_axismask));
}
static void
@@ -1760,6 +1725,8 @@ EvdevProc(DeviceIntPtr device, int what)
close(pInfo->fd);
pInfo->fd = -1;
}
+ if (pEvdev->mtdev)
+ mtdev_close(pEvdev->mtdev);
EvdevRemoveDevice(pInfo);
pEvdev->min_maj = 0;
break;
@@ -2149,18 +2116,38 @@ EvdevProbe(InputInfoPtr pInfo)
(pInfo->flags & XI86_CONFIGURED))
{
pEvdev->flags |= EVDEV_MULTITOUCH;
- pEvdev->mt_max_tps = xf86SetIntOption(pInfo->options,
- "MaxMTTouchPoints", 10);
+ pEvdev->mt_num_slots = xf86SetIntOption(pInfo->options,
+ "MaxMTTouchPoints", 10);
xf86Msg(X_INFO, "%s: Adding multitouch support (%d touchpoints)\n",
- pInfo->name, pEvdev->mt_max_tps);
- pEvdev->mt_active_tps = calloc(pEvdev->mt_max_tps, sizeof(int));
- pEvdev->mt_all_tps = calloc(pEvdev->mt_max_tps, sizeof(int));
- if (!pEvdev->mt_active_tps || !pEvdev->mt_all_tps)
+ pInfo->name, pEvdev->mt_num_slots);
+
+ pEvdev->mtdev = malloc(sizeof(struct mtdev));
+ if (!pEvdev->mtdev)
+ {
+ xf86Msg(X_ERROR, "%s: Couldn't allocate mtdev structure\n",
+ pInfo->name);
+ return BadAlloc;
+ }
+
+ if (mtdev_open(pEvdev->mtdev, pInfo->fd))
+ {
+ pEvdev->mtdev = NULL;
+ xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name);
+ return BadAlloc;
+ }
+
+ pEvdev->mt_ids = calloc(pEvdev->mt_num_slots, sizeof(unsigned int));
+ if (!pEvdev->mt_ids)
{
- xf86Msg(X_ERROR, "%s: Couldn't allocate MT axis values\n",
+ free(pEvdev->mtdev);
+ pEvdev->mtdev = NULL;
+ xf86Msg(X_ERROR, "%s: Couldn't allocate MT tracking IDs\n",
pInfo->name);
return BadAlloc;
}
+
+ for (i = 0; i < pEvdev->mt_num_slots; i++)
+ pEvdev->mt_ids[i] = -1;
}
if ((pInfo->flags & XI86_CONFIGURED) == 0) {
@@ -2332,6 +2319,8 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
EvdevDragLockPreInit(pInfo);
}
+ pEvdev->mt_cur_slot = -1;
+
return Success;
error:
diff --git a/src/evdev.h b/src/evdev.h
index 2f874a2..41f4941 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -39,6 +39,8 @@
#include <xf86_OSproc.h>
#include <xkbstr.h>
+#include <mtdev.h>
+
#ifndef EV_CNT /* linux 2.6.23 kernels and earlier lack _CNT defines */
#define EV_CNT (EV_MAX+1)
#endif
@@ -55,7 +57,8 @@
#define LED_CNT (LED_MAX+1)
#endif
-#define MT_NUM_AXES (ABS_MT_TRACKING_ID - ABS_MT_TOUCH_MAJOR)
+#define MT_NUM_AXES (ABS_MT_PRESSURE - ABS_MT_TOUCH_MAJOR)
+#define MT_AXIS(x) (x) - ABS_MT_TOUCH_MAJOR
#define EVDEV_MAXBUTTONS 32
#define EVDEV_MAXQUEUE 32
@@ -126,11 +129,11 @@ typedef struct {
int vals[MAX_VALUATORS];
int old_vals[MAX_VALUATORS]; /* Translate absolute inputs to relative */
- int *mt_active_tps; /* Active touchpoints in this event stream only */
- int *mt_all_tps; /* All currently active touchpoints */
- int mt_max_tps; /* Maximum number of active touchpoints */
- int mt_tp_axes[MT_NUM_AXES]; /* Valuators for the current touchpoint */
- unsigned long mt_tp_axismask[NLONGS(ABS_CNT)];
+ int mt_slot[MT_NUM_AXES]; /* Multitouch touch slots */
+ unsigned int mt_num_slots; /* Number of touch slots */
+ int mt_cur_slot; /* Current slot for MT values */
+ int *mt_ids; /* Tracking IDs of touch slots */
+ uint8_t mt_axismask[(MT_NUM_AXES + 7) / 8]; /* Bitmask of new values */
int flags;
int proximity;
@@ -202,6 +205,7 @@ typedef struct {
/* Event queue used to defer keyboard/button events until EV_SYN time. */
int num_queue;
EventQueueRec queue[EVDEV_MAXQUEUE];
+ struct mtdev *mtdev;
} EvdevRec, *EvdevPtr;
/* Event posting functions */