eventcomm: Add touch event handling

Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Chase Douglas
2012-01-19 13:05:50 -08:00
committed by Peter Hutterer
parent efdc34859b
commit d15c391544
2 changed files with 258 additions and 22 deletions

View File

@@ -68,9 +68,124 @@ struct eventcomm_proto_data
#ifdef HAVE_MTDEV
struct mtdev *mtdev;
int axis_map[MT_ABS_SIZE];
int cur_slot;
enum
{
SLOTSTATE_OPEN = 0,
SLOTSTATE_CLOSE,
SLOTSTATE_UPDATE,
SLOTSTATE_EMPTY,
} slot_state;
ValuatorMask *mt_mask;
ValuatorMask **last_mt_vals;
#endif
};
#ifdef HAVE_MTDEV
static int
num_slots(const struct eventcomm_proto_data *proto_data)
{
int value = proto_data->mtdev->caps.slot.maximum -
proto_data->mtdev->caps.slot.minimum + 1;
/* If we don't know how many slots there are, assume at least 10 */
return value > 1 ? value : 10;
}
static int
last_mt_vals_slot(const struct eventcomm_proto_data *proto_data)
{
int value = proto_data->cur_slot - proto_data->mtdev->caps.slot.minimum;
return value < num_slots(proto_data) ? value : -1;
}
static void
UninitializeTouch(InputInfoPtr pInfo)
{
SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
struct eventcomm_proto_data *proto_data = (struct eventcomm_proto_data*)priv->proto_data;
if (!proto_data->mtdev)
return;
valuator_mask_free(&proto_data->mt_mask);
if (proto_data->last_mt_vals)
{
int i;
for (i = 0; i < num_slots(proto_data); i++)
valuator_mask_free(&proto_data->last_mt_vals[i]);
free(proto_data->last_mt_vals);
proto_data->last_mt_vals = NULL;
}
mtdev_close(proto_data->mtdev);
proto_data->mtdev = NULL;
}
static void
InitializeTouch(InputInfoPtr pInfo)
{
SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
struct eventcomm_proto_data *proto_data = (struct eventcomm_proto_data*)priv->proto_data;
int i;
proto_data->mtdev = mtdev_new_open(pInfo->fd);
if (!proto_data->mtdev)
{
xf86IDrvMsg(pInfo, X_WARNING,
"failed to create mtdev instance, ignoring touch events\n");
return;
}
proto_data->cur_slot = proto_data->mtdev->caps.slot.value;
/* Axes 0-4 are for X, Y, and scrolling. num_mt_axes does not include X and
* Y. */
proto_data->mt_mask = valuator_mask_new(4 + priv->num_mt_axes);
if (!proto_data->mt_mask)
{
xf86IDrvMsg(pInfo, X_WARNING,
"failed to create MT valuator mask, ignoring touch "
"events\n");
UninitializeTouch(pInfo);
return;
}
proto_data->last_mt_vals = calloc(num_slots(proto_data),
sizeof(ValuatorMask *));
if (!proto_data->last_mt_vals)
{
xf86IDrvMsg(pInfo, X_WARNING,
"failed to allocate MT last values mask array\n");
UninitializeTouch(pInfo);
return;
}
for (i = 0; i < num_slots(proto_data); i++)
{
int j;
proto_data->last_mt_vals[i] = valuator_mask_new(4 + priv->num_mt_axes);
if (!proto_data->last_mt_vals[i])
{
xf86IDrvMsg(pInfo, X_WARNING,
"failed to allocate MT last values mask\n");
UninitializeTouch(pInfo);
return;
}
/* Axes 0-4 are for X, Y, and scrolling. num_mt_axes does not include X
* and Y. */
valuator_mask_set(proto_data->last_mt_vals[i], 0, 0);
valuator_mask_set(proto_data->last_mt_vals[i], 1, 0);
for (j = 4; j < priv->num_mt_axes; j++)
valuator_mask_set(proto_data->last_mt_vals[i], j, 0);
}
}
#endif
static Bool
EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters *para)
{
@@ -91,18 +206,22 @@ EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters *para)
proto_data->need_grab = FALSE;
#ifdef HAVE_MTDEV
proto_data->mtdev = mtdev_new_open(pInfo->fd);
if (!proto_data->mtdev)
{
xf86IDrvMsg(pInfo, X_WARNING,
"failed to create mtdev instance, ignoring touch events\n");
priv->has_touch = FALSE;
}
InitializeTouch(pInfo);
#endif
return TRUE;
}
static Bool
EventDeviceOffHook(InputInfoPtr pInfo)
{
#ifdef HAVE_MTDEV
UninitializeTouch(pInfo);
#endif
return Success;
}
/**
* Test if the device on the file descriptior is recognized as touchpad
* device. Required bits for touchpad recognition are:
@@ -392,6 +511,87 @@ SynapticsReadEvent(InputInfoPtr pInfo, struct input_event *ev)
return rc;
}
static void
EventProcessTouch(InputInfoPtr pInfo)
{
#ifdef HAVE_MTDEV
SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
struct eventcomm_proto_data *proto_data = priv->proto_data;
int type;
if (proto_data->cur_slot < 0 || !priv->has_touch)
return;
/* If the ABS_MT_SLOT is the first event we get after EV_SYN, skip this */
if (proto_data->slot_state == SLOTSTATE_EMPTY)
return;
switch (proto_data->slot_state)
{
case SLOTSTATE_CLOSE:
type = XI_TouchEnd;
break;
case SLOTSTATE_OPEN:
type = XI_TouchBegin;
break;
default:
type = XI_TouchUpdate;
break;
}
xf86PostTouchEvent(pInfo->dev, proto_data->cur_slot, type, 0,
proto_data->mt_mask);
proto_data->slot_state = SLOTSTATE_EMPTY;
valuator_mask_zero(proto_data->mt_mask);
#endif
}
static void
EventProcessTouchEvent(InputInfoPtr pInfo, struct CommData *comm,
struct input_event *ev)
{
#ifdef HAVE_MTDEV
SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
struct eventcomm_proto_data *proto_data = priv->proto_data;
if (ev->code == ABS_MT_SLOT)
{
EventProcessTouch(pInfo);
proto_data->cur_slot = ev->value;
} else
{
int slot_index = last_mt_vals_slot(proto_data);
if (proto_data->slot_state == SLOTSTATE_EMPTY)
proto_data->slot_state = SLOTSTATE_UPDATE;
if (ev->code == ABS_MT_TRACKING_ID)
{
if (ev->value >= 0)
{
proto_data->slot_state = SLOTSTATE_OPEN;
if (slot_index >= 0)
valuator_mask_copy(proto_data->mt_mask,
proto_data->last_mt_vals[slot_index]);
else
xf86IDrvMsg(pInfo, X_WARNING,
"Attempted to copy values from out-of-range "
"slot, touch events may be incorrect.\n");
} else
proto_data->slot_state = SLOTSTATE_CLOSE;
} else
{
int map = proto_data->axis_map[ev->code - ABS_MT_TOUCH_MAJOR];
valuator_mask_set(proto_data->mt_mask, map, ev->value);
if (slot_index >= 0)
valuator_mask_set(proto_data->last_mt_vals[slot_index], map,
ev->value);
}
}
#endif
}
/**
* Count the number of fingers based on the CommData information.
* The CommData struct contains the event information based on previous
@@ -430,6 +630,7 @@ EventReadHwState(InputInfoPtr pInfo,
case EV_SYN:
switch (ev.code) {
case SYN_REPORT:
EventProcessTouch(pInfo);
hw->numFingers = count_fingers(comm);
hw->millis = 1000 * ev.time.tv_sec + ev.time.tv_usec / 1000;
*hwRet = *hw;
@@ -494,20 +695,23 @@ EventReadHwState(InputInfoPtr pInfo,
}
break;
case EV_ABS:
switch (ev.code) {
case ABS_X:
hw->x = ev.value;
break;
case ABS_Y:
hw->y = ev.value;
break;
case ABS_PRESSURE:
hw->z = ev.value;
break;
case ABS_TOOL_WIDTH:
hw->fingerWidth = ev.value;
break;
}
if (ev.code < ABS_MT_SLOT) {
switch (ev.code) {
case ABS_X:
hw->x = ev.value;
break;
case ABS_Y:
hw->y = ev.value;
break;
case ABS_PRESSURE:
hw->z = ev.value;
break;
case ABS_TOOL_WIDTH:
hw->fingerWidth = ev.value;
break;
}
} else
EventProcessTouchEvent(pInfo, comm, &ev);
break;
}
}
@@ -651,6 +855,7 @@ EventReadDevDimensions(InputInfoPtr pInfo)
#ifdef HAVE_MTDEV
for (i = 0; i < MT_ABS_SIZE; i++)
proto_data->axis_map[i] = -1;
proto_data->cur_slot = -1;
#endif
if (event_query_is_touchpad(pInfo->fd, (proto_data) ? proto_data->need_grab : TRUE))
@@ -736,7 +941,7 @@ EventAutoDevProbe(InputInfoPtr pInfo, const char *device)
struct SynapticsProtocolOperations event_proto_operations = {
EventDeviceOnHook,
NULL,
EventDeviceOffHook,
EventQueryHardware,
EventReadHwState,
EventAutoDevProbe,

View File

@@ -450,3 +450,34 @@ Bool QueueWorkProc (
{
return FALSE;
}
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
_X_EXPORT ValuatorMask *valuator_mask_new(int num_valuators)
{
return NULL;
}
_X_EXPORT void valuator_mask_free(ValuatorMask **mask)
{
}
_X_EXPORT void valuator_mask_set(ValuatorMask *mask, int valuator, int data)
{
}
_X_EXPORT void valuator_mask_zero(ValuatorMask *mask)
{
}
_X_EXPORT void valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src)
{
}
#endif
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 16
_X_EXPORT void xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid,
uint16_t type, uint32_t flags,
const ValuatorMask *mask)
{
}
#endif