diff options
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 | } | ||
