summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-09-09 10:17:09 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-09-09 10:17:09 +0200
commit9bdd12a8046f33a6d190bb33371eb30d3ee59062 (patch)
treee23f8c501a3fd056836c0474666ab665deb25ccd /src
parent293c6123865c2ec6106949226b790ac54f0eaef6 (diff)
Support legacy devices
Simulate MT touch events for legacy devices that support the DOUBLETAP, TRIPLETAP and QUADTAP events. This allows multi-finger tap and drag gestures to be emitted, providing a basic level of MT functionality for legacy devices. Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'src')
-rw-r--r--src/touch-caps.c37
-rw-r--r--src/touch-dev.c87
2 files changed, 122 insertions, 2 deletions
diff --git a/src/touch-caps.c b/src/touch-caps.c
index 7f243c5..a51912c 100644
--- a/src/touch-caps.c
+++ b/src/touch-caps.c
@@ -21,6 +21,7 @@
21 ****************************************************************************/ 21 ****************************************************************************/
22 22
23#include <grail-touch.h> 23#include <grail-touch.h>
24#include <errno.h>
24#include <math.h> 25#include <math.h>
25 26
26/* see mtdev-mapping.h */ 27/* see mtdev-mapping.h */
@@ -29,6 +30,42 @@
29#define MTDEV_ORIENTATION 4 30#define MTDEV_ORIENTATION 4
30#define MTDEV_PRESSURE 10 31#define MTDEV_PRESSURE 10
31 32
33#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
34
35static const int bits_per_long = 8 * sizeof(long);
36
37static inline int nlongs(int nbit)
38{
39 return (nbit + bits_per_long - 1) / bits_per_long;
40}
41
42static inline int getbit(const unsigned long *map, int key)
43{
44 return (map[key / bits_per_long] >> (key % bits_per_long)) & 0x01;
45}
46
47int touch_caps_is_supported(struct touch_dev *dev, int fd)
48{
49 unsigned long keybits[nlongs(KEY_MAX)];
50 unsigned long absbits[nlongs(ABS_MAX)];
51 int rc;
52
53 if (dev->mtdev.caps.has_mtdata)
54 return 1;
55
56 SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits));
57 if (rc < 0)
58 return 0;
59 SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits));
60 if (rc < 0)
61 return 0;
62
63 return getbit(absbits, ABS_X) &&
64 getbit(absbits, ABS_Y) &&
65 getbit(keybits, BTN_TOUCH) &&
66 getbit(keybits, BTN_TOOL_DOUBLETAP);
67}
68
32void touch_caps_init(struct touch_dev *dev) 69void touch_caps_init(struct touch_dev *dev)
33{ 70{
34 const struct mtdev_caps *mt = &dev->mtdev.caps; 71 const struct mtdev_caps *mt = &dev->mtdev.caps;
diff --git a/src/touch-dev.c b/src/touch-dev.c
index 17082ed..d8e192e 100644
--- a/src/touch-dev.c
+++ b/src/touch-dev.c
@@ -53,13 +53,45 @@ static void finish_touch(struct touch_dev *dev, struct touch_frame *frame)
53 dev->state = 0; 53 dev->state = 0;
54} 54}
55 55
56static void finish_legacy(struct touch_dev *dev, struct touch_frame *frame)
57{
58 static int trkid;
59 int i;
60 for (i = 0; i < frame->nactive; i++) {
61 struct touch *t = &frame->touch[i];
62 t->active = 1;
63 if (t->id < 0) {
64 t->id = trkid++ & 0xffff;
65 frame->ncreate++;
66 }
67 if (i > 0) {
68 SET_PROP(x, frame->touch[0].x);
69 SET_PROP(y, frame->touch[0].y);
70 SET_PROP(pressure, frame->touch[0].pressure);
71 }
72 grail_mask_set(frame->touches, i);
73 }
74 for (i = frame->nactive; i < DIM_TOUCH; i++) {
75 struct touch *t = &frame->touch[i];
76 t->active = 0;
77 if (t->id >= 0) {
78 t->id = -1;
79 frame->ndestroy++;
80 }
81 grail_mask_clear(frame->touches, i);
82 }
83}
84
56static void finish_packet(struct touch_dev *dev, 85static void finish_packet(struct touch_dev *dev,
57 const struct input_event *syn) 86 const struct input_event *syn)
58{ 87{
59 static const touch_time_t ms = 1000; 88 static const touch_time_t ms = 1000;
60 struct touch_frame *frame = &dev->frame; 89 struct touch_frame *frame = &dev->frame;
61 int i, nslot = 0; 90 int i, nslot = 0;
62 finish_touch(dev, frame); 91 if (dev->mtdev.caps.has_mtdata)
92 finish_touch(dev, frame);
93 else
94 finish_legacy(dev, frame);
63 grail_mask_foreach(i, frame->touches, DIM_TOUCH_BYTES) 95 grail_mask_foreach(i, frame->touches, DIM_TOUCH_BYTES)
64 frame->active[nslot++] = &frame->touch[i]; 96 frame->active[nslot++] = &frame->touch[i];
65 frame->nactive = nslot; 97 frame->nactive = nslot;
@@ -77,6 +109,21 @@ static int handle_abs_event(struct touch_dev *dev,
77 struct touch_frame *frame = &dev->frame; 109 struct touch_frame *frame = &dev->frame;
78 struct touch *t = &frame->touch[dev->slot]; 110 struct touch *t = &frame->touch[dev->slot];
79 switch (ev->code) { 111 switch (ev->code) {
112 case ABS_X:
113 if (dev->mtdev.caps.has_mtdata)
114 return 0;
115 SET_PROP(x, ev->value);
116 return 0;
117 case ABS_Y:
118 if (dev->mtdev.caps.has_mtdata)
119 return 0;
120 SET_PROP(y, ev->value);
121 return 0;
122 case ABS_PRESSURE:
123 if (dev->mtdev.caps.has_mtdata)
124 return 0;
125 SET_PROP(pressure, ev->value);
126 return 0;
80 case ABS_MT_SLOT: 127 case ABS_MT_SLOT:
81 if (ev->value >= 0 && ev->value < DIM_TOUCH) { 128 if (ev->value >= 0 && ev->value < DIM_TOUCH) {
82 if (dev->slot != ev->value) 129 if (dev->slot != ev->value)
@@ -128,6 +175,40 @@ static int handle_abs_event(struct touch_dev *dev,
128 } 175 }
129} 176}
130 177
178static int handle_key_event(struct touch_dev *dev,
179 const struct input_event *ev)
180{
181 struct touch_frame *frame = &dev->frame;
182 if (dev->mtdev.caps.has_mtdata)
183 return 0;
184 switch (ev->code) {
185 case BTN_TOUCH:
186 if (ev->value && !frame->nactive)
187 frame->nactive = 1;
188 else if (!ev->value && frame->nactive)
189 frame->nactive = 0;
190 return 0;
191 case BTN_TOOL_FINGER:
192 if (ev->value)
193 frame->nactive = 1;
194 return 0;
195 case BTN_TOOL_DOUBLETAP:
196 if (ev->value)
197 frame->nactive = 2;
198 return 0;
199 case BTN_TOOL_TRIPLETAP:
200 if (ev->value)
201 frame->nactive = 3;
202 return 0;
203 case BTN_TOOL_QUADTAP:
204 if (ev->value)
205 frame->nactive = 4;
206 return 0;
207 default:
208 return 0;
209 }
210}
211
131int touch_dev_open(struct touch_dev *dev, int fd) 212int touch_dev_open(struct touch_dev *dev, int fd)
132{ 213{
133 struct touch_frame *frame = &dev->frame; 214 struct touch_frame *frame = &dev->frame;
@@ -139,7 +220,7 @@ int touch_dev_open(struct touch_dev *dev, int fd)
139 t->id = MT_ID_NULL; 220 t->id = MT_ID_NULL;
140 } 221 }
141 ret = mtdev_open(&dev->mtdev, fd); 222 ret = mtdev_open(&dev->mtdev, fd);
142 if (!ret && !dev->mtdev.caps.has_mtdata) 223 if (!ret && !touch_caps_is_supported(dev, fd))
143 ret = -ENODEV; 224 ret = -ENODEV;
144 if (ret) 225 if (ret)
145 goto error; 226 goto error;
@@ -166,6 +247,8 @@ int touch_dev_pull(struct touch_dev *dev, int fd)
166 consumed++; 247 consumed++;
167 } else if (ev.type == EV_ABS) { 248 } else if (ev.type == EV_ABS) {
168 consumed += handle_abs_event(dev, &ev); 249 consumed += handle_abs_event(dev, &ev);
250 } else if (ev.type == EV_KEY) {
251 consumed += handle_key_event(dev, &ev);
169 } 252 }
170 if (!consumed && dev->event) 253 if (!consumed && dev->event)
171 dev->event(dev, &ev); 254 dev->event(dev, &ev);