aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPing Cheng <pinglinux@gmail.com>2011-03-12 23:34:42 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-03-12 23:37:20 -0500
commita43c7c53835ba1ff4e488806d0f8b98e9dce9b0e (patch)
tree1a0d4d39432636d2dabe861e88c5cf0103d0f78a
parent8aa9a9ac89baa0e423da0211e0883d28165697e0 (diff)
Input: wacom - support one finger touch the touchscreen way
There are two types of 1FGT devices supported in wacom_wac.c. Changing them to follow the existing touchscreen format, i.e., only report BTN_TOUCH as a valid tool type. Touch data will be ignored if pen is in proximity. This requires a touch up event sent if touch was down when pen comes in. The touch up event should be sent before any pen events are emitted. Otherwise, two pointers would race for the cursor. However, we can not send a touch up inside wacom_tpc_pen since pen and touch are on different logical port. That is why we have to check if touch is up before sending pen events. Reviewed-by: Henrik Rydberg <rydberg@euromail.se> Reviewed-by: Chris Bagwell <chris@cnpbagwell.com> Signed-off-by: Ping Cheng <pingc@wacom.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/input/tablet/wacom_wac.c139
-rw-r--r--drivers/input/tablet/wacom_wac.h1
2 files changed, 50 insertions, 90 deletions
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 15bab99a4c7e..adf8946e8f0d 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -675,51 +675,37 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
675 return 1; 675 return 1;
676} 676}
677 677
678static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) 678static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
679{
680 struct input_dev *input = wacom->input;
681 int finger = idx + 1;
682
683 input_report_abs(input, ABS_X, 0);
684 input_report_abs(input, ABS_Y, 0);
685 input_report_abs(input, ABS_MISC, 0);
686 input_report_key(input, wacom->tool[finger], 0);
687 if (!idx)
688 input_report_key(input, BTN_TOUCH, 0);
689 input_event(input, EV_MSC, MSC_SERIAL, finger);
690 input_sync(input);
691}
692
693static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len)
694{ 679{
695 char *data = wacom->data; 680 char *data = wacom->data;
696 struct input_dev *input = wacom->input; 681 struct input_dev *input = wacom->input;
682 bool prox;
683 int x = 0, y = 0;
697 684
698 wacom->tool[1] = BTN_TOOL_DOUBLETAP; 685 if (!wacom->shared->stylus_in_proximity) {
699 wacom->id[0] = TOUCH_DEVICE_ID; 686 if (len == WACOM_PKGLEN_TPC1FG) {
687 prox = data[0] & 0x01;
688 x = get_unaligned_le16(&data[1]);
689 y = get_unaligned_le16(&data[3]);
690 } else { /* with capacity */
691 prox = data[1] & 0x01;
692 x = le16_to_cpup((__le16 *)&data[2]);
693 y = le16_to_cpup((__le16 *)&data[4]);
694 }
695 } else
696 /* force touch out when pen is in prox */
697 prox = 0;
700 698
701 if (len != WACOM_PKGLEN_TPC1FG) { 699 if (prox) {
700 input_report_abs(input, ABS_X, x);
701 input_report_abs(input, ABS_Y, y);
702 }
703 input_report_key(input, BTN_TOUCH, prox);
702 704
703 switch (data[0]) { 705 /* keep touch state for pen events */
706 wacom->shared->touch_down = prox;
704 707
705 case WACOM_REPORT_TPC1FG: 708 return 1;
706 input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
707 input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
708 input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6]));
709 input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6]));
710 input_report_abs(input, ABS_MISC, wacom->id[0]);
711 input_report_key(input, wacom->tool[1], 1);
712 input_sync(input);
713 break;
714 }
715 } else {
716 input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
717 input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
718 input_report_key(input, BTN_TOUCH, 1);
719 input_report_abs(input, ABS_MISC, wacom->id[1]);
720 input_report_key(input, wacom->tool[1], 1);
721 input_sync(input);
722 }
723} 709}
724 710
725static int wacom_tpc_pen(struct wacom_wac *wacom) 711static int wacom_tpc_pen(struct wacom_wac *wacom)
@@ -727,71 +713,43 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
727 struct wacom_features *features = &wacom->features; 713 struct wacom_features *features = &wacom->features;
728 char *data = wacom->data; 714 char *data = wacom->data;
729 struct input_dev *input = wacom->input; 715 struct input_dev *input = wacom->input;
730 int prox, pressure; 716 int pressure;
731 717 bool prox = data[1] & 0x20;
732 prox = data[1] & 0x20;
733 718
734 if (!wacom->shared->stylus_in_proximity) { /* first in prox */ 719 if (!wacom->shared->stylus_in_proximity) /* first in prox */
735 /* Going into proximity select tool */ 720 /* Going into proximity select tool */
736 wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; 721 wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
737 if (wacom->tool[0] == BTN_TOOL_PEN)
738 wacom->id[0] = STYLUS_DEVICE_ID;
739 else
740 wacom->id[0] = ERASER_DEVICE_ID;
741 722
742 wacom->shared->stylus_in_proximity = true; 723 /* keep pen state for touch events */
743 } 724 wacom->shared->stylus_in_proximity = prox;
744 input_report_key(input, BTN_STYLUS, data[1] & 0x02); 725
745 input_report_key(input, BTN_STYLUS2, data[1] & 0x10); 726 /* send pen events only when touch is up or forced out */
746 input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); 727 if (!wacom->shared->touch_down) {
747 input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); 728 input_report_key(input, BTN_STYLUS, data[1] & 0x02);
748 pressure = ((data[7] & 0x01) << 8) | data[6]; 729 input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
749 if (pressure < 0) 730 input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
750 pressure = features->pressure_max + pressure + 1; 731 input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
751 input_report_abs(input, ABS_PRESSURE, pressure); 732 pressure = ((data[7] & 0x01) << 8) | data[6];
752 input_report_key(input, BTN_TOUCH, data[1] & 0x05); 733 if (pressure < 0)
753 if (!prox) { /* out-prox */ 734 pressure = features->pressure_max + pressure + 1;
754 wacom->id[0] = 0; 735 input_report_abs(input, ABS_PRESSURE, pressure);
755 wacom->shared->stylus_in_proximity = false; 736 input_report_key(input, BTN_TOUCH, data[1] & 0x05);
737 input_report_key(input, wacom->tool[0], prox);
738 return 1;
756 } 739 }
757 input_report_key(input, wacom->tool[0], prox);
758 740
759 return 1; 741 return 0;
760} 742}
761 743
762static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) 744static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
763{ 745{
764 char *data = wacom->data; 746 char *data = wacom->data;
765 int prox = 0;
766 747
767 dbg("wacom_tpc_irq: received report #%d", data[0]); 748 dbg("wacom_tpc_irq: received report #%d", data[0]);
768 749
769 if (len == WACOM_PKGLEN_TPC1FG || 750 if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG)
770 data[0] == WACOM_REPORT_TPC1FG) { /* single touch */ 751 return wacom_tpc_single_touch(wacom, len);
771 752 else if (data[0] == WACOM_REPORT_PENABLED)
772 if (wacom->shared->stylus_in_proximity) {
773 if (wacom->id[1] & 0x01)
774 wacom_tpc_touch_out(wacom, 0);
775
776 wacom->id[1] = 0;
777 return 0;
778 }
779
780 if (len == WACOM_PKGLEN_TPC1FG)
781 prox = data[0] & 0x01;
782 else /* with capacity */
783 prox = data[1] & 0x01;
784
785 if (prox)
786 wacom_tpc_touch_in(wacom, len);
787 else {
788 wacom_tpc_touch_out(wacom, 0);
789
790 wacom->id[0] = 0;
791 }
792 /* keep prox bit to send proper out-prox event */
793 wacom->id[1] = prox;
794 } else if (data[0] == WACOM_REPORT_PENABLED)
795 return wacom_tpc_pen(wacom); 753 return wacom_tpc_pen(wacom);
796 754
797 return 0; 755 return 0;
@@ -1172,6 +1130,8 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
1172 /* fall through */ 1130 /* fall through */
1173 1131
1174 case TABLETPC: 1132 case TABLETPC:
1133 __clear_bit(ABS_MISC, input_dev->absbit);
1134
1175 if (features->device_type == BTN_TOOL_DOUBLETAP || 1135 if (features->device_type == BTN_TOOL_DOUBLETAP ||
1176 features->device_type == BTN_TOOL_TRIPLETAP) { 1136 features->device_type == BTN_TOOL_TRIPLETAP) {
1177 input_abs_set_res(input_dev, ABS_X, 1137 input_abs_set_res(input_dev, ABS_X,
@@ -1180,7 +1140,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
1180 input_abs_set_res(input_dev, ABS_Y, 1140 input_abs_set_res(input_dev, ABS_Y,
1181 wacom_calculate_touch_res(features->y_max, 1141 wacom_calculate_touch_res(features->y_max,
1182 features->y_phy)); 1142 features->y_phy));
1183 __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
1184 } 1143 }
1185 1144
1186 if (features->device_type != BTN_TOOL_PEN) 1145 if (features->device_type != BTN_TOOL_PEN)
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 8f747dd1214e..835f756b150c 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -88,6 +88,7 @@ struct wacom_features {
88 88
89struct wacom_shared { 89struct wacom_shared {
90 bool stylus_in_proximity; 90 bool stylus_in_proximity;
91 bool touch_down;
91}; 92};
92 93
93struct wacom_wac { 94struct wacom_wac {