summaryrefslogtreecommitdiff
path: root/src/touch-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/touch-dev.c')
-rw-r--r--src/touch-dev.c218
1 files changed, 218 insertions, 0 deletions
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 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#include <grail-touch.h>
26#include <malloc.h>
27#include <string.h>
28#include <errno.h>
29
30/* from mtdev-mapping.h */
31#define MT_TOUCH_MAJOR 0
32#define MT_TOUCH_MINOR 1
33#define MT_WIDTH_MAJOR 2
34#define MT_WIDTH_MINOR 3
35#define MT_ORIENTATION 4
36#define MT_POSITION_X 5
37#define MT_POSITION_Y 6
38#define MT_TRACKING_ID 9
39#define MT_PRESSURE 10
40
41int mtdev_fetch_event(struct mtdev *dev, int fd, struct input_event *ev);
42void mtdev_put_event(struct mtdev *dev, const struct input_event *ev);
43int mtdev_empty(struct mtdev *dev);
44void mtdev_get_event(struct mtdev *dev, struct input_event* ev);
45
46struct touch_dev_impl {
47 int id[DIM_TOUCH];
48 int slot;
49 int status;
50 grail_mask_t mask[DIM_TOUCH_BYTES];
51 touch_prop_t prop[DIM_TOUCH_PROP];
52 struct mtdev mtdev;
53};
54
55static inline void set_info(struct touch_dev_caps *caps, int code,
56 const struct input_absinfo *info)
57{
58 grail_mask_set(caps->mask, code);
59 caps->info[code] = *info;
60}
61
62static void set_caps(struct touch_dev_caps *caps,
63 const struct mtdev_caps *mtcaps)
64{
65 if (mtcaps->has_abs[MT_POSITION_X])
66 set_info(caps, TP_POS_X, &mtcaps->abs[MT_POSITION_X]);
67 if (mtcaps->has_abs[MT_POSITION_Y])
68 set_info(caps, TP_POS_Y, &mtcaps->abs[MT_POSITION_Y]);
69 if (mtcaps->has_abs[MT_TOUCH_MAJOR])
70 set_info(caps, TP_TOUCH_MAJOR, &mtcaps->abs[MT_TOUCH_MAJOR]);
71 if (mtcaps->has_abs[MT_TOUCH_MINOR])
72 set_info(caps, TP_TOUCH_MINOR, &mtcaps->abs[MT_TOUCH_MINOR]);
73 if (mtcaps->has_abs[MT_WIDTH_MAJOR])
74 set_info(caps, TP_WIDTH_MAJOR, &mtcaps->abs[MT_WIDTH_MAJOR]);
75 if (mtcaps->has_abs[MT_WIDTH_MINOR])
76 set_info(caps, TP_WIDTH_MINOR, &mtcaps->abs[MT_WIDTH_MINOR]);
77 if (mtcaps->has_abs[MT_ORIENTATION])
78 set_info(caps, TP_ORIENTATION, &mtcaps->abs[MT_ORIENTATION]);
79 if (mtcaps->has_abs[MT_PRESSURE])
80 set_info(caps, TP_PRESSURE, &mtcaps->abs[MT_PRESSURE]);
81}
82
83static inline void set_prop(struct touch_dev_impl *x, int code, int value)
84{
85 grail_mask_set(x->mask, code);
86 x->prop[code] = value;
87}
88
89static void finish_touch(struct touch_dev *dev,
90 struct touch_dev_impl *x)
91{
92 if (x->status < 0 && dev->destroy)
93 dev->destroy(dev, x->slot);
94 if (x->status > 0 && dev->create)
95 dev->create(dev, x->slot, x->mask, x->prop);
96 if (x->status == 0 && dev->modify &&
97 grail_mask_count(x->mask, sizeof(x->mask)))
98 dev->modify(dev, x->slot, x->mask, x->prop);
99 x->status = 0;
100 memset(x->mask, 0, sizeof(x->mask));
101}
102
103static void finish_packet(struct touch_dev *dev,
104 const struct input_event *syn)
105{
106 finish_touch(dev, dev->impl);
107 if (dev->sync)
108 dev->sync(dev, syn);
109}
110
111static int handle_abs_event(struct touch_dev *dev,
112 const struct input_event *ev)
113{
114 struct touch_dev_impl *x = dev->impl;
115 switch (ev->code) {
116 case ABS_MT_SLOT:
117 if (ev->value >= 0 && ev->value < DIM_TOUCH) {
118 if (x->slot != ev->value)
119 finish_touch(dev, x);
120 x->slot = ev->value;
121 }
122 return 1;
123 case ABS_MT_POSITION_X:
124 set_prop(x, TP_POS_X, ev->value);
125 return 1;
126 case ABS_MT_POSITION_Y:
127 set_prop(x, TP_POS_Y, ev->value);
128 return 1;
129 case ABS_MT_TOUCH_MAJOR:
130 set_prop(x, TP_TOUCH_MAJOR, ev->value);
131 return 1;
132 case ABS_MT_TOUCH_MINOR:
133 set_prop(x, TP_TOUCH_MINOR, ev->value);
134 return 1;
135 case ABS_MT_WIDTH_MAJOR:
136 set_prop(x, TP_WIDTH_MAJOR, ev->value);
137 return 1;
138 case ABS_MT_WIDTH_MINOR:
139 set_prop(x, TP_WIDTH_MINOR, ev->value);
140 return 1;
141 case ABS_MT_ORIENTATION:
142 set_prop(x, TP_ORIENTATION, ev->value);
143 return 1;
144 case ABS_MT_PRESSURE:
145 set_prop(x, TP_PRESSURE, ev->value);
146 return 1;
147 case ABS_MT_TRACKING_ID:
148 if (x->id[x->slot] != ev->value) {
149 if (x->id[x->slot] != MT_ID_NULL) {
150 x->status = -1;
151 finish_touch(dev, x);
152 }
153 if (ev->value != MT_ID_NULL)
154 x->status = 1;
155 }
156 x->id[x->slot] = ev->value;
157 return 1;
158 default:
159 return 0;
160 }
161}
162
163int touch_dev_open(struct touch_dev *dev, int fd)
164{
165 struct touch_dev_impl *x;
166 int ret, i;
167 memset(dev, 0, sizeof(*dev));
168 x = calloc(1, sizeof(*x));
169 if (!x)
170 return -ENOMEM;
171 ret = mtdev_open(&x->mtdev, fd);
172 if (!ret && !x->mtdev.caps.has_mtdata)
173 ret = -ENODEV;
174 if (ret)
175 goto error;
176 for (i = 0; i < DIM_TOUCH; i++)
177 x->id[i] = MT_ID_NULL;
178 set_caps(&dev->caps, &x->mtdev.caps);
179 dev->impl = x;
180 return 0;
181 error:
182 free(x);
183 return ret;
184}
185
186int touch_dev_idle(struct touch_dev *dev, int fd, int ms)
187{
188 return mtdev_idle(&dev->impl->mtdev, fd, ms);
189}
190
191int touch_dev_pull(struct touch_dev *dev, int fd)
192{
193 struct touch_dev_impl *x = dev->impl;
194 struct input_event ev;
195 int ret, count = 0, consumed;
196 while ((ret = mtdev_get(&x->mtdev, fd, &ev, 1)) > 0) {
197 consumed = 0;
198 if (ev.type == EV_SYN) {
199 if (ev.code == SYN_REPORT)
200 finish_packet(dev, &ev);
201 consumed++;
202 } else if (ev.type == EV_ABS) {
203 consumed += handle_abs_event(dev, &ev);
204 }
205 if (!consumed && dev->event)
206 dev->event(dev, &ev);
207 count++;
208 }
209 return count > 0 ? count : ret;
210}
211
212void touch_dev_close(struct touch_dev *dev, int fd)
213{
214 struct touch_dev_impl *x = dev->impl;
215 mtdev_close(&x->mtdev);
216 free(x);
217 memset(dev, 0, sizeof(*dev));
218}