diff options
Diffstat (limited to 'drivers/hid/hid-multitouch.c')
-rw-r--r-- | drivers/hid/hid-multitouch.c | 88 |
1 files changed, 23 insertions, 65 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 1df86a7536b8..eee19c9f7b36 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -56,7 +56,6 @@ struct mt_slot { | |||
56 | __s32 x, y, p, w, h; | 56 | __s32 x, y, p, w, h; |
57 | __s32 contactid; /* the device ContactID assigned to this slot */ | 57 | __s32 contactid; /* the device ContactID assigned to this slot */ |
58 | bool touch_state; /* is the touch valid? */ | 58 | bool touch_state; /* is the touch valid? */ |
59 | bool seen_in_this_frame;/* has this slot been updated */ | ||
60 | }; | 59 | }; |
61 | 60 | ||
62 | struct mt_class { | 61 | struct mt_class { |
@@ -94,7 +93,6 @@ struct mt_device { | |||
94 | * > 1 means hybrid (multitouch) protocol */ | 93 | * > 1 means hybrid (multitouch) protocol */ |
95 | bool serial_maybe; /* need to check for serial protocol */ | 94 | bool serial_maybe; /* need to check for serial protocol */ |
96 | bool curvalid; /* is the current contact valid? */ | 95 | bool curvalid; /* is the current contact valid? */ |
97 | struct mt_slot *slots; | ||
98 | unsigned mt_flags; /* flags to pass to input-mt */ | 96 | unsigned mt_flags; /* flags to pass to input-mt */ |
99 | }; | 97 | }; |
100 | 98 | ||
@@ -136,25 +134,6 @@ static int cypress_compute_slot(struct mt_device *td) | |||
136 | return -1; | 134 | return -1; |
137 | } | 135 | } |
138 | 136 | ||
139 | static int find_slot_from_contactid(struct mt_device *td) | ||
140 | { | ||
141 | int i; | ||
142 | for (i = 0; i < td->maxcontacts; ++i) { | ||
143 | if (td->slots[i].contactid == td->curdata.contactid && | ||
144 | td->slots[i].touch_state) | ||
145 | return i; | ||
146 | } | ||
147 | for (i = 0; i < td->maxcontacts; ++i) { | ||
148 | if (!td->slots[i].seen_in_this_frame && | ||
149 | !td->slots[i].touch_state) | ||
150 | return i; | ||
151 | } | ||
152 | /* should not occurs. If this happens that means | ||
153 | * that the device sent more touches that it says | ||
154 | * in the report descriptor. It is ignored then. */ | ||
155 | return -1; | ||
156 | } | ||
157 | |||
158 | static struct mt_class mt_classes[] = { | 137 | static struct mt_class mt_classes[] = { |
159 | { .name = MT_CLS_DEFAULT, | 138 | { .name = MT_CLS_DEFAULT, |
160 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, | 139 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, |
@@ -448,7 +427,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
448 | return -1; | 427 | return -1; |
449 | } | 428 | } |
450 | 429 | ||
451 | static int mt_compute_slot(struct mt_device *td) | 430 | static int mt_compute_slot(struct mt_device *td, struct input_dev *input) |
452 | { | 431 | { |
453 | __s32 quirks = td->mtclass.quirks; | 432 | __s32 quirks = td->mtclass.quirks; |
454 | 433 | ||
@@ -464,42 +443,23 @@ static int mt_compute_slot(struct mt_device *td) | |||
464 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE) | 443 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE) |
465 | return td->curdata.contactid - 1; | 444 | return td->curdata.contactid - 1; |
466 | 445 | ||
467 | return find_slot_from_contactid(td); | 446 | return input_mt_get_slot_by_key(input, td->curdata.contactid); |
468 | } | 447 | } |
469 | 448 | ||
470 | /* | 449 | /* |
471 | * this function is called when a whole contact has been processed, | 450 | * this function is called when a whole contact has been processed, |
472 | * so that it can assign it to a slot and store the data there | 451 | * so that it can assign it to a slot and store the data there |
473 | */ | 452 | */ |
474 | static void mt_complete_slot(struct mt_device *td) | 453 | static void mt_complete_slot(struct mt_device *td, struct input_dev *input) |
475 | { | 454 | { |
476 | td->curdata.seen_in_this_frame = true; | ||
477 | if (td->curvalid) { | 455 | if (td->curvalid) { |
478 | int slotnum = mt_compute_slot(td); | 456 | int slotnum = mt_compute_slot(td, input); |
479 | 457 | struct mt_slot *s = &td->curdata; | |
480 | if (slotnum >= 0 && slotnum < td->maxcontacts) | ||
481 | td->slots[slotnum] = td->curdata; | ||
482 | } | ||
483 | td->num_received++; | ||
484 | } | ||
485 | |||
486 | |||
487 | /* | ||
488 | * this function is called when a whole packet has been received and processed, | ||
489 | * so that it can decide what to send to the input layer. | ||
490 | */ | ||
491 | static void mt_emit_event(struct mt_device *td, struct input_dev *input) | ||
492 | { | ||
493 | int i; | ||
494 | 458 | ||
495 | for (i = 0; i < td->maxcontacts; ++i) { | 459 | if (slotnum < 0 || slotnum >= td->maxcontacts) |
496 | struct mt_slot *s = &(td->slots[i]); | 460 | return; |
497 | if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && | ||
498 | !s->seen_in_this_frame) { | ||
499 | s->touch_state = false; | ||
500 | } | ||
501 | 461 | ||
502 | input_mt_slot(input, i); | 462 | input_mt_slot(input, slotnum); |
503 | input_mt_report_slot_state(input, MT_TOOL_FINGER, | 463 | input_mt_report_slot_state(input, MT_TOOL_FINGER, |
504 | s->touch_state); | 464 | s->touch_state); |
505 | if (s->touch_state) { | 465 | if (s->touch_state) { |
@@ -516,24 +476,29 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input) | |||
516 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); | 476 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); |
517 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); | 477 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); |
518 | } | 478 | } |
519 | s->seen_in_this_frame = false; | ||
520 | |||
521 | } | 479 | } |
522 | 480 | ||
481 | td->num_received++; | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | * this function is called when a whole packet has been received and processed, | ||
486 | * so that it can decide what to send to the input layer. | ||
487 | */ | ||
488 | static void mt_sync_frame(struct mt_device *td, struct input_dev *input) | ||
489 | { | ||
523 | input_mt_sync_frame(input); | 490 | input_mt_sync_frame(input); |
524 | input_sync(input); | 491 | input_sync(input); |
525 | td->num_received = 0; | 492 | td->num_received = 0; |
526 | } | 493 | } |
527 | 494 | ||
528 | |||
529 | |||
530 | static int mt_event(struct hid_device *hid, struct hid_field *field, | 495 | static int mt_event(struct hid_device *hid, struct hid_field *field, |
531 | struct hid_usage *usage, __s32 value) | 496 | struct hid_usage *usage, __s32 value) |
532 | { | 497 | { |
533 | struct mt_device *td = hid_get_drvdata(hid); | 498 | struct mt_device *td = hid_get_drvdata(hid); |
534 | __s32 quirks = td->mtclass.quirks; | 499 | __s32 quirks = td->mtclass.quirks; |
535 | 500 | ||
536 | if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { | 501 | if (hid->claimed & HID_CLAIMED_INPUT) { |
537 | switch (usage->hid) { | 502 | switch (usage->hid) { |
538 | case HID_DG_INRANGE: | 503 | case HID_DG_INRANGE: |
539 | if (quirks & MT_QUIRK_ALWAYS_VALID) | 504 | if (quirks & MT_QUIRK_ALWAYS_VALID) |
@@ -586,11 +551,11 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, | |||
586 | } | 551 | } |
587 | 552 | ||
588 | if (usage->hid == td->last_slot_field) | 553 | if (usage->hid == td->last_slot_field) |
589 | mt_complete_slot(td); | 554 | mt_complete_slot(td, field->hidinput->input); |
590 | 555 | ||
591 | if (field->index == td->last_field_index | 556 | if (field->index == td->last_field_index |
592 | && td->num_received >= td->num_expected) | 557 | && td->num_received >= td->num_expected) |
593 | mt_emit_event(td, field->hidinput->input); | 558 | mt_sync_frame(td, field->hidinput->input); |
594 | 559 | ||
595 | } | 560 | } |
596 | 561 | ||
@@ -690,6 +655,9 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) | |||
690 | if (cls->is_indirect) | 655 | if (cls->is_indirect) |
691 | td->mt_flags |= INPUT_MT_POINTER; | 656 | td->mt_flags |= INPUT_MT_POINTER; |
692 | 657 | ||
658 | if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) | ||
659 | td->mt_flags |= INPUT_MT_DROP_UNUSED; | ||
660 | |||
693 | input_mt_init_slots(input, td->maxcontacts, td->mt_flags); | 661 | input_mt_init_slots(input, td->maxcontacts, td->mt_flags); |
694 | 662 | ||
695 | td->mt_flags = 0; | 663 | td->mt_flags = 0; |
@@ -743,15 +711,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
743 | if (ret) | 711 | if (ret) |
744 | goto fail; | 712 | goto fail; |
745 | 713 | ||
746 | td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), | ||
747 | GFP_KERNEL); | ||
748 | if (!td->slots) { | ||
749 | dev_err(&hdev->dev, "cannot allocate multitouch slots\n"); | ||
750 | hid_hw_stop(hdev); | ||
751 | ret = -ENOMEM; | ||
752 | goto fail; | ||
753 | } | ||
754 | |||
755 | ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); | 714 | ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); |
756 | 715 | ||
757 | mt_set_maxcontacts(hdev); | 716 | mt_set_maxcontacts(hdev); |
@@ -782,7 +741,6 @@ static void mt_remove(struct hid_device *hdev) | |||
782 | struct mt_device *td = hid_get_drvdata(hdev); | 741 | struct mt_device *td = hid_get_drvdata(hdev); |
783 | sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); | 742 | sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); |
784 | hid_hw_stop(hdev); | 743 | hid_hw_stop(hdev); |
785 | kfree(td->slots); | ||
786 | kfree(td); | 744 | kfree(td); |
787 | hid_set_drvdata(hdev, NULL); | 745 | hid_set_drvdata(hdev, NULL); |
788 | } | 746 | } |