diff options
author | Ping Cheng <pingc@wacom.com> | 2010-04-06 02:07:41 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-04-14 02:24:56 -0400 |
commit | ab687b18aa77aeda5472d9ea054bf92c45c49c0c (patch) | |
tree | 8d103b1aa4827a95d063f0b41b783fddf60eb3d3 | |
parent | 252f77698fe37bdd784e514820852a3ea9827fd0 (diff) |
Input: wacom - streamline 2-finger touch support
Clean up 2-finger touch support. This still needs to be converted to
proper multi-touch protocol.
Signed-off-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r-- | drivers/input/tablet/wacom_wac.c | 148 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_wac.h | 5 |
2 files changed, 80 insertions, 73 deletions
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 950a81d7a67c..847fd0135bcf 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -236,13 +236,12 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) | |||
236 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); | 236 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); |
237 | input_report_rel(input, REL_WHEEL, rw); | 237 | input_report_rel(input, REL_WHEEL, rw); |
238 | input_report_key(input, BTN_TOOL_FINGER, 0xf0); | 238 | input_report_key(input, BTN_TOOL_FINGER, 0xf0); |
239 | input_report_abs(input, ABS_MISC, wacom->id[1]); | ||
240 | if (!prox) | 239 | if (!prox) |
241 | wacom->id[1] = 0; | 240 | wacom->id[1] = 0; |
242 | input_report_abs(input, ABS_MISC, wacom->id[1]); | 241 | input_report_abs(input, ABS_MISC, wacom->id[1]); |
243 | input_event(input, EV_MSC, MSC_SERIAL, 0xf0); | 242 | input_event(input, EV_MSC, MSC_SERIAL, 0xf0); |
243 | retval = 1; | ||
244 | } | 244 | } |
245 | retval = 1; | ||
246 | break; | 245 | break; |
247 | 246 | ||
248 | case WACOM_MO: | 247 | case WACOM_MO: |
@@ -616,43 +615,59 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
616 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) | 615 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) |
617 | { | 616 | { |
618 | struct input_dev *input = wacom->input; | 617 | struct input_dev *input = wacom->input; |
618 | int finger = idx + 1; | ||
619 | int x = le16_to_cpup((__le16 *)&data[finger * 2]) & 0x7fff; | ||
620 | int y = le16_to_cpup((__le16 *)&data[4 + finger * 2]) & 0x7fff; | ||
621 | |||
622 | /* | ||
623 | * Work around input core suppressing "duplicate" events since | ||
624 | * we are abusing ABS_X/ABS_Y to transmit multi-finger data. | ||
625 | * This should go away once we switch to true multitouch | ||
626 | * protocol. | ||
627 | */ | ||
628 | if (wacom->last_finger != finger) { | ||
629 | if (x == input->abs[ABS_X]) | ||
630 | x++; | ||
631 | |||
632 | if (y == input->abs[ABS_Y]) | ||
633 | y++; | ||
634 | } | ||
619 | 635 | ||
620 | input_report_abs(input, ABS_X, | 636 | input_report_abs(input, ABS_X, x); |
621 | data[2 + idx * 2] | ((data[3 + idx * 2] & 0x7f) << 8)); | 637 | input_report_abs(input, ABS_Y, y); |
622 | input_report_abs(input, ABS_Y, | ||
623 | data[6 + idx * 2] | ((data[7 + idx * 2] & 0x7f) << 8)); | ||
624 | input_report_abs(input, ABS_MISC, wacom->id[0]); | 638 | input_report_abs(input, ABS_MISC, wacom->id[0]); |
625 | input_report_key(input, wacom->tool[idx], 1); | 639 | input_report_key(input, wacom->tool[finger], 1); |
626 | if (idx) | 640 | if (!idx) |
627 | input_event(input, EV_MSC, MSC_SERIAL, 0xf0); | ||
628 | else | ||
629 | input_report_key(input, BTN_TOUCH, 1); | 641 | input_report_key(input, BTN_TOUCH, 1); |
642 | input_event(input, EV_MSC, MSC_SERIAL, finger); | ||
643 | input_sync(wacom->input); | ||
644 | |||
645 | wacom->last_finger = finger; | ||
630 | } | 646 | } |
631 | 647 | ||
632 | static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) | 648 | static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) |
633 | { | 649 | { |
634 | struct input_dev *input = wacom->input; | 650 | struct input_dev *input = wacom->input; |
651 | int finger = idx + 1; | ||
635 | 652 | ||
636 | input_report_abs(input, ABS_X, 0); | 653 | input_report_abs(input, ABS_X, 0); |
637 | input_report_abs(input, ABS_Y, 0); | 654 | input_report_abs(input, ABS_Y, 0); |
638 | input_report_abs(input, ABS_MISC, 0); | 655 | input_report_abs(input, ABS_MISC, 0); |
639 | input_report_key(input, wacom->tool[idx], 0); | 656 | input_report_key(input, wacom->tool[finger], 0); |
640 | if (idx) | 657 | if (!idx) |
641 | input_event(input, EV_MSC, MSC_SERIAL, 0xf0); | ||
642 | else | ||
643 | input_report_key(input, BTN_TOUCH, 0); | 658 | input_report_key(input, BTN_TOUCH, 0); |
659 | input_event(input, EV_MSC, MSC_SERIAL, finger); | ||
660 | input_sync(input); | ||
644 | } | 661 | } |
645 | 662 | ||
646 | static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) | 663 | static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) |
647 | { | 664 | { |
648 | char *data = wacom->data; | 665 | char *data = wacom->data; |
649 | struct input_dev *input = wacom->input; | 666 | struct input_dev *input = wacom->input; |
650 | static int firstFinger = 0; | ||
651 | static int secondFinger = 0; | ||
652 | 667 | ||
653 | wacom->tool[0] = BTN_TOOL_DOUBLETAP; | 668 | wacom->tool[1] = BTN_TOOL_DOUBLETAP; |
654 | wacom->id[0] = TOUCH_DEVICE_ID; | 669 | wacom->id[0] = TOUCH_DEVICE_ID; |
655 | wacom->tool[1] = BTN_TOOL_TRIPLETAP; | 670 | wacom->tool[2] = BTN_TOOL_TRIPLETAP; |
656 | 671 | ||
657 | if (len != WACOM_PKGLEN_TPC1FG) { | 672 | if (len != WACOM_PKGLEN_TPC1FG) { |
658 | 673 | ||
@@ -664,45 +679,29 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) | |||
664 | input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); | 679 | input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); |
665 | input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6])); | 680 | input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6])); |
666 | input_report_abs(input, ABS_MISC, wacom->id[0]); | 681 | input_report_abs(input, ABS_MISC, wacom->id[0]); |
667 | input_report_key(input, wacom->tool[0], 1); | 682 | input_report_key(input, wacom->tool[1], 1); |
683 | input_sync(input); | ||
668 | break; | 684 | break; |
669 | 685 | ||
670 | case WACOM_REPORT_TPC2FG: | 686 | case WACOM_REPORT_TPC2FG: |
671 | /* keep this byte to send proper out-prox event */ | 687 | if (data[1] & 0x01) |
672 | wacom->id[1] = data[1] & 0x03; | ||
673 | |||
674 | if (data[1] & 0x01) { | ||
675 | wacom_tpc_finger_in(wacom, data, 0); | 688 | wacom_tpc_finger_in(wacom, data, 0); |
676 | firstFinger = 1; | 689 | else if (wacom->id[1] & 0x01) |
677 | } else if (firstFinger) { | ||
678 | wacom_tpc_touch_out(wacom, 0); | 690 | wacom_tpc_touch_out(wacom, 0); |
679 | } | ||
680 | |||
681 | if (data[1] & 0x02) { | ||
682 | /* sync first finger data */ | ||
683 | if (firstFinger) | ||
684 | input_sync(input); | ||
685 | 691 | ||
692 | if (data[1] & 0x02) | ||
686 | wacom_tpc_finger_in(wacom, data, 1); | 693 | wacom_tpc_finger_in(wacom, data, 1); |
687 | secondFinger = 1; | 694 | else if (wacom->id[1] & 0x02) |
688 | } else if (secondFinger) { | ||
689 | /* sync first finger data */ | ||
690 | if (firstFinger) | ||
691 | input_sync(input); | ||
692 | |||
693 | wacom_tpc_touch_out(wacom, 1); | 695 | wacom_tpc_touch_out(wacom, 1); |
694 | secondFinger = 0; | ||
695 | } | ||
696 | if (!(data[1] & 0x01)) | ||
697 | firstFinger = 0; | ||
698 | break; | 696 | break; |
699 | } | 697 | } |
700 | } else { | 698 | } else { |
701 | input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); | 699 | input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); |
702 | input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); | 700 | input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); |
703 | input_report_key(input, BTN_TOUCH, 1); | 701 | input_report_key(input, BTN_TOUCH, 1); |
704 | input_report_abs(input, ABS_MISC, wacom->id[0]); | 702 | input_report_abs(input, ABS_MISC, wacom->id[1]); |
705 | input_report_key(input, wacom->tool[0], 1); | 703 | input_report_key(input, wacom->tool[1], 1); |
704 | input_sync(input); | ||
706 | } | 705 | } |
707 | } | 706 | } |
708 | 707 | ||
@@ -711,13 +710,26 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
711 | struct wacom_features *features = &wacom->features; | 710 | struct wacom_features *features = &wacom->features; |
712 | char *data = wacom->data; | 711 | char *data = wacom->data; |
713 | struct input_dev *input = wacom->input; | 712 | struct input_dev *input = wacom->input; |
714 | int prox = 0, pressure, idx = -1; | 713 | int prox = 0, pressure; |
714 | int retval = 0; | ||
715 | 715 | ||
716 | dbg("wacom_tpc_irq: received report #%d", data[0]); | 716 | dbg("wacom_tpc_irq: received report #%d", data[0]); |
717 | 717 | ||
718 | if (len == WACOM_PKGLEN_TPC1FG || /* single touch */ | 718 | if (len == WACOM_PKGLEN_TPC1FG || /* single touch */ |
719 | data[0] == WACOM_REPORT_TPC1FG || /* single touch */ | 719 | data[0] == WACOM_REPORT_TPC1FG || /* single touch */ |
720 | data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ | 720 | data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ |
721 | |||
722 | if (wacom->shared->stylus_in_proximity) { | ||
723 | if (wacom->id[1] & 0x01) | ||
724 | wacom_tpc_touch_out(wacom, 0); | ||
725 | |||
726 | if (wacom->id[1] & 0x02) | ||
727 | wacom_tpc_touch_out(wacom, 1); | ||
728 | |||
729 | wacom->id[1] = 0; | ||
730 | return 0; | ||
731 | } | ||
732 | |||
721 | if (len == WACOM_PKGLEN_TPC1FG) { /* with touch */ | 733 | if (len == WACOM_PKGLEN_TPC1FG) { /* with touch */ |
722 | prox = data[0] & 0x01; | 734 | prox = data[0] & 0x01; |
723 | } else { /* with capacity */ | 735 | } else { /* with capacity */ |
@@ -729,36 +741,30 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
729 | prox = data[1] & 0x03; | 741 | prox = data[1] & 0x03; |
730 | } | 742 | } |
731 | 743 | ||
732 | if (!wacom->shared->stylus_in_proximity) { | 744 | if (prox) { |
733 | if (prox) { | 745 | if (!wacom->id[1]) |
734 | wacom_tpc_touch_in(wacom, len); | 746 | wacom->last_finger = 1; |
735 | } else { | 747 | wacom_tpc_touch_in(wacom, len); |
736 | if (data[0] == WACOM_REPORT_TPC2FG) { | 748 | } else { |
737 | /* 2FGT out-prox */ | 749 | if (data[0] == WACOM_REPORT_TPC2FG) { |
738 | idx = (wacom->id[1] & 0x01) - 1; | 750 | /* 2FGT out-prox */ |
739 | if (idx == 0) { | 751 | if (wacom->id[1] & 0x01) |
740 | wacom_tpc_touch_out(wacom, idx); | ||
741 | /* sync first finger event */ | ||
742 | if (wacom->id[1] & 0x02) | ||
743 | input_sync(input); | ||
744 | } | ||
745 | idx = (wacom->id[1] & 0x02) - 1; | ||
746 | if (idx == 1) | ||
747 | wacom_tpc_touch_out(wacom, idx); | ||
748 | } else { | ||
749 | /* one finger touch */ | ||
750 | wacom_tpc_touch_out(wacom, 0); | 752 | wacom_tpc_touch_out(wacom, 0); |
751 | } | 753 | |
752 | wacom->id[0] = 0; | 754 | if (wacom->id[1] & 0x02) |
753 | } | 755 | wacom_tpc_touch_out(wacom, 1); |
754 | } else if (wacom->id[0]) { /* force touch out-prox */ | 756 | } else |
755 | wacom_tpc_touch_out(wacom, 0); | 757 | /* one finger touch */ |
758 | wacom_tpc_touch_out(wacom, 0); | ||
759 | |||
760 | wacom->id[0] = 0; | ||
756 | } | 761 | } |
757 | return 1; | 762 | /* keep prox bit to send proper out-prox event */ |
763 | wacom->id[1] = prox; | ||
758 | } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ | 764 | } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ |
759 | prox = data[1] & 0x20; | 765 | prox = data[1] & 0x20; |
760 | 766 | ||
761 | if (!wacom->id[0]) { /* first in prox */ | 767 | if (!wacom->shared->stylus_in_proximity) { /* first in prox */ |
762 | /* Going into proximity select tool */ | 768 | /* Going into proximity select tool */ |
763 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 769 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
764 | if (wacom->tool[0] == BTN_TOOL_PEN) | 770 | if (wacom->tool[0] == BTN_TOOL_PEN) |
@@ -783,9 +789,9 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
783 | } | 789 | } |
784 | input_report_key(input, wacom->tool[0], prox); | 790 | input_report_key(input, wacom->tool[0], prox); |
785 | input_report_abs(input, ABS_MISC, wacom->id[0]); | 791 | input_report_abs(input, ABS_MISC, wacom->id[0]); |
786 | return 1; | 792 | retval = 1; |
787 | } | 793 | } |
788 | return 0; | 794 | return retval; |
789 | } | 795 | } |
790 | 796 | ||
791 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | 797 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 69098a2aa690..063f1af3204f 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
@@ -80,9 +80,10 @@ struct wacom_shared { | |||
80 | struct wacom_wac { | 80 | struct wacom_wac { |
81 | char name[64]; | 81 | char name[64]; |
82 | unsigned char *data; | 82 | unsigned char *data; |
83 | int tool[2]; | 83 | int tool[3]; |
84 | int id[2]; | 84 | int id[3]; |
85 | __u32 serial[2]; | 85 | __u32 serial[2]; |
86 | int last_finger; | ||
86 | struct wacom_features features; | 87 | struct wacom_features features; |
87 | struct wacom_shared *shared; | 88 | struct wacom_shared *shared; |
88 | struct input_dev *input; | 89 | struct input_dev *input; |