aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/mouse/synaptics.c
diff options
context:
space:
mode:
authorDaniel Kurtz <djkurtz@chromium.org>2011-08-23 23:02:31 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-08-23 23:08:16 -0700
commita6ca40c11eb5d98e53176adf527e430f7037a8c9 (patch)
tree74d08548873d3b6a9d58c8f0728025881d818b58 /drivers/input/mouse/synaptics.c
parent3cdfee9ea7e98eb6e8c3d4d66f2dfcfffe6afc4d (diff)
Input: synaptics - decode AGM packet types
A Synaptics image sensor tracks 5 fingers, but can only report 2. The algorithm for choosing which 2 fingers to report and in which packet: Touchpad maintains 5 slots, numbered 0 to 4 Initially all slots are empty As new fingers are detected, assign them to the lowest available slots The touchpad always reports: SGM: lowest numbered non-empty slot AGM: highest numbered non-empty slot, if there is one In addition, these touchpads have a special AGM packet type which reports the number of fingers currently being tracked, and which finger is in each of the two slots. Unfortunately, these "TYPE=2" packets are only used when more than 3 fingers are being tracked. When less than 4 fingers are present, the 'w' value must be used to track how many fingers are present, and knowing which fingers are being reported is much more difficult, if not impossible. Signed-off-by: Daniel Kurtz <djkurtz@chromium.org> Acked-by: Chase Douglas <chase.douglas@canonical.com> Acked-by: Henrik Rydberg <rydberg@euromail.se> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/mouse/synaptics.c')
-rw-r--r--drivers/input/mouse/synaptics.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index e6e59c59391d..a7af8565e2de 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -420,15 +420,39 @@ static void synaptics_pt_create(struct psmouse *psmouse)
* Functions to interpret the absolute mode packets
****************************************************************************/
+static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count,
+ int sgm, int agm)
+{
+ state->count = count;
+ state->sgm = sgm;
+ state->agm = agm;
+}
+
static void synaptics_parse_agm(const unsigned char buf[],
- struct synaptics_data *priv)
+ struct synaptics_data *priv,
+ struct synaptics_hw_state *hw)
{
struct synaptics_hw_state *agm = &priv->agm;
+ int agm_packet_type;
+
+ agm_packet_type = (buf[5] & 0x30) >> 4;
+ switch (agm_packet_type) {
+ case 1:
+ /* Gesture packet: (x, y, z) half resolution */
+ agm->w = hw->w;
+ agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
+ agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
+ agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+ break;
- /* Gesture packet: (x, y, z) at half resolution */
- agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
- agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
- agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+ case 2:
+ /* AGM-CONTACT packet: (count, sgm, agm) */
+ synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]);
+ break;
+
+ default:
+ break;
+ }
}
static int synaptics_parse_hw_state(const unsigned char buf[],
@@ -467,7 +491,7 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
hw->w == 2) {
- synaptics_parse_agm(buf, priv);
+ synaptics_parse_agm(buf, priv, hw);
return 1;
}