aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPing Cheng <pingc@wacom.com>2010-04-06 02:07:41 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-04-14 02:24:56 -0400
commitab687b18aa77aeda5472d9ea054bf92c45c49c0c (patch)
tree8d103b1aa4827a95d063f0b41b783fddf60eb3d3
parent252f77698fe37bdd784e514820852a3ea9827fd0 (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.c148
-rw-r--r--drivers/input/tablet/wacom_wac.h5
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)
616static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) 615static 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
632static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) 648static 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
646static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) 663static 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
791void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) 797void 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 {
80struct wacom_wac { 80struct 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;