aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/tablet/wacom_wac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/tablet/wacom_wac.c')
-rw-r--r--drivers/input/tablet/wacom_wac.c247
1 files changed, 90 insertions, 157 deletions
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 367fa82a607e..5597637cfd41 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -675,169 +675,87 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
675 return 1; 675 return 1;
676} 676}
677 677
678 678static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
679static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx)
680{ 679{
681 struct input_dev *input = wacom->input; 680 struct input_dev *input = wacom->input;
682 int finger = idx + 1; 681 unsigned char *data = wacom->data;
683 int x = le16_to_cpup((__le16 *)&data[finger * 2]) & 0x7fff; 682 int contact_with_no_pen_down_count = 0;
684 int y = le16_to_cpup((__le16 *)&data[4 + finger * 2]) & 0x7fff; 683 int i;
685 684
686 /* 685 for (i = 0; i < 2; i++) {
687 * Work around input core suppressing "duplicate" events since 686 int p = data[1] & (1 << i);
688 * we are abusing ABS_X/ABS_Y to transmit multi-finger data. 687 bool touch = p && !wacom->shared->stylus_in_proximity;
689 * This should go away once we switch to true multitouch 688
690 * protocol. 689 input_mt_slot(input, i);
691 */ 690 input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
692 if (wacom->last_finger != finger) { 691 if (touch) {
693 if (x == input_abs_get_val(input, ABS_X)) 692 int x = le16_to_cpup((__le16 *)&data[i * 2 + 2]) & 0x7fff;
694 x++; 693 int y = le16_to_cpup((__le16 *)&data[i * 2 + 6]) & 0x7fff;
695 694
696 if (y == input_abs_get_val(input, ABS_Y)) 695 input_report_abs(input, ABS_MT_POSITION_X, x);
697 y++; 696 input_report_abs(input, ABS_MT_POSITION_Y, y);
697 contact_with_no_pen_down_count++;
698 }
698 } 699 }
699 700
700 input_report_abs(input, ABS_X, x); 701 /* keep touch state for pen event */
701 input_report_abs(input, ABS_Y, y); 702 wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
702 input_report_abs(input, ABS_MISC, wacom->id[0]);
703 input_report_key(input, wacom->tool[finger], 1);
704 if (!idx)
705 input_report_key(input, BTN_TOUCH, 1);
706 input_event(input, EV_MSC, MSC_SERIAL, finger);
707 input_sync(input);
708 703
709 wacom->last_finger = finger; 704 input_mt_report_pointer_emulation(input, true);
710}
711 705
712static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) 706 return 1;
713{
714 struct input_dev *input = wacom->input;
715 int finger = idx + 1;
716
717 input_report_abs(input, ABS_X, 0);
718 input_report_abs(input, ABS_Y, 0);
719 input_report_abs(input, ABS_MISC, 0);
720 input_report_key(input, wacom->tool[finger], 0);
721 if (!idx)
722 input_report_key(input, BTN_TOUCH, 0);
723 input_event(input, EV_MSC, MSC_SERIAL, finger);
724 input_sync(input);
725} 707}
726 708
727static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) 709static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
728{ 710{
729 char *data = wacom->data; 711 char *data = wacom->data;
730 struct input_dev *input = wacom->input; 712 struct input_dev *input = wacom->input;
713 bool prox;
714 int x = 0, y = 0;
731 715
732 wacom->tool[1] = BTN_TOOL_DOUBLETAP; 716 if (!wacom->shared->stylus_in_proximity) {
733 wacom->id[0] = TOUCH_DEVICE_ID; 717 if (len == WACOM_PKGLEN_TPC1FG) {
734 wacom->tool[2] = BTN_TOOL_TRIPLETAP; 718 prox = data[0] & 0x01;
735 719 x = get_unaligned_le16(&data[1]);
736 if (len != WACOM_PKGLEN_TPC1FG) { 720 y = get_unaligned_le16(&data[3]);
737 721 } else { /* with capacity */
738 switch (data[0]) { 722 prox = data[1] & 0x01;
723 x = le16_to_cpup((__le16 *)&data[2]);
724 y = le16_to_cpup((__le16 *)&data[4]);
725 }
726 } else
727 /* force touch out when pen is in prox */
728 prox = 0;
739 729
740 case WACOM_REPORT_TPC1FG: 730 if (prox) {
741 input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); 731 input_report_abs(input, ABS_X, x);
742 input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); 732 input_report_abs(input, ABS_Y, y);
743 input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); 733 }
744 input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6])); 734 input_report_key(input, BTN_TOUCH, prox);
745 input_report_abs(input, ABS_MISC, wacom->id[0]);
746 input_report_key(input, wacom->tool[1], 1);
747 input_sync(input);
748 break;
749 735
750 case WACOM_REPORT_TPC2FG: 736 /* keep touch state for pen events */
751 if (data[1] & 0x01) 737 wacom->shared->touch_down = prox;
752 wacom_tpc_finger_in(wacom, data, 0);
753 else if (wacom->id[1] & 0x01)
754 wacom_tpc_touch_out(wacom, 0);
755 738
756 if (data[1] & 0x02) 739 return 1;
757 wacom_tpc_finger_in(wacom, data, 1);
758 else if (wacom->id[1] & 0x02)
759 wacom_tpc_touch_out(wacom, 1);
760 break;
761 }
762 } else {
763 input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
764 input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
765 input_report_key(input, BTN_TOUCH, 1);
766 input_report_abs(input, ABS_MISC, wacom->id[1]);
767 input_report_key(input, wacom->tool[1], 1);
768 input_sync(input);
769 }
770} 740}
771 741
772static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) 742static int wacom_tpc_pen(struct wacom_wac *wacom)
773{ 743{
774 struct wacom_features *features = &wacom->features; 744 struct wacom_features *features = &wacom->features;
775 char *data = wacom->data; 745 char *data = wacom->data;
776 struct input_dev *input = wacom->input; 746 struct input_dev *input = wacom->input;
777 int prox = 0, pressure; 747 int pressure;
778 int retval = 0; 748 bool prox = data[1] & 0x20;
779 749
780 dbg("wacom_tpc_irq: received report #%d", data[0]); 750 if (!wacom->shared->stylus_in_proximity) /* first in prox */
781 751 /* Going into proximity select tool */
782 if (len == WACOM_PKGLEN_TPC1FG || /* single touch */ 752 wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
783 data[0] == WACOM_REPORT_TPC1FG || /* single touch */
784 data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */
785
786 if (wacom->shared->stylus_in_proximity) {
787 if (wacom->id[1] & 0x01)
788 wacom_tpc_touch_out(wacom, 0);
789
790 if (wacom->id[1] & 0x02)
791 wacom_tpc_touch_out(wacom, 1);
792
793 wacom->id[1] = 0;
794 return 0;
795 }
796
797 if (len == WACOM_PKGLEN_TPC1FG) { /* with touch */
798 prox = data[0] & 0x01;
799 } else { /* with capacity */
800 if (data[0] == WACOM_REPORT_TPC1FG)
801 /* single touch */
802 prox = data[1] & 0x01;
803 else
804 /* 2FG touch data */
805 prox = data[1] & 0x03;
806 }
807
808 if (prox) {
809 if (!wacom->id[1])
810 wacom->last_finger = 1;
811 wacom_tpc_touch_in(wacom, len);
812 } else {
813 if (data[0] == WACOM_REPORT_TPC2FG) {
814 /* 2FGT out-prox */
815 if (wacom->id[1] & 0x01)
816 wacom_tpc_touch_out(wacom, 0);
817 753
818 if (wacom->id[1] & 0x02) 754 /* keep pen state for touch events */
819 wacom_tpc_touch_out(wacom, 1); 755 wacom->shared->stylus_in_proximity = prox;
820 } else
821 /* one finger touch */
822 wacom_tpc_touch_out(wacom, 0);
823 756
824 wacom->id[0] = 0; 757 /* send pen events only when touch is up or forced out */
825 } 758 if (!wacom->shared->touch_down) {
826 /* keep prox bit to send proper out-prox event */
827 wacom->id[1] = prox;
828 } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */
829 prox = data[1] & 0x20;
830
831 if (!wacom->shared->stylus_in_proximity) { /* first in prox */
832 /* Going into proximity select tool */
833 wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
834 if (wacom->tool[0] == BTN_TOOL_PEN)
835 wacom->id[0] = STYLUS_DEVICE_ID;
836 else
837 wacom->id[0] = ERASER_DEVICE_ID;
838
839 wacom->shared->stylus_in_proximity = true;
840 }
841 input_report_key(input, BTN_STYLUS, data[1] & 0x02); 759 input_report_key(input, BTN_STYLUS, data[1] & 0x02);
842 input_report_key(input, BTN_STYLUS2, data[1] & 0x10); 760 input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
843 input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); 761 input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
@@ -847,15 +765,27 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
847 pressure = features->pressure_max + pressure + 1; 765 pressure = features->pressure_max + pressure + 1;
848 input_report_abs(input, ABS_PRESSURE, pressure); 766 input_report_abs(input, ABS_PRESSURE, pressure);
849 input_report_key(input, BTN_TOUCH, data[1] & 0x05); 767 input_report_key(input, BTN_TOUCH, data[1] & 0x05);
850 if (!prox) { /* out-prox */
851 wacom->id[0] = 0;
852 wacom->shared->stylus_in_proximity = false;
853 }
854 input_report_key(input, wacom->tool[0], prox); 768 input_report_key(input, wacom->tool[0], prox);
855 input_report_abs(input, ABS_MISC, wacom->id[0]); 769 return 1;
856 retval = 1;
857 } 770 }
858 return retval; 771
772 return 0;
773}
774
775static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
776{
777 char *data = wacom->data;
778
779 dbg("wacom_tpc_irq: received report #%d", data[0]);
780
781 if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG)
782 return wacom_tpc_single_touch(wacom, len);
783 else if (data[0] == WACOM_REPORT_TPC2FG)
784 return wacom_tpc_mt_touch(wacom);
785 else if (data[0] == WACOM_REPORT_PENABLED)
786 return wacom_tpc_pen(wacom);
787
788 return 0;
859} 789}
860 790
861static int wacom_bpt_touch(struct wacom_wac *wacom) 791static int wacom_bpt_touch(struct wacom_wac *wacom)
@@ -1078,7 +1008,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
1078{ 1008{
1079 1009
1080 /* touch device found but size is not defined. use default */ 1010 /* touch device found but size is not defined. use default */
1081 if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) { 1011 if (features->device_type == BTN_TOOL_FINGER && !features->x_max) {
1082 features->x_max = 1023; 1012 features->x_max = 1023;
1083 features->y_max = 1023; 1013 features->y_max = 1023;
1084 } 1014 }
@@ -1090,7 +1020,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
1090 1020
1091 /* quirks for bamboo touch */ 1021 /* quirks for bamboo touch */
1092 if (features->type == BAMBOO_PT && 1022 if (features->type == BAMBOO_PT &&
1093 features->device_type == BTN_TOOL_TRIPLETAP) { 1023 features->device_type == BTN_TOOL_DOUBLETAP) {
1094 features->x_max <<= 5; 1024 features->x_max <<= 5;
1095 features->y_max <<= 5; 1025 features->y_max <<= 5;
1096 features->x_fuzz <<= 5; 1026 features->x_fuzz <<= 5;
@@ -1226,27 +1156,30 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
1226 break; 1156 break;
1227 1157
1228 case TABLETPC2FG: 1158 case TABLETPC2FG:
1229 if (features->device_type == BTN_TOOL_TRIPLETAP) { 1159 if (features->device_type == BTN_TOOL_DOUBLETAP) {
1230 __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); 1160
1231 input_set_capability(input_dev, EV_MSC, MSC_SERIAL); 1161 input_mt_init_slots(input_dev, 2);
1162 input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
1163 0, MT_TOOL_MAX, 0, 0);
1164 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
1165 0, features->x_max, 0, 0);
1166 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
1167 0, features->y_max, 0, 0);
1232 } 1168 }
1233 /* fall through */ 1169 /* fall through */
1234 1170
1235 case TABLETPC: 1171 case TABLETPC:
1236 if (features->device_type == BTN_TOOL_DOUBLETAP || 1172 __clear_bit(ABS_MISC, input_dev->absbit);
1237 features->device_type == BTN_TOOL_TRIPLETAP) { 1173
1174 if (features->device_type != BTN_TOOL_PEN) {
1238 input_abs_set_res(input_dev, ABS_X, 1175 input_abs_set_res(input_dev, ABS_X,
1239 wacom_calculate_touch_res(features->x_max, 1176 wacom_calculate_touch_res(features->x_max,
1240 features->x_phy)); 1177 features->x_phy));
1241 input_abs_set_res(input_dev, ABS_Y, 1178 input_abs_set_res(input_dev, ABS_Y,
1242 wacom_calculate_touch_res(features->y_max, 1179 wacom_calculate_touch_res(features->y_max,
1243 features->y_phy)); 1180 features->y_phy));
1244 __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
1245 }
1246
1247 if (features->device_type != BTN_TOOL_PEN)
1248 break; /* no need to process stylus stuff */ 1181 break; /* no need to process stylus stuff */
1249 1182 }
1250 /* fall through */ 1183 /* fall through */
1251 1184
1252 case PL: 1185 case PL:
@@ -1264,7 +1197,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
1264 case BAMBOO_PT: 1197 case BAMBOO_PT:
1265 __clear_bit(ABS_MISC, input_dev->absbit); 1198 __clear_bit(ABS_MISC, input_dev->absbit);
1266 1199
1267 if (features->device_type == BTN_TOOL_TRIPLETAP) { 1200 if (features->device_type == BTN_TOOL_DOUBLETAP) {
1268 __set_bit(BTN_LEFT, input_dev->keybit); 1201 __set_bit(BTN_LEFT, input_dev->keybit);
1269 __set_bit(BTN_FORWARD, input_dev->keybit); 1202 __set_bit(BTN_FORWARD, input_dev->keybit);
1270 __set_bit(BTN_BACK, input_dev->keybit); 1203 __set_bit(BTN_BACK, input_dev->keybit);