diff options
| author | Henrik Rydberg <rydberg@euromail.se> | 2010-12-22 18:29:00 +0100 |
|---|---|---|
| committer | Henrik Rydberg <rydberg@euromail.se> | 2010-12-22 18:29:00 +0100 |
| commit | 56a77e68fb91eef928d8a95c50ae14508e37ae0f (patch) | |
| tree | 51af9bb9dd508bca58e8b9416479e79f8bb7ee10 /src/core.c | |
| parent | 0e2ab3b5940e70493aaabdfe5e8da1c75db4db72 (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.c | 126 |
1 files changed, 80 insertions, 46 deletions
| @@ -32,10 +32,16 @@ | |||
| 32 | #include "match.h" | 32 | #include "match.h" |
| 33 | 33 | ||
| 34 | static inline int istouch(const struct mtdev_slot *data, | 34 | static 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 | |||
| 41 | static 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 | */ |
| 72 | static void solve(struct mtdev_state *state, const struct mtdev_caps *caps, | 78 | static 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 | */ |
| 109 | static void assign_tracking_id(struct mtdev_state *state, | 115 | static 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 | */ |
| 218 | static void filter_data(const struct mtdev_state *state, | 221 | static 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 | */ |
| 277 | static void apply_typeA_changes(struct mtdev_state *state, | 281 | static 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 | */ |
| 320 | static void convert_A_to_B(struct mtdev_state *state, | 324 | static 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 | |||
| 343 | struct mtdev *mtdev_new(void) | ||
| 344 | { | ||
| 345 | return calloc(1, sizeof(struct mtdev)); | ||
| 337 | } | 346 | } |
| 338 | 347 | ||
| 339 | int mtdev_init(struct mtdev *dev) | 348 | int 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 | ||
| 376 | struct 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 | |||
| 367 | void mtdev_put_event(struct mtdev *dev, const struct input_event *ev) | 390 | void 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 | ||
| 406 | void mtdev_close_delete(struct mtdev *dev) | ||
| 407 | { | ||
| 408 | mtdev_close(dev); | ||
| 409 | mtdev_delete(dev); | ||
| 410 | } | ||
| 411 | |||
| 383 | void mtdev_close(struct mtdev *dev) | 412 | void 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 | |||
| 418 | void mtdev_delete(struct mtdev *dev) | ||
| 419 | { | ||
| 420 | free(dev); | ||
| 421 | } | ||
