aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/tablet
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/tablet')
-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 {