summaryrefslogtreecommitdiff
path: root/src/core.c
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-12-22 18:29:00 +0100
committerHenrik Rydberg <rydberg@euromail.se>2010-12-22 18:29:00 +0100
commit56a77e68fb91eef928d8a95c50ae14508e37ae0f (patch)
tree51af9bb9dd508bca58e8b9416479e79f8bb7ee10 /src/core.c
parent0e2ab3b5940e70493aaabdfe5e8da1c75db4db72 (diff)
Introduce a stable ABI
The current mtdev is not ABI stable, and the upcoming additions to the kernel api will break ABI. This patch starts the process of keeping binary compatibility with old programs, by moving the abi-specific parts under a special flag, MTDEV_NO_LEGACY_API, and makes sure the internal parts compiles with MTDEV_NO_LEGACY_API set. This way, older programs will still work, old programs will still compile, and new programs will be able to use the additions. Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'src/core.c')
-rw-r--r--src/core.c126
1 files changed, 80 insertions, 46 deletions
diff --git a/src/core.c b/src/core.c
index a6798b0..1f7c1fe 100644
--- a/src/core.c
+++ b/src/core.c
@@ -32,10 +32,16 @@
32#include "match.h" 32#include "match.h"
33 33
34static inline int istouch(const struct mtdev_slot *data, 34static inline int istouch(const struct mtdev_slot *data,
35 const struct mtdev_caps *caps) 35 const struct mtdev *dev)
36{ 36{
37 return data->abs[MTDEV_TOUCH_MAJOR] || 37 return data->touch_major ||
38 !caps->has_abs[MTDEV_TOUCH_MAJOR]; 38 !mtdev_has_mt_event(dev, ABS_MT_TOUCH_MAJOR);
39}
40
41static inline int isfilled(unsigned int mask)
42{
43 return GETBIT(mask, mtdev_abs2mt(ABS_MT_POSITION_X)) &&
44 GETBIT(mask, mtdev_abs2mt(ABS_MT_POSITION_Y));
39} 45}
40 46
41/* Response-augmented EWMA filter, courtesy of Vojtech Pavlik */ 47/* Response-augmented EWMA filter, courtesy of Vojtech Pavlik */
@@ -58,7 +64,7 @@ static int defuzz(int value, int old_val, int fuzz)
58/* 64/*
59 * solve - solve contact matching problem 65 * solve - solve contact matching problem
60 * @state: mtdev state 66 * @state: mtdev state
61 * @caps: device capabilities 67 * @dev: device capabilities
62 * @sid: array of current tracking ids 68 * @sid: array of current tracking ids
63 * @sx: array of current position x 69 * @sx: array of current position x
64 * @sy: array of current position y 70 * @sy: array of current position y
@@ -69,7 +75,7 @@ static int defuzz(int value, int old_val, int fuzz)
69 * @nn: number of new contacts 75 * @nn: number of new contacts
70 * @touch: which of the new contacts to fill 76 * @touch: which of the new contacts to fill
71 */ 77 */
72static void solve(struct mtdev_state *state, const struct mtdev_caps *caps, 78static void solve(struct mtdev_state *state, const struct mtdev *dev,
73 const int *sid, const int *sx, const int *sy, int sn, 79 const int *sid, const int *sx, const int *sy, int sn,
74 int *nid, const int *nx, const int *ny, int nn, 80 int *nid, const int *nx, const int *ny, int nn,
75 bitmask_t touch) 81 bitmask_t touch)
@@ -100,34 +106,33 @@ static void solve(struct mtdev_state *state, const struct mtdev_caps *caps,
100/* 106/*
101 * assign_tracking_id - assign tracking ids to all contacts 107 * assign_tracking_id - assign tracking ids to all contacts
102 * @state: mtdev state 108 * @state: mtdev state
103 * @caps: device capabilities 109 * @dev: device capabilities
104 * @data: array of all present contacts, to be filled 110 * @data: array of all present contacts, to be filled
105 * @prop: array of all set contacts properties 111 * @prop: array of all set contacts properties
106 * @size: number of contacts in array 112 * @size: number of contacts in array
107 * @touch: which of the contacts are actual touches 113 * @touch: which of the contacts are actual touches
108 */ 114 */
109static void assign_tracking_id(struct mtdev_state *state, 115static void assign_tracking_id(struct mtdev_state *state,
110 const struct mtdev_caps *caps, 116 const struct mtdev *dev,
111 struct mtdev_slot *data, bitmask_t *prop, 117 struct mtdev_slot *data, bitmask_t *prop,
112 int size, bitmask_t touch) 118 int size, bitmask_t touch)
113{ 119{
114 int sid[DIM_FINGER], sx[DIM_FINGER], sy[DIM_FINGER], sn = 0; 120 int sid[DIM_FINGER], sx[DIM_FINGER], sy[DIM_FINGER], sn = 0;
115 int nid[DIM_FINGER], nx[DIM_FINGER], ny[DIM_FINGER], i; 121 int nid[DIM_FINGER], nx[DIM_FINGER], ny[DIM_FINGER], i;
116 foreach_bit(i, state->used) { 122 foreach_bit(i, state->used) {
117 sid[sn] = state->data[i].abs[MTDEV_TRACKING_ID]; 123 sid[sn] = state->data[i].tracking_id;
118 sx[sn] = state->data[i].abs[MTDEV_POSITION_X]; 124 sx[sn] = state->data[i].position_x;
119 sy[sn] = state->data[i].abs[MTDEV_POSITION_Y]; 125 sy[sn] = state->data[i].position_y;
120 sn++; 126 sn++;
121 } 127 }
122 for (i = 0; i < size; i++) { 128 for (i = 0; i < size; i++) {
123 nx[i] = data[i].abs[MTDEV_POSITION_X]; 129 nx[i] = data[i].position_x;
124 ny[i] = data[i].abs[MTDEV_POSITION_Y]; 130 ny[i] = data[i].position_y;
125 } 131 }
126 solve(state, caps, sid, sx, sy, sn, nid, nx, ny, size, touch); 132 solve(state, dev, sid, sx, sy, sn, nid, nx, ny, size, touch);
127 for (i = 0; i < size; i++) { 133 for (i = 0; i < size; i++) {
128 data[i].abs[MTDEV_TRACKING_ID] = 134 data[i].tracking_id = GETBIT(touch, i) ? nid[i] : MT_ID_NULL;
129 GETBIT(touch, i) ? nid[i] : MT_ID_NULL; 135 SETBIT(prop[i], mtdev_abs2mt(ABS_MT_TRACKING_ID));
130 prop[i] |= BITMASK(MTDEV_TRACKING_ID);
131 } 136 }
132} 137}
133 138
@@ -157,9 +162,7 @@ static int process_typeA(struct mtdev_state *state,
157 case EV_SYN: 162 case EV_SYN:
158 switch (ev.code) { 163 switch (ev.code) {
159 case SYN_MT_REPORT: 164 case SYN_MT_REPORT:
160 if (size < DIM_FINGER && 165 if (size < DIM_FINGER && isfilled(prop[size]))
161 GETBIT(prop[size], MTDEV_POSITION_X) &&
162 GETBIT(prop[size], MTDEV_POSITION_Y))
163 size++; 166 size++;
164 if (size < DIM_FINGER) 167 if (size < DIM_FINGER)
165 prop[size] = 0; 168 prop[size] = 0;
@@ -178,8 +181,8 @@ static int process_typeA(struct mtdev_state *state,
178 case EV_ABS: 181 case EV_ABS:
179 if (size < DIM_FINGER && mtdev_is_absmt(ev.code)) { 182 if (size < DIM_FINGER && mtdev_is_absmt(ev.code)) {
180 mtcode = mtdev_abs2mt(ev.code); 183 mtcode = mtdev_abs2mt(ev.code);
181 data[size].abs[mtcode] = ev.value; 184 set_sval(&data[size], mtcode, ev.value);
182 prop[size] |= BITMASK(mtcode); 185 SETBIT(prop[size], mtcode);
183 mtcnt++; 186 mtcnt++;
184 consumed = 1; 187 consumed = 1;
185 } 188 }
@@ -210,21 +213,22 @@ static void process_typeB(struct mtdev_state *state)
210/* 213/*
211 * filter_data - apply input filtering on new incoming data 214 * filter_data - apply input filtering on new incoming data
212 * @state: mtdev state 215 * @state: mtdev state
213 * @caps: device capabilities 216 * @dev: device capabilities
214 * @data: the incoming data to filter 217 * @data: the incoming data to filter
215 * @prop: the properties to filter 218 * @prop: the properties to filter
216 * @slot: the slot the data refers to 219 * @slot: the slot the data refers to
217 */ 220 */
218static void filter_data(const struct mtdev_state *state, 221static void filter_data(const struct mtdev_state *state,
219 const struct mtdev_caps *caps, 222 const struct mtdev *dev,
220 struct mtdev_slot *data, bitmask_t prop, 223 struct mtdev_slot *data, bitmask_t prop,
221 int slot) 224 int slot)
222{ 225{
223 int i; 226 int i;
224 foreach_bit(i, prop) { 227 foreach_bit(i, prop) {
225 int fuzz = caps->abs[i].fuzz; 228 int fuzz = mtdev_get_abs_fuzz(dev, mtdev_mt2abs(i));
226 int oldval = state->data[slot].abs[i]; 229 int oldval = get_sval(&state->data[slot], i);
227 data->abs[i] = defuzz(data->abs[i], oldval, fuzz); 230 int value = get_sval(data, i);
231 set_sval(data, i, defuzz(value, oldval, fuzz));
228 } 232 }
229} 233}
230 234
@@ -243,7 +247,7 @@ static void push_slot_changes(struct mtdev_state *state,
243 struct input_event ev; 247 struct input_event ev;
244 int i, count = 0; 248 int i, count = 0;
245 foreach_bit(i, prop) 249 foreach_bit(i, prop)
246 if (state->data[slot].abs[i] != data->abs[i]) 250 if (get_sval(&state->data[slot], i) != get_sval(data, i))
247 count++; 251 count++;
248 if (!count) 252 if (!count)
249 return; 253 return;
@@ -257,10 +261,10 @@ static void push_slot_changes(struct mtdev_state *state,
257 } 261 }
258 foreach_bit(i, prop) { 262 foreach_bit(i, prop) {
259 ev.code = mtdev_mt2abs(i); 263 ev.code = mtdev_mt2abs(i);
260 ev.value = data->abs[i]; 264 ev.value = get_sval(data, i);
261 if (state->data[slot].abs[i] != ev.value) { 265 if (get_sval(&state->data[slot], i) != ev.value) {
262 evbuf_put(&state->outbuf, &ev); 266 evbuf_put(&state->outbuf, &ev);
263 state->data[slot].abs[i] = ev.value; 267 set_sval(&state->data[slot], i, ev.value);
264 } 268 }
265 } 269 }
266} 270}
@@ -268,14 +272,14 @@ static void push_slot_changes(struct mtdev_state *state,
268/* 272/*
269 * apply_typeA_changes - parse and propagate state changes 273 * apply_typeA_changes - parse and propagate state changes
270 * @state: mtdev state 274 * @state: mtdev state
271 * @caps: device capabilities 275 * @dev: device capabilities
272 * @data: array of data to apply 276 * @data: array of data to apply
273 * @prop: array of properties to apply 277 * @prop: array of properties to apply
274 * @size: number of contacts in array 278 * @size: number of contacts in array
275 * @syn: reference to the SYN_REPORT event 279 * @syn: reference to the SYN_REPORT event
276 */ 280 */
277static void apply_typeA_changes(struct mtdev_state *state, 281static void apply_typeA_changes(struct mtdev_state *state,
278 const struct mtdev_caps *caps, 282 const struct mtdev *dev,
279 struct mtdev_slot *data, const bitmask_t *prop, 283 struct mtdev_slot *data, const bitmask_t *prop,
280 int size, const struct input_event *syn) 284 int size, const struct input_event *syn)
281{ 285{
@@ -283,11 +287,11 @@ static void apply_typeA_changes(struct mtdev_state *state,
283 bitmask_t used = 0; 287 bitmask_t used = 0;
284 int i, slot, id; 288 int i, slot, id;
285 for (i = 0; i < size; i++) { 289 for (i = 0; i < size; i++) {
286 id = data[i].abs[MTDEV_TRACKING_ID]; 290 id = data[i].tracking_id;
287 foreach_bit(slot, state->used) { 291 foreach_bit(slot, state->used) {
288 if (state->data[slot].abs[MTDEV_TRACKING_ID] != id) 292 if (state->data[slot].tracking_id != id)
289 continue; 293 continue;
290 filter_data(state, caps, &data[i], prop[i], slot); 294 filter_data(state, dev, &data[i], prop[i], slot);
291 push_slot_changes(state, &data[i], prop[i], slot, syn); 295 push_slot_changes(state, &data[i], prop[i], slot, syn);
292 SETBIT(used, slot); 296 SETBIT(used, slot);
293 id = MT_ID_NULL; 297 id = MT_ID_NULL;
@@ -304,8 +308,8 @@ static void apply_typeA_changes(struct mtdev_state *state,
304 /* clear unused slots and update slot usage */ 308 /* clear unused slots and update slot usage */
305 foreach_bit(slot, state->used & ~used) { 309 foreach_bit(slot, state->used & ~used) {
306 struct mtdev_slot tdata = state->data[slot]; 310 struct mtdev_slot tdata = state->data[slot];
307 bitmask_t tprop = BITMASK(MTDEV_TRACKING_ID); 311 bitmask_t tprop = BITMASK(mtdev_abs2mt(ABS_MT_TRACKING_ID));
308 tdata.abs[MTDEV_TRACKING_ID] = MT_ID_NULL; 312 tdata.tracking_id = MT_ID_NULL;
309 push_slot_changes(state, &tdata, tprop, slot, syn); 313 push_slot_changes(state, &tdata, tprop, slot, syn);
310 } 314 }
311 state->used = used; 315 state->used = used;
@@ -314,11 +318,11 @@ static void apply_typeA_changes(struct mtdev_state *state,
314/* 318/*
315 * convert_A_to_B - propagate a type A packet as a type B packet 319 * convert_A_to_B - propagate a type A packet as a type B packet
316 * @state: mtdev state 320 * @state: mtdev state
317 * @caps: device capabilities 321 * @dev: device capabilities
318 * @syn: reference to the SYN_REPORT event 322 * @syn: reference to the SYN_REPORT event
319 */ 323 */
320static void convert_A_to_B(struct mtdev_state *state, 324static void convert_A_to_B(struct mtdev_state *state,
321 const struct mtdev_caps *caps, 325 const struct mtdev *dev,
322 const struct input_event *syn) 326 const struct input_event *syn)
323{ 327{
324 struct mtdev_slot data[DIM_FINGER]; 328 struct mtdev_slot data[DIM_FINGER];
@@ -326,14 +330,19 @@ static void convert_A_to_B(struct mtdev_state *state,
326 int size = process_typeA(state, data, prop); 330 int size = process_typeA(state, data, prop);
327 if (size < 0) 331 if (size < 0)
328 return; 332 return;
329 if (!caps->has_abs[MTDEV_TRACKING_ID]) { 333 if (!mtdev_has_mt_event(dev, ABS_MT_TRACKING_ID)) {
330 bitmask_t touch = 0; 334 bitmask_t touch = 0;
331 int i; 335 int i;
332 for (i = 0; i < size; i++) 336 for (i = 0; i < size; i++)
333 MODBIT(touch, i, istouch(&data[i], caps)); 337 MODBIT(touch, i, istouch(&data[i], dev));
334 assign_tracking_id(state, caps, data, prop, size, touch); 338 assign_tracking_id(state, dev, data, prop, size, touch);
335 } 339 }
336 apply_typeA_changes(state, caps, data, prop, size, syn); 340 apply_typeA_changes(state, dev, data, prop, size, syn);
341}
342
343struct mtdev *mtdev_new(void)
344{
345 return calloc(1, sizeof(struct mtdev));
337} 346}
338 347
339int mtdev_init(struct mtdev *dev) 348int mtdev_init(struct mtdev *dev)
@@ -344,7 +353,7 @@ int mtdev_init(struct mtdev *dev)
344 if (!dev->state) 353 if (!dev->state)
345 return -ENOMEM; 354 return -ENOMEM;
346 for (i = 0; i < DIM_FINGER; i++) 355 for (i = 0; i < DIM_FINGER; i++)
347 dev->state->data[i].abs[MTDEV_TRACKING_ID] = MT_ID_NULL; 356 dev->state->data[i].tracking_id = MT_ID_NULL;
348 return 0; 357 return 0;
349} 358}
350 359
@@ -364,15 +373,29 @@ int mtdev_open(struct mtdev *dev, int fd)
364 return ret; 373 return ret;
365} 374}
366 375
376struct mtdev *mtdev_new_open(int fd)
377{
378 struct mtdev *dev;
379
380 dev = mtdev_new();
381 if (!dev)
382 return NULL;
383 if (!mtdev_open(dev, fd))
384 return dev;
385
386 mtdev_delete(dev);
387 return NULL;
388}
389
367void mtdev_put_event(struct mtdev *dev, const struct input_event *ev) 390void mtdev_put_event(struct mtdev *dev, const struct input_event *ev)
368{ 391{
369 struct mtdev_state *state = dev->state; 392 struct mtdev_state *state = dev->state;
370 if (ev->type == EV_SYN && ev->code == SYN_REPORT) { 393 if (ev->type == EV_SYN && ev->code == SYN_REPORT) {
371 bitmask_t head = state->outbuf.head; 394 bitmask_t head = state->outbuf.head;
372 if (dev->caps.has_slot) 395 if (mtdev_has_mt_event(dev, ABS_MT_SLOT))
373 process_typeB(state); 396 process_typeB(state);
374 else 397 else
375 convert_A_to_B(state, &dev->caps, ev); 398 convert_A_to_B(state, dev, ev);
376 if (state->outbuf.head != head) 399 if (state->outbuf.head != head)
377 evbuf_put(&state->outbuf, ev); 400 evbuf_put(&state->outbuf, ev);
378 } else { 401 } else {
@@ -380,8 +403,19 @@ void mtdev_put_event(struct mtdev *dev, const struct input_event *ev)
380 } 403 }
381} 404}
382 405
406void mtdev_close_delete(struct mtdev *dev)
407{
408 mtdev_close(dev);
409 mtdev_delete(dev);
410}
411
383void mtdev_close(struct mtdev *dev) 412void mtdev_close(struct mtdev *dev)
384{ 413{
385 free(dev->state); 414 free(dev->state);
386 memset(dev, 0, sizeof(struct mtdev)); 415 memset(dev, 0, sizeof(struct mtdev));
387} 416}
417
418void mtdev_delete(struct mtdev *dev)
419{
420 free(dev);
421}