aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/input/mouse/synaptics.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index aec9cf7124f8..30c85a5b7184 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -762,6 +762,10 @@ static void synaptics_image_sensor_1f(struct synaptics_data *priv,
synaptics_mt_state_set(mt_state, 1, -1, -1);
priv->mt_state_lost = true;
break;
+ case 4:
+ case 5:
+ /* mt_state was updated by AGM-CONTACT packet */
+ break;
}
}
@@ -816,6 +820,10 @@ static void synaptics_image_sensor_2f(struct synaptics_data *priv,
synaptics_mt_state_set(mt_state, 2, -1, -1);
priv->mt_state_lost = true;
break;
+ case 4:
+ case 5:
+ /* mt_state was updated by AGM-CONTACT packet */
+ break;
}
}
@@ -844,6 +852,22 @@ static void synaptics_image_sensor_3f(struct synaptics_data *priv,
break;
case 2:
/*
+ * If the AGM previously contained slot 3 or higher, then the
+ * newly touching finger is in the lowest available slot.
+ *
+ * If SGM was previously 1 or higher, then the new SGM is
+ * now slot 0 (with a new finger), otherwise, the new finger
+ * is now in a hidden slot between 0 and AGM's slot.
+ *
+ * In all such cases, the SGM now contains slot 0, and the AGM
+ * continues to contain the same slot as before.
+ */
+ if (old->agm >= 3) {
+ synaptics_mt_state_set(mt_state, 3, 0, old->agm);
+ break;
+ }
+
+ /*
* After some 3->1 and all 3->2 transitions, we lose track
* of which slot is reported by SGM and AGM.
*
@@ -883,9 +907,22 @@ static void synaptics_image_sensor_3f(struct synaptics_data *priv,
* received AGM-CONTACT packet.
*/
break;
+
+ case 4:
+ case 5:
+ /* mt_state was updated by AGM-CONTACT packet */
+ break;
}
}
+/* Handle case where mt_state->count = 4, or = 5 */
+static void synaptics_image_sensor_45f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ /* mt_state was updated correctly by AGM-CONTACT packet */
+ priv->mt_state_lost = false;
+}
+
static void synaptics_image_sensor_process(struct psmouse *psmouse,
struct synaptics_hw_state *sgm)
{
@@ -905,8 +942,10 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse,
synaptics_image_sensor_1f(priv, &mt_state);
else if (sgm->w == 0)
synaptics_image_sensor_2f(priv, &mt_state);
- else if (sgm->w == 1)
+ else if (sgm->w == 1 && mt_state.count <= 3)
synaptics_image_sensor_3f(priv, &mt_state);
+ else
+ synaptics_image_sensor_45f(priv, &mt_state);
/* Send resulting input events to user space */
synaptics_report_mt_data(psmouse, &mt_state, sgm);
@@ -1110,6 +1149,10 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
ABS_MT_POSITION_Y);
/* Image sensors can report per-contact pressure */
input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
+ /* Image sensors can signal 4 and 5 finger clicks */
+ __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+ __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
/* Non-image sensors with AGM use semi-mt */
__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);