All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] alps: bugfixes, cleanups and new hardware support
@ 2014-07-09 15:24 Hans de Goede
  2014-07-09 15:24 ` [PATCH 01/14] alps: Fix rushmore packet decoding Hans de Goede
                   ` (14 more replies)
  0 siblings, 15 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input

Hi All,

This series started out as a single patch to add support for a new model
of alps touchpad, called PROTO_V7 in this patchset.

While working on this I ended up doing some refactoring as preparation, which
I tested on a Rushmore alps touchpad, which lead to some bugfixes and more
cleanups, etc.

The result is a 14 patch patch-set, which:

1) Significantly improves multi-touch support on V3 and V4 models (including
   the Rushmore V3 variant)
2) Improves the code quality / readability quite a bit
3) Adds support for PROTO_V7

Regards,

Hans

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 01/14] alps: Fix rushmore packet decoding
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 02/14] alps: Always report 2 fingers (or more) when receiving mt data on v3 models Hans de Goede
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

From: Yunkang Tang <yunkang.tang@cn.alps.com>

Signed-off-by: Yunkang Tang <yunkang.tang@cn.alps.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index fb15c64..0448331 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -559,6 +559,9 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
 {
 	alps_decode_pinnacle(f, p, psmouse);
 
+	/* rushmore's packet decode has a bit difference with pinnacle's */
+	f->is_mp = !!(p[5] & 0x40);
+	f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1;
 	f->x_map |= (p[5] & 0x10) << 11;
 	f->y_map |= (p[5] & 0x20) << 6;
 }
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 02/14] alps: Always report 2 fingers (or more) when receiving mt data on v3 models
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
  2014-07-09 15:24 ` [PATCH 01/14] alps: Fix rushmore packet decoding Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 03/14] alps: process_bitmap: Don't invert the Y-axis on Rushmore Hans de Goede
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

V3 models only report mt bitmap data when there are 2 or more fingers on
the touchpad. So always generate 2 positions in alps_process_bitmap, and
for v3 models only fall back to st data when there was no mt data in a
mt packet (which should never happen).

This fixes 2 finger scrolling not working when using 2 fingers close to
each other.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 60 +++++++++++++++++++---------------------------
 1 file changed, 24 insertions(+), 36 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 0448331..b69205e 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -407,23 +407,20 @@ static int alps_process_bitmap(struct alps_data *priv,
 	fingers = max(fingers_x, fingers_y);
 
 	/*
-	 * If total fingers is > 1 but either axis reports only a single
-	 * contact, we have overlapping or adjacent fingers. For the
-	 * purposes of creating a bounding box, divide the single contact
-	 * (roughly) equally between the two points.
+	 * If an axis reports only a single contact, we have overlapping or
+	 * adjacent fingers. Divide the single contact between the two points.
 	 */
-	if (fingers > 1) {
-		if (fingers_x == 1) {
-			i = x_low.num_bits / 2;
-			x_low.num_bits = x_low.num_bits - i;
-			x_high.start_bit = x_low.start_bit + i;
-			x_high.num_bits = max(i, 1);
-		} else if (fingers_y == 1) {
-			i = y_low.num_bits / 2;
-			y_low.num_bits = y_low.num_bits - i;
-			y_high.start_bit = y_low.start_bit + i;
-			y_high.num_bits = max(i, 1);
-		}
+	if (fingers_x == 1) {
+		i = x_low.num_bits / 2;
+		x_low.num_bits = x_low.num_bits - i;
+		x_high.start_bit = x_low.start_bit + i;
+		x_high.num_bits = max(i, 1);
+	}
+	if (fingers_y == 1) {
+		i = y_low.num_bits / 2;
+		y_low.num_bits = y_low.num_bits - i;
+		y_high.start_bit = y_low.start_bit + i;
+		y_high.num_bits = max(i, 1);
 	}
 
 	*x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
@@ -431,14 +428,12 @@ static int alps_process_bitmap(struct alps_data *priv,
 	*y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
 	      (2 * (priv->y_bits - 1));
 
-	if (fingers > 1) {
-		*x2 = (priv->x_max *
-		       (2 * x_high.start_bit + x_high.num_bits - 1)) /
-		      (2 * (priv->x_bits - 1));
-		*y2 = (priv->y_max *
-		       (2 * y_high.start_bit + y_high.num_bits - 1)) /
-		      (2 * (priv->y_bits - 1));
-	}
+	*x2 = (priv->x_max *
+	       (2 * x_high.start_bit + x_high.num_bits - 1)) /
+	      (2 * (priv->x_bits - 1));
+	*y2 = (priv->y_max *
+	       (2 * y_high.start_bit + y_high.num_bits - 1)) /
+	      (2 * (priv->y_bits - 1));
 
 	return fingers;
 }
@@ -607,8 +602,7 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 	unsigned char *packet = psmouse->packet;
 	struct input_dev *dev = psmouse->dev;
 	struct input_dev *dev2 = priv->dev2;
-	int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
-	int fingers = 0, bmap_fn;
+	int x1 = 0, y1 = 0, x2 = 0, y2 = 0, fingers = 0;
 	struct alps_fields f = {0};
 
 	priv->decode_fields(&f, packet, psmouse);
@@ -629,16 +623,10 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 		if (f.is_mp) {
 			fingers = f.fingers;
 			if (priv->proto_version == ALPS_PROTO_V3) {
-				bmap_fn = alps_process_bitmap(priv, f.x_map,
-							      f.y_map, &x1, &y1,
-							      &x2, &y2);
-
-				/*
-				 * We shouldn't report more than one finger if
-				 * we don't have two coordinates.
-				 */
-				if (fingers > 1 && bmap_fn < 2)
-					fingers = bmap_fn;
+				if (alps_process_bitmap(priv, f.x_map,
+							f.y_map, &x1, &y1,
+							&x2, &y2) == 0)
+					fingers = 0; /* Use st data */
 
 				/* Now process position packet */
 				priv->decode_fields(&f, priv->multi_data,
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 03/14] alps: process_bitmap: Don't invert the Y-axis on Rushmore
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
  2014-07-09 15:24 ` [PATCH 01/14] alps: Fix rushmore packet decoding Hans de Goede
  2014-07-09 15:24 ` [PATCH 02/14] alps: Always report 2 fingers (or more) when receiving mt data on v3 models Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 04/14] alps: process_bitmap: Add alps_get_bitmap_points() helper function Hans de Goede
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

Rushmore models don't have the Y-axis data in the bitmap inverted. Since
we now have 2 different Y orientations, make the Y bitmap data processing
use a forward loop like the X bitmap data processing, unifying the 2,
and invert the data later, except on Rushmore.

So far no-one has noticed this because the synaptics driver only uses the non
mt coordinates (except on clickpads, and there are no alps clickpads using
process_bitmap).

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 17 ++++++++++-------
 drivers/input/mouse/alps.h |  4 ++--
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index b69205e..5768fb6 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -99,6 +99,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
 #define ALPS_FOUR_BUTTONS	0x40	/* 4 direction button present */
 #define ALPS_PS2_INTERLEAVED	0x80	/* 3-byte PS/2 packet interleaved with
 					   6-byte ALPS packet */
+#define ALPS_IS_RUSHMORE	0x100	/* device is a rushmore */
 
 static const struct alps_model_info alps_model_data[] = {
 	{ { 0x32, 0x02, 0x14 },	0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },	/* Toshiba Salellite Pro M10 */
@@ -376,15 +377,10 @@ static int alps_process_bitmap(struct alps_data *priv,
 		prev_bit = bit;
 	}
 
-	/*
-	 * y bitmap is reversed for what we need (lower positions are in
-	 * higher bits), so we process from the top end.
-	 */
-	y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits);
 	prev_bit = 0;
 	point = &y_low;
-	for (i = 0; y_map != 0; i++, y_map <<= 1) {
-		bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1));
+	for (i = 0; y_map != 0; i++, y_map >>= 1) {
+		bit = y_map & 1;
 		if (bit) {
 			if (!prev_bit) {
 				point->start_bit = i;
@@ -435,6 +431,12 @@ static int alps_process_bitmap(struct alps_data *priv,
 	       (2 * y_high.start_bit + y_high.num_bits - 1)) /
 	      (2 * (priv->y_bits - 1));
 
+	/* y-bitmap order is reversed, except on rushmore */
+	if (!(priv->flags & ALPS_IS_RUSHMORE)) {
+		*y1 = priv->y_max - *y1;
+		*y2 = priv->y_max - *y2;
+	}
+
 	return fingers;
 }
 
@@ -1981,6 +1983,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
 		priv->decode_fields = alps_decode_rushmore;
 		priv->x_bits = 16;
 		priv->y_bits = 12;
+		priv->flags |= ALPS_IS_RUSHMORE;
 
 		/* hack to make addr_command, nibble_command available */
 		psmouse->private = priv;
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 03f88b6..6d2666c 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -46,7 +46,7 @@ struct alps_model_info {
 	unsigned char command_mode_resp;
 	unsigned char proto_version;
 	unsigned char byte0, mask0;
-	unsigned char flags;
+	int flags;
 };
 
 /**
@@ -142,7 +142,7 @@ struct alps_data {
 	int addr_command;
 	unsigned char proto_version;
 	unsigned char byte0, mask0;
-	unsigned char flags;
+	int flags;
 	int x_max;
 	int y_max;
 	int x_bits;
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 04/14] alps: process_bitmap: Add alps_get_bitmap_points() helper function
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (2 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 03/14] alps: process_bitmap: Don't invert the Y-axis on Rushmore Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 05/14] alps: process_bitmap: Fix counting of high point bits Hans de Goede
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

Factor out the identical code for getting the bitmap points for x and y into
a helper function.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 75 +++++++++++++++++++---------------------------
 drivers/input/mouse/alps.h |  5 ++++
 2 files changed, 35 insertions(+), 45 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 5768fb6..00c735d 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -328,6 +328,33 @@ static void alps_process_bitmap_dolphin(struct alps_data *priv,
 	}
 }
 
+static void alps_get_bitmap_points(unsigned int map,
+				   struct alps_bitmap_point *low,
+				   struct alps_bitmap_point *high,
+				   int *fingers)
+{
+	struct alps_bitmap_point *point;
+	int i, bit, prev_bit = 0;
+
+	point = low;
+	for (i = 0; map != 0; i++, map >>= 1) {
+		bit = map & 1;
+		if (bit) {
+			if (!prev_bit) {
+				point->start_bit = i;
+				(*fingers)++;
+			}
+			point->num_bits++;
+		} else {
+			if (prev_bit)
+				point = high;
+			else
+				point->num_bits = 0;
+		}
+		prev_bit = bit;
+	}
+}
+
 /*
  * Process bitmap data from v3 and v4 protocols. Returns the number of
  * fingers detected. A return value of 0 means at least one of the
@@ -342,59 +369,17 @@ static int alps_process_bitmap(struct alps_data *priv,
 			       unsigned int x_map, unsigned int y_map,
 			       int *x1, int *y1, int *x2, int *y2)
 {
-	struct alps_bitmap_point {
-		int start_bit;
-		int num_bits;
-	};
-
-	int fingers_x = 0, fingers_y = 0, fingers;
-	int i, bit, prev_bit;
+	int i, fingers_x = 0, fingers_y = 0, fingers;
 	struct alps_bitmap_point x_low = {0,}, x_high = {0,};
 	struct alps_bitmap_point y_low = {0,}, y_high = {0,};
-	struct alps_bitmap_point *point;
 
 	if (!x_map || !y_map)
 		return 0;
 
 	*x1 = *y1 = *x2 = *y2 = 0;
 
-	prev_bit = 0;
-	point = &x_low;
-	for (i = 0; x_map != 0; i++, x_map >>= 1) {
-		bit = x_map & 1;
-		if (bit) {
-			if (!prev_bit) {
-				point->start_bit = i;
-				fingers_x++;
-			}
-			point->num_bits++;
-		} else {
-			if (prev_bit)
-				point = &x_high;
-			else
-				point->num_bits = 0;
-		}
-		prev_bit = bit;
-	}
-
-	prev_bit = 0;
-	point = &y_low;
-	for (i = 0; y_map != 0; i++, y_map >>= 1) {
-		bit = y_map & 1;
-		if (bit) {
-			if (!prev_bit) {
-				point->start_bit = i;
-				fingers_y++;
-			}
-			point->num_bits++;
-		} else {
-			if (prev_bit)
-				point = &y_high;
-			else
-				point->num_bits = 0;
-		}
-		prev_bit = bit;
-	}
+	alps_get_bitmap_points(x_map, &x_low, &x_high, &fingers_x);
+	alps_get_bitmap_points(y_map, &y_low, &y_high, &fingers_y);
 
 	/*
 	 * Fingers can overlap, so we use the maximum count of fingers
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 6d2666c..e900a08 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -65,6 +65,11 @@ struct alps_nibble_commands {
 	unsigned char data;
 };
 
+struct alps_bitmap_point {
+	int start_bit;
+	int num_bits;
+};
+
 /**
  * struct alps_fields - decoded version of the report packet
  * @x_map: Bitmap of active X positions for MT.
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 05/14] alps: process_bitmap: Fix counting of high point bits
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (3 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 04/14] alps: process_bitmap: Add alps_get_bitmap_points() helper function Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 06/14] alps: process_bitmap: Round down when spreading adjescent fingers over 2 points Hans de Goede
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

alps_process_bitmap was resetting the point bit-count as soon as it saw
2 0 bits in a row. This means that unless the high point actually is at
the end of the bitmap, it would always get its num_bits set to 0.

Instead reset num_bits to 0 on a 0-1 transition, so that with > 2 fingers
we only count the number of bits occupied by the highest finger.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 00c735d..ebf8187 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -342,14 +342,13 @@ static void alps_get_bitmap_points(unsigned int map,
 		if (bit) {
 			if (!prev_bit) {
 				point->start_bit = i;
+				point->num_bits = 0;
 				(*fingers)++;
 			}
 			point->num_bits++;
 		} else {
 			if (prev_bit)
 				point = high;
-			else
-				point->num_bits = 0;
 		}
 		prev_bit = bit;
 	}
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 06/14] alps: process_bitmap: Round down when spreading adjescent fingers over 2 points
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (4 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 05/14] alps: process_bitmap: Fix counting of high point bits Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 07/14] alps: Use struct input_mt_pos to track coordinates Hans de Goede
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

This fixes 2 fingers at the same height or width on the touchpad getting
reported at different y / x coordinates.

Note num_bits is always at least 1.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index ebf8187..f8c04fc 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -391,13 +391,13 @@ static int alps_process_bitmap(struct alps_data *priv,
 	 * adjacent fingers. Divide the single contact between the two points.
 	 */
 	if (fingers_x == 1) {
-		i = x_low.num_bits / 2;
+		i = (x_low.num_bits - 1) / 2;
 		x_low.num_bits = x_low.num_bits - i;
 		x_high.start_bit = x_low.start_bit + i;
 		x_high.num_bits = max(i, 1);
 	}
 	if (fingers_y == 1) {
-		i = y_low.num_bits / 2;
+		i = (y_low.num_bits - 1) / 2;
 		y_low.num_bits = y_low.num_bits - i;
 		y_high.start_bit = y_low.start_bit + i;
 		y_high.num_bits = max(i, 1);
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 07/14] alps: Use struct input_mt_pos to track coordinates
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (5 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 06/14] alps: process_bitmap: Round down when spreading adjescent fingers over 2 points Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 08/14] alps: Use input_mt_assign_slots && input_mt_sync_frame instead of DIY Hans de Goede
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

This is a preparation patch for switching the DIY mt handling to using
input_mt_assign_slots && input_mt_sync_frame.

struct alps_fields is quite large, so while making changes to almost all uses
of it lets put it in our priv data instead of on the stack.

Having it in our priv data also allows using it directly for storing values
which need to be cached, rather then having separate x, y, z, fingers, etc.
copies in our priv data.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 199 ++++++++++++++++++++-------------------------
 drivers/input/mouse/alps.h |  27 +++---
 2 files changed, 104 insertions(+), 122 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index f8c04fc..772e4b0 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -282,11 +282,10 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse)
  *
  * The bitmaps don't have enough data to track fingers, so this function
  * only generates points representing a bounding box of at most two contacts.
- * These two points are returned in x1, y1, x2, and y2.
+ * These two points are returned in fields->mt.
  */
 static void alps_process_bitmap_dolphin(struct alps_data *priv,
-					struct alps_fields *fields,
-					int *x1, int *y1, int *x2, int *y2)
+					struct alps_fields *fields)
 {
 	int box_middle_x, box_middle_y;
 	unsigned int x_map, y_map;
@@ -309,8 +308,6 @@ static void alps_process_bitmap_dolphin(struct alps_data *priv,
 	if (x_msb > priv->x_bits || y_msb > priv->y_bits)
 		return;
 
-	*x1 = *y1 = *x2 = *y2 = 0;
-
 	if (fields->fingers > 1) {
 		start_bit = priv->x_bits - x_msb;
 		end_bit = priv->x_bits - x_lsb;
@@ -321,10 +318,9 @@ static void alps_process_bitmap_dolphin(struct alps_data *priv,
 		end_bit = y_msb - 1;
 		box_middle_y = (priv->y_max * (start_bit + end_bit)) /
 				(2 * (priv->y_bits - 1));
-		*x1 = fields->x;
-		*y1 = fields->y;
-		*x2 = 2 * box_middle_x - *x1;
-		*y2 = 2 * box_middle_y - *y1;
+		fields->mt[0] = fields->st;
+		fields->mt[1].x = 2 * box_middle_x - fields->mt[0].x;
+		fields->mt[1].y = 2 * box_middle_y - fields->mt[0].y;
 	}
 }
 
@@ -361,24 +357,21 @@ static void alps_get_bitmap_points(unsigned int map,
  *
  * The bitmaps don't have enough data to track fingers, so this function
  * only generates points representing a bounding box of all contacts.
- * These points are returned in x1, y1, x2, and y2 when the return value
+ * These points are returned in fields->mt when the return value
  * is greater than 0.
  */
 static int alps_process_bitmap(struct alps_data *priv,
-			       unsigned int x_map, unsigned int y_map,
-			       int *x1, int *y1, int *x2, int *y2)
+			       struct alps_fields *fields)
 {
 	int i, fingers_x = 0, fingers_y = 0, fingers;
 	struct alps_bitmap_point x_low = {0,}, x_high = {0,};
 	struct alps_bitmap_point y_low = {0,}, y_high = {0,};
 
-	if (!x_map || !y_map)
+	if (!fields->x_map || !fields->y_map)
 		return 0;
 
-	*x1 = *y1 = *x2 = *y2 = 0;
-
-	alps_get_bitmap_points(x_map, &x_low, &x_high, &fingers_x);
-	alps_get_bitmap_points(y_map, &y_low, &y_high, &fingers_y);
+	alps_get_bitmap_points(fields->x_map, &x_low, &x_high, &fingers_x);
+	alps_get_bitmap_points(fields->y_map, &y_low, &y_high, &fingers_y);
 
 	/*
 	 * Fingers can overlap, so we use the maximum count of fingers
@@ -403,22 +396,24 @@ static int alps_process_bitmap(struct alps_data *priv,
 		y_high.num_bits = max(i, 1);
 	}
 
-	*x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
-	      (2 * (priv->x_bits - 1));
-	*y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
-	      (2 * (priv->y_bits - 1));
+	fields->mt[0].x =
+		(priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
+		(2 * (priv->x_bits - 1));
+	fields->mt[0].y =
+		(priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
+		(2 * (priv->y_bits - 1));
 
-	*x2 = (priv->x_max *
-	       (2 * x_high.start_bit + x_high.num_bits - 1)) /
-	      (2 * (priv->x_bits - 1));
-	*y2 = (priv->y_max *
-	       (2 * y_high.start_bit + y_high.num_bits - 1)) /
-	      (2 * (priv->y_bits - 1));
+	fields->mt[1].x =
+		(priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
+		(2 * (priv->x_bits - 1));
+	fields->mt[1].y =
+		(priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
+		(2 * (priv->y_bits - 1));
 
 	/* y-bitmap order is reversed, except on rushmore */
 	if (!(priv->flags & ALPS_IS_RUSHMORE)) {
-		*y1 = priv->y_max - *y1;
-		*y2 = priv->y_max - *y2;
+		fields->mt[0].y = priv->y_max - fields->mt[0].y;
+		fields->mt[1].y = priv->y_max - fields->mt[1].y;
 	}
 
 	return fingers;
@@ -435,11 +430,14 @@ static void alps_set_slot(struct input_dev *dev, int slot, bool active,
 	}
 }
 
-static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers,
-				     int x1, int y1, int x2, int y2)
+static void alps_report_semi_mt_data(struct psmouse *psmouse, int num_fingers)
 {
-	alps_set_slot(dev, 0, num_fingers != 0, x1, y1);
-	alps_set_slot(dev, 1, num_fingers == 2, x2, y2);
+	struct alps_data *priv = psmouse->private;
+	struct input_dev *dev = psmouse->dev;
+	struct alps_fields *f = &priv->f;
+
+	alps_set_slot(dev, 0, num_fingers != 0, f->mt[0].x, f->mt[0].y);
+	alps_set_slot(dev, 1, num_fingers == 2, f->mt[1].x, f->mt[1].y);
 }
 
 static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
@@ -527,10 +525,10 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
 		   ((p[2] & 0x7f) << 1) |
 		   (p[4] & 0x01);
 
-	f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
+	f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
 	       ((p[0] & 0x30) >> 4);
-	f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
-	f->z = p[5] & 0x7f;
+	f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
+	f->pressure = p[5] & 0x7f;
 
 	alps_decode_buttons_v3(f, p);
 }
@@ -557,9 +555,9 @@ static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
 	f->is_mp = !!(p[0] & 0x20);
 
 	if (!f->is_mp) {
-		f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
-		f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
-		f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
+		f->st.x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
+		f->st.y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
+		f->pressure = (p[0] & 4) ? 0 : p[5] & 0x7f;
 		alps_decode_buttons_v3(f, p);
 	} else {
 		f->fingers = ((p[0] & 0x6) >> 1 |
@@ -588,10 +586,12 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 	unsigned char *packet = psmouse->packet;
 	struct input_dev *dev = psmouse->dev;
 	struct input_dev *dev2 = priv->dev2;
-	int x1 = 0, y1 = 0, x2 = 0, y2 = 0, fingers = 0;
-	struct alps_fields f = {0};
+	struct alps_fields *f = &priv->f;
+	int fingers = 0;
+
+	memset(f, 0, sizeof(*f));
 
-	priv->decode_fields(&f, packet, psmouse);
+	priv->decode_fields(f, packet, psmouse);
 
 	/*
 	 * There's no single feature of touchpad position and bitmap packets
@@ -606,16 +606,14 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 		 * packet. Check for this, and when it happens process the
 		 * position packet as usual.
 		 */
-		if (f.is_mp) {
-			fingers = f.fingers;
+		if (f->is_mp) {
+			fingers = f->fingers;
 			if (priv->proto_version == ALPS_PROTO_V3) {
-				if (alps_process_bitmap(priv, f.x_map,
-							f.y_map, &x1, &y1,
-							&x2, &y2) == 0)
+				if (alps_process_bitmap(priv, f) == 0)
 					fingers = 0; /* Use st data */
 
 				/* Now process position packet */
-				priv->decode_fields(&f, priv->multi_data,
+				priv->decode_fields(f, priv->multi_data,
 						    psmouse);
 			} else {
 				/*
@@ -624,15 +622,14 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 				 * calculate Pt2, so we need to do position
 				 * packet decode first.
 				 */
-				priv->decode_fields(&f, priv->multi_data,
+				priv->decode_fields(f, priv->multi_data,
 						    psmouse);
 
 				/*
 				 * Since Dolphin's finger number is reliable,
 				 * there is no need to compare with bmap_fn.
 				 */
-				alps_process_bitmap_dolphin(priv, &f, &x1, &y1,
-							    &x2, &y2);
+				alps_process_bitmap_dolphin(priv, f);
 			}
 		} else {
 			priv->multi_packet = 0;
@@ -647,10 +644,10 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 	 * out misidentified bitmap packets, we reject anything with this
 	 * bit set.
 	 */
-	if (f.is_mp)
+	if (f->is_mp)
 		return;
 
-	if (!priv->multi_packet && f.first_mp) {
+	if (!priv->multi_packet && f->first_mp) {
 		priv->multi_packet = 1;
 		memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
 		return;
@@ -664,7 +661,7 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 	 * with x, y, and z all zero, so these seem to be flukes.
 	 * Ignore them.
 	 */
-	if (f.x && f.y && !f.z)
+	if (f->st.x && f->st.y && !f->pressure)
 		return;
 
 	/*
@@ -672,36 +669,36 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 	 * to rely on ST data.
 	 */
 	if (!fingers) {
-		x1 = f.x;
-		y1 = f.y;
-		fingers = f.z > 0 ? 1 : 0;
+		f->mt[0].x = f->st.x;
+		f->mt[0].y = f->st.y;
+		fingers = f->pressure > 0 ? 1 : 0;
 	}
 
-	if (f.z >= 64)
+	if (f->pressure >= 64)
 		input_report_key(dev, BTN_TOUCH, 1);
 	else
 		input_report_key(dev, BTN_TOUCH, 0);
 
-	alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
+	alps_report_semi_mt_data(psmouse, fingers);
 
 	input_mt_report_finger_count(dev, fingers);
 
-	input_report_key(dev, BTN_LEFT, f.left);
-	input_report_key(dev, BTN_RIGHT, f.right);
-	input_report_key(dev, BTN_MIDDLE, f.middle);
+	input_report_key(dev, BTN_LEFT, f->left);
+	input_report_key(dev, BTN_RIGHT, f->right);
+	input_report_key(dev, BTN_MIDDLE, f->middle);
 
-	if (f.z > 0) {
-		input_report_abs(dev, ABS_X, f.x);
-		input_report_abs(dev, ABS_Y, f.y);
+	if (f->pressure > 0) {
+		input_report_abs(dev, ABS_X, f->st.x);
+		input_report_abs(dev, ABS_Y, f->st.y);
 	}
-	input_report_abs(dev, ABS_PRESSURE, f.z);
+	input_report_abs(dev, ABS_PRESSURE, f->pressure);
 
 	input_sync(dev);
 
 	if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) {
-		input_report_key(dev2, BTN_LEFT, f.ts_left);
-		input_report_key(dev2, BTN_RIGHT, f.ts_right);
-		input_report_key(dev2, BTN_MIDDLE, f.ts_middle);
+		input_report_key(dev2, BTN_LEFT, f->ts_left);
+		input_report_key(dev2, BTN_RIGHT, f->ts_right);
+		input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
 		input_sync(dev2);
 	}
 }
@@ -801,12 +798,8 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
 	struct alps_data *priv = psmouse->private;
 	unsigned char *packet = psmouse->packet;
 	struct input_dev *dev = psmouse->dev;
-	int offset;
-	int x, y, z;
-	int left, right;
-	int x1, y1, x2, y2;
-	int fingers = 0;
-	unsigned int x_bitmap, y_bitmap;
+	struct alps_fields *f = &priv->f;
+	int offset, fingers = 0;
 
 	/*
 	 * v4 has a 6-byte encoding for bitmap data, but this data is
@@ -828,67 +821,55 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
 	if (++priv->multi_packet > 2) {
 		priv->multi_packet = 0;
 
-		x_bitmap = ((priv->multi_data[2] & 0x1f) << 10) |
+		f->x_map = ((priv->multi_data[2] & 0x1f) << 10) |
 			   ((priv->multi_data[3] & 0x60) << 3) |
 			   ((priv->multi_data[0] & 0x3f) << 2) |
 			   ((priv->multi_data[1] & 0x60) >> 5);
-		y_bitmap = ((priv->multi_data[5] & 0x01) << 10) |
+		f->y_map = ((priv->multi_data[5] & 0x01) << 10) |
 			   ((priv->multi_data[3] & 0x1f) << 5) |
 			    (priv->multi_data[1] & 0x1f);
 
-		fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap,
-					      &x1, &y1, &x2, &y2);
-
-		/* Store MT data.*/
-		priv->fingers = fingers;
-		priv->x1 = x1;
-		priv->x2 = x2;
-		priv->y1 = y1;
-		priv->y2 = y2;
+		f->fingers = alps_process_bitmap(priv, f);
 	}
 
-	left = packet[4] & 0x01;
-	right = packet[4] & 0x02;
+	f->left = packet[4] & 0x01;
+	f->right = packet[4] & 0x02;
 
-	x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
-	    ((packet[0] & 0x30) >> 4);
-	y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
-	z = packet[5] & 0x7f;
+	f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
+		  ((packet[0] & 0x30) >> 4);
+	f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
+	f->pressure = packet[5] & 0x7f;
 
 	/*
 	 * If there were no contacts in the bitmap, use ST
 	 * points in MT reports.
 	 * If there were two contacts or more, report MT data.
 	 */
-	if (priv->fingers < 2) {
-		x1 = x;
-		y1 = y;
-		fingers = z > 0 ? 1 : 0;
+	if (f->fingers < 2) {
+		f->mt[0].x = f->st.x;
+		f->mt[0].y = f->st.y;
+		fingers = f->pressure > 0 ? 1 : 0;
 	} else {
-		fingers = priv->fingers;
-		x1 = priv->x1;
-		x2 = priv->x2;
-		y1 = priv->y1;
-		y2 = priv->y2;
+		fingers = f->fingers;
 	}
 
-	if (z >= 64)
+	if (f->pressure >= 64)
 		input_report_key(dev, BTN_TOUCH, 1);
 	else
 		input_report_key(dev, BTN_TOUCH, 0);
 
-	alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
+	alps_report_semi_mt_data(psmouse, fingers);
 
 	input_mt_report_finger_count(dev, fingers);
 
-	input_report_key(dev, BTN_LEFT, left);
-	input_report_key(dev, BTN_RIGHT, right);
+	input_report_key(dev, BTN_LEFT, f->left);
+	input_report_key(dev, BTN_RIGHT, f->right);
 
-	if (z > 0) {
-		input_report_abs(dev, ABS_X, x);
-		input_report_abs(dev, ABS_Y, y);
+	if (f->pressure > 0) {
+		input_report_abs(dev, ABS_X, f->st.x);
+		input_report_abs(dev, ABS_Y, f->st.y);
 	}
-	input_report_abs(dev, ABS_PRESSURE, z);
+	input_report_abs(dev, ABS_PRESSURE, f->pressure);
 
 	input_sync(dev);
 }
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index e900a08..ee841e5 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -12,6 +12,8 @@
 #ifndef _ALPS_H
 #define _ALPS_H
 
+#include <linux/input/mt.h>
+
 #define ALPS_PROTO_V1	1
 #define ALPS_PROTO_V2	2
 #define ALPS_PROTO_V3	3
@@ -19,6 +21,8 @@
 #define ALPS_PROTO_V5	5
 #define ALPS_PROTO_V6	6
 
+#define MAX_TOUCHES	2
+
 #define DOLPHIN_COUNT_PER_ELECTRODE	64
 #define DOLPHIN_PROFILE_XOFFSET		8	/* x-electrode offset */
 #define DOLPHIN_PROFILE_YOFFSET		1	/* y-electrode offset */
@@ -75,9 +79,9 @@ struct alps_bitmap_point {
  * @x_map: Bitmap of active X positions for MT.
  * @y_map: Bitmap of active Y positions for MT.
  * @fingers: Number of fingers for MT.
- * @x: X position for ST.
- * @y: Y position for ST.
- * @z: Z position for ST.
+ * @pressure: Pressure.
+ * @st: position for ST.
+ * @mt: position for MT.
  * @first_mp: Packet is the first of a multi-packet report.
  * @is_mp: Packet is part of a multi-packet report.
  * @left: Left touchpad button is active.
@@ -91,9 +95,11 @@ struct alps_fields {
 	unsigned int x_map;
 	unsigned int y_map;
 	unsigned int fingers;
-	unsigned int x;
-	unsigned int y;
-	unsigned int z;
+
+	int pressure;
+	struct input_mt_pos st;
+	struct input_mt_pos mt[MAX_TOUCHES];
+
 	unsigned int first_mp:1;
 	unsigned int is_mp:1;
 
@@ -130,11 +136,7 @@ struct alps_fields {
  * @prev_fin: Finger bit from previous packet.
  * @multi_packet: Multi-packet data in progress.
  * @multi_data: Saved multi-packet data.
- * @x1: First X coordinate from last MT report.
- * @x2: Second X coordinate from last MT report.
- * @y1: First Y coordinate from last MT report.
- * @y2: Second Y coordinate from last MT report.
- * @fingers: Number of fingers from last MT report.
+ * @f: Decoded packet data fields.
  * @quirks: Bitmap of ALPS_QUIRK_*.
  * @timer: Timer for flushing out the final report packet in the stream.
  */
@@ -162,8 +164,7 @@ struct alps_data {
 	int prev_fin;
 	int multi_packet;
 	unsigned char multi_data[6];
-	int x1, x2, y1, y2;
-	int fingers;
+	struct alps_fields f;
 	u8 quirks;
 	struct timer_list timer;
 };
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 08/14] alps: Use input_mt_assign_slots && input_mt_sync_frame instead of DIY
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (6 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 07/14] alps: Use struct input_mt_pos to track coordinates Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 09/14] alps: Use single touch data when v3 mt data contains only one finger Hans de Goede
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

When there are 2 fingers on the pad we don't know which one is which, so
use input_mt_assign_slots to make sure the right set of coordinates ends
up in the right slot.

Besides ensuring things end up in the right slot, this also results in a nice
cleanup, since sync_frame also handles non mt position and btn_touch reporting.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 52 ++++++++++++++--------------------------------
 1 file changed, 16 insertions(+), 36 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 772e4b0..9bebeb4 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -419,25 +419,26 @@ static int alps_process_bitmap(struct alps_data *priv,
 	return fingers;
 }
 
-static void alps_set_slot(struct input_dev *dev, int slot, bool active,
-			  int x, int y)
+static void alps_set_slot(struct input_dev *dev, int slot, int x, int y)
 {
 	input_mt_slot(dev, slot);
-	input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
-	if (active) {
-		input_report_abs(dev, ABS_MT_POSITION_X, x);
-		input_report_abs(dev, ABS_MT_POSITION_Y, y);
-	}
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+	input_report_abs(dev, ABS_MT_POSITION_X, x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, y);
 }
 
-static void alps_report_semi_mt_data(struct psmouse *psmouse, int num_fingers)
+static void alps_report_mt_data(struct psmouse *psmouse, int n)
 {
 	struct alps_data *priv = psmouse->private;
 	struct input_dev *dev = psmouse->dev;
 	struct alps_fields *f = &priv->f;
+	int i, slot[MAX_TOUCHES];
+
+	input_mt_assign_slots(dev, slot, f->mt, n);
+	for (i = 0; i < n; i++)
+		alps_set_slot(dev, slot[i], f->mt[i].x, f->mt[i].y);
 
-	alps_set_slot(dev, 0, num_fingers != 0, f->mt[0].x, f->mt[0].y);
-	alps_set_slot(dev, 1, num_fingers == 2, f->mt[1].x, f->mt[1].y);
+	input_mt_sync_frame(dev);
 }
 
 static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
@@ -674,12 +675,7 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 		fingers = f->pressure > 0 ? 1 : 0;
 	}
 
-	if (f->pressure >= 64)
-		input_report_key(dev, BTN_TOUCH, 1);
-	else
-		input_report_key(dev, BTN_TOUCH, 0);
-
-	alps_report_semi_mt_data(psmouse, fingers);
+	alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 1);
 
 	input_mt_report_finger_count(dev, fingers);
 
@@ -687,10 +683,6 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 	input_report_key(dev, BTN_RIGHT, f->right);
 	input_report_key(dev, BTN_MIDDLE, f->middle);
 
-	if (f->pressure > 0) {
-		input_report_abs(dev, ABS_X, f->st.x);
-		input_report_abs(dev, ABS_Y, f->st.y);
-	}
 	input_report_abs(dev, ABS_PRESSURE, f->pressure);
 
 	input_sync(dev);
@@ -853,22 +845,13 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
 		fingers = f->fingers;
 	}
 
-	if (f->pressure >= 64)
-		input_report_key(dev, BTN_TOUCH, 1);
-	else
-		input_report_key(dev, BTN_TOUCH, 0);
-
-	alps_report_semi_mt_data(psmouse, fingers);
+	alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 1);
 
 	input_mt_report_finger_count(dev, fingers);
 
 	input_report_key(dev, BTN_LEFT, f->left);
 	input_report_key(dev, BTN_RIGHT, f->right);
 
-	if (f->pressure > 0) {
-		input_report_abs(dev, ABS_X, f->st.x);
-		input_report_abs(dev, ABS_Y, f->st.y);
-	}
 	input_report_abs(dev, ABS_PRESSURE, f->pressure);
 
 	input_sync(dev);
@@ -2003,17 +1986,14 @@ static void alps_set_abs_params_st(struct alps_data *priv,
 static void alps_set_abs_params_mt(struct alps_data *priv,
 				   struct input_dev *dev1)
 {
-	set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
-	input_mt_init_slots(dev1, 2, 0);
 	input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
 	input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
 
-	set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit);
+	input_mt_init_slots(dev1, MAX_TOUCHES, INPUT_MT_POINTER |
+		INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK | INPUT_MT_SEMI_MT);
+
 	set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
 	set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
-
-	input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
-	input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
 }
 
 int alps_init(struct psmouse *psmouse)
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 09/14] alps: Use single touch data when v3 mt data contains only one finger
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (7 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 08/14] alps: Use input_mt_assign_slots && input_mt_sync_frame instead of DIY Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 10/14] alps: Add an alps_report_semi_mt_data function Hans de Goede
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

For v3 protocol devices, use the more accurate single touch data when the
mt data contains only one finger. Note the mt data reporting a finger count
of 1 should never happen, but better safe then sorry.

This brings the v3 bitmap handling in line with what the v4 code does,
allowing to factor out the common bits into a helper function.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 9bebeb4..c9991b4 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -669,7 +669,7 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 	 * If we don't have MT data or the bitmaps were empty, we have
 	 * to rely on ST data.
 	 */
-	if (!fingers) {
+	if (fingers < 2) {
 		f->mt[0].x = f->st.x;
 		f->mt[0].y = f->st.y;
 		fingers = f->pressure > 0 ? 1 : 0;
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 10/14] alps: Add an alps_report_semi_mt_data function
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (8 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 09/14] alps: Use single touch data when v3 mt data contains only one finger Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 11/14] alps: Report 2 touches when we've > 2 fingers Hans de Goede
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

Move all the semi-mt specific handling shared between the v3 and v4 handling
code to a common helper function.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 76 ++++++++++++++++++----------------------------
 1 file changed, 29 insertions(+), 47 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index c9991b4..adc90ab 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -441,6 +441,32 @@ static void alps_report_mt_data(struct psmouse *psmouse, int n)
 	input_mt_sync_frame(dev);
 }
 
+static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers)
+{
+	struct alps_data *priv = psmouse->private;
+	struct input_dev *dev = psmouse->dev;
+	struct alps_fields *f = &priv->f;
+
+	/* Use st data when we don't have mt data */
+	if (fingers < 2) {
+		f->mt[0].x = f->st.x;
+		f->mt[0].y = f->st.y;
+		fingers = f->pressure > 0 ? 1 : 0;
+	}
+
+	alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 1);
+
+	input_mt_report_finger_count(dev, fingers);
+
+	input_report_key(dev, BTN_LEFT, f->left);
+	input_report_key(dev, BTN_RIGHT, f->right);
+	input_report_key(dev, BTN_MIDDLE, f->middle);
+
+	input_report_abs(dev, ABS_PRESSURE, f->pressure);
+
+	input_sync(dev);
+}
+
 static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
@@ -585,7 +611,6 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
 	unsigned char *packet = psmouse->packet;
-	struct input_dev *dev = psmouse->dev;
 	struct input_dev *dev2 = priv->dev2;
 	struct alps_fields *f = &priv->f;
 	int fingers = 0;
@@ -665,27 +690,7 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 	if (f->st.x && f->st.y && !f->pressure)
 		return;
 
-	/*
-	 * If we don't have MT data or the bitmaps were empty, we have
-	 * to rely on ST data.
-	 */
-	if (fingers < 2) {
-		f->mt[0].x = f->st.x;
-		f->mt[0].y = f->st.y;
-		fingers = f->pressure > 0 ? 1 : 0;
-	}
-
-	alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 1);
-
-	input_mt_report_finger_count(dev, fingers);
-
-	input_report_key(dev, BTN_LEFT, f->left);
-	input_report_key(dev, BTN_RIGHT, f->right);
-	input_report_key(dev, BTN_MIDDLE, f->middle);
-
-	input_report_abs(dev, ABS_PRESSURE, f->pressure);
-
-	input_sync(dev);
+	alps_report_semi_mt_data(psmouse, fingers);
 
 	if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) {
 		input_report_key(dev2, BTN_LEFT, f->ts_left);
@@ -789,9 +794,8 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
 	unsigned char *packet = psmouse->packet;
-	struct input_dev *dev = psmouse->dev;
 	struct alps_fields *f = &priv->f;
-	int offset, fingers = 0;
+	int offset;
 
 	/*
 	 * v4 has a 6-byte encoding for bitmap data, but this data is
@@ -832,29 +836,7 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
 	f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
 	f->pressure = packet[5] & 0x7f;
 
-	/*
-	 * If there were no contacts in the bitmap, use ST
-	 * points in MT reports.
-	 * If there were two contacts or more, report MT data.
-	 */
-	if (f->fingers < 2) {
-		f->mt[0].x = f->st.x;
-		f->mt[0].y = f->st.y;
-		fingers = f->pressure > 0 ? 1 : 0;
-	} else {
-		fingers = f->fingers;
-	}
-
-	alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 1);
-
-	input_mt_report_finger_count(dev, fingers);
-
-	input_report_key(dev, BTN_LEFT, f->left);
-	input_report_key(dev, BTN_RIGHT, f->right);
-
-	input_report_abs(dev, ABS_PRESSURE, f->pressure);
-
-	input_sync(dev);
+	alps_report_semi_mt_data(psmouse, f->fingers);
 }
 
 static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 11/14] alps: Report 2 touches when we've > 2 fingers
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (9 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 10/14] alps: Add an alps_report_semi_mt_data function Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 12/14] alps: Change decode function prototype to return an int Hans de Goede
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

If we detect more then 2 fingers report 2 touches, rather then only
reporting the upper left corner of the bounding box.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index adc90ab..93c6087 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -454,7 +454,7 @@ static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers)
 		fingers = f->pressure > 0 ? 1 : 0;
 	}
 
-	alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 1);
+	alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 2);
 
 	input_mt_report_finger_count(dev, fingers);
 
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 12/14] alps: Change decode function prototype to return an int
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (10 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 11/14] alps: Report 2 touches when we've > 2 fingers Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 13/14] alps: Cache firmware version Hans de Goede
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

So that decode functions can return a failure when appropriate.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 12 +++++++++---
 drivers/input/mouse/alps.h |  2 +-
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 93c6087..140471d 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -538,7 +538,7 @@ static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p)
 	f->ts_middle = !!(p[3] & 0x40);
 }
 
-static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
+static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
 				 struct psmouse *psmouse)
 {
 	f->first_mp = !!(p[4] & 0x40);
@@ -558,9 +558,11 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
 	f->pressure = p[5] & 0x7f;
 
 	alps_decode_buttons_v3(f, p);
+
+	return 0;
 }
 
-static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
+static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
 				 struct psmouse *psmouse)
 {
 	alps_decode_pinnacle(f, p, psmouse);
@@ -570,9 +572,11 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
 	f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1;
 	f->x_map |= (p[5] & 0x10) << 11;
 	f->y_map |= (p[5] & 0x20) << 6;
+
+	return 0;
 }
 
-static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
+static int alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
 				struct psmouse *psmouse)
 {
 	u64 palm_data = 0;
@@ -605,6 +609,8 @@ static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
 		f->x_map = (palm_data >> priv->y_bits) &
 			   (BIT(priv->x_bits) - 1);
 	}
+
+	return 0;
 }
 
 static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index ee841e5..17e3ae3 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -157,7 +157,7 @@ struct alps_data {
 
 	int (*hw_init)(struct psmouse *psmouse);
 	void (*process_packet)(struct psmouse *psmouse);
-	void (*decode_fields)(struct alps_fields *f, unsigned char *p,
+	int (*decode_fields)(struct alps_fields *f, unsigned char *p,
 			      struct psmouse *psmouse);
 	void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1);
 
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 13/14] alps: Cache firmware version
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (11 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 12/14] alps: Change decode function prototype to return an int Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-09 15:24 ` [PATCH 14/14] alps: Add support for v7 devices Hans de Goede
  2014-07-26  5:59 ` [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Dmitry Torokhov
  14 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 3 +++
 drivers/input/mouse/alps.h | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 140471d..ad3a708 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1901,6 +1901,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
 	    alps_exit_command_mode(psmouse))
 		return -EIO;
 
+	/* Save the Firmware version */
+	memcpy(priv->fw_ver, ec, 3);
+
 	if (alps_match_table(psmouse, priv, e7, ec) == 0) {
 		return 0;
 	} else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 17e3ae3..e3d0f09 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -124,6 +124,7 @@ struct alps_fields {
  *   known format for this model.  The first byte of the report, ANDed with
  *   mask0, should match byte0.
  * @mask0: The mask used to check the first byte of the report.
+ * @fw_ver: cached copy of firmware version (EC report)
  * @flags: Additional device capabilities (passthrough port, trackstick, etc.).
  * @x_max: Largest possible X position value.
  * @y_max: Largest possible Y position value.
@@ -149,6 +150,7 @@ struct alps_data {
 	int addr_command;
 	unsigned char proto_version;
 	unsigned char byte0, mask0;
+	unsigned char fw_ver[3];
 	int flags;
 	int x_max;
 	int y_max;
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 14/14] alps: Add support for v7 devices
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (12 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 13/14] alps: Cache firmware version Hans de Goede
@ 2014-07-09 15:24 ` Hans de Goede
  2014-07-26  5:58   ` Dmitry Torokhov
  2014-07-26  5:59 ` [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Dmitry Torokhov
  14 siblings, 1 reply; 18+ messages in thread
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede

From: Yunkang Tang <yunkang.tang@cn.alps.com>

Such as found on the new Toshiba Portégé Z30-A and Z40-A.

Signed-off-by: Yunkang Tang <yunkang.tang@cn.alps.com>
[hdegoede@redhat.com: Remove softbutton handling, this is done in userspace]
[hdegoede@redhat.com: Report INPUT_PROP_BUTTONPAD]
[hdegoede@redhat.com: Do not report fake PRESSURE, reporting BTN_TOUCH is
 enough]
[hdegoede@redhat.com: Various cleanups / refactoring]
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/mouse/alps.c | 257 ++++++++++++++++++++++++++++++++++++++++++++-
 drivers/input/mouse/alps.h |  18 ++++
 2 files changed, 272 insertions(+), 3 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index ad3a708..8b9b4b0 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -100,6 +100,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
 #define ALPS_PS2_INTERLEAVED	0x80	/* 3-byte PS/2 packet interleaved with
 					   6-byte ALPS packet */
 #define ALPS_IS_RUSHMORE	0x100	/* device is a rushmore */
+#define ALPS_BUTTONPAD		0x200	/* device is a clickpad */
 
 static const struct alps_model_info alps_model_data[] = {
 	{ { 0x32, 0x02, 0x14 },	0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },	/* Toshiba Salellite Pro M10 */
@@ -845,6 +846,177 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
 	alps_report_semi_mt_data(psmouse, f->fingers);
 }
 
+static bool alps_is_valid_package_v7(struct psmouse *psmouse)
+{
+	if ((psmouse->pktcnt == 3) && ((psmouse->packet[2] & 0x40) != 0x40))
+		return false;
+	if ((psmouse->pktcnt == 4) && ((psmouse->packet[3] & 0x48) != 0x48))
+		return false;
+	if ((psmouse->pktcnt == 6) && ((psmouse->packet[5] & 0x40) != 0x0))
+		return false;
+	return true;
+}
+
+static unsigned char alps_get_packet_id_v7(char *byte)
+{
+	unsigned char packet_id;
+
+	if (byte[4] & 0x40)
+		packet_id = V7_PACKET_ID_TWO;
+	else if (byte[4] & 0x01)
+		packet_id = V7_PACKET_ID_MULTI;
+	else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
+		packet_id = V7_PACKET_ID_NEW;
+	else if (byte[1] == 0x00 && byte[4] == 0x00)
+		packet_id = V7_PACKET_ID_IDLE;
+	else
+		packet_id = V7_PACKET_ID_UNKNOWN;
+
+	return packet_id;
+}
+
+static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
+					  unsigned char *pkt,
+					  unsigned char pkt_id)
+{
+	mt[0].x = ((pkt[2] & 0x80) << 4);
+	mt[0].x |= ((pkt[2] & 0x3F) << 5);
+	mt[0].x |= ((pkt[3] & 0x30) >> 1);
+	mt[0].x |= (pkt[3] & 0x07);
+	mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07);
+
+	mt[1].x = ((pkt[3] & 0x80) << 4);
+	mt[1].x |= ((pkt[4] & 0x80) << 3);
+	mt[1].x |= ((pkt[4] & 0x3F) << 4);
+	mt[1].y = ((pkt[5] & 0x80) << 3);
+	mt[1].y |= ((pkt[5] & 0x3F) << 4);
+
+	if (pkt_id == V7_PACKET_ID_TWO) {
+		mt[1].x &= ~0x000F;
+		mt[1].y |= 0x000F;
+	} else if (pkt_id == V7_PACKET_ID_MULTI) {
+		mt[1].x &= ~0x003F;
+		mt[1].y &= ~0x0020;
+		mt[1].y |= ((pkt[4] & 0x02) << 4);
+		mt[1].y |= 0x001F;
+	} else if (pkt_id == V7_PACKET_ID_NEW) {
+		mt[1].x &= ~0x003F;
+		mt[1].x |= (pkt[0] & 0x20);
+		mt[1].y |= 0x000F;
+	}
+
+	mt[0].y = 0x7FF - mt[0].y;
+	mt[1].y = 0x7FF - mt[1].y;
+}
+
+static int alps_get_mt_count(struct input_mt_pos *mt)
+{
+	int i;
+
+	for (i = 0; i < MAX_TOUCHES && mt[i].x != 0 && mt[i].y != 0; i++)
+		;
+
+	return i;
+}
+
+static int alps_decode_packet_v7(struct alps_fields *f,
+				  unsigned char *p,
+				  struct psmouse *psmouse)
+{
+	unsigned char pkt_id;
+
+	pkt_id = alps_get_packet_id_v7(p);
+	if (pkt_id == V7_PACKET_ID_IDLE)
+		return 0;
+	if (pkt_id == V7_PACKET_ID_UNKNOWN)
+		return -1;
+
+	alps_get_finger_coordinate_v7(f->mt, p, pkt_id);
+
+	if (pkt_id == V7_PACKET_ID_TWO || pkt_id == V7_PACKET_ID_MULTI) {
+		f->left = (p[0] & 0x80) >> 7;
+		f->right = (p[0] & 0x20) >> 5;
+		f->middle = (p[0] & 0x10) >> 4;
+	}
+
+	if (pkt_id == V7_PACKET_ID_TWO)
+		f->fingers = alps_get_mt_count(f->mt);
+	else if (pkt_id == V7_PACKET_ID_MULTI)
+		f->fingers = 3 + (p[5] & 0x03);
+
+	return 0;
+}
+
+static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
+{
+	struct alps_data *priv = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	struct input_dev *dev2 = priv->dev2;
+	int x, y, z, left, right, middle;
+
+	/*
+	 *        b7 b6 b5 b4 b3 b2 b1 b0
+	 * Byte0   0  1  0  0  1  0  0  0
+	 * Byte1   1  1  *  *  1  M  R  L
+	 * Byte2  X7  1 X5 X4 X3 X2 X1 X0
+	 * Byte3  Z6  1 Y6 X6  1 Y2 Y1 Y0
+	 * Byte4  Y7  0 Y5 Y4 Y3  1  1  0
+	 * Byte5 T&P  0 Z5 Z4 Z3 Z2 Z1 Z0
+	 * M / R / L: Middle / Right / Left button
+	 */
+
+	x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2);
+	y = (packet[3] & 0x07) | (packet[4] & 0xb8) |
+	    ((packet[3] & 0x20) << 1);
+	z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
+
+	left = (packet[1] & 0x01);
+	right = (packet[1] & 0x02) >> 1;
+	middle = (packet[1] & 0x04) >> 2;
+
+	/* Divide 2 since trackpoint's speed is too fast */
+	input_report_rel(dev2, REL_X, (char)x / 2);
+	input_report_rel(dev2, REL_Y, -((char)y / 2));
+
+	input_report_key(dev2, BTN_LEFT, left);
+	input_report_key(dev2, BTN_RIGHT, right);
+	input_report_key(dev2, BTN_MIDDLE, middle);
+
+	input_sync(dev2);
+}
+
+static void alps_process_touchpad_packet_v7(struct psmouse *psmouse)
+{
+	struct alps_data *priv = psmouse->private;
+	struct input_dev *dev = psmouse->dev;
+	struct alps_fields *f = &priv->f;
+
+	memset(f, 0, sizeof(*f));
+
+	if (priv->decode_fields(f, psmouse->packet, psmouse))
+		return;
+
+	alps_report_mt_data(psmouse, alps_get_mt_count(f->mt));
+
+	input_mt_report_finger_count(dev, f->fingers);
+
+	input_report_key(dev, BTN_LEFT, f->left);
+	input_report_key(dev, BTN_RIGHT, f->right);
+	input_report_key(dev, BTN_MIDDLE, f->middle);
+
+	input_sync(dev);
+}
+
+static void alps_process_packet_v7(struct psmouse *psmouse)
+{
+	unsigned char *packet = psmouse->packet;
+
+	if ((packet[0] == 0x48) && ((packet[4] & 0x47) == 0x06))
+		alps_process_trackstick_packet_v7(psmouse);
+	else
+		alps_process_touchpad_packet_v7(psmouse);
+}
+
 static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
 					unsigned char packet[],
 					bool report_buttons)
@@ -1009,6 +1181,14 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
 		return PSMOUSE_BAD_DATA;
 	}
 
+	if (priv->proto_version == ALPS_PROTO_V7 &&
+			!alps_is_valid_package_v7(psmouse)) {
+		psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
+			    psmouse->pktcnt - 1,
+			    psmouse->packet[psmouse->pktcnt - 1]);
+		return PSMOUSE_BAD_DATA;
+	}
+
 	if (psmouse->pktcnt == psmouse->pktsize) {
 		priv->process_packet(psmouse);
 		return PSMOUSE_FULL_PACKET;
@@ -1121,6 +1301,22 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
 	return 0;
 }
 
+static int alps_check_valid_firmware_id(unsigned char id[])
+{
+	int valid = 1;
+
+	if (id[0] == 0x73)
+		valid = 1;
+	else if (id[0] == 0x88) {
+		if ((id[1] == 0x07) ||
+		    (id[1] == 0x08) ||
+		    ((id[1] & 0xf0) == 0xB0))
+			valid = 1;
+	}
+
+	return valid;
+}
+
 static int alps_enter_command_mode(struct psmouse *psmouse)
 {
 	unsigned char param[4];
@@ -1130,8 +1326,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse)
 		return -1;
 	}
 
-	if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
-	    param[0] != 0x73) {
+	if (!alps_check_valid_firmware_id(param)) {
 		psmouse_dbg(psmouse,
 			    "unknown response while entering command mode\n");
 		return -1;
@@ -1785,6 +1980,32 @@ static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
 	return 0;
 }
 
+static int alps_hw_init_v7(struct psmouse *psmouse)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	int reg_val, ret = -1;
+
+	if (alps_enter_command_mode(psmouse) ||
+	    alps_command_mode_read_reg(psmouse, 0xc2d9) == -1)
+		goto error;
+
+	if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
+		goto error;
+
+	reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
+	if (reg_val == -1)
+		goto error;
+	if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
+		goto error;
+
+	alps_exit_command_mode(psmouse);
+	return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+
+error:
+	alps_exit_command_mode(psmouse);
+	return ret;
+}
+
 static void alps_set_defaults(struct alps_data *priv)
 {
 	priv->byte0 = 0x8f;
@@ -1843,6 +2064,21 @@ static void alps_set_defaults(struct alps_data *priv)
 		priv->x_max = 2047;
 		priv->y_max = 1535;
 		break;
+	case ALPS_PROTO_V7:
+		priv->hw_init = alps_hw_init_v7;
+		priv->process_packet = alps_process_packet_v7;
+		priv->decode_fields = alps_decode_packet_v7;
+		priv->set_abs_params = alps_set_abs_params_mt;
+		priv->nibble_commands = alps_v3_nibble_commands;
+		priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
+		priv->x_max = 0xfff;
+		priv->y_max = 0x7ff;
+		priv->byte0 = 0x48;
+		priv->mask0 = 0x48;
+
+		if (priv->fw_ver[1] != 0xba)
+			priv->flags |= ALPS_BUTTONPAD;
+		break;
 	}
 }
 
@@ -1914,6 +2150,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
 			return -EIO;
 		else
 			return 0;
+	} else if (ec[0] == 0x88 &&
+		   ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) {
+		priv->proto_version = ALPS_PROTO_V7;
+		alps_set_defaults(priv);
+
+		return 0;
 	} else if (ec[0] == 0x88 && ec[1] == 0x08) {
 		priv->proto_version = ALPS_PROTO_V3;
 		alps_set_defaults(priv);
@@ -1985,6 +2227,10 @@ static void alps_set_abs_params_mt(struct alps_data *priv,
 
 	set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
 	set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
+
+	/* V7 is real multi-touch */
+	if (priv->proto_version == ALPS_PROTO_V7)
+		clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
 }
 
 int alps_init(struct psmouse *psmouse)
@@ -2030,7 +2276,9 @@ int alps_init(struct psmouse *psmouse)
 	dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
 
 	priv->set_abs_params(priv, dev1);
-	input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
+	/* No pressure on V7 */
+	if (priv->proto_version != ALPS_PROTO_V7)
+		input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
 
 	if (priv->flags & ALPS_WHEEL) {
 		dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
@@ -2047,6 +2295,9 @@ int alps_init(struct psmouse *psmouse)
 		dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
 		dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
 		dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
+	} else if (priv->flags & ALPS_BUTTONPAD) {
+		set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit);
+		clear_bit(BTN_RIGHT, dev1->keybit);
 	} else {
 		dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
 	}
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index e3d0f09..a98ac9b 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -20,6 +20,7 @@
 #define ALPS_PROTO_V4	4
 #define ALPS_PROTO_V5	5
 #define ALPS_PROTO_V6	6
+#define ALPS_PROTO_V7	7	/* t3btl t4s */
 
 #define MAX_TOUCHES	2
 
@@ -27,6 +28,23 @@
 #define DOLPHIN_PROFILE_XOFFSET		8	/* x-electrode offset */
 #define DOLPHIN_PROFILE_YOFFSET		1	/* y-electrode offset */
 
+/*
+ * enum V7_PACKET_ID - defines the packet type for V7
+ * V7_PACKET_ID_IDLE: There's no finger and no button activity.
+ * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad
+ *  or there's button activities.
+ * V7_PACKET_ID_MULTI: There are at least three non-resting fingers.
+ * V7_PACKET_ID_NEW: The finger position in slot is not continues from
+ *  previous packet.
+*/
+enum V7_PACKET_ID {
+	 V7_PACKET_ID_IDLE,
+	 V7_PACKET_ID_TWO,
+	 V7_PACKET_ID_MULTI,
+	 V7_PACKET_ID_NEW,
+	 V7_PACKET_ID_UNKNOWN,
+};
+
 /**
  * struct alps_model_info - touchpad ID table
  * @signature: E7 response string to match.
-- 
2.0.0

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 14/14] alps: Add support for v7 devices
  2014-07-09 15:24 ` [PATCH 14/14] alps: Add support for v7 devices Hans de Goede
@ 2014-07-26  5:58   ` Dmitry Torokhov
  2014-07-26  8:22     ` Hans de Goede
  0 siblings, 1 reply; 18+ messages in thread
From: Dmitry Torokhov @ 2014-07-26  5:58 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Yunkang Tang, linux-input

Hi Hans,

On Wed, Jul 09, 2014 at 05:24:19PM +0200, Hans de Goede wrote:
> From: Yunkang Tang <yunkang.tang@cn.alps.com>
> 
> Such as found on the new Toshiba Portégé Z30-A and Z40-A.
> 
> Signed-off-by: Yunkang Tang <yunkang.tang@cn.alps.com>
> [hdegoede@redhat.com: Remove softbutton handling, this is done in userspace]
> [hdegoede@redhat.com: Report INPUT_PROP_BUTTONPAD]
> [hdegoede@redhat.com: Do not report fake PRESSURE, reporting BTN_TOUCH is
>  enough]
> [hdegoede@redhat.com: Various cleanups / refactoring]
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/input/mouse/alps.c | 257 ++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/input/mouse/alps.h |  18 ++++
>  2 files changed, 272 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
> index ad3a708..8b9b4b0 100644
> --- a/drivers/input/mouse/alps.c
> +++ b/drivers/input/mouse/alps.c
> @@ -100,6 +100,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
>  #define ALPS_PS2_INTERLEAVED	0x80	/* 3-byte PS/2 packet interleaved with
>  					   6-byte ALPS packet */
>  #define ALPS_IS_RUSHMORE	0x100	/* device is a rushmore */
> +#define ALPS_BUTTONPAD		0x200	/* device is a clickpad */
>  
>  static const struct alps_model_info alps_model_data[] = {
>  	{ { 0x32, 0x02, 0x14 },	0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },	/* Toshiba Salellite Pro M10 */
> @@ -845,6 +846,177 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
>  	alps_report_semi_mt_data(psmouse, f->fingers);
>  }
>  
> +static bool alps_is_valid_package_v7(struct psmouse *psmouse)
> +{
> +	if ((psmouse->pktcnt == 3) && ((psmouse->packet[2] & 0x40) != 0x40))
> +		return false;
> +	if ((psmouse->pktcnt == 4) && ((psmouse->packet[3] & 0x48) != 0x48))
> +		return false;
> +	if ((psmouse->pktcnt == 6) && ((psmouse->packet[5] & 0x40) != 0x0))
> +		return false;
> +	return true;

Maybe:

	switch (psmouse->pktcnt) {
	case 3:
		return (psmouse->packet[2] & 0x40) == 0x40;

	case 4:
		return (psmouse->packet[3] & 0x48) == 0x48;

	case 6:
		return (psmouse->packet[5] & 0x40) == 0x00;
	}

	return true;

?


> +}
> +
> +static unsigned char alps_get_packet_id_v7(char *byte)
> +{
> +	unsigned char packet_id;
> +
> +	if (byte[4] & 0x40)
> +		packet_id = V7_PACKET_ID_TWO;
> +	else if (byte[4] & 0x01)
> +		packet_id = V7_PACKET_ID_MULTI;
> +	else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
> +		packet_id = V7_PACKET_ID_NEW;
> +	else if (byte[1] == 0x00 && byte[4] == 0x00)
> +		packet_id = V7_PACKET_ID_IDLE;
> +	else
> +		packet_id = V7_PACKET_ID_UNKNOWN;
> +
> +	return packet_id;
> +}
> +
> +static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
> +					  unsigned char *pkt,
> +					  unsigned char pkt_id)
> +{
> +	mt[0].x = ((pkt[2] & 0x80) << 4);
> +	mt[0].x |= ((pkt[2] & 0x3F) << 5);
> +	mt[0].x |= ((pkt[3] & 0x30) >> 1);
> +	mt[0].x |= (pkt[3] & 0x07);
> +	mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07);
> +
> +	mt[1].x = ((pkt[3] & 0x80) << 4);
> +	mt[1].x |= ((pkt[4] & 0x80) << 3);
> +	mt[1].x |= ((pkt[4] & 0x3F) << 4);
> +	mt[1].y = ((pkt[5] & 0x80) << 3);
> +	mt[1].y |= ((pkt[5] & 0x3F) << 4);
> +
> +	if (pkt_id == V7_PACKET_ID_TWO) {
> +		mt[1].x &= ~0x000F;
> +		mt[1].y |= 0x000F;
> +	} else if (pkt_id == V7_PACKET_ID_MULTI) {
> +		mt[1].x &= ~0x003F;
> +		mt[1].y &= ~0x0020;
> +		mt[1].y |= ((pkt[4] & 0x02) << 4);
> +		mt[1].y |= 0x001F;
> +	} else if (pkt_id == V7_PACKET_ID_NEW) {
> +		mt[1].x &= ~0x003F;
> +		mt[1].x |= (pkt[0] & 0x20);
> +		mt[1].y |= 0x000F;
> +	}
> +
> +	mt[0].y = 0x7FF - mt[0].y;
> +	mt[1].y = 0x7FF - mt[1].y;
> +}
> +
> +static int alps_get_mt_count(struct input_mt_pos *mt)
> +{
> +	int i;
> +
> +	for (i = 0; i < MAX_TOUCHES && mt[i].x != 0 && mt[i].y != 0; i++)
> +		;

		/* empty */;

just to make sure...

> +
> +	return i;
> +}
> +
> +static int alps_decode_packet_v7(struct alps_fields *f,
> +				  unsigned char *p,
> +				  struct psmouse *psmouse)
> +{
> +	unsigned char pkt_id;
> +
> +	pkt_id = alps_get_packet_id_v7(p);
> +	if (pkt_id == V7_PACKET_ID_IDLE)
> +		return 0;
> +	if (pkt_id == V7_PACKET_ID_UNKNOWN)
> +		return -1;
> +
> +	alps_get_finger_coordinate_v7(f->mt, p, pkt_id);
> +
> +	if (pkt_id == V7_PACKET_ID_TWO || pkt_id == V7_PACKET_ID_MULTI) {
> +		f->left = (p[0] & 0x80) >> 7;
> +		f->right = (p[0] & 0x20) >> 5;
> +		f->middle = (p[0] & 0x10) >> 4;
> +	}
> +
> +	if (pkt_id == V7_PACKET_ID_TWO)
> +		f->fingers = alps_get_mt_count(f->mt);
> +	else if (pkt_id == V7_PACKET_ID_MULTI)
> +		f->fingers = 3 + (p[5] & 0x03);
> +
> +	return 0;
> +}
> +
> +static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
> +{
> +	struct alps_data *priv = psmouse->private;
> +	unsigned char *packet = psmouse->packet;
> +	struct input_dev *dev2 = priv->dev2;
> +	int x, y, z, left, right, middle;
> +
> +	/*
> +	 *        b7 b6 b5 b4 b3 b2 b1 b0
> +	 * Byte0   0  1  0  0  1  0  0  0
> +	 * Byte1   1  1  *  *  1  M  R  L
> +	 * Byte2  X7  1 X5 X4 X3 X2 X1 X0
> +	 * Byte3  Z6  1 Y6 X6  1 Y2 Y1 Y0
> +	 * Byte4  Y7  0 Y5 Y4 Y3  1  1  0
> +	 * Byte5 T&P  0 Z5 Z4 Z3 Z2 Z1 Z0
> +	 * M / R / L: Middle / Right / Left button
> +	 */
> +
> +	x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2);
> +	y = (packet[3] & 0x07) | (packet[4] & 0xb8) |
> +	    ((packet[3] & 0x20) << 1);
> +	z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
> +
> +	left = (packet[1] & 0x01);
> +	right = (packet[1] & 0x02) >> 1;
> +	middle = (packet[1] & 0x04) >> 2;
> +
> +	/* Divide 2 since trackpoint's speed is too fast */
> +	input_report_rel(dev2, REL_X, (char)x / 2);
> +	input_report_rel(dev2, REL_Y, -((char)y / 2));
> +
> +	input_report_key(dev2, BTN_LEFT, left);
> +	input_report_key(dev2, BTN_RIGHT, right);
> +	input_report_key(dev2, BTN_MIDDLE, middle);
> +
> +	input_sync(dev2);
> +}
> +
> +static void alps_process_touchpad_packet_v7(struct psmouse *psmouse)
> +{
> +	struct alps_data *priv = psmouse->private;
> +	struct input_dev *dev = psmouse->dev;
> +	struct alps_fields *f = &priv->f;
> +
> +	memset(f, 0, sizeof(*f));
> +
> +	if (priv->decode_fields(f, psmouse->packet, psmouse))
> +		return;
> +
> +	alps_report_mt_data(psmouse, alps_get_mt_count(f->mt));
> +
> +	input_mt_report_finger_count(dev, f->fingers);
> +
> +	input_report_key(dev, BTN_LEFT, f->left);
> +	input_report_key(dev, BTN_RIGHT, f->right);
> +	input_report_key(dev, BTN_MIDDLE, f->middle);
> +
> +	input_sync(dev);
> +}
> +
> +static void alps_process_packet_v7(struct psmouse *psmouse)
> +{
> +	unsigned char *packet = psmouse->packet;
> +
> +	if ((packet[0] == 0x48) && ((packet[4] & 0x47) == 0x06))
> +		alps_process_trackstick_packet_v7(psmouse);
> +	else
> +		alps_process_touchpad_packet_v7(psmouse);
> +}
> +
>  static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
>  					unsigned char packet[],
>  					bool report_buttons)
> @@ -1009,6 +1181,14 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
>  		return PSMOUSE_BAD_DATA;
>  	}
>  
> +	if (priv->proto_version == ALPS_PROTO_V7 &&
> +			!alps_is_valid_package_v7(psmouse)) {
> +		psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
> +			    psmouse->pktcnt - 1,
> +			    psmouse->packet[psmouse->pktcnt - 1]);
> +		return PSMOUSE_BAD_DATA;
> +	}
> +
>  	if (psmouse->pktcnt == psmouse->pktsize) {
>  		priv->process_packet(psmouse);
>  		return PSMOUSE_FULL_PACKET;
> @@ -1121,6 +1301,22 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
>  	return 0;
>  }
>  
> +static int alps_check_valid_firmware_id(unsigned char id[])

bool

> +{
> +	int valid = 1;

bool; true

> +
> +	if (id[0] == 0x73)
> +		valid = 1;

true

> +	else if (id[0] == 0x88) {
> +		if ((id[1] == 0x07) ||
> +		    (id[1] == 0x08) ||
> +		    ((id[1] & 0xf0) == 0xB0))
> +			valid = 1;

true

> +	}
> +
> +	return valid;

Hmmm, does not make sense - it is never false...

> +}
> +
>  static int alps_enter_command_mode(struct psmouse *psmouse)
>  {
>  	unsigned char param[4];
> @@ -1130,8 +1326,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse)
>  		return -1;
>  	}
>  
> -	if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
> -	    param[0] != 0x73) {
> +	if (!alps_check_valid_firmware_id(param)) {
>  		psmouse_dbg(psmouse,
>  			    "unknown response while entering command mode\n");
>  		return -1;
> @@ -1785,6 +1980,32 @@ static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
>  	return 0;
>  }
>  
> +static int alps_hw_init_v7(struct psmouse *psmouse)
> +{
> +	struct ps2dev *ps2dev = &psmouse->ps2dev;
> +	int reg_val, ret = -1;
> +
> +	if (alps_enter_command_mode(psmouse) ||
> +	    alps_command_mode_read_reg(psmouse, 0xc2d9) == -1)
> +		goto error;
> +
> +	if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
> +		goto error;
> +
> +	reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
> +	if (reg_val == -1)
> +		goto error;
> +	if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
> +		goto error;
> +
> +	alps_exit_command_mode(psmouse);
> +	return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
> +
> +error:
> +	alps_exit_command_mode(psmouse);
> +	return ret;
> +}
> +
>  static void alps_set_defaults(struct alps_data *priv)
>  {
>  	priv->byte0 = 0x8f;
> @@ -1843,6 +2064,21 @@ static void alps_set_defaults(struct alps_data *priv)
>  		priv->x_max = 2047;
>  		priv->y_max = 1535;
>  		break;
> +	case ALPS_PROTO_V7:
> +		priv->hw_init = alps_hw_init_v7;
> +		priv->process_packet = alps_process_packet_v7;
> +		priv->decode_fields = alps_decode_packet_v7;
> +		priv->set_abs_params = alps_set_abs_params_mt;
> +		priv->nibble_commands = alps_v3_nibble_commands;
> +		priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
> +		priv->x_max = 0xfff;
> +		priv->y_max = 0x7ff;
> +		priv->byte0 = 0x48;
> +		priv->mask0 = 0x48;
> +
> +		if (priv->fw_ver[1] != 0xba)
> +			priv->flags |= ALPS_BUTTONPAD;
> +		break;
>  	}
>  }
>  
> @@ -1914,6 +2150,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
>  			return -EIO;
>  		else
>  			return 0;
> +	} else if (ec[0] == 0x88 &&
> +		   ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) {
> +		priv->proto_version = ALPS_PROTO_V7;
> +		alps_set_defaults(priv);
> +
> +		return 0;
>  	} else if (ec[0] == 0x88 && ec[1] == 0x08) {
>  		priv->proto_version = ALPS_PROTO_V3;
>  		alps_set_defaults(priv);
> @@ -1985,6 +2227,10 @@ static void alps_set_abs_params_mt(struct alps_data *priv,
>  
>  	set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
>  	set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
> +
> +	/* V7 is real multi-touch */
> +	if (priv->proto_version == ALPS_PROTO_V7)
> +		clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
>  }
>  
>  int alps_init(struct psmouse *psmouse)
> @@ -2030,7 +2276,9 @@ int alps_init(struct psmouse *psmouse)
>  	dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
>  
>  	priv->set_abs_params(priv, dev1);
> -	input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
> +	/* No pressure on V7 */
> +	if (priv->proto_version != ALPS_PROTO_V7)
> +		input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
>  
>  	if (priv->flags & ALPS_WHEEL) {
>  		dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
> @@ -2047,6 +2295,9 @@ int alps_init(struct psmouse *psmouse)
>  		dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
>  		dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
>  		dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
> +	} else if (priv->flags & ALPS_BUTTONPAD) {
> +		set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit);
> +		clear_bit(BTN_RIGHT, dev1->keybit);
>  	} else {
>  		dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
>  	}
> diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
> index e3d0f09..a98ac9b 100644
> --- a/drivers/input/mouse/alps.h
> +++ b/drivers/input/mouse/alps.h
> @@ -20,6 +20,7 @@
>  #define ALPS_PROTO_V4	4
>  #define ALPS_PROTO_V5	5
>  #define ALPS_PROTO_V6	6
> +#define ALPS_PROTO_V7	7	/* t3btl t4s */
>  
>  #define MAX_TOUCHES	2
>  
> @@ -27,6 +28,23 @@
>  #define DOLPHIN_PROFILE_XOFFSET		8	/* x-electrode offset */
>  #define DOLPHIN_PROFILE_YOFFSET		1	/* y-electrode offset */
>  
> +/*
> + * enum V7_PACKET_ID - defines the packet type for V7
> + * V7_PACKET_ID_IDLE: There's no finger and no button activity.
> + * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad
> + *  or there's button activities.
> + * V7_PACKET_ID_MULTI: There are at least three non-resting fingers.
> + * V7_PACKET_ID_NEW: The finger position in slot is not continues from
> + *  previous packet.
> +*/
> +enum V7_PACKET_ID {
> +	 V7_PACKET_ID_IDLE,
> +	 V7_PACKET_ID_TWO,
> +	 V7_PACKET_ID_MULTI,
> +	 V7_PACKET_ID_NEW,
> +	 V7_PACKET_ID_UNKNOWN,
> +};
> +
>  /**
>   * struct alps_model_info - touchpad ID table
>   * @signature: E7 response string to match.
> -- 
> 2.0.0
> 

Thanks.

-- 
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 00/14] alps: bugfixes, cleanups and new hardware support
  2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
                   ` (13 preceding siblings ...)
  2014-07-09 15:24 ` [PATCH 14/14] alps: Add support for v7 devices Hans de Goede
@ 2014-07-26  5:59 ` Dmitry Torokhov
  14 siblings, 0 replies; 18+ messages in thread
From: Dmitry Torokhov @ 2014-07-26  5:59 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Yunkang Tang, linux-input

Hi Hans,

On Wed, Jul 09, 2014 at 05:24:05PM +0200, Hans de Goede wrote:
> Hi All,
> 
> This series started out as a single patch to add support for a new model
> of alps touchpad, called PROTO_V7 in this patchset.
> 
> While working on this I ended up doing some refactoring as preparation, which
> I tested on a Rushmore alps touchpad, which lead to some bugfixes and more
> cleanups, etc.
> 
> The result is a 14 patch patch-set, which:
> 
> 1) Significantly improves multi-touch support on V3 and V4 models (including
>    the Rushmore V3 variant)
> 2) Improves the code quality / readability quite a bit
> 3) Adds support for PROTO_V7

Excellent series, very easy to read. I have applied everything but v7
support as I have questions about that patch.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 14/14] alps: Add support for v7 devices
  2014-07-26  5:58   ` Dmitry Torokhov
@ 2014-07-26  8:22     ` Hans de Goede
  0 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2014-07-26  8:22 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input

Hi,

On 07/26/2014 07:59 AM, Dmitry Torokhov wrote:> Hi Hans,
>
> On Wed, Jul 09, 2014 at 05:24:05PM +0200, Hans de Goede wrote:
>> Hi All,
>>
>> This series started out as a single patch to add support for a new model
>> of alps touchpad, called PROTO_V7 in this patchset.
>>
>> While working on this I ended up doing some refactoring as preparation, which
>> I tested on a Rushmore alps touchpad, which lead to some bugfixes and more
>> cleanups, etc.
>>
>> The result is a 14 patch patch-set, which:
>>
>> 1) Significantly improves multi-touch support on V3 and V4 models (including
>>    the Rushmore V3 variant)
>> 2) Improves the code quality / readability quite a bit
>> 3) Adds support for PROTO_V7
>
> Excellent series, very easy to read. I have applied everything but v7
> support as I have questions about that patch.

I'm glad you like the series, that shows that my work to split it into
manageable bits was worth the extra effort, so that is good to hear.

On 07/26/2014 07:58 AM, Dmitry Torokhov wrote:
> Hi Hans,
> 
> On Wed, Jul 09, 2014 at 05:24:19PM +0200, Hans de Goede wrote:
>> From: Yunkang Tang <yunkang.tang@cn.alps.com>
>>
>> Such as found on the new Toshiba Portégé Z30-A and Z40-A.
>>
>> Signed-off-by: Yunkang Tang <yunkang.tang@cn.alps.com>
>> [hdegoede@redhat.com: Remove softbutton handling, this is done in userspace]
>> [hdegoede@redhat.com: Report INPUT_PROP_BUTTONPAD]
>> [hdegoede@redhat.com: Do not report fake PRESSURE, reporting BTN_TOUCH is
>>  enough]
>> [hdegoede@redhat.com: Various cleanups / refactoring]
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>  drivers/input/mouse/alps.c | 257 ++++++++++++++++++++++++++++++++++++++++++++-
>>  drivers/input/mouse/alps.h |  18 ++++
>>  2 files changed, 272 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
>> index ad3a708..8b9b4b0 100644
>> --- a/drivers/input/mouse/alps.c
>> +++ b/drivers/input/mouse/alps.c
>> @@ -100,6 +100,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
>>  #define ALPS_PS2_INTERLEAVED	0x80	/* 3-byte PS/2 packet interleaved with
>>  					   6-byte ALPS packet */
>>  #define ALPS_IS_RUSHMORE	0x100	/* device is a rushmore */
>> +#define ALPS_BUTTONPAD		0x200	/* device is a clickpad */
>>  
>>  static const struct alps_model_info alps_model_data[] = {
>>  	{ { 0x32, 0x02, 0x14 },	0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },	/* Toshiba Salellite Pro M10 */
>> @@ -845,6 +846,177 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
>>  	alps_report_semi_mt_data(psmouse, f->fingers);
>>  }
>>  
>> +static bool alps_is_valid_package_v7(struct psmouse *psmouse)
>> +{
>> +	if ((psmouse->pktcnt == 3) && ((psmouse->packet[2] & 0x40) != 0x40))
>> +		return false;
>> +	if ((psmouse->pktcnt == 4) && ((psmouse->packet[3] & 0x48) != 0x48))
>> +		return false;
>> +	if ((psmouse->pktcnt == 6) && ((psmouse->packet[5] & 0x40) != 0x0))
>> +		return false;
>> +	return true;
> 
> Maybe:
> 
> 	switch (psmouse->pktcnt) {
> 	case 3:
> 		return (psmouse->packet[2] & 0x40) == 0x40;
> 
> 	case 4:
> 		return (psmouse->packet[3] & 0x48) == 0x48;
> 
> 	case 6:
> 		return (psmouse->packet[5] & 0x40) == 0x00;
> 	}
> 
> 	return true;
> 
> ?

Will fix.

> 
> 
>> +}
>> +
>> +static unsigned char alps_get_packet_id_v7(char *byte)
>> +{
>> +	unsigned char packet_id;
>> +
>> +	if (byte[4] & 0x40)
>> +		packet_id = V7_PACKET_ID_TWO;
>> +	else if (byte[4] & 0x01)
>> +		packet_id = V7_PACKET_ID_MULTI;
>> +	else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
>> +		packet_id = V7_PACKET_ID_NEW;
>> +	else if (byte[1] == 0x00 && byte[4] == 0x00)
>> +		packet_id = V7_PACKET_ID_IDLE;
>> +	else
>> +		packet_id = V7_PACKET_ID_UNKNOWN;
>> +
>> +	return packet_id;
>> +}
>> +
>> +static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
>> +					  unsigned char *pkt,
>> +					  unsigned char pkt_id)
>> +{
>> +	mt[0].x = ((pkt[2] & 0x80) << 4);
>> +	mt[0].x |= ((pkt[2] & 0x3F) << 5);
>> +	mt[0].x |= ((pkt[3] & 0x30) >> 1);
>> +	mt[0].x |= (pkt[3] & 0x07);
>> +	mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07);
>> +
>> +	mt[1].x = ((pkt[3] & 0x80) << 4);
>> +	mt[1].x |= ((pkt[4] & 0x80) << 3);
>> +	mt[1].x |= ((pkt[4] & 0x3F) << 4);
>> +	mt[1].y = ((pkt[5] & 0x80) << 3);
>> +	mt[1].y |= ((pkt[5] & 0x3F) << 4);
>> +
>> +	if (pkt_id == V7_PACKET_ID_TWO) {
>> +		mt[1].x &= ~0x000F;
>> +		mt[1].y |= 0x000F;
>> +	} else if (pkt_id == V7_PACKET_ID_MULTI) {
>> +		mt[1].x &= ~0x003F;
>> +		mt[1].y &= ~0x0020;
>> +		mt[1].y |= ((pkt[4] & 0x02) << 4);
>> +		mt[1].y |= 0x001F;
>> +	} else if (pkt_id == V7_PACKET_ID_NEW) {
>> +		mt[1].x &= ~0x003F;
>> +		mt[1].x |= (pkt[0] & 0x20);
>> +		mt[1].y |= 0x000F;
>> +	}
>> +
>> +	mt[0].y = 0x7FF - mt[0].y;
>> +	mt[1].y = 0x7FF - mt[1].y;
>> +}
>> +
>> +static int alps_get_mt_count(struct input_mt_pos *mt)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < MAX_TOUCHES && mt[i].x != 0 && mt[i].y != 0; i++)
>> +		;
> 
> 		/* empty */;
> 
> just to make sure...

Will fix.

> 
>> +
>> +	return i;
>> +}
>> +
>> +static int alps_decode_packet_v7(struct alps_fields *f,
>> +				  unsigned char *p,
>> +				  struct psmouse *psmouse)
>> +{
>> +	unsigned char pkt_id;
>> +
>> +	pkt_id = alps_get_packet_id_v7(p);
>> +	if (pkt_id == V7_PACKET_ID_IDLE)
>> +		return 0;
>> +	if (pkt_id == V7_PACKET_ID_UNKNOWN)
>> +		return -1;
>> +
>> +	alps_get_finger_coordinate_v7(f->mt, p, pkt_id);
>> +
>> +	if (pkt_id == V7_PACKET_ID_TWO || pkt_id == V7_PACKET_ID_MULTI) {
>> +		f->left = (p[0] & 0x80) >> 7;
>> +		f->right = (p[0] & 0x20) >> 5;
>> +		f->middle = (p[0] & 0x10) >> 4;
>> +	}
>> +
>> +	if (pkt_id == V7_PACKET_ID_TWO)
>> +		f->fingers = alps_get_mt_count(f->mt);
>> +	else if (pkt_id == V7_PACKET_ID_MULTI)
>> +		f->fingers = 3 + (p[5] & 0x03);
>> +
>> +	return 0;
>> +}
>> +
>> +static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
>> +{
>> +	struct alps_data *priv = psmouse->private;
>> +	unsigned char *packet = psmouse->packet;
>> +	struct input_dev *dev2 = priv->dev2;
>> +	int x, y, z, left, right, middle;
>> +
>> +	/*
>> +	 *        b7 b6 b5 b4 b3 b2 b1 b0
>> +	 * Byte0   0  1  0  0  1  0  0  0
>> +	 * Byte1   1  1  *  *  1  M  R  L
>> +	 * Byte2  X7  1 X5 X4 X3 X2 X1 X0
>> +	 * Byte3  Z6  1 Y6 X6  1 Y2 Y1 Y0
>> +	 * Byte4  Y7  0 Y5 Y4 Y3  1  1  0
>> +	 * Byte5 T&P  0 Z5 Z4 Z3 Z2 Z1 Z0
>> +	 * M / R / L: Middle / Right / Left button
>> +	 */
>> +
>> +	x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2);
>> +	y = (packet[3] & 0x07) | (packet[4] & 0xb8) |
>> +	    ((packet[3] & 0x20) << 1);
>> +	z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
>> +
>> +	left = (packet[1] & 0x01);
>> +	right = (packet[1] & 0x02) >> 1;
>> +	middle = (packet[1] & 0x04) >> 2;
>> +
>> +	/* Divide 2 since trackpoint's speed is too fast */
>> +	input_report_rel(dev2, REL_X, (char)x / 2);
>> +	input_report_rel(dev2, REL_Y, -((char)y / 2));
>> +
>> +	input_report_key(dev2, BTN_LEFT, left);
>> +	input_report_key(dev2, BTN_RIGHT, right);
>> +	input_report_key(dev2, BTN_MIDDLE, middle);
>> +
>> +	input_sync(dev2);
>> +}
>> +
>> +static void alps_process_touchpad_packet_v7(struct psmouse *psmouse)
>> +{
>> +	struct alps_data *priv = psmouse->private;
>> +	struct input_dev *dev = psmouse->dev;
>> +	struct alps_fields *f = &priv->f;
>> +
>> +	memset(f, 0, sizeof(*f));
>> +
>> +	if (priv->decode_fields(f, psmouse->packet, psmouse))
>> +		return;
>> +
>> +	alps_report_mt_data(psmouse, alps_get_mt_count(f->mt));
>> +
>> +	input_mt_report_finger_count(dev, f->fingers);
>> +
>> +	input_report_key(dev, BTN_LEFT, f->left);
>> +	input_report_key(dev, BTN_RIGHT, f->right);
>> +	input_report_key(dev, BTN_MIDDLE, f->middle);
>> +
>> +	input_sync(dev);
>> +}
>> +
>> +static void alps_process_packet_v7(struct psmouse *psmouse)
>> +{
>> +	unsigned char *packet = psmouse->packet;
>> +
>> +	if ((packet[0] == 0x48) && ((packet[4] & 0x47) == 0x06))
>> +		alps_process_trackstick_packet_v7(psmouse);
>> +	else
>> +		alps_process_touchpad_packet_v7(psmouse);
>> +}
>> +
>>  static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
>>  					unsigned char packet[],
>>  					bool report_buttons)
>> @@ -1009,6 +1181,14 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
>>  		return PSMOUSE_BAD_DATA;
>>  	}
>>  
>> +	if (priv->proto_version == ALPS_PROTO_V7 &&
>> +			!alps_is_valid_package_v7(psmouse)) {
>> +		psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
>> +			    psmouse->pktcnt - 1,
>> +			    psmouse->packet[psmouse->pktcnt - 1]);
>> +		return PSMOUSE_BAD_DATA;
>> +	}
>> +
>>  	if (psmouse->pktcnt == psmouse->pktsize) {
>>  		priv->process_packet(psmouse);
>>  		return PSMOUSE_FULL_PACKET;
>> @@ -1121,6 +1301,22 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
>>  	return 0;
>>  }
>>  
>> +static int alps_check_valid_firmware_id(unsigned char id[])
> 
> bool
> 
>> +{
>> +	int valid = 1;
> 
> bool; true
> 
>> +
>> +	if (id[0] == 0x73)
>> +		valid = 1;
> 
> true
> 
>> +	else if (id[0] == 0x88) {
>> +		if ((id[1] == 0x07) ||
>> +		    (id[1] == 0x08) ||
>> +		    ((id[1] & 0xf0) == 0xB0))
>> +			valid = 1;
> 
> true
> 
>> +	}
>> +
>> +	return valid;
> 
> Hmmm, does not make sense - it is never false...

Right, if you look at the code it factors out (below)
valid should clearly be initialized to false, good catch.

Or even better, don't have valid at all simply use
"return true" in the if blocks and "return false"
at the end, that's what I'll do for v2.




> 
>> +}
>> +
>>  static int alps_enter_command_mode(struct psmouse *psmouse)
>>  {
>>  	unsigned char param[4];
>> @@ -1130,8 +1326,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse)
>>  		return -1;
>>  	}
>>  
>> -	if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
>> -	    param[0] != 0x73) {
>> +	if (!alps_check_valid_firmware_id(param)) {
>>  		psmouse_dbg(psmouse,
>>  			    "unknown response while entering command mode\n");
>>  		return -1;
>> @@ -1785,6 +1980,32 @@ static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
>>  	return 0;
>>  }


Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2014-07-26  8:22 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-09 15:24 [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Hans de Goede
2014-07-09 15:24 ` [PATCH 01/14] alps: Fix rushmore packet decoding Hans de Goede
2014-07-09 15:24 ` [PATCH 02/14] alps: Always report 2 fingers (or more) when receiving mt data on v3 models Hans de Goede
2014-07-09 15:24 ` [PATCH 03/14] alps: process_bitmap: Don't invert the Y-axis on Rushmore Hans de Goede
2014-07-09 15:24 ` [PATCH 04/14] alps: process_bitmap: Add alps_get_bitmap_points() helper function Hans de Goede
2014-07-09 15:24 ` [PATCH 05/14] alps: process_bitmap: Fix counting of high point bits Hans de Goede
2014-07-09 15:24 ` [PATCH 06/14] alps: process_bitmap: Round down when spreading adjescent fingers over 2 points Hans de Goede
2014-07-09 15:24 ` [PATCH 07/14] alps: Use struct input_mt_pos to track coordinates Hans de Goede
2014-07-09 15:24 ` [PATCH 08/14] alps: Use input_mt_assign_slots && input_mt_sync_frame instead of DIY Hans de Goede
2014-07-09 15:24 ` [PATCH 09/14] alps: Use single touch data when v3 mt data contains only one finger Hans de Goede
2014-07-09 15:24 ` [PATCH 10/14] alps: Add an alps_report_semi_mt_data function Hans de Goede
2014-07-09 15:24 ` [PATCH 11/14] alps: Report 2 touches when we've > 2 fingers Hans de Goede
2014-07-09 15:24 ` [PATCH 12/14] alps: Change decode function prototype to return an int Hans de Goede
2014-07-09 15:24 ` [PATCH 13/14] alps: Cache firmware version Hans de Goede
2014-07-09 15:24 ` [PATCH 14/14] alps: Add support for v7 devices Hans de Goede
2014-07-26  5:58   ` Dmitry Torokhov
2014-07-26  8:22     ` Hans de Goede
2014-07-26  5:59 ` [PATCH 00/14] alps: bugfixes, cleanups and new hardware support Dmitry Torokhov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.