From 7db9d8d76ff61c4802ac15559dcea6fa54ff567a Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Fri, 6 Aug 2010 21:11:17 +0200 Subject: initial bzr repo at rev 27 --- src/touch-dev.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 src/touch-dev.c (limited to 'src/touch-dev.c') diff --git a/src/touch-dev.c b/src/touch-dev.c new file mode 100644 index 0000000..4cc8d55 --- /dev/null +++ b/src/touch-dev.c @@ -0,0 +1,218 @@ +/***************************************************************************** + * + * grail - Gesture Recognition And Instantiation Library + * + * Copyright (C) 2010 Canonical Ltd. + * + * 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 3 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, see . + * + * Authors: + * Henrik Rydberg + * + ****************************************************************************/ + +#include +#include +#include +#include + +/* from mtdev-mapping.h */ +#define MT_TOUCH_MAJOR 0 +#define MT_TOUCH_MINOR 1 +#define MT_WIDTH_MAJOR 2 +#define MT_WIDTH_MINOR 3 +#define MT_ORIENTATION 4 +#define MT_POSITION_X 5 +#define MT_POSITION_Y 6 +#define MT_TRACKING_ID 9 +#define MT_PRESSURE 10 + +int mtdev_fetch_event(struct mtdev *dev, int fd, struct input_event *ev); +void mtdev_put_event(struct mtdev *dev, const struct input_event *ev); +int mtdev_empty(struct mtdev *dev); +void mtdev_get_event(struct mtdev *dev, struct input_event* ev); + +struct touch_dev_impl { + int id[DIM_TOUCH]; + int slot; + int status; + grail_mask_t mask[DIM_TOUCH_BYTES]; + touch_prop_t prop[DIM_TOUCH_PROP]; + struct mtdev mtdev; +}; + +static inline void set_info(struct touch_dev_caps *caps, int code, + const struct input_absinfo *info) +{ + grail_mask_set(caps->mask, code); + caps->info[code] = *info; +} + +static void set_caps(struct touch_dev_caps *caps, + const struct mtdev_caps *mtcaps) +{ + if (mtcaps->has_abs[MT_POSITION_X]) + set_info(caps, TP_POS_X, &mtcaps->abs[MT_POSITION_X]); + if (mtcaps->has_abs[MT_POSITION_Y]) + set_info(caps, TP_POS_Y, &mtcaps->abs[MT_POSITION_Y]); + if (mtcaps->has_abs[MT_TOUCH_MAJOR]) + set_info(caps, TP_TOUCH_MAJOR, &mtcaps->abs[MT_TOUCH_MAJOR]); + if (mtcaps->has_abs[MT_TOUCH_MINOR]) + set_info(caps, TP_TOUCH_MINOR, &mtcaps->abs[MT_TOUCH_MINOR]); + if (mtcaps->has_abs[MT_WIDTH_MAJOR]) + set_info(caps, TP_WIDTH_MAJOR, &mtcaps->abs[MT_WIDTH_MAJOR]); + if (mtcaps->has_abs[MT_WIDTH_MINOR]) + set_info(caps, TP_WIDTH_MINOR, &mtcaps->abs[MT_WIDTH_MINOR]); + if (mtcaps->has_abs[MT_ORIENTATION]) + set_info(caps, TP_ORIENTATION, &mtcaps->abs[MT_ORIENTATION]); + if (mtcaps->has_abs[MT_PRESSURE]) + set_info(caps, TP_PRESSURE, &mtcaps->abs[MT_PRESSURE]); +} + +static inline void set_prop(struct touch_dev_impl *x, int code, int value) +{ + grail_mask_set(x->mask, code); + x->prop[code] = value; +} + +static void finish_touch(struct touch_dev *dev, + struct touch_dev_impl *x) +{ + if (x->status < 0 && dev->destroy) + dev->destroy(dev, x->slot); + if (x->status > 0 && dev->create) + dev->create(dev, x->slot, x->mask, x->prop); + if (x->status == 0 && dev->modify && + grail_mask_count(x->mask, sizeof(x->mask))) + dev->modify(dev, x->slot, x->mask, x->prop); + x->status = 0; + memset(x->mask, 0, sizeof(x->mask)); +} + +static void finish_packet(struct touch_dev *dev, + const struct input_event *syn) +{ + finish_touch(dev, dev->impl); + if (dev->sync) + dev->sync(dev, syn); +} + +static int handle_abs_event(struct touch_dev *dev, + const struct input_event *ev) +{ + struct touch_dev_impl *x = dev->impl; + switch (ev->code) { + case ABS_MT_SLOT: + if (ev->value >= 0 && ev->value < DIM_TOUCH) { + if (x->slot != ev->value) + finish_touch(dev, x); + x->slot = ev->value; + } + return 1; + case ABS_MT_POSITION_X: + set_prop(x, TP_POS_X, ev->value); + return 1; + case ABS_MT_POSITION_Y: + set_prop(x, TP_POS_Y, ev->value); + return 1; + case ABS_MT_TOUCH_MAJOR: + set_prop(x, TP_TOUCH_MAJOR, ev->value); + return 1; + case ABS_MT_TOUCH_MINOR: + set_prop(x, TP_TOUCH_MINOR, ev->value); + return 1; + case ABS_MT_WIDTH_MAJOR: + set_prop(x, TP_WIDTH_MAJOR, ev->value); + return 1; + case ABS_MT_WIDTH_MINOR: + set_prop(x, TP_WIDTH_MINOR, ev->value); + return 1; + case ABS_MT_ORIENTATION: + set_prop(x, TP_ORIENTATION, ev->value); + return 1; + case ABS_MT_PRESSURE: + set_prop(x, TP_PRESSURE, ev->value); + return 1; + case ABS_MT_TRACKING_ID: + if (x->id[x->slot] != ev->value) { + if (x->id[x->slot] != MT_ID_NULL) { + x->status = -1; + finish_touch(dev, x); + } + if (ev->value != MT_ID_NULL) + x->status = 1; + } + x->id[x->slot] = ev->value; + return 1; + default: + return 0; + } +} + +int touch_dev_open(struct touch_dev *dev, int fd) +{ + struct touch_dev_impl *x; + int ret, i; + memset(dev, 0, sizeof(*dev)); + x = calloc(1, sizeof(*x)); + if (!x) + return -ENOMEM; + ret = mtdev_open(&x->mtdev, fd); + if (!ret && !x->mtdev.caps.has_mtdata) + ret = -ENODEV; + if (ret) + goto error; + for (i = 0; i < DIM_TOUCH; i++) + x->id[i] = MT_ID_NULL; + set_caps(&dev->caps, &x->mtdev.caps); + dev->impl = x; + return 0; + error: + free(x); + return ret; +} + +int touch_dev_idle(struct touch_dev *dev, int fd, int ms) +{ + return mtdev_idle(&dev->impl->mtdev, fd, ms); +} + +int touch_dev_pull(struct touch_dev *dev, int fd) +{ + struct touch_dev_impl *x = dev->impl; + struct input_event ev; + int ret, count = 0, consumed; + while ((ret = mtdev_get(&x->mtdev, fd, &ev, 1)) > 0) { + consumed = 0; + if (ev.type == EV_SYN) { + if (ev.code == SYN_REPORT) + finish_packet(dev, &ev); + consumed++; + } else if (ev.type == EV_ABS) { + consumed += handle_abs_event(dev, &ev); + } + if (!consumed && dev->event) + dev->event(dev, &ev); + count++; + } + return count > 0 ? count : ret; +} + +void touch_dev_close(struct touch_dev *dev, int fd) +{ + struct touch_dev_impl *x = dev->impl; + mtdev_close(&x->mtdev); + free(x); + memset(dev, 0, sizeof(*dev)); +} -- cgit v1.2.3