aboutsummaryrefslogtreecommitdiffstats
path: root/mtdev/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'mtdev/core.c')
-rw-r--r--mtdev/core.c402
1 files changed, 0 insertions, 402 deletions
diff --git a/mtdev/core.c b/mtdev/core.c
deleted file mode 100644
index f13da13..0000000
--- a/mtdev/core.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/***************************************************************************
- *
- * Multitouch X driver
- * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- **************************************************************************/
-
-#include "mtdev.h"
-#include "mtbit.h"
-
-/**
- * struct MTSlot - represents the state of an input MT slot
- * @abs: current values of ABS_MT axes for this slot
- */
-struct MTSlot {
- int abs[MT_ABS_SIZE];
-};
-
-/**
- * struct MTDevState - MT slot parsing
- * @data: array of scratch slot data
- * @used: bitmask of currently used slots
- * @slot: slot currently being modified
- * @lastid: last used tracking id
- */
-struct MTDevState {
- struct MTSlot data[DIM_FINGER];
- bitmask_t used;
- bitmask_t slot;
- bitmask_t lastid;
-};
-
-/**
- * mtdev_init - init MT device
- * @dev: device to initialize
- * @caps: device capabilities
- */
-int mtdev_init(struct MTDev *dev, const struct Capabilities *caps)
-{
- memset(dev, 0, sizeof(struct MTDev));
- if (!caps->has_mtdata)
- return -ENODEV;
- if (!caps->has_slot) {
- dev->priv = calloc(1, sizeof(struct MTDevState));
- if (!dev->priv)
- return -ENOMEM;
- }
- return 0;
-}
-
-static inline int istouch(const struct MTSlot *data,
- const struct Capabilities *caps)
-{
- return data->abs[BIT_TOUCH_MAJOR] || !caps->has_abs[BIT_TOUCH_MAJOR];
-}
-
-/* Dmitry Torokhov's code from kernel/driver/input/input.c */
-static int defuzz(int value, int old_val, int fuzz)
-{
- if (fuzz) {
- if (value > old_val - fuzz / 2 && value < old_val + fuzz / 2)
- return old_val;
-
- if (value > old_val - fuzz && value < old_val + fuzz)
- return (old_val * 3 + value) / 4;
-
- if (value > old_val - fuzz * 2 && value < old_val + fuzz * 2)
- return (old_val + value) / 2;
- }
-
- return value;
-}
-
-/*
- * solve - solve contact matching problem
- * @priv: parsing state
- * @caps: device capabilities
- * @sid: array of current tracking ids
- * @sx: array of current position x
- * @sy: array of current position y
- * @sn: number of current contacts
- * @nid: array of new or matched tracking ids, to be filled
- * @nx: array of new position x
- * @ny: array of new position y
- * @nn: number of new contacts
- * @touch: which of the new contacts to fill
- */
-static void solve(struct MTDevState *priv, const struct Capabilities *caps,
- const int *sid, const int *sx, const int *sy, int sn,
- int *nid, const int *nx, const int *ny, int nn,
- bitmask_t touch)
-{
- int A[DIM2_FINGER], *row;
- int n2s[DIM_FINGER];
- int id, i, j;
-
- /* setup distance matrix for contact matching */
- for (j = 0; j < sn; j++) {
- row = A + nn * j;
- for (i = 0; i < nn; i++)
- row[i] = dist2(nx[i] - sx[j], ny[i] - sy[j]);
- }
-
- match_fingers(n2s, A, nn, sn);
-
- /* update matched contacts and create new ones */
- foreach_bit(i, touch) {
- j = n2s[i];
- id = j >= 0 ? sid[j] : caps->nullid;
- while (id == caps->nullid)
- id = ++priv->lastid;
- nid[i] = id;
- }
-}
-
-/*
- * assign_tracking_id - assign tracking ids to all contacts
- * @priv: parsing state
- * @caps: device capabilities
- * @data: array of all present contacts, to be filled
- * @prop: array of all set contacts properties
- * @size: number of contacts in array
- * @touch: which of the contacts are actual touches
- */
-static void assign_tracking_id(struct MTDevState *priv,
- const struct Capabilities *caps,
- struct MTSlot *data, bitmask_t *prop,
- int size, bitmask_t touch)
-{
- int sid[DIM_FINGER], sx[DIM_FINGER], sy[DIM_FINGER], sn = 0;
- int nid[DIM_FINGER], nx[DIM_FINGER], ny[DIM_FINGER], i;
- foreach_bit(i, priv->used) {
- sid[sn] = priv->data[i].abs[BIT_TRACKING_ID];
- sx[sn] = priv->data[i].abs[BIT_POSITION_X];
- sy[sn] = priv->data[i].abs[BIT_POSITION_Y];
- sn++;
- }
- for (i = 0; i < size; i++) {
- nx[i] = data[i].abs[BIT_POSITION_X];
- ny[i] = data[i].abs[BIT_POSITION_Y];
- }
- solve(priv, caps, sid, sx, sy, sn, nid, nx, ny, size, touch);
- for (i = 0; i < size; i++) {
- data[i].abs[BIT_TRACKING_ID] =
- GETBIT(touch, i) ? nid[i] : caps->nullid;
- prop[i] |= BITMASK(BIT_TRACKING_ID);
- }
-}
-
-/*
- * process_typeA - consume MT events and update parsing state
- * @dev: MT device
- * @data: array of all present contacts, to be filled
- * @prop: array of all set contacts properties, to be filled
- *
- * This function is called when a SYN_REPORT is seen, right before
- * that event is pushed to the queue.
- *
- * Returns -1 if the packet is not MT related and should not affect
- * the current parsing state.
- */
-static int process_typeA(struct MTDev *dev,
- struct MTSlot *data, bitmask_t *prop)
-{
- struct input_event ev;
- int consumed, mtcode;
- int mtcnt = 0, size = 0;
- prop[size] = 0;
- while (!evbuf_empty(&dev->inbuf)) {
- evbuf_get(&dev->inbuf, &ev);
- consumed = 0;
- switch (ev.type) {
- case EV_SYN:
- switch (ev.code) {
- case SYN_MT_REPORT:
- if (size < DIM_FINGER &&
- GETBIT(prop[size], BIT_POSITION_X) &&
- GETBIT(prop[size], BIT_POSITION_Y))
- size++;
- if (size < DIM_FINGER)
- prop[size] = 0;
- mtcnt++;
- consumed = 1;
- break;
- }
- break;
- case EV_KEY:
- switch (ev.code) {
- case BTN_TOUCH:
- mtcnt++;
- break;
- }
- break;
- case EV_ABS:
- if (size < DIM_FINGER && has_abs2mt(ev.code)) {
- mtcode = abs2mt(ev.code);
- data[size].abs[mtcode] = ev.value;
- prop[size] |= BITMASK(mtcode);
- mtcnt++;
- consumed = 1;
- }
- break;
- }
- if (!consumed)
- evbuf_put(&dev->outbuf, &ev);
- }
- return mtcnt ? size : -1;
-}
-
-/*
- * process_typeB - propagate events without parsing
- * @dev: MT device
- *
- * This function is called when a SYN_REPORT is seen, right before
- * that event is pushed to the queue.
- */
-static void process_typeB(struct MTDev *dev)
-{
- struct input_event ev;
- while (!evbuf_empty(&dev->inbuf)) {
- evbuf_get(&dev->inbuf, &ev);
- evbuf_put(&dev->outbuf, &ev);
- }
-}
-
-/*
- * filter_data - apply input filtering on new incoming data
- * @priv: parsing state
- * @caps: device capabilities
- * @data: the incoming data to filter
- * @prop: the properties to filter
- * @slot: the slot the data refers to
- */
-static void filter_data(const struct MTDevState *priv,
- const struct Capabilities *caps,
- struct MTSlot *data, bitmask_t prop,
- int slot)
-{
- int i;
- foreach_bit(i, prop) {
- int fuzz = caps->abs[i].fuzz;
- int oldval = priv->data[slot].abs[i];
- data->abs[i] = defuzz(data->abs[i], oldval, fuzz);
- }
-}
-
-/*
- * push_slot_changes - propagate state changes
- * @dev: MT device
- * @data: the incoming data to propagate
- * @prop: the properties to propagate
- * @slot: the slot the data refers to
- * @syn: reference to the SYN_REPORT event
- */
-static void push_slot_changes(struct MTDev *dev,
- const struct MTSlot *data, bitmask_t prop,
- int slot, const struct input_event *syn)
-{
- struct MTDevState *priv = dev->priv;
- struct input_event ev;
- int i, count = 0;
- foreach_bit(i, prop)
- if (priv->data[slot].abs[i] != data->abs[i])
- count++;
- if (!count)
- return;
- ev.time = syn->time;
- ev.type = EV_ABS;
- ev.code = ABS_MT_SLOT;
- ev.value = slot;
- if (priv->slot != ev.value) {
- evbuf_put(&dev->outbuf, &ev);
- priv->slot = ev.value;
- }
- foreach_bit(i, prop) {
- ev.code = mt2abs(i);
- ev.value = data->abs[i];
- if (priv->data[slot].abs[i] != ev.value) {
- evbuf_put(&dev->outbuf, &ev);
- priv->data[slot].abs[i] = ev.value;
- }
- }
-}
-
-/*
- * apply_typeA_changes - parse and propagate state changes
- * @dev: MT device
- * @caps: device capabilities
- * @data: array of data to apply
- * @prop: array of properties to apply
- * @size: number of contacts in array
- * @syn: reference to the SYN_REPORT event
- */
-static void apply_typeA_changes(struct MTDev *dev,
- const struct Capabilities *caps,
- struct MTSlot *data, const bitmask_t *prop,
- int size, const struct input_event *syn)
-{
- struct MTDevState *priv = dev->priv;
- bitmask_t unused = ~priv->used;
- bitmask_t used = 0;
- int i, slot, id;
- for (i = 0; i < size; i++) {
- id = data[i].abs[BIT_TRACKING_ID];
- foreach_bit(slot, priv->used) {
- if (priv->data[slot].abs[BIT_TRACKING_ID] != id)
- continue;
- filter_data(priv, caps, &data[i], prop[i], slot);
- push_slot_changes(dev, &data[i], prop[i], slot, syn);
- SETBIT(used, slot);
- id = caps->nullid;
- break;
- }
- if (id != caps->nullid) {
- slot = firstbit(unused);
- push_slot_changes(dev, &data[i], prop[i], slot, syn);
- SETBIT(used, slot);
- CLEARBIT(unused, slot);
- }
- }
-
- /* clear unused slots and update slot usage */
- foreach_bit(slot, priv->used & ~used) {
- struct MTSlot tdata = priv->data[slot];
- bitmask_t tprop = BITMASK(BIT_TRACKING_ID);
- tdata.abs[BIT_TRACKING_ID] = caps->nullid;
- push_slot_changes(dev, &tdata, tprop, slot, syn);
- }
- priv->used = used;
-}
-
-/*
- * convert_A_to_B - propagate a type A packet as a type B packet
- * @dev: MT device
- * @caps: device capabilities
- * @syn: reference to the SYN_REPORT event
- */
-static void convert_A_to_B(struct MTDev *dev,
- const struct Capabilities *caps,
- const struct input_event *syn)
-{
- struct MTSlot data[DIM_FINGER];
- bitmask_t prop[DIM_FINGER];
- int size = process_typeA(dev, data, prop);
- if (size < 0)
- return;
- if (!caps->has_abs[BIT_TRACKING_ID]) {
- bitmask_t touch = 0;
- int i;
- for (i = 0; i < size; i++)
- MODBIT(touch, i, istouch(&data[i], caps));
- assign_tracking_id(dev->priv, caps, data, prop, size, touch);
- }
- apply_typeA_changes(dev, caps, data, prop, size, syn);
-}
-
-/**
- * mtdev_put - insert event into MT device
- * @dev: MT device
- * @caps: device capabilities
- * @syn: reference to the SYN_REPORT event
- */
-void mtdev_put(struct MTDev *dev,
- const struct Capabilities *caps,
- const struct input_event *ev)
-{
- if (ev->type == EV_SYN && ev->code == SYN_REPORT) {
- bitmask_t head = dev->outbuf.head;
- if (dev->priv)
- convert_A_to_B(dev, caps, ev);
- else
- process_typeB(dev);
- if (dev->outbuf.head != head)
- evbuf_put(&dev->outbuf, ev);
- } else {
- evbuf_put(&dev->inbuf, ev);
- }
-}
-
-/**
- * mtdev_destroy - destroy MT device
- * @dev: MT device
- */
-void mtdev_destroy(struct MTDev *dev)
-{
- free(dev->priv);
- memset(dev, 0, sizeof(struct MTDev));
-}