summaryrefslogtreecommitdiff
path: root/src/evdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/evdev.c')
-rw-r--r--src/evdev.c253
1 files changed, 121 insertions, 132 deletions
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: