From a704984e03d28b4be40e12c43be1b163bc9e09e2 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 19 Aug 2010 20:03:15 +0200 Subject: Simplify touch machinery To be able to model touch information uniformly across all supported devices, the semantics of the touch attributes has to be treated explicitly. Drop the generic touch property array and replace it by an actual structure. In addition, the touch-engine abstraction turned out to not be needed, so drop it as well. Signed-off-by: Henrik Rydberg --- src/Makefile.am | 2 +- src/grail-api.c | 46 ++++++++------- src/grail-gestures.c | 24 ++++---- src/grail-inserter.c | 4 +- src/touch-caps.c | 73 +++++++++++++++++++++++ src/touch-dev.c | 164 ++++++++++++++++++++------------------------------- src/touch-engine.c | 135 ------------------------------------------ 7 files changed, 177 insertions(+), 271 deletions(-) create mode 100644 src/touch-caps.c delete mode 100644 src/touch-engine.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 3171edd..eec0eeb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,7 +9,7 @@ libutouch_grail_la_SOURCES = \ evbuf.h \ gebuf.h \ touch-dev.c \ - touch-engine.c \ + touch-caps.c \ grail-bits.c \ grail-inserter.c \ grail-inserter.h \ diff --git a/src/grail-api.c b/src/grail-api.c index 7c054a9..afd97b9 100644 --- a/src/grail-api.c +++ b/src/grail-api.c @@ -33,16 +33,15 @@ struct grail_impl { struct touch_dev dev; - struct touch_engine engine; struct evbuf evbuf; int filter_abs; int hack_status; }; -static void tp_event(struct touch_engine *engine, +static void tp_event(struct touch_dev *dev, const struct input_event *ev) { - struct grail *ge = engine->priv; + struct grail *ge = dev->priv; struct grail_impl *x = ge->impl; evbuf_put(&x->evbuf, ev); } @@ -62,14 +61,14 @@ static int extra_filtered(const struct input_event *ev) return 0; } -static void tp_sync(struct touch_engine *engine, +static void tp_sync(struct touch_dev *dev, const struct input_event *syn) { struct input_event ev; - struct grail *ge = engine->priv; + struct grail *ge = dev->priv; struct grail_impl *x = ge->impl; struct gesture_recognizer *gru = ge->gru; - struct touch_frame *frame = &engine->frame; + struct touch_frame *frame = &dev->frame; grail_mask_t filtered[DIM_EV_TYPE_BYTES]; int dofilt, hack, nevent = 0; gin_frame_begin(ge, frame); @@ -120,22 +119,27 @@ int grail_open(struct grail *ge, int fd) if (!x) return -ENOMEM; ge->impl = x; - ret = gin_init(ge); + + ret = touch_dev_open(&x->dev, fd); if (ret) goto freemem; - ret = touch_dev_open(&x->dev, fd); + x->dev.event = tp_event; + x->dev.sync = tp_sync; + x->dev.priv = ge; + + ret = gin_init(ge); if (ret) - goto freegin; + goto freedev; + ret = gru_init(ge); if (ret) - goto freedev; - touch_engine_init(&x->engine, tp_event, tp_sync, ge); - touch_engine_attach(&x->engine, &x->dev); + goto freegin; + return 0; - freedev: - touch_dev_close(&x->dev, fd); freegin: gin_destroy(ge); + freedev: + touch_dev_close(&x->dev, fd); freemem: free(x); ge->impl = 0; @@ -146,10 +150,9 @@ void grail_close(struct grail *ge, int fd) { struct grail_impl *x = ge->impl; void *status; - touch_engine_detach(&x->engine, &x->dev); gru_destroy(ge); - touch_dev_close(&x->dev, fd); gin_destroy(ge); + touch_dev_close(&x->dev, fd); free(ge->impl); ge->impl = 0; } @@ -169,9 +172,10 @@ int grail_pull(struct grail *ge, int fd) void grail_get_units(const struct grail *ge, struct grail_coord *min, struct grail_coord *max) { - const struct touch_dev_caps *caps = &ge->impl->dev.caps; - min->x = caps->info[TP_POS_X].minimum; - min->y = caps->info[TP_POS_Y].minimum; - max->x = caps->info[TP_POS_X].maximum; - max->y = caps->info[TP_POS_Y].maximum; + const struct touch_caps *caps = &ge->impl->dev.caps; + min->x = caps->min_x; + min->y = caps->min_y; + max->x = caps->max_x; + max->y = caps->max_y; } + diff --git a/src/grail-gestures.c b/src/grail-gestures.c index 33d848c..95c1b57 100644 --- a/src/grail-gestures.c +++ b/src/grail-gestures.c @@ -39,8 +39,8 @@ static void compute_position(float *x, float *y, return; for (i = 0; i < n; i++) { const struct touch *t = frame->active[i]; - *x += t->prop[TP_POS_X]; - *y += t->prop[TP_POS_Y]; + *x += t->x; + *y += t->y; } *x /= n; *y /= n; @@ -55,8 +55,8 @@ static float compute_radius(float x, float y, return r; for (i = 0; i < n; i++) { const struct touch *t = frame->active[i]; - float dx = t->prop[TP_POS_X] - x; - float dy = t->prop[TP_POS_Y] - y; + float dx = t->x - x; + float dy = t->y - y; r2 += dx * dx + dy * dy; } r2 /= n; @@ -75,10 +75,10 @@ static float compute_rotation(float x, float y, float r, for (i = 0; i < n; i++) { const struct touch *t = frame->active[i]; const struct touch *ot = &prev->touch[t->slot]; - float dx = t->prop[TP_POS_X] - x; - float dy = t->prop[TP_POS_Y] - y; - float mx = t->prop[TP_POS_X] - ot->prop[TP_POS_X]; - float my = t->prop[TP_POS_Y] - ot->prop[TP_POS_Y]; + float dx = t->x - x; + float dy = t->y - y; + float mx = t->x - ot->x; + float my = t->y - ot->y; darc2 += dx * my - dy * mx; } darc2 /= n; @@ -225,13 +225,13 @@ void gru_compute_bbox(struct grail_coord *min, struct grail_coord *max, int i; if (frame->nactive < 1) return; - x = frame->active[0]->prop[TP_POS_X]; - y = frame->active[0]->prop[TP_POS_Y]; + x = frame->active[0]->x; + y = frame->active[0]->y; min->x = max->x = x; min->y = max->y = y; for (i = 1; i < frame->nactive; i++) { - x = frame->active[i]->prop[TP_POS_X]; - y = frame->active[i]->prop[TP_POS_Y]; + x = frame->active[i]->x; + y = frame->active[i]->y; if (x < min->x) min->x = x; if (y < min->y) diff --git a/src/grail-inserter.c b/src/grail-inserter.c index 8b0296e..9769d94 100644 --- a/src/grail-inserter.c +++ b/src/grail-inserter.c @@ -187,8 +187,8 @@ static void setup_new_gestures(struct grail *ge, int ncoord = 0; grail_mask_foreach(i, span, sizeof(span)) { const struct touch *t = &frame->touch[i]; - coord[ncoord].x = t->prop[TP_POS_X]; - coord[ncoord].y = t->prop[TP_POS_Y]; + coord[ncoord].x = t->x; + coord[ncoord].y = t->y; transform_pos(gin, &coord[ncoord]); ncoord++; } diff --git a/src/touch-caps.c b/src/touch-caps.c new file mode 100644 index 0000000..50306e0 --- /dev/null +++ b/src/touch-caps.c @@ -0,0 +1,73 @@ +/***************************************************************************** + * + * grail - Gesture Recognition And Instantiation Library + * + * Copyright (C) 2010 Canonical Ltd. + * Copyright (C) 2010 Henrik Rydberg + * + * 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 . + * + ****************************************************************************/ + +#include +#include + +/* see mtdev-mapping.h */ +#define MTDEV_POSITION_X 5 +#define MTDEV_POSITION_Y 6 +#define MTDEV_ORIENTATION 4 +#define MTDEV_PRESSURE 10 + +void touch_caps_init(struct touch_dev *dev) +{ + const struct mtdev_caps *mt = &dev->mtdev.caps; + struct touch_caps *caps = &dev->caps; + caps->min_x = mt->abs[MTDEV_POSITION_X].minimum; + caps->max_x = mt->abs[MTDEV_POSITION_X].maximum; + caps->min_y = mt->abs[MTDEV_POSITION_Y].minimum; + caps->max_y = mt->abs[MTDEV_POSITION_Y].maximum; + caps->min_orient = mt->abs[MTDEV_ORIENTATION].minimum; + caps->max_orient = mt->abs[MTDEV_ORIENTATION].maximum; + caps->min_press = mt->abs[MTDEV_PRESSURE].minimum; + caps->max_press = mt->abs[MTDEV_PRESSURE].maximum; + if (caps->min_x == caps->max_x) { + caps->min_x = 0; + caps->max_x = 1024; + } + if (caps->min_y == caps->max_y) { + caps->min_y = 0; + caps->max_y = 768; + } + if (caps->min_orient == caps->max_orient) { + caps->min_orient = 0; + caps->max_orient = 1; + } + if (caps->min_press == caps->max_press) { + caps->min_press = 0; + caps->max_press = 256; + } +} + +float touch_angle(const struct touch_dev *dev, int orient) +{ + const struct touch_caps *caps = &dev->caps; + double div = caps->max_orient - caps->min_orient; + return ((orient - caps->min_orient) / div - 0.5) * M_PI; +} + +float touch_pressure(const struct touch_dev *dev, int press) +{ + const struct touch_caps *caps = &dev->caps; + return (press - caps->min_press) / (caps->max_press - caps->min_press); +} diff --git a/src/touch-dev.c b/src/touch-dev.c index b88cb8d..287076a 100644 --- a/src/touch-dev.c +++ b/src/touch-dev.c @@ -25,128 +25,97 @@ #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 - -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; -} +#define SET_PROP(name, value) \ + if (t->name != value) { \ + t->name = value; \ + frame->nmodify++; \ + } -static void finish_touch(struct touch_dev *dev, - struct touch_dev_impl *x) +static void finish_touch(struct touch_dev *dev, struct touch_frame *frame) { - 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)); + struct touch *t = &frame->touch[dev->slot]; + if (dev->state > 0) { + t->active = 1; + grail_mask_set(frame->touches, dev->slot); + frame->ncreate++; + } + if (dev->state < 0) { + t->active = 0; + grail_mask_clear(frame->touches, dev->slot); + frame->ndestroy++; + } + dev->state = 0; } static void finish_packet(struct touch_dev *dev, const struct input_event *syn) { - finish_touch(dev, dev->impl); + static const touch_time_t ms = 1000; + struct touch_frame *frame = &dev->frame; + int i, nslot = 0; + finish_touch(dev, frame); + grail_mask_foreach(i, frame->touches, DIM_TOUCH_BYTES) + frame->active[nslot++] = &frame->touch[i]; + frame->nactive = nslot; + frame->time = syn->time.tv_usec / ms + syn->time.tv_sec * ms; if (dev->sync) dev->sync(dev, syn); + frame->ncreate = 0; + frame->nmodify = 0; + frame->ndestroy = 0; } static int handle_abs_event(struct touch_dev *dev, const struct input_event *ev) { - struct touch_dev_impl *x = dev->impl; + struct touch_frame *frame = &dev->frame; + struct touch *t = &frame->touch[dev->slot]; 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; + if (dev->slot != ev->value) + finish_touch(dev, frame); + dev->slot = ev->value; + t = &frame->touch[dev->slot]; } return 1; case ABS_MT_POSITION_X: - set_prop(x, TP_POS_X, ev->value); + SET_PROP(x, ev->value); return 1; case ABS_MT_POSITION_Y: - set_prop(x, TP_POS_Y, ev->value); + SET_PROP(y, ev->value); return 1; case ABS_MT_TOUCH_MAJOR: - set_prop(x, TP_TOUCH_MAJOR, ev->value); + SET_PROP(touch_major, ev->value); return 1; case ABS_MT_TOUCH_MINOR: - set_prop(x, TP_TOUCH_MINOR, ev->value); + SET_PROP(touch_minor, ev->value); return 1; case ABS_MT_WIDTH_MAJOR: - set_prop(x, TP_WIDTH_MAJOR, ev->value); + SET_PROP(width_major, ev->value); return 1; case ABS_MT_WIDTH_MINOR: - set_prop(x, TP_WIDTH_MINOR, ev->value); + SET_PROP(width_minor, ev->value); return 1; case ABS_MT_ORIENTATION: - set_prop(x, TP_ORIENTATION, ev->value); + SET_PROP(orientation, ev->value); return 1; case ABS_MT_PRESSURE: - set_prop(x, TP_PRESSURE, ev->value); + SET_PROP(pressure, ev->value); + return 1; + case ABS_MT_TOOL_TYPE: + SET_PROP(tool_type, 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 (t->id != ev->value) { + if (t->id != MT_ID_NULL) { + dev->state = -1; + finish_touch(dev, frame); } if (ev->value != MT_ID_NULL) - x->status = 1; + dev->state = 1; + t->id = ev->value; } - x->id[x->slot] = ev->value; return 1; default: return 0; @@ -155,38 +124,35 @@ static int handle_abs_event(struct touch_dev *dev, int touch_dev_open(struct touch_dev *dev, int fd) { - struct touch_dev_impl *x; + struct touch_frame *frame = &dev->frame; 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) + for (i = 0; i < DIM_TOUCH; i++) { + struct touch *t = &frame->touch[i]; + t->slot = i; + t->id = MT_ID_NULL; + } + ret = mtdev_open(&dev->mtdev, fd); + if (!ret && !dev->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; + touch_caps_init(dev); 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); + return mtdev_idle(&dev->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) { + while ((ret = mtdev_get(&dev->mtdev, fd, &ev, 1)) > 0) { consumed = 0; if (ev.type == EV_SYN) { if (ev.code == SYN_REPORT) @@ -204,8 +170,6 @@ int touch_dev_pull(struct touch_dev *dev, int fd) void touch_dev_close(struct touch_dev *dev, int fd) { - struct touch_dev_impl *x = dev->impl; - mtdev_close(&x->mtdev); - free(x); + mtdev_close(&dev->mtdev); memset(dev, 0, sizeof(*dev)); } diff --git a/src/touch-engine.c b/src/touch-engine.c deleted file mode 100644 index d13785d..0000000 --- a/src/touch-engine.c +++ /dev/null @@ -1,135 +0,0 @@ -/***************************************************************************** - * - * grail - Gesture Recognition And Instantiation Library - * - * Copyright (C) 2010 Canonical Ltd. - * Copyright (C) 2010 Henrik Rydberg - * - * 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 . - * - ****************************************************************************/ - -#include -#include - -static void tp_event(struct touch_dev *dev, const struct input_event *ev) -{ - struct touch_engine *engine = dev->priv; - if (engine && engine->event) - engine->event(engine, ev); -} - -static void update_frame(struct touch_frame *frame, - int slot, int active, - const grail_mask_t *mask, - const touch_prop_t *prop) -{ - struct touch *t = &frame->touch[slot]; - int i; - t->active = active; - grail_mask_modify(frame->touches, slot, active); - if (mask && prop) - grail_mask_foreach(i, mask, DIM_TOUCH_PROP_BYTES) - t->prop[i] = prop[i]; -} - -static void finalize_frame(struct touch_frame *frame, touch_time_t time) -{ - int i, nslot = 0; - grail_mask_foreach(i, frame->touches, DIM_TOUCH_BYTES) - frame->active[nslot++] = &frame->touch[i]; - frame->nactive = nslot; - frame->time = time; -} - -static void tp_create(struct touch_dev *dev, int slot, - const grail_mask_t *mask, const touch_prop_t *prop) -{ - struct touch_engine *engine = dev->priv; - if (engine) { - engine->frame.ncreate++; - update_frame(&engine->frame, slot, 1, mask, prop); - } -} - -static void tp_modify(struct touch_dev *dev, int slot, - const grail_mask_t *mask, const touch_prop_t *prop) -{ - struct touch_engine *engine = dev->priv; - if (engine) { - engine->frame.nmodify++; - update_frame(&engine->frame, slot, 1, mask, prop); - } -} - -static void tp_destroy(struct touch_dev *dev, int slot) -{ - struct touch_engine *engine = dev->priv; - if (engine) { - engine->frame.ndestroy++; - update_frame(&engine->frame, slot, 0, 0, 0); - } -} - -static void tp_sync(struct touch_dev *dev, const struct input_event *syn) -{ - static const touch_time_t ms = 1000; - struct touch_engine *engine = dev->priv; - touch_time_t time = syn->time.tv_usec / ms + syn->time.tv_sec * ms; - if (engine) { - finalize_frame(&engine->frame, time); - if (engine->sync) - engine->sync(engine, syn); - engine->frame.ncreate = 0; - engine->frame.nmodify = 0; - engine->frame.ndestroy = 0; - } -} - -void touch_engine_init(struct touch_engine *engine, - void (*event)(struct touch_engine *engine, - const struct input_event *ev), - void (*sync)(struct touch_engine *engine, - const struct input_event *ev), - void *priv) -{ - int i; - memset(engine, 0, sizeof(*engine)); - for (i = 0; i < DIM_TOUCH; i++) - engine->frame.touch[i].slot = i; - engine->event = event; - engine->sync = sync; - engine->priv = priv; -} - -void touch_engine_attach(struct touch_engine *engine, struct touch_dev *dev) -{ - dev->priv = engine; - dev->event = tp_event; - dev->create = tp_create; - dev->modify = tp_modify; - dev->destroy = tp_destroy; - dev->sync = tp_sync; -} - -void touch_engine_detach(struct touch_engine *engine, struct touch_dev *dev) -{ - dev->sync = 0; - dev->destroy = 0; - dev->modify = 0; - dev->create = 0; - dev->event = 0; - dev->priv = 0; -} - -- cgit v1.2.3