summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-08-19 20:03:15 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-08-19 20:03:15 +0200
commita704984e03d28b4be40e12c43be1b163bc9e09e2 (patch)
treec4720a59aa77918ffef742d7ec7ef2a7e2eda16e
parentcb2cad3b8c506a08a6bdad548a10ff47f85ef38b (diff)
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 <rydberg@euromail.se>
-rw-r--r--include/grail-touch.h65
-rw-r--r--src/Makefile.am2
-rw-r--r--src/grail-api.c46
-rw-r--r--src/grail-gestures.c24
-rw-r--r--src/grail-inserter.c4
-rw-r--r--src/touch-caps.c73
-rw-r--r--src/touch-dev.c164
-rw-r--r--src/touch-engine.c135
-rw-r--r--test/grail-touch.c29
9 files changed, 218 insertions, 324 deletions
diff --git a/include/grail-touch.h b/include/grail-touch.h
index 9d96cc3..acfc779 100644
--- a/include/grail-touch.h
+++ b/include/grail-touch.h
@@ -29,27 +29,20 @@
29#define DIM_TOUCH 32 29#define DIM_TOUCH 32
30#define DIM_TOUCH_BYTES ((DIM_TOUCH + 7) >> 3) 30#define DIM_TOUCH_BYTES ((DIM_TOUCH + 7) >> 3)
31 31
32typedef int touch_prop_t;
33typedef __u64 touch_time_t; 32typedef __u64 touch_time_t;
34 33
35enum touch_prop_list {
36 TP_POS_X,
37 TP_POS_Y,
38 TP_TOUCH_MAJOR,
39 TP_TOUCH_MINOR,
40 TP_WIDTH_MAJOR,
41 TP_WIDTH_MINOR,
42 TP_ORIENTATION,
43 TP_PRESSURE,
44 DIM_TOUCH_PROP
45};
46
47#define DIM_TOUCH_PROP_BYTES ((DIM_TOUCH_PROP + 7) >> 3)
48
49struct touch { 34struct touch {
50 int active; 35 int active;
51 int slot; 36 int slot;
52 touch_prop_t prop[DIM_TOUCH_PROP]; 37 int id;
38 int tool_type;
39 int x, y;
40 int touch_major;
41 int touch_minor;
42 int width_major;
43 int width_minor;
44 int orientation;
45 int pressure;
53}; 46};
54 47
55struct touch_frame { 48struct touch_frame {
@@ -61,45 +54,31 @@ struct touch_frame {
61 struct touch touch[DIM_TOUCH]; 54 struct touch touch[DIM_TOUCH];
62}; 55};
63 56
64struct touch_dev_caps { 57struct touch_caps {
65 grail_mask_t mask[DIM_TOUCH_PROP_BYTES]; 58 float min_x, max_x;
66 struct input_absinfo info[DIM_TOUCH_PROP]; 59 float min_y, max_y;
60 float min_orient, max_orient;
61 float min_press, max_press;
67}; 62};
68 63
69struct touch_dev { 64struct touch_dev {
70 void (*event)(struct touch_dev *dev, const struct input_event *ev); 65 void (*event)(struct touch_dev *dev, const struct input_event *ev);
71 void (*create)(struct touch_dev *dev, int slot,
72 const grail_mask_t *mask, const touch_prop_t *prop);
73 void (*modify)(struct touch_dev *dev, int slot,
74 const grail_mask_t *mask, const touch_prop_t *prop);
75 void (*destroy)(struct touch_dev *dev, int slot);
76 void (*sync)(struct touch_dev *dev, const struct input_event *syn); 66 void (*sync)(struct touch_dev *dev, const struct input_event *syn);
77 struct touch_dev_caps caps;
78 struct touch_dev_impl *impl;
79 void *priv; 67 void *priv;
80}; 68 struct mtdev mtdev;
81
82struct touch_engine {
83 void (*event)(struct touch_engine *engine,
84 const struct input_event *ev);
85 void (*sync)(struct touch_engine *engine,
86 const struct input_event *syn);
87 struct touch_frame frame; 69 struct touch_frame frame;
88 void *priv; 70 struct touch_caps caps;
71 int slot;
72 int state;
89}; 73};
90 74
75void touch_caps_init(struct touch_dev *dev);
76float touch_angle(const struct touch_dev *dev, int orientation);
77float touch_pressure(const struct touch_dev *dev, int pressure);
78
91int touch_dev_open(struct touch_dev *dev, int fd); 79int touch_dev_open(struct touch_dev *dev, int fd);
92int touch_dev_idle(struct touch_dev *dev, int fd, int ms); 80int touch_dev_idle(struct touch_dev *dev, int fd, int ms);
93int touch_dev_pull(struct touch_dev *dev, int fd); 81int touch_dev_pull(struct touch_dev *dev, int fd);
94void touch_dev_close(struct touch_dev *dev, int fd); 82void touch_dev_close(struct touch_dev *dev, int fd);
95 83
96void touch_engine_init(struct touch_engine *engine,
97 void (*event)(struct touch_engine *engine,
98 const struct input_event *ev),
99 void (*sync)(struct touch_engine *engine,
100 const struct input_event *ev),
101 void *priv);
102void touch_engine_attach(struct touch_engine *engine, struct touch_dev *dev);
103void touch_engine_detach(struct touch_engine *engine, struct touch_dev *dev);
104
105#endif 84#endif
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 = \
9 evbuf.h \ 9 evbuf.h \
10 gebuf.h \ 10 gebuf.h \
11 touch-dev.c \ 11 touch-dev.c \
12 touch-engine.c \ 12 touch-caps.c \
13 grail-bits.c \ 13 grail-bits.c \
14 grail-inserter.c \ 14 grail-inserter.c \
15 grail-inserter.h \ 15 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 @@
33 33
34struct grail_impl { 34struct grail_impl {
35 struct touch_dev dev; 35 struct touch_dev dev;
36 struct touch_engine engine;
37 struct evbuf evbuf; 36 struct evbuf evbuf;
38 int filter_abs; 37 int filter_abs;
39 int hack_status; 38 int hack_status;
40}; 39};
41 40
42static void tp_event(struct touch_engine *engine, 41static void tp_event(struct touch_dev *dev,
43 const struct input_event *ev) 42 const struct input_event *ev)
44{ 43{
45 struct grail *ge = engine->priv; 44 struct grail *ge = dev->priv;
46 struct grail_impl *x = ge->impl; 45 struct grail_impl *x = ge->impl;
47 evbuf_put(&x->evbuf, ev); 46 evbuf_put(&x->evbuf, ev);
48} 47}
@@ -62,14 +61,14 @@ static int extra_filtered(const struct input_event *ev)
62 return 0; 61 return 0;
63} 62}
64 63
65static void tp_sync(struct touch_engine *engine, 64static void tp_sync(struct touch_dev *dev,
66 const struct input_event *syn) 65 const struct input_event *syn)
67{ 66{
68 struct input_event ev; 67 struct input_event ev;
69 struct grail *ge = engine->priv; 68 struct grail *ge = dev->priv;
70 struct grail_impl *x = ge->impl; 69 struct grail_impl *x = ge->impl;
71 struct gesture_recognizer *gru = ge->gru; 70 struct gesture_recognizer *gru = ge->gru;
72 struct touch_frame *frame = &engine->frame; 71 struct touch_frame *frame = &dev->frame;
73 grail_mask_t filtered[DIM_EV_TYPE_BYTES]; 72 grail_mask_t filtered[DIM_EV_TYPE_BYTES];
74 int dofilt, hack, nevent = 0; 73 int dofilt, hack, nevent = 0;
75 gin_frame_begin(ge, frame); 74 gin_frame_begin(ge, frame);
@@ -120,22 +119,27 @@ int grail_open(struct grail *ge, int fd)
120 if (!x) 119 if (!x)
121 return -ENOMEM; 120 return -ENOMEM;
122 ge->impl = x; 121 ge->impl = x;
123 ret = gin_init(ge); 122
123 ret = touch_dev_open(&x->dev, fd);
124 if (ret) 124 if (ret)
125 goto freemem; 125 goto freemem;
126 ret = touch_dev_open(&x->dev, fd); 126 x->dev.event = tp_event;
127 x->dev.sync = tp_sync;
128 x->dev.priv = ge;
129
130 ret = gin_init(ge);
127 if (ret) 131 if (ret)
128 goto freegin; 132 goto freedev;
133
129 ret = gru_init(ge); 134 ret = gru_init(ge);
130 if (ret) 135 if (ret)
131 goto freedev; 136 goto freegin;
132 touch_engine_init(&x->engine, tp_event, tp_sync, ge); 137
133 touch_engine_attach(&x->engine, &x->dev);
134 return 0; 138 return 0;
135 freedev:
136 touch_dev_close(&x->dev, fd);
137 freegin: 139 freegin:
138 gin_destroy(ge); 140 gin_destroy(ge);
141 freedev:
142 touch_dev_close(&x->dev, fd);
139 freemem: 143 freemem:
140 free(x); 144 free(x);
141 ge->impl = 0; 145 ge->impl = 0;
@@ -146,10 +150,9 @@ void grail_close(struct grail *ge, int fd)
146{ 150{
147 struct grail_impl *x = ge->impl; 151 struct grail_impl *x = ge->impl;
148 void *status; 152 void *status;
149 touch_engine_detach(&x->engine, &x->dev);
150 gru_destroy(ge); 153 gru_destroy(ge);
151 touch_dev_close(&x->dev, fd);
152 gin_destroy(ge); 154 gin_destroy(ge);
155 touch_dev_close(&x->dev, fd);
153 free(ge->impl); 156 free(ge->impl);
154 ge->impl = 0; 157 ge->impl = 0;
155} 158}
@@ -169,9 +172,10 @@ int grail_pull(struct grail *ge, int fd)
169void grail_get_units(const struct grail *ge, 172void grail_get_units(const struct grail *ge,
170 struct grail_coord *min, struct grail_coord *max) 173 struct grail_coord *min, struct grail_coord *max)
171{ 174{
172 const struct touch_dev_caps *caps = &ge->impl->dev.caps; 175 const struct touch_caps *caps = &ge->impl->dev.caps;
173 min->x = caps->info[TP_POS_X].minimum; 176 min->x = caps->min_x;
174 min->y = caps->info[TP_POS_Y].minimum; 177 min->y = caps->min_y;
175 max->x = caps->info[TP_POS_X].maximum; 178 max->x = caps->max_x;
176 max->y = caps->info[TP_POS_Y].maximum; 179 max->y = caps->max_y;
177} 180}
181
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,
39 return; 39 return;
40 for (i = 0; i < n; i++) { 40 for (i = 0; i < n; i++) {
41 const struct touch *t = frame->active[i]; 41 const struct touch *t = frame->active[i];
42 *x += t->prop[TP_POS_X]; 42 *x += t->x;
43 *y += t->prop[TP_POS_Y]; 43 *y += t->y;
44 } 44 }
45 *x /= n; 45 *x /= n;
46 *y /= n; 46 *y /= n;
@@ -55,8 +55,8 @@ static float compute_radius(float x, float y,
55 return r; 55 return r;
56 for (i = 0; i < n; i++) { 56 for (i = 0; i < n; i++) {
57 const struct touch *t = frame->active[i]; 57 const struct touch *t = frame->active[i];
58 float dx = t->prop[TP_POS_X] - x; 58 float dx = t->x - x;
59 float dy = t->prop[TP_POS_Y] - y; 59 float dy = t->y - y;
60 r2 += dx * dx + dy * dy; 60 r2 += dx * dx + dy * dy;
61 } 61 }
62 r2 /= n; 62 r2 /= n;
@@ -75,10 +75,10 @@ static float compute_rotation(float x, float y, float r,
75 for (i = 0; i < n; i++) { 75 for (i = 0; i < n; i++) {
76 const struct touch *t = frame->active[i]; 76 const struct touch *t = frame->active[i];
77 const struct touch *ot = &prev->touch[t->slot]; 77 const struct touch *ot = &prev->touch[t->slot];
78 float dx = t->prop[TP_POS_X] - x; 78 float dx = t->x - x;
79 float dy = t->prop[TP_POS_Y] - y; 79 float dy = t->y - y;
80 float mx = t->prop[TP_POS_X] - ot->prop[TP_POS_X]; 80 float mx = t->x - ot->x;
81 float my = t->prop[TP_POS_Y] - ot->prop[TP_POS_Y]; 81 float my = t->y - ot->y;
82 darc2 += dx * my - dy * mx; 82 darc2 += dx * my - dy * mx;
83 } 83 }
84 darc2 /= n; 84 darc2 /= n;
@@ -225,13 +225,13 @@ void gru_compute_bbox(struct grail_coord *min, struct grail_coord *max,
225 int i; 225 int i;
226 if (frame->nactive < 1) 226 if (frame->nactive < 1)
227 return; 227 return;
228 x = frame->active[0]->prop[TP_POS_X]; 228 x = frame->active[0]->x;
229 y = frame->active[0]->prop[TP_POS_Y]; 229 y = frame->active[0]->y;
230 min->x = max->x = x; 230 min->x = max->x = x;
231 min->y = max->y = y; 231 min->y = max->y = y;
232 for (i = 1; i < frame->nactive; i++) { 232 for (i = 1; i < frame->nactive; i++) {
233 x = frame->active[i]->prop[TP_POS_X]; 233 x = frame->active[i]->x;
234 y = frame->active[i]->prop[TP_POS_Y]; 234 y = frame->active[i]->y;
235 if (x < min->x) 235 if (x < min->x)
236 min->x = x; 236 min->x = x;
237 if (y < min->y) 237 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,
187 int ncoord = 0; 187 int ncoord = 0;
188 grail_mask_foreach(i, span, sizeof(span)) { 188 grail_mask_foreach(i, span, sizeof(span)) {
189 const struct touch *t = &frame->touch[i]; 189 const struct touch *t = &frame->touch[i];
190 coord[ncoord].x = t->prop[TP_POS_X]; 190 coord[ncoord].x = t->x;
191 coord[ncoord].y = t->prop[TP_POS_Y]; 191 coord[ncoord].y = t->y;
192 transform_pos(gin, &coord[ncoord]); 192 transform_pos(gin, &coord[ncoord]);
193 ncoord++; 193 ncoord++;
194 } 194 }
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 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 * Copyright (C) 2010 Henrik Rydberg <rydberg@bitmath.org>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23#include <grail-touch.h>
24#include <math.h>
25
26/* see mtdev-mapping.h */
27#define MTDEV_POSITION_X 5
28#define MTDEV_POSITION_Y 6
29#define MTDEV_ORIENTATION 4
30#define MTDEV_PRESSURE 10
31
32void touch_caps_init(struct touch_dev *dev)
33{
34 const struct mtdev_caps *mt = &dev->mtdev.caps;
35 struct touch_caps *caps = &dev->caps;
36 caps->min_x = mt->abs[MTDEV_POSITION_X].minimum;
37 caps->max_x = mt->abs[MTDEV_POSITION_X].maximum;
38 caps->min_y = mt->abs[MTDEV_POSITION_Y].minimum;
39 caps->max_y = mt->abs[MTDEV_POSITION_Y].maximum;
40 caps->min_orient = mt->abs[MTDEV_ORIENTATION].minimum;
41 caps->max_orient = mt->abs[MTDEV_ORIENTATION].maximum;
42 caps->min_press = mt->abs[MTDEV_PRESSURE].minimum;
43 caps->max_press = mt->abs[MTDEV_PRESSURE].maximum;
44 if (caps->min_x == caps->max_x) {
45 caps->min_x = 0;
46 caps->max_x = 1024;
47 }
48 if (caps->min_y == caps->max_y) {
49 caps->min_y = 0;
50 caps->max_y = 768;
51 }
52 if (caps->min_orient == caps->max_orient) {
53 caps->min_orient = 0;
54 caps->max_orient = 1;
55 }
56 if (caps->min_press == caps->max_press) {
57 caps->min_press = 0;
58 caps->max_press = 256;
59 }
60}
61
62float touch_angle(const struct touch_dev *dev, int orient)
63{
64 const struct touch_caps *caps = &dev->caps;
65 double div = caps->max_orient - caps->min_orient;
66 return ((orient - caps->min_orient) / div - 0.5) * M_PI;
67}
68
69float touch_pressure(const struct touch_dev *dev, int press)
70{
71 const struct touch_caps *caps = &dev->caps;
72 return (press - caps->min_press) / (caps->max_press - caps->min_press);
73}
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 @@
25#include <string.h> 25#include <string.h>
26#include <errno.h> 26#include <errno.h>
27 27
28/* from mtdev-mapping.h */ 28#define SET_PROP(name, value) \
29#define MT_TOUCH_MAJOR 0 29 if (t->name != value) { \
30#define MT_TOUCH_MINOR 1 30 t->name = value; \
31#define MT_WIDTH_MAJOR 2 31 frame->nmodify++; \
32#define MT_WIDTH_MINOR 3 32 }
33#define MT_ORIENTATION 4
34#define MT_POSITION_X 5
35#define MT_POSITION_Y 6
36#define MT_TRACKING_ID 9
37#define MT_PRESSURE 10
38
39struct touch_dev_impl {
40 int id[DIM_TOUCH];
41 int slot;
42 int status;
43 grail_mask_t mask[DIM_TOUCH_BYTES];
44 touch_prop_t prop[DIM_TOUCH_PROP];
45 struct mtdev mtdev;
46};
47
48static inline void set_info(struct touch_dev_caps *caps, int code,
49 const struct input_absinfo *info)
50{
51 grail_mask_set(caps->mask, code);
52 caps->info[code] = *info;
53}
54
55static void set_caps(struct touch_dev_caps *caps,
56 const struct mtdev_caps *mtcaps)
57{
58 if (mtcaps->has_abs[MT_POSITION_X])
59 set_info(caps, TP_POS_X, &mtcaps->abs[MT_POSITION_X]);
60 if (mtcaps->has_abs[MT_POSITION_Y])
61 set_info(caps, TP_POS_Y, &mtcaps->abs[MT_POSITION_Y]);
62 if (mtcaps->has_abs[MT_TOUCH_MAJOR])
63 set_info(caps, TP_TOUCH_MAJOR, &mtcaps->abs[MT_TOUCH_MAJOR]);
64 if (mtcaps->has_abs[MT_TOUCH_MINOR])
65 set_info(caps, TP_TOUCH_MINOR, &mtcaps->abs[MT_TOUCH_MINOR]);
66 if (mtcaps->has_abs[MT_WIDTH_MAJOR])
67 set_info(caps, TP_WIDTH_MAJOR, &mtcaps->abs[MT_WIDTH_MAJOR]);
68 if (mtcaps->has_abs[MT_WIDTH_MINOR])
69 set_info(caps, TP_WIDTH_MINOR, &mtcaps->abs[MT_WIDTH_MINOR]);
70 if (mtcaps->has_abs[MT_ORIENTATION])
71 set_info(caps, TP_ORIENTATION, &mtcaps->abs[MT_ORIENTATION]);
72 if (mtcaps->has_abs[MT_PRESSURE])
73 set_info(caps, TP_PRESSURE, &mtcaps->abs[MT_PRESSURE]);
74}
75
76static inline void set_prop(struct touch_dev_impl *x, int code, int value)
77{
78 grail_mask_set(x->mask, code);
79 x->prop[code] = value;
80}
81 33
82static void finish_touch(struct touch_dev *dev, 34static void finish_touch(struct touch_dev *dev, struct touch_frame *frame)
83 struct touch_dev_impl *x)
84{ 35{
85 if (x->status < 0 && dev->destroy) 36 struct touch *t = &frame->touch[dev->slot];
86 dev->destroy(dev, x->slot); 37 if (dev->state > 0) {
87 if (x->status > 0 && dev->create) 38 t->active = 1;
88 dev->create(dev, x->slot, x->mask, x->prop); 39 grail_mask_set(frame->touches, dev->slot);
89 if (x->status == 0 && dev->modify && 40 frame->ncreate++;
90 grail_mask_count(x->mask, sizeof(x->mask))) 41 }
91 dev->modify(dev, x->slot, x->mask, x->prop); 42 if (dev->state < 0) {
92 x->status = 0; 43 t->active = 0;
93 memset(x->mask, 0, sizeof(x->mask)); 44 grail_mask_clear(frame->touches, dev->slot);
45 frame->ndestroy++;
46 }
47 dev->state = 0;
94} 48}
95 49
96static void finish_packet(struct touch_dev *dev, 50static void finish_packet(struct touch_dev *dev,
97 const struct input_event *syn) 51 const struct input_event *syn)
98{ 52{
99 finish_touch(dev, dev->impl); 53 static const touch_time_t ms = 1000;
54 struct touch_frame *frame = &dev->frame;
55 int i, nslot = 0;
56 finish_touch(dev, frame);
57 grail_mask_foreach(i, frame->touches, DIM_TOUCH_BYTES)
58 frame->active[nslot++] = &frame->touch[i];
59 frame->nactive = nslot;
60 frame->time = syn->time.tv_usec / ms + syn->time.tv_sec * ms;
100 if (dev->sync) 61 if (dev->sync)
101 dev->sync(dev, syn); 62 dev->sync(dev, syn);
63 frame->ncreate = 0;
64 frame->nmodify = 0;
65 frame->ndestroy = 0;
102} 66}
103 67
104static int handle_abs_event(struct touch_dev *dev, 68static int handle_abs_event(struct touch_dev *dev,
105 const struct input_event *ev) 69 const struct input_event *ev)
106{ 70{
107 struct touch_dev_impl *x = dev->impl; 71 struct touch_frame *frame = &dev->frame;
72 struct touch *t = &frame->touch[dev->slot];
108 switch (ev->code) { 73 switch (ev->code) {
109 case ABS_MT_SLOT: 74 case ABS_MT_SLOT:
110 if (ev->value >= 0 && ev->value < DIM_TOUCH) { 75 if (ev->value >= 0 && ev->value < DIM_TOUCH) {
111 if (x->slot != ev->value) 76 if (dev->slot != ev->value)
112 finish_touch(dev, x); 77 finish_touch(dev, frame);
113 x->slot = ev->value; 78 dev->slot = ev->value;
79 t = &frame->touch[dev->slot];
114 } 80 }
115 return 1; 81 return 1;
116 case ABS_MT_POSITION_X: 82 case ABS_MT_POSITION_X:
117 set_prop(x, TP_POS_X, ev->value); 83 SET_PROP(x, ev->value);
118 return 1; 84 return 1;
119 case ABS_MT_POSITION_Y: 85 case ABS_MT_POSITION_Y:
120 set_prop(x, TP_POS_Y, ev->value); 86 SET_PROP(y, ev->value);
121 return 1; 87 return 1;
122 case ABS_MT_TOUCH_MAJOR: 88 case ABS_MT_TOUCH_MAJOR:
123 set_prop(x, TP_TOUCH_MAJOR, ev->value); 89 SET_PROP(touch_major, ev->value);
124 return 1; 90 return 1;
125 case ABS_MT_TOUCH_MINOR: 91 case ABS_MT_TOUCH_MINOR:
126 set_prop(x, TP_TOUCH_MINOR, ev->value); 92 SET_PROP(touch_minor, ev->value);
127 return 1; 93 return 1;
128 case ABS_MT_WIDTH_MAJOR: 94 case ABS_MT_WIDTH_MAJOR:
129 set_prop(x, TP_WIDTH_MAJOR, ev->value); 95 SET_PROP(width_major, ev->value);
130 return 1; 96 return 1;
131 case ABS_MT_WIDTH_MINOR: 97 case ABS_MT_WIDTH_MINOR:
132 set_prop(x, TP_WIDTH_MINOR, ev->value); 98 SET_PROP(width_minor, ev->value);
133 return 1; 99 return 1;
134 case ABS_MT_ORIENTATION: 100 case ABS_MT_ORIENTATION:
135 set_prop(x, TP_ORIENTATION, ev->value); 101 SET_PROP(orientation, ev->value);
136 return 1; 102 return 1;
137 case ABS_MT_PRESSURE: 103 case ABS_MT_PRESSURE:
138 set_prop(x, TP_PRESSURE, ev->value); 104 SET_PROP(pressure, ev->value);
105 return 1;
106 case ABS_MT_TOOL_TYPE:
107 SET_PROP(tool_type, ev->value);
139 return 1; 108 return 1;
140 case ABS_MT_TRACKING_ID: 109 case ABS_MT_TRACKING_ID:
141 if (x->id[x->slot] != ev->value) { 110 if (t->id != ev->value) {
142 if (x->id[x->slot] != MT_ID_NULL) { 111 if (t->id != MT_ID_NULL) {
143 x->status = -1; 112 dev->state = -1;
144 finish_touch(dev, x); 113 finish_touch(dev, frame);
145 } 114 }
146 if (ev->value != MT_ID_NULL) 115 if (ev->value != MT_ID_NULL)
147 x->status = 1; 116 dev->state = 1;
117 t->id = ev->value;
148 } 118 }
149 x->id[x->slot] = ev->value;
150 return 1; 119 return 1;
151 default: 120 default:
152 return 0; 121 return 0;
@@ -155,38 +124,35 @@ static int handle_abs_event(struct touch_dev *dev,
155 124
156int touch_dev_open(struct touch_dev *dev, int fd) 125int touch_dev_open(struct touch_dev *dev, int fd)
157{ 126{
158 struct touch_dev_impl *x; 127 struct touch_frame *frame = &dev->frame;
159 int ret, i; 128 int ret, i;
160 memset(dev, 0, sizeof(*dev)); 129 memset(dev, 0, sizeof(*dev));
161 x = calloc(1, sizeof(*x)); 130 for (i = 0; i < DIM_TOUCH; i++) {
162 if (!x) 131 struct touch *t = &frame->touch[i];
163 return -ENOMEM; 132 t->slot = i;
164 ret = mtdev_open(&x->mtdev, fd); 133 t->id = MT_ID_NULL;
165 if (!ret && !x->mtdev.caps.has_mtdata) 134 }
135 ret = mtdev_open(&dev->mtdev, fd);
136 if (!ret && !dev->mtdev.caps.has_mtdata)
166 ret = -ENODEV; 137 ret = -ENODEV;
167 if (ret) 138 if (ret)
168 goto error; 139 goto error;
169 for (i = 0; i < DIM_TOUCH; i++) 140 touch_caps_init(dev);
170 x->id[i] = MT_ID_NULL;
171 set_caps(&dev->caps, &x->mtdev.caps);
172 dev->impl = x;
173 return 0; 141 return 0;
174 error: 142 error:
175 free(x);
176 return ret; 143 return ret;
177} 144}
178 145
179int touch_dev_idle(struct touch_dev *dev, int fd, int ms) 146int touch_dev_idle(struct touch_dev *dev, int fd, int ms)
180{ 147{
181 return mtdev_idle(&dev->impl->mtdev, fd, ms); 148 return mtdev_idle(&dev->mtdev, fd, ms);
182} 149}
183 150
184int touch_dev_pull(struct touch_dev *dev, int fd) 151int touch_dev_pull(struct touch_dev *dev, int fd)
185{ 152{
186 struct touch_dev_impl *x = dev->impl;
187 struct input_event ev; 153 struct input_event ev;
188 int ret, count = 0, consumed; 154 int ret, count = 0, consumed;
189 while ((ret = mtdev_get(&x->mtdev, fd, &ev, 1)) > 0) { 155 while ((ret = mtdev_get(&dev->mtdev, fd, &ev, 1)) > 0) {
190 consumed = 0; 156 consumed = 0;
191 if (ev.type == EV_SYN) { 157 if (ev.type == EV_SYN) {
192 if (ev.code == SYN_REPORT) 158 if (ev.code == SYN_REPORT)
@@ -204,8 +170,6 @@ int touch_dev_pull(struct touch_dev *dev, int fd)
204 170
205void touch_dev_close(struct touch_dev *dev, int fd) 171void touch_dev_close(struct touch_dev *dev, int fd)
206{ 172{
207 struct touch_dev_impl *x = dev->impl; 173 mtdev_close(&dev->mtdev);
208 mtdev_close(&x->mtdev);
209 free(x);
210 memset(dev, 0, sizeof(*dev)); 174 memset(dev, 0, sizeof(*dev));
211} 175}
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 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 * Copyright (C) 2010 Henrik Rydberg <rydberg@bitmath.org>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23#include <grail-touch.h>
24#include <string.h>
25
26static void tp_event(struct touch_dev *dev, const struct input_event *ev)
27{
28 struct touch_engine *engine = dev->priv;
29 if (engine && engine->event)
30 engine->event(engine, ev);
31}
32
33static void update_frame(struct touch_frame *frame,
34 int slot, int active,
35 const grail_mask_t *mask,
36 const touch_prop_t *prop)
37{
38 struct touch *t = &frame->touch[slot];
39 int i;
40 t->active = active;
41 grail_mask_modify(frame->touches, slot, active);
42 if (mask && prop)
43 grail_mask_foreach(i, mask, DIM_TOUCH_PROP_BYTES)
44 t->prop[i] = prop[i];
45}
46
47static void finalize_frame(struct touch_frame *frame, touch_time_t time)
48{
49 int i, nslot = 0;
50 grail_mask_foreach(i, frame->touches, DIM_TOUCH_BYTES)
51 frame->active[nslot++] = &frame->touch[i];
52 frame->nactive = nslot;
53 frame->time = time;
54}
55
56static void tp_create(struct touch_dev *dev, int slot,
57 const grail_mask_t *mask, const touch_prop_t *prop)
58{
59 struct touch_engine *engine = dev->priv;
60 if (engine) {
61 engine->frame.ncreate++;
62 update_frame(&engine->frame, slot, 1, mask, prop);
63 }
64}
65
66static void tp_modify(struct touch_dev *dev, int slot,
67 const grail_mask_t *mask, const touch_prop_t *prop)
68{
69 struct touch_engine *engine = dev->priv;
70 if (engine) {
71 engine->frame.nmodify++;
72 update_frame(&engine->frame, slot, 1, mask, prop);
73 }
74}
75
76static void tp_destroy(struct touch_dev *dev, int slot)
77{
78 struct touch_engine *engine = dev->priv;
79 if (engine) {
80 engine->frame.ndestroy++;
81 update_frame(&engine->frame, slot, 0, 0, 0);
82 }
83}
84
85static void tp_sync(struct touch_dev *dev, const struct input_event *syn)
86{
87 static const touch_time_t ms = 1000;
88 struct touch_engine *engine = dev->priv;
89 touch_time_t time = syn->time.tv_usec / ms + syn->time.tv_sec * ms;
90 if (engine) {
91 finalize_frame(&engine->frame, time);
92 if (engine->sync)
93 engine->sync(engine, syn);
94 engine->frame.ncreate = 0;
95 engine->frame.nmodify = 0;
96 engine->frame.ndestroy = 0;
97 }
98}
99
100void touch_engine_init(struct touch_engine *engine,
101 void (*event)(struct touch_engine *engine,
102 const struct input_event *ev),
103 void (*sync)(struct touch_engine *engine,
104 const struct input_event *ev),
105 void *priv)
106{
107 int i;
108 memset(engine, 0, sizeof(*engine));
109 for (i = 0; i < DIM_TOUCH; i++)
110 engine->frame.touch[i].slot = i;
111 engine->event = event;
112 engine->sync = sync;
113 engine->priv = priv;
114}
115
116void touch_engine_attach(struct touch_engine *engine, struct touch_dev *dev)
117{
118 dev->priv = engine;
119 dev->event = tp_event;
120 dev->create = tp_create;
121 dev->modify = tp_modify;
122 dev->destroy = tp_destroy;
123 dev->sync = tp_sync;
124}
125
126void touch_engine_detach(struct touch_engine *engine, struct touch_dev *dev)
127{
128 dev->sync = 0;
129 dev->destroy = 0;
130 dev->modify = 0;
131 dev->create = 0;
132 dev->event = 0;
133 dev->priv = 0;
134}
135
diff --git a/test/grail-touch.c b/test/grail-touch.c
index bed31c3..c5ecae3 100644
--- a/test/grail-touch.c
+++ b/test/grail-touch.c
@@ -28,22 +28,33 @@
28#include <unistd.h> 28#include <unistd.h>
29#include <fcntl.h> 29#include <fcntl.h>
30 30
31static void tp_event(struct touch_engine *engine, 31static void tp_event(struct touch_dev *dev,
32 const struct input_event *ev) 32 const struct input_event *ev)
33{ 33{
34 fprintf(stderr, "event %d 0x%x %d\n", ev->type, ev->code, ev->value); 34 fprintf(stderr, "event %d 0x%x %d\n", ev->type, ev->code, ev->value);
35} 35}
36 36
37static void tp_sync(struct touch_engine *engine, 37static void tp_sync(struct touch_dev *dev,
38 const struct input_event *syn) 38 const struct input_event *syn)
39{ 39{
40 struct touch_frame *frame = &engine->frame; 40 struct touch_frame *frame = &dev->frame;
41 int i, j; 41 int i, j;
42 for (i = 0; i < frame->nactive; i++) { 42 for (i = 0; i < frame->nactive; i++) {
43 struct touch *t = frame->active[i]; 43 struct touch *t = frame->active[i];
44 fprintf(stderr, "touch %d %d\n", i, t->slot); 44 fprintf(stderr, "touch %d\n", i);
45 for (j = 0; j < DIM_TOUCH_PROP; j++) 45 fprintf(stderr, " slot: %d\n", t->slot);
46 fprintf(stderr, " %d\n", t->prop[j]); 46 fprintf(stderr, " id: %d\n", t->id);
47 fprintf(stderr, " tool_type: %d\n", t->tool_type);
48 fprintf(stderr, " x: %d\n", t->x);
49 fprintf(stderr, " y: %d\n", t->y);
50 fprintf(stderr, " touch_major: %d\n", t->touch_major);
51 fprintf(stderr, " touch_minor: %d\n", t->touch_minor);
52 fprintf(stderr, " width_major: %d\n", t->width_major);
53 fprintf(stderr, " width_minor: %d\n", t->width_minor);
54 fprintf(stderr, " angle: %f\n",
55 touch_angle(dev, t->orientation));
56 fprintf(stderr, " pressure: %f\n",
57 touch_pressure(dev, t->pressure));
47 } 58 }
48 fprintf(stderr, "sync %d %lld %d %d\n", 59 fprintf(stderr, "sync %d %lld %d %d\n",
49 frame->nactive, frame->time, frame->ncreate, frame->ndestroy); 60 frame->nactive, frame->time, frame->ncreate, frame->ndestroy);
@@ -51,12 +62,10 @@ static void tp_sync(struct touch_engine *engine,
51 62
52static void loop_device(struct touch_dev *dev, int fd) 63static void loop_device(struct touch_dev *dev, int fd)
53{ 64{
54 struct touch_engine engine; 65 dev->event = tp_event;
55 touch_engine_init(&engine, tp_event, tp_sync, 0); 66 dev->sync = tp_sync;
56 touch_engine_attach(&engine, dev);
57 while (!touch_dev_idle(dev, fd, 5000)) 67 while (!touch_dev_idle(dev, fd, 5000))
58 touch_dev_pull(dev, fd); 68 touch_dev_pull(dev, fd);
59 touch_engine_detach(&engine, dev);
60} 69}
61 70
62int main(int argc, char *argv[]) 71int main(int argc, char *argv[])