aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/synaptics.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2014-12-29 17:15:24 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-12-29 17:23:00 -0500
commite9e8520f229bd6881b51d03c010df6c0312bfef8 (patch)
tree445a07697dc7b6f486b04ee3e67cff1fdd70cca6 /drivers/input/mouse/synaptics.c
parentf361a2febfdad7c91de75a69ca1855f170485604 (diff)
Input: synaptics - use in-kernel tracking for reporting mt data
The current code tries to consider all states and transitions to properly detect which finger is attached to which slot. The code is quite huge and difficult to read. If the sensor manages to group the touch points but is not reliable in giving tracking ids, we can simply use the kernel tracking method. Note that it is already used by Cr-48 Chromebooks. Incidentaly, this fixes a bug reported by Peter Hutterer: """ on the Lenovo T440, run: evemu-record /dev/input/event4 | grep BTN_ then put one, two, three, two fingers down when you go from 3 to 2 fingers the driver sends a spurious BTN_TOUCH 0 event: E: 0.000000 0001 014a 0001 # EV_KEY / BTN_TOUCH 1 E: 0.000000 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1 E: 0.770008 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0 E: 0.770008 0001 014d 0001 # EV_KEY / BTN_TOOL_DOUBLETAP 1 E: 1.924716 0001 014d 0000 # EV_KEY / BTN_TOOL_DOUBLETAP 0 E: 1.924716 0001 014e 0001 # EV_KEY / BTN_TOOL_TRIPLETAP 1 .. changing from 3 to 2 fingers now E: 3.152641 0001 014a 0000 # EV_KEY / BTN_TOUCH 0 E: 3.152641 0001 014d 0001 # EV_KEY / BTN_TOOL_DOUBLETAP 1 E: 3.152641 0001 014e 0000 # EV_KEY / BTN_TOOL_TRIPLETAP 0 E: 3.176948 0001 014a 0001 # EV_KEY / BTN_TOUCH 1 quick look in the kernel shows it's caused by hw.z going to 0 for a packet, so probably a firmware bug. either way, it makes it hard to track BTN_TOUCH as signal that at least one finger is down. """ The in-kernel tracking is enough to remove this spurious BTN_TOUCH 0. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/mouse/synaptics.c')
-rw-r--r--drivers/input/mouse/synaptics.c397
1 files changed, 33 insertions, 364 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 9031a0a28ea4..fd89249751e3 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -569,14 +569,6 @@ static void synaptics_pt_create(struct psmouse *psmouse)
569 * Functions to interpret the absolute mode packets 569 * Functions to interpret the absolute mode packets
570 ****************************************************************************/ 570 ****************************************************************************/
571 571
572static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count,
573 int sgm, int agm)
574{
575 state->count = count;
576 state->sgm = sgm;
577 state->agm = agm;
578}
579
580static void synaptics_parse_agm(const unsigned char buf[], 572static void synaptics_parse_agm(const unsigned char buf[],
581 struct synaptics_data *priv, 573 struct synaptics_data *priv,
582 struct synaptics_hw_state *hw) 574 struct synaptics_hw_state *hw)
@@ -595,16 +587,13 @@ static void synaptics_parse_agm(const unsigned char buf[],
595 break; 587 break;
596 588
597 case 2: 589 case 2:
598 /* AGM-CONTACT packet: (count, sgm, agm) */ 590 /* AGM-CONTACT packet: we are only interested in the count */
599 synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]); 591 priv->agm_count = buf[1];
600 break; 592 break;
601 593
602 default: 594 default:
603 break; 595 break;
604 } 596 }
605
606 /* Record that at least one AGM has been received since last SGM */
607 priv->agm_pending = true;
608} 597}
609 598
610static bool is_forcepad; 599static bool is_forcepad;
@@ -798,388 +787,68 @@ static void synaptics_report_buttons(struct psmouse *psmouse,
798 input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i)); 787 input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i));
799} 788}
800 789
801static void synaptics_report_slot(struct input_dev *dev, int slot,
802 const struct synaptics_hw_state *hw)
803{
804 input_mt_slot(dev, slot);
805 input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL));
806 if (!hw)
807 return;
808
809 input_report_abs(dev, ABS_MT_POSITION_X, hw->x);
810 input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y));
811 input_report_abs(dev, ABS_MT_PRESSURE, hw->z);
812}
813
814static void synaptics_report_mt_data(struct psmouse *psmouse, 790static void synaptics_report_mt_data(struct psmouse *psmouse,
815 struct synaptics_mt_state *mt_state, 791 const struct synaptics_hw_state *sgm,
816 const struct synaptics_hw_state *sgm) 792 int num_fingers)
817{ 793{
818 struct input_dev *dev = psmouse->dev; 794 struct input_dev *dev = psmouse->dev;
819 struct synaptics_data *priv = psmouse->private; 795 struct synaptics_data *priv = psmouse->private;
820 struct synaptics_hw_state *agm = &priv->agm; 796 const struct synaptics_hw_state *hw[2] = { sgm, &priv->agm };
821 struct synaptics_mt_state *old = &priv->mt_state; 797 struct input_mt_pos pos[2];
798 int slot[2], nsemi, i;
822 799
823 switch (mt_state->count) { 800 nsemi = clamp_val(num_fingers, 0, 2);
824 case 0:
825 synaptics_report_slot(dev, 0, NULL);
826 synaptics_report_slot(dev, 1, NULL);
827 break;
828 case 1:
829 if (mt_state->sgm == -1) {
830 synaptics_report_slot(dev, 0, NULL);
831 synaptics_report_slot(dev, 1, NULL);
832 } else if (mt_state->sgm == 0) {
833 synaptics_report_slot(dev, 0, sgm);
834 synaptics_report_slot(dev, 1, NULL);
835 } else {
836 synaptics_report_slot(dev, 0, NULL);
837 synaptics_report_slot(dev, 1, sgm);
838 }
839 break;
840 default:
841 /*
842 * If the finger slot contained in SGM is valid, and either
843 * hasn't changed, or is new, or the old SGM has now moved to
844 * AGM, then report SGM in MTB slot 0.
845 * Otherwise, empty MTB slot 0.
846 */
847 if (mt_state->sgm != -1 &&
848 (mt_state->sgm == old->sgm ||
849 old->sgm == -1 || mt_state->agm == old->sgm))
850 synaptics_report_slot(dev, 0, sgm);
851 else
852 synaptics_report_slot(dev, 0, NULL);
853 801
854 /* 802 for (i = 0; i < nsemi; i++) {
855 * If the finger slot contained in AGM is valid, and either 803 pos[i].x = hw[i]->x;
856 * hasn't changed, or is new, then report AGM in MTB slot 1. 804 pos[i].y = synaptics_invert_y(hw[i]->y);
857 * Otherwise, empty MTB slot 1.
858 *
859 * However, in the case where the AGM is new, make sure that
860 * that it is either the same as the old SGM, or there was no
861 * SGM.
862 *
863 * Otherwise, if the SGM was just 1, and the new AGM is 2, then
864 * the new AGM will keep the old SGM's tracking ID, which can
865 * cause apparent drumroll. This happens if in the following
866 * valid finger sequence:
867 *
868 * Action SGM AGM (MTB slot:Contact)
869 * 1. Touch contact 0 (0:0)
870 * 2. Touch contact 1 (0:0, 1:1)
871 * 3. Lift contact 0 (1:1)
872 * 4. Touch contacts 2,3 (0:2, 1:3)
873 *
874 * In step 4, contact 3, in AGM must not be given the same
875 * tracking ID as contact 1 had in step 3. To avoid this,
876 * the first agm with contact 3 is dropped and slot 1 is
877 * invalidated (tracking ID = -1).
878 */
879 if (mt_state->agm != -1 &&
880 (mt_state->agm == old->agm ||
881 (old->agm == -1 &&
882 (old->sgm == -1 || mt_state->agm == old->sgm))))
883 synaptics_report_slot(dev, 1, agm);
884 else
885 synaptics_report_slot(dev, 1, NULL);
886 break;
887 } 805 }
888 806
807 input_mt_assign_slots(dev, slot, pos, nsemi);
808
809 for (i = 0; i < nsemi; i++) {
810 input_mt_slot(dev, slot[i]);
811 input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
812 input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x);
813 input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y);
814 input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z);
815 }
816
817 input_mt_drop_unused(dev);
818
889 /* Don't use active slot count to generate BTN_TOOL events. */ 819 /* Don't use active slot count to generate BTN_TOOL events. */
890 input_mt_report_pointer_emulation(dev, false); 820 input_mt_report_pointer_emulation(dev, false);
891 821
892 /* Send the number of fingers reported by touchpad itself. */ 822 /* Send the number of fingers reported by touchpad itself. */
893 input_mt_report_finger_count(dev, mt_state->count); 823 input_mt_report_finger_count(dev, num_fingers);
894 824
895 synaptics_report_buttons(psmouse, sgm); 825 synaptics_report_buttons(psmouse, sgm);
896 826
897 input_sync(dev); 827 input_sync(dev);
898} 828}
899 829
900/* Handle case where mt_state->count = 0 */
901static void synaptics_image_sensor_0f(struct synaptics_data *priv,
902 struct synaptics_mt_state *mt_state)
903{
904 synaptics_mt_state_set(mt_state, 0, -1, -1);
905 priv->mt_state_lost = false;
906}
907
908/* Handle case where mt_state->count = 1 */
909static void synaptics_image_sensor_1f(struct synaptics_data *priv,
910 struct synaptics_mt_state *mt_state)
911{
912 struct synaptics_hw_state *agm = &priv->agm;
913 struct synaptics_mt_state *old = &priv->mt_state;
914
915 /*
916 * If the last AGM was (0,0,0), and there is only one finger left,
917 * then we absolutely know that SGM contains slot 0, and all other
918 * fingers have been removed.
919 */
920 if (priv->agm_pending && agm->z == 0) {
921 synaptics_mt_state_set(mt_state, 1, 0, -1);
922 priv->mt_state_lost = false;
923 return;
924 }
925
926 switch (old->count) {
927 case 0:
928 synaptics_mt_state_set(mt_state, 1, 0, -1);
929 break;
930 case 1:
931 /*
932 * If mt_state_lost, then the previous transition was 3->1,
933 * and SGM now contains either slot 0 or 1, but we don't know
934 * which. So, we just assume that the SGM now contains slot 1.
935 *
936 * If pending AGM and either:
937 * (a) the previous SGM slot contains slot 0, or
938 * (b) there was no SGM slot
939 * then, the SGM now contains slot 1
940 *
941 * Case (a) happens with very rapid "drum roll" gestures, where
942 * slot 0 finger is lifted and a new slot 1 finger touches
943 * within one reporting interval.
944 *
945 * Case (b) happens if initially two or more fingers tap
946 * briefly, and all but one lift before the end of the first
947 * reporting interval.
948 *
949 * (In both these cases, slot 0 will becomes empty, so SGM
950 * contains slot 1 with the new finger)
951 *
952 * Else, if there was no previous SGM, it now contains slot 0.
953 *
954 * Otherwise, SGM still contains the same slot.
955 */
956 if (priv->mt_state_lost ||
957 (priv->agm_pending && old->sgm <= 0))
958 synaptics_mt_state_set(mt_state, 1, 1, -1);
959 else if (old->sgm == -1)
960 synaptics_mt_state_set(mt_state, 1, 0, -1);
961 break;
962 case 2:
963 /*
964 * If mt_state_lost, we don't know which finger SGM contains.
965 *
966 * So, report 1 finger, but with both slots empty.
967 * We will use slot 1 on subsequent 1->1
968 */
969 if (priv->mt_state_lost) {
970 synaptics_mt_state_set(mt_state, 1, -1, -1);
971 break;
972 }
973 /*
974 * Since the last AGM was NOT (0,0,0), it was the finger in
975 * slot 0 that has been removed.
976 * So, SGM now contains previous AGM's slot, and AGM is now
977 * empty.
978 */
979 synaptics_mt_state_set(mt_state, 1, old->agm, -1);
980 break;
981 case 3:
982 /*
983 * Since last AGM was not (0,0,0), we don't know which finger
984 * is left.
985 *
986 * So, report 1 finger, but with both slots empty.
987 * We will use slot 1 on subsequent 1->1
988 */
989 synaptics_mt_state_set(mt_state, 1, -1, -1);
990 priv->mt_state_lost = true;
991 break;
992 case 4:
993 case 5:
994 /* mt_state was updated by AGM-CONTACT packet */
995 break;
996 }
997}
998
999/* Handle case where mt_state->count = 2 */
1000static void synaptics_image_sensor_2f(struct synaptics_data *priv,
1001 struct synaptics_mt_state *mt_state)
1002{
1003 struct synaptics_mt_state *old = &priv->mt_state;
1004
1005 switch (old->count) {
1006 case 0:
1007 synaptics_mt_state_set(mt_state, 2, 0, 1);
1008 break;
1009 case 1:
1010 /*
1011 * If previous SGM contained slot 1 or higher, SGM now contains
1012 * slot 0 (the newly touching finger) and AGM contains SGM's
1013 * previous slot.
1014 *
1015 * Otherwise, SGM still contains slot 0 and AGM now contains
1016 * slot 1.
1017 */
1018 if (old->sgm >= 1)
1019 synaptics_mt_state_set(mt_state, 2, 0, old->sgm);
1020 else
1021 synaptics_mt_state_set(mt_state, 2, 0, 1);
1022 break;
1023 case 2:
1024 /*
1025 * If mt_state_lost, SGM now contains either finger 1 or 2, but
1026 * we don't know which.
1027 * So, we just assume that the SGM contains slot 0 and AGM 1.
1028 */
1029 if (priv->mt_state_lost)
1030 synaptics_mt_state_set(mt_state, 2, 0, 1);
1031 /*
1032 * Otherwise, use the same mt_state, since it either hasn't
1033 * changed, or was updated by a recently received AGM-CONTACT
1034 * packet.
1035 */
1036 break;
1037 case 3:
1038 /*
1039 * 3->2 transitions have two unsolvable problems:
1040 * 1) no indication is given which finger was removed
1041 * 2) no way to tell if agm packet was for finger 3
1042 * before 3->2, or finger 2 after 3->2.
1043 *
1044 * So, report 2 fingers, but empty all slots.
1045 * We will guess slots [0,1] on subsequent 2->2.
1046 */
1047 synaptics_mt_state_set(mt_state, 2, -1, -1);
1048 priv->mt_state_lost = true;
1049 break;
1050 case 4:
1051 case 5:
1052 /* mt_state was updated by AGM-CONTACT packet */
1053 break;
1054 }
1055}
1056
1057/* Handle case where mt_state->count = 3 */
1058static void synaptics_image_sensor_3f(struct synaptics_data *priv,
1059 struct synaptics_mt_state *mt_state)
1060{
1061 struct synaptics_mt_state *old = &priv->mt_state;
1062
1063 switch (old->count) {
1064 case 0:
1065 synaptics_mt_state_set(mt_state, 3, 0, 2);
1066 break;
1067 case 1:
1068 /*
1069 * If previous SGM contained slot 2 or higher, SGM now contains
1070 * slot 0 (one of the newly touching fingers) and AGM contains
1071 * SGM's previous slot.
1072 *
1073 * Otherwise, SGM now contains slot 0 and AGM contains slot 2.
1074 */
1075 if (old->sgm >= 2)
1076 synaptics_mt_state_set(mt_state, 3, 0, old->sgm);
1077 else
1078 synaptics_mt_state_set(mt_state, 3, 0, 2);
1079 break;
1080 case 2:
1081 /*
1082 * If the AGM previously contained slot 3 or higher, then the
1083 * newly touching finger is in the lowest available slot.
1084 *
1085 * If SGM was previously 1 or higher, then the new SGM is
1086 * now slot 0 (with a new finger), otherwise, the new finger
1087 * is now in a hidden slot between 0 and AGM's slot.
1088 *
1089 * In all such cases, the SGM now contains slot 0, and the AGM
1090 * continues to contain the same slot as before.
1091 */
1092 if (old->agm >= 3) {
1093 synaptics_mt_state_set(mt_state, 3, 0, old->agm);
1094 break;
1095 }
1096
1097 /*
1098 * After some 3->1 and all 3->2 transitions, we lose track
1099 * of which slot is reported by SGM and AGM.
1100 *
1101 * For 2->3 in this state, report 3 fingers, but empty all
1102 * slots, and we will guess (0,2) on a subsequent 0->3.
1103 *
1104 * To userspace, the resulting transition will look like:
1105 * 2:[0,1] -> 3:[-1,-1] -> 3:[0,2]
1106 */
1107 if (priv->mt_state_lost) {
1108 synaptics_mt_state_set(mt_state, 3, -1, -1);
1109 break;
1110 }
1111
1112 /*
1113 * If the (SGM,AGM) really previously contained slots (0, 1),
1114 * then we cannot know what slot was just reported by the AGM,
1115 * because the 2->3 transition can occur either before or after
1116 * the AGM packet. Thus, this most recent AGM could contain
1117 * either the same old slot 1 or the new slot 2.
1118 * Subsequent AGMs will be reporting slot 2.
1119 *
1120 * To userspace, the resulting transition will look like:
1121 * 2:[0,1] -> 3:[0,-1] -> 3:[0,2]
1122 */
1123 synaptics_mt_state_set(mt_state, 3, 0, -1);
1124 break;
1125 case 3:
1126 /*
1127 * If, for whatever reason, the previous agm was invalid,
1128 * Assume SGM now contains slot 0, AGM now contains slot 2.
1129 */
1130 if (old->agm <= 2)
1131 synaptics_mt_state_set(mt_state, 3, 0, 2);
1132 /*
1133 * mt_state either hasn't changed, or was updated by a recently
1134 * received AGM-CONTACT packet.
1135 */
1136 break;
1137
1138 case 4:
1139 case 5:
1140 /* mt_state was updated by AGM-CONTACT packet */
1141 break;
1142 }
1143}
1144
1145/* Handle case where mt_state->count = 4, or = 5 */
1146static void synaptics_image_sensor_45f(struct synaptics_data *priv,
1147 struct synaptics_mt_state *mt_state)
1148{
1149 /* mt_state was updated correctly by AGM-CONTACT packet */
1150 priv->mt_state_lost = false;
1151}
1152
1153static void synaptics_image_sensor_process(struct psmouse *psmouse, 830static void synaptics_image_sensor_process(struct psmouse *psmouse,
1154 struct synaptics_hw_state *sgm) 831 struct synaptics_hw_state *sgm)
1155{ 832{
1156 struct synaptics_data *priv = psmouse->private; 833 struct synaptics_data *priv = psmouse->private;
1157 struct synaptics_hw_state *agm = &priv->agm; 834 int num_fingers;
1158 struct synaptics_mt_state mt_state;
1159
1160 /* Initialize using current mt_state (as updated by last agm) */
1161 mt_state = agm->mt_state;
1162 835
1163 /* 836 /*
1164 * Update mt_state using the new finger count and current mt_state. 837 * Update mt_state using the new finger count and current mt_state.
1165 */ 838 */
1166 if (sgm->z == 0) 839 if (sgm->z == 0)
1167 synaptics_image_sensor_0f(priv, &mt_state); 840 num_fingers = 0;
1168 else if (sgm->w >= 4) 841 else if (sgm->w >= 4)
1169 synaptics_image_sensor_1f(priv, &mt_state); 842 num_fingers = 1;
1170 else if (sgm->w == 0) 843 else if (sgm->w == 0)
1171 synaptics_image_sensor_2f(priv, &mt_state); 844 num_fingers = 2;
1172 else if (sgm->w == 1 && mt_state.count <= 3) 845 else if (sgm->w == 1)
1173 synaptics_image_sensor_3f(priv, &mt_state); 846 num_fingers = priv->agm_count ? priv->agm_count : 3;
1174 else 847 else
1175 synaptics_image_sensor_45f(priv, &mt_state); 848 num_fingers = 4;
1176 849
1177 /* Send resulting input events to user space */ 850 /* Send resulting input events to user space */
1178 synaptics_report_mt_data(psmouse, &mt_state, sgm); 851 synaptics_report_mt_data(psmouse, sgm, num_fingers);
1179
1180 /* Store updated mt_state */
1181 priv->mt_state = agm->mt_state = mt_state;
1182 priv->agm_pending = false;
1183} 852}
1184 853
1185static void synaptics_profile_sensor_process(struct psmouse *psmouse, 854static void synaptics_profile_sensor_process(struct psmouse *psmouse,
@@ -1439,7 +1108,7 @@ static void set_input_params(struct psmouse *psmouse,
1439 ABS_MT_POSITION_Y); 1108 ABS_MT_POSITION_Y);
1440 /* Image sensors can report per-contact pressure */ 1109 /* Image sensors can report per-contact pressure */
1441 input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); 1110 input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
1442 input_mt_init_slots(dev, 2, INPUT_MT_POINTER); 1111 input_mt_init_slots(dev, 2, INPUT_MT_POINTER | INPUT_MT_TRACK);
1443 1112
1444 /* Image sensors can signal 4 and 5 finger clicks */ 1113 /* Image sensors can signal 4 and 5 finger clicks */
1445 __set_bit(BTN_TOOL_QUADTAP, dev->keybit); 1114 __set_bit(BTN_TOOL_QUADTAP, dev->keybit);