summaryrefslogtreecommitdiff
path: root/usr/src/dkms_source_tree/input-mt.c
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-11-16 14:25:19 +0100
committerHenrik Rydberg <rydberg@euromail.se>2010-11-16 14:25:19 +0100
commit5bd76821fca3d6422a586b691436583224158b01 (patch)
tree96ffe55bb1ca8402d0d4be47c85915466c85817d /usr/src/dkms_source_tree/input-mt.c
parente56d270d5dd472219864c1735d8eee16d6f1ccdb (diff)
Experimental mainline MT supportHEADmaster
This patchset is in flux, and a cooperative effort between Takashi Iwai, Chase Douglas, Chris Bagwell and myself. Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'usr/src/dkms_source_tree/input-mt.c')
-rw-r--r--usr/src/dkms_source_tree/input-mt.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/usr/src/dkms_source_tree/input-mt.c b/usr/src/dkms_source_tree/input-mt.c
new file mode 100644
index 0000000..236360f
--- /dev/null
+++ b/usr/src/dkms_source_tree/input-mt.c
@@ -0,0 +1,307 @@
1/*
2 * Input Multitouch Library
3 *
4 * Copyright (c) 2008-2010 Henrik Rydberg
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#include "input-mt.h"
12
13
14#define TRKID_BITS 16
15#define TRKID_MAX ((1 << TRKID_BITS) - 1)
16#define TRKID_SGN (1 << (TRKID_BITS - 1))
17
18static int trkid; // destined for input_dev
19
20int input_mt_create_slots_new(struct input_dev *dev, unsigned int num_slots)
21{
22 int ret;
23
24 ret = input_mt_create_slots(dev, num_slots);
25 if (ret)
26 return ret;
27
28 input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
29
30 return 0;
31}
32
33/**
34 * input_mt_report_state() - report contact state
35 * @dev: input device with allocated MT slots
36 * @active: true if contact is active, false otherwise
37 *
38 * Reports an active touch via ABS_MT_TRACKING_ID. If active is
39 * true and the slot is currently inactive, a new tracking id is
40 * assigned to the slot.
41 */
42void input_mt_report_state(struct input_dev *dev, bool active)
43{
44 int id = -1;
45
46 if (dev->mt && active) {
47 id = input_mt_get_value(&dev->mt[dev->slot], ABS_MT_TRACKING_ID);
48 if (id < 0)
49 id = trkid++ & TRKID_MAX;
50 }
51
52 input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
53}
54
55/**
56 * input_mt_report_emulation() - common pointer emulation
57 * @dev: input device with allocated MT slots
58 *
59 * Performs legacy emulation emulation via BTN_TOUCH, etc.
60 */
61void input_mt_report_emulation(struct input_dev *dev)
62{
63 struct input_mt_slot *oldest = 0;
64 int oldid = -1;
65 int count = 0;
66 int i;
67
68 for (i = 0; i < dev->mtsize; ++i) {
69 struct input_mt_slot *slot = &dev->mt[i];
70 int id = input_mt_get_value(slot, ABS_MT_TRACKING_ID);
71
72 if (id < 0)
73 continue;
74
75 if (!oldest || ((id - oldid) & TRKID_SGN)) {
76 oldest = slot;
77 oldid = id;
78 }
79 count++;
80 }
81
82 input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
83 input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1);
84 input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
85 input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
86 input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count > 3);
87
88 if (oldest) {
89 int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
90 int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
91 int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
92
93 input_event(dev, EV_ABS, ABS_X, x);
94 input_event(dev, EV_ABS, ABS_Y, y);
95 input_event(dev, EV_ABS, ABS_PRESSURE, p);
96 } else {
97 input_event(dev, EV_ABS, ABS_PRESSURE, 0);
98 }
99}
100
101
102/* generated by mtdev-kernel - do not edit */
103static const u8 match_data[] = {
104 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 0, 0, 0, 1, 1,
105 1, 0, 0, 0, 1, 2, 1, 1, 0, 2, 2, 1, 2, 0, 0, 0,
106 1, 2, 3, 1, 1, 0, 2, 3, 2, 1, 2, 0, 3, 3, 1, 2,
107 3, 0, 0, 0, 1, 1, 1, 2, 1, 0, 0, 3, 0, 1, 1, 3,
108 1, 0, 2, 2, 3, 1, 2, 0, 0, 4, 0, 1, 2, 2, 4, 2,
109 1, 0, 0, 5, 0, 2, 1, 1, 5, 2, 0, 1, 1, 4, 1, 0,
110 2, 3, 2, 4, 1, 2, 0, 3, 3, 4, 1, 2, 3, 0, 0, 5,
111 0, 1, 2, 3, 2, 5, 2, 1, 0, 3, 3, 5, 2, 1, 3, 0,
112 0, 6, 0, 2, 1, 3, 1, 6, 2, 0, 1, 3, 3, 6, 2, 3,
113 1, 0, 0, 7, 0, 2, 3, 1, 1, 7, 2, 0, 3, 1, 2, 7,
114 2, 3, 0, 1, 0, 0, 1, 1, 2, 2, 1, 2, 1, 0, 0, 3,
115 0, 1, 1, 4, 2, 0, 3, 4, 2, 1, 0, 5, 0, 2, 2, 5,
116 1, 2, 2, 4, 6, 2, 1, 0, 1, 5, 6, 2, 0, 1, 2, 3,
117 7, 1, 2, 0, 0, 5, 7, 0, 2, 1, 1, 3, 8, 1, 0, 2,
118 0, 4, 8, 0, 1, 2, 2, 5, 8, 2, 1, 0, 3, 3, 5, 8,
119 2, 1, 3, 0, 1, 6, 8, 2, 0, 1, 3, 3, 6, 8, 2, 3,
120 1, 0, 1, 7, 8, 2, 0, 3, 1, 2, 7, 8, 2, 3, 0, 1,
121 2, 4, 9, 1, 2, 0, 3, 3, 4, 9, 1, 2, 3, 0, 0, 6,
122 9, 0, 2, 1, 3, 3, 6, 9, 3, 2, 1, 0, 0, 7, 9, 0,
123 2, 3, 1, 2, 7, 9, 3, 2, 0, 1, 1, 4, 10, 1, 0, 2,
124 3, 3, 4, 10, 1, 3, 2, 0, 0, 5, 10, 0, 1, 2, 3, 3,
125 5, 10, 3, 1, 2, 0, 0, 7, 10, 0, 3, 2, 1, 1, 7, 10,
126 3, 0, 2, 1, 1, 4, 11, 1, 0, 3, 2, 2, 4, 11, 1, 3,
127 0, 2, 0, 5, 11, 0, 1, 3, 2, 2, 5, 11, 3, 1, 0, 2,
128 0, 6, 11, 0, 3, 1, 2, 1, 6, 11, 3, 0, 1, 2, 0, 0,
129 1, 1, 2, 2, 3, 3, 1, 2, 1, 0, 0, 3, 0, 1, 1, 4,
130 2, 0, 3, 4, 2, 1, 0, 5, 0, 2, 2, 5, 1, 2, 1, 6,
131 3, 0, 3, 6, 3, 1, 5, 6, 3, 2, 0, 7, 0, 3, 2, 7,
132 1, 3, 4, 7, 2, 3, 2, 4, 6, 2, 1, 0, 1, 5, 6, 2,
133 0, 1, 2, 3, 7, 1, 2, 0, 0, 5, 7, 0, 2, 1, 1, 3,
134 8, 1, 0, 2, 0, 4, 8, 0, 1, 2, 2, 4, 9, 3, 1, 0,
135 1, 5, 9, 3, 0, 1, 2, 7, 9, 3, 2, 0, 5, 7, 9, 3,
136 2, 1, 1, 8, 9, 3, 0, 2, 4, 8, 9, 3, 1, 2, 2, 3,
137 10, 1, 3, 0, 0, 5, 10, 0, 3, 1, 2, 6, 10, 2, 3, 0,
138 5, 6, 10, 2, 3, 1, 0, 8, 10, 0, 3, 2, 3, 8, 10, 1,
139 3, 2, 1, 3, 11, 1, 0, 3, 0, 4, 11, 0, 1, 3, 1, 6,
140 11, 2, 0, 3, 4, 6, 11, 2, 1, 3, 0, 7, 11, 0, 2, 3,
141 3, 7, 11, 1, 2, 3, 3, 6, 9, 12, 3, 2, 1, 0, 2, 7,
142 9, 12, 3, 2, 0, 1, 3, 5, 10, 12, 3, 1, 2, 0, 1, 7,
143 10, 12, 3, 0, 2, 1, 2, 5, 11, 12, 3, 1, 0, 2, 1, 6,
144 11, 12, 3, 0, 1, 2, 3, 6, 8, 13, 2, 3, 1, 0, 2, 7,
145 8, 13, 2, 3, 0, 1, 3, 4, 10, 13, 1, 3, 2, 0, 0, 7,
146 10, 13, 0, 3, 2, 1, 2, 4, 11, 13, 1, 3, 0, 2, 0, 6,
147 11, 13, 0, 3, 1, 2, 3, 5, 8, 14, 2, 1, 3, 0, 1, 7,
148 8, 14, 2, 0, 3, 1, 3, 4, 9, 14, 1, 2, 3, 0, 0, 7,
149 9, 14, 0, 2, 3, 1, 1, 4, 11, 14, 1, 0, 3, 2, 0, 5,
150 11, 14, 0, 1, 3, 2, 2, 5, 8, 15, 2, 1, 0, 3, 1, 6,
151 8, 15, 2, 0, 1, 3, 2, 4, 9, 15, 1, 2, 0, 3, 0, 6,
152 9, 15, 0, 2, 1, 3, 1, 4, 10, 15, 1, 0, 2, 3, 0, 5,
153 10, 15, 0, 1, 2, 3,
154};
155
156/* generated by mtdev-kernel - do not edit */
157static const int match_index[][5] = {
158 { 0, 0, 1, 3, 6 },
159 { 10, 10, 12, 18, 30 },
160 { 50, 50, 54, 62, 92 },
161 { 164, 164, 170, 194, 230 },
162 { 398, 398, 406, 454, 598 },
163 { 790 }
164};
165
166static void set_dist(u32 *dist,
167 const struct trk_coord *b1, const struct trk_coord *e1,
168 const struct trk_coord *b2, const struct trk_coord *e2)
169{
170 const struct trk_coord *p, *q;
171
172 for (p = b1; p != e1; p++)
173 for (q = b2; q != e2; q++)
174 *dist++ = abs(q->x - p->x) + abs(q->y - p->y);
175}
176
177const u8 *match_four(const struct trk_coord *old, int nslot,
178 const struct trk_coord *pos, int npos)
179{
180 u32 d[16], obj, t;
181 const u8 *p, *b, *e;
182 const int *at;
183
184 set_dist(d, old, old + nslot, pos, pos + npos);
185
186 at = &match_index[nslot][npos];
187 b = &match_data[at[0]];
188 e = &match_data[at[1]];
189
190 obj = UINT_MAX, p = b;
191
192 switch (min(nslot, npos)) {
193 case 1:
194 for (; b != e; b += npos) {
195 t = d[*b++];
196 if (t < obj)
197 obj = t, p = b;
198 }
199 break;
200 case 2:
201 for (; b != e; b += npos) {
202 t = d[*b++], t += d[*b++];
203 if (t < obj)
204 obj = t, p = b;
205 }
206 break;
207 case 3:
208 for (; b != e; b += npos) {
209 t = d[*b++], t += d[*b++], t += d[*b++];
210 if (t < obj)
211 obj = t, p = b;
212 }
213 break;
214 case 4:
215 for (; b != e; b += npos) {
216 t = d[*b++], t += d[*b++], t += d[*b++], t += d[*b++];
217 if (t < obj)
218 obj = t, p = b;
219 }
220 break;
221 }
222
223 return p;
224}
225
226/**
227 * input_mt_assign_slots_by_coord() - perform a best-match assignment
228 * @dev: input device with allocated MT slots
229 * @slots: the slot assignment to be filled
230 * @coords: the coordinate array to match
231 * @num_coords: number of coordinates
232 *
233 * Performs a best match against the current contacts and returns
234 * the slot assignment list. New contacts are assigned to unused
235 * slots.
236 *
237 * Returns zero on success, or negative error in case of failure.
238 */
239int input_mt_assign_slots_by_coord(struct input_dev *dev, int *slots,
240 const struct trk_coord *coords,
241 int num_coords)
242{
243 struct trk_coord old[4];
244 int old2slot[4], nold, i;
245 const u8 *p;
246
247 if (!dev->mt)
248 return -ENXIO;
249 if (dev->mtsize < 2 || dev->mtsize > 4)
250 return -ENXIO;
251 if (num_coords > dev->mtsize)
252 return -EINVAL;
253 if (num_coords < 1)
254 return 0;
255
256 nold = 0;
257 for (i = 0; i < dev->mtsize; i++) {
258 const struct input_mt_slot *mt = &dev->mt[i];
259 if (input_mt_get_value(mt, ABS_MT_TRACKING_ID) < 0)
260 continue;
261 old[nold].x = input_mt_get_value(mt, ABS_MT_POSITION_X);
262 old[nold].y = input_mt_get_value(mt, ABS_MT_POSITION_Y);
263 old2slot[nold++] = i;
264 }
265
266 p = match_four(old, nold, coords, num_coords);
267
268 for (i = 0; i < dev->mtsize; i++)
269 if (input_mt_get_value(&dev->mt[i], ABS_MT_TRACKING_ID) < 0)
270 old2slot[nold++] = i;
271
272 for (i = 0; i < num_coords; i++)
273 slots[i] = old2slot[p[i]];
274
275 return 0;
276}
277
278
279/**
280 * input_mt_sync_slot_complement() - send touchup for remaining slots
281 * @dev: input device with allocated MT slots
282 * @slots: the slot assignment to be filled
283 * @coords: the coordinate array to match
284 * @num_coords: number of coordinates
285 *
286 * Performs a best match against the current contacts and returns
287 * the slot assignment list. New contacts are assigned to unused
288 * slots.
289 *
290 * Returns zero on success, or negative error in case of failure.
291 */
292void input_mt_sync_slot_complement(struct input_dev *dev,
293 const int *slots, int num_slots)
294{
295 unsigned long mask = 0;
296 int i;
297
298 for (i = 0; i < num_slots; i++)
299 mask |= BIT(slots[i]);
300
301 for (i = 0; i < dev->mtsize; i++) {
302 if (mask & BIT(i))
303 continue;
304 input_mt_slot(dev, i);
305 input_mt_report_state(dev, false);
306 }
307}