All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/8] Input: elantech: add support for newer hardware
@ 2011-08-29  8:28 ` JJ Ding
  0 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

Hi Lists,

This is a series of patches to add support for newer generations of ELAN
touchpad.

Patches #1~#6 are essentially fixes and cleanups that pave the way for
patch #7 and patch #8, which really adds code for v3 and v4 hardware.

Any comments, suggestoins are welcome.

Note:
Please review patch #8, which adds support for the latest touchpads from ELAN.
This is a true multi-touch capable touchpad that can track up to 5 fingers.
Support is implemented using MT-B protocol. I used synaptics and multitouch X
driver to test this driver, both worked fine.

Thank you very much.

Changes since v1:
- drop EC workaround patch.
- add patch #2, make ST and MT have the same range, as Dmitry suggested.
- add patch #4, remove ETP_EDGE_FUZZ_V2, as Éric suggested.
- rename all packet checking functions so they are consistent.
- some code cleanup, and don't report ABS_[XY] when fingers == 0, as Seth suggested.
- add document for v3 debounce, and now check debounce in elantech_packet_check_v3.

Changes since v2:
- fix v3 hardware packet checking (reported by Seth and fix by Dmitry.)

Changes since v3:
- fix a tiny style problem (useless space on end-of-line, reported by Seth)
- v3 hardware can track 2 fingers well, so do not set INPUT_PROP_SEMI_MT on v3
  (As suggested earlier by Éric.)
- add patch #8, which adds support for v4 hardware.

JJ Ding (8):
  Input: elantech - correct x, y value range for v2 hardware
  Input: elantech - get rid of ETP_2FT_* in elantech.h
  Input: elantech - use firmware provided x, y ranges
  Input: elantech - remove ETP_EDGE_FUZZ_V2
  Input: elantech - packet checking for v2 hardware
  Input: elantech - clean up elantech_init
  Input: elantech - add v3 hardware support
  Input: elantech - add v4 hardware support

 Documentation/input/elantech.txt |  295 +++++++++++++++++-
 drivers/input/mouse/elantech.c   |  614 ++++++++++++++++++++++++++++++++-----
 drivers/input/mouse/elantech.h   |   56 +++-
 3 files changed, 849 insertions(+), 116 deletions(-)

-- 
1.7.4.1


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

* [PATCH v4 0/8] Input: elantech: add support for newer hardware
@ 2011-08-29  8:28 ` JJ Ding
  0 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

Hi Lists,

This is a series of patches to add support for newer generations of ELAN
touchpad.

Patches #1~#6 are essentially fixes and cleanups that pave the way for
patch #7 and patch #8, which really adds code for v3 and v4 hardware.

Any comments, suggestoins are welcome.

Note:
Please review patch #8, which adds support for the latest touchpads from ELAN.
This is a true multi-touch capable touchpad that can track up to 5 fingers.
Support is implemented using MT-B protocol. I used synaptics and multitouch X
driver to test this driver, both worked fine.

Thank you very much.

Changes since v1:
- drop EC workaround patch.
- add patch #2, make ST and MT have the same range, as Dmitry suggested.
- add patch #4, remove ETP_EDGE_FUZZ_V2, as Éric suggested.
- rename all packet checking functions so they are consistent.
- some code cleanup, and don't report ABS_[XY] when fingers == 0, as Seth suggested.
- add document for v3 debounce, and now check debounce in elantech_packet_check_v3.

Changes since v2:
- fix v3 hardware packet checking (reported by Seth and fix by Dmitry.)

Changes since v3:
- fix a tiny style problem (useless space on end-of-line, reported by Seth)
- v3 hardware can track 2 fingers well, so do not set INPUT_PROP_SEMI_MT on v3
  (As suggested earlier by Éric.)
- add patch #8, which adds support for v4 hardware.

JJ Ding (8):
  Input: elantech - correct x, y value range for v2 hardware
  Input: elantech - get rid of ETP_2FT_* in elantech.h
  Input: elantech - use firmware provided x, y ranges
  Input: elantech - remove ETP_EDGE_FUZZ_V2
  Input: elantech - packet checking for v2 hardware
  Input: elantech - clean up elantech_init
  Input: elantech - add v3 hardware support
  Input: elantech - add v4 hardware support

 Documentation/input/elantech.txt |  295 +++++++++++++++++-
 drivers/input/mouse/elantech.c   |  614 ++++++++++++++++++++++++++++++++-----
 drivers/input/mouse/elantech.h   |   56 +++-
 3 files changed, 849 insertions(+), 116 deletions(-)

-- 
1.7.4.1

--
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] 23+ messages in thread

* [PATCH v4 1/8] Input: elantech - correct x, y value range for v2 hardware
  2011-08-29  8:28 ` JJ Ding
  (?)
@ 2011-08-29  8:28 ` JJ Ding
  -1 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

x, y values are actually 12-bit long. Also update protocol document to reflect
the change.

Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Acked-by: Daniel Kurtz <djkurtz@chromium.org>
---
 Documentation/input/elantech.txt |    8 ++++----
 drivers/input/mouse/elantech.c   |    8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt
index db798af..bce9941 100644
--- a/Documentation/input/elantech.txt
+++ b/Documentation/input/elantech.txt
@@ -389,14 +389,14 @@ byte 0:
 byte 1:
 
    bit   7   6   5   4   3   2   1   0
-	 p7  p6  p5  p4  .  x10 x9  x8
+	 p7  p6  p5  p4 x11 x10 x9  x8
 
 byte 2:
 
    bit   7   6   5   4   3   2   1   0
 	 x7  x6  x5  x4  x3  x2  x1  x0
 
-         x10..x0 = absolute x value (horizontal)
+         x11..x0 = absolute x value (horizontal)
 
 byte 3:
 
@@ -420,7 +420,7 @@ byte 3:
 byte 4:
 
    bit   7   6   5   4   3   2   1   0
-        p3  p1  p2  p0   .   .  y9  y8
+        p3  p1  p2  p0  y11 y10 y9  y8
 
 	 p7..p0 = pressure (not EF113)
 
@@ -429,7 +429,7 @@ byte 5:
    bit   7   6   5   4   3   2   1   0
         y7  y6  y5  y4  y3  y2  y1  y0
 
-         y9..y0 = absolute y value (vertical)
+         y11..y0 = absolute y value (vertical)
 
 
 4.2.2 Two finger touch
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 3250356..da161da 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -290,15 +290,15 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 		/* pass through... */
 	case 1:
 		/*
-		 * byte 1:  .   .   .   .   .  x10 x9  x8
+		 * byte 1:  .   .   .   .  x11 x10 x9  x8
 		 * byte 2: x7  x6  x5  x4  x4  x2  x1  x0
 		 */
-		x1 = ((packet[1] & 0x07) << 8) | packet[2];
+		x1 = ((packet[1] & 0x0f) << 8) | packet[2];
 		/*
-		 * byte 4:  .   .   .   .   .   .  y9  y8
+		 * byte 4:  .   .   .   .  y11 y10 y9  y8
 		 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
 		 */
-		y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]);
+		y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]);
 
 		input_report_abs(dev, ABS_X, x1);
 		input_report_abs(dev, ABS_Y, y1);
-- 
1.7.4.1


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

* [PATCH v4 2/8] Input: elantech - get rid of ETP_2FT_* in elantech.h
  2011-08-29  8:28 ` JJ Ding
  (?)
  (?)
@ 2011-08-29  8:28 ` JJ Ding
  -1 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

For two finger touches the coordinate of each finger gets reported
separately but with reduced resolution.

With this change, we now have the same range for ST and MT data and
scale MT data because it has lower resolution to match ST.

Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Acked-by: Daniel Kurtz <djkurtz@chromium.org>
---
 drivers/input/mouse/elantech.c |   28 +++++++++++++---------------
 drivers/input/mouse/elantech.h |   11 -----------
 2 files changed, 13 insertions(+), 26 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index da161da..cd8e2e5 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -273,11 +273,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 	struct elantech_data *etd = psmouse->private;
 	struct input_dev *dev = psmouse->dev;
 	unsigned char *packet = psmouse->packet;
-	unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0;
+	unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+	unsigned int width = 0, pres = 0;
 
 	/* byte 0: n1  n0   .   .   .   .   R   L */
 	fingers = (packet[0] & 0xc0) >> 6;
-	input_report_key(dev, BTN_TOUCH, fingers != 0);
 
 	switch (fingers) {
 	case 3:
@@ -300,9 +300,6 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 		 */
 		y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]);
 
-		input_report_abs(dev, ABS_X, x1);
-		input_report_abs(dev, ABS_Y, y1);
-
 		pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
 		width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
 		break;
@@ -314,22 +311,18 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 		 * byte 0:  .   .  ay8 ax8  .   .   .   .
 		 * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0
 		 */
-		x1 = ((packet[0] & 0x10) << 4) | packet[1];
+		x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2;
 		/* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */
-		y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]);
+		y1 = ETP_YMAX_V2 -
+			((((packet[0] & 0x20) << 3) | packet[2]) << 2);
 		/*
 		 * byte 3:  .   .  by8 bx8  .   .   .   .
 		 * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0
 		 */
-		x2 = ((packet[3] & 0x10) << 4) | packet[4];
+		x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2;
 		/* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */
-		y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]);
-		/*
-		 * For compatibility with the X Synaptics driver scale up
-		 * one coordinate and report as ordinary mouse movent
-		 */
-		input_report_abs(dev, ABS_X, x1 << 2);
-		input_report_abs(dev, ABS_Y, y1 << 2);
+		y2 = ETP_YMAX_V2 -
+			((((packet[3] & 0x20) << 3) | packet[5]) << 2);
 
 		/* Unknown so just report sensible values */
 		pres = 127;
@@ -337,6 +330,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 		break;
 	}
 
+	input_report_key(dev, BTN_TOUCH, fingers != 0);
+	if (fingers != 0) {
+		input_report_abs(dev, ABS_X, x1);
+		input_report_abs(dev, ABS_Y, y1);
+	}
 	elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
 	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
 	input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index fabb2b9..1c5894e 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -82,17 +82,6 @@
 #define ETP_WMIN_V2			0
 #define ETP_WMAX_V2			15
 
-/*
- * For two finger touches the coordinate of each finger gets reported
- * separately but with reduced resolution.
- */
-#define ETP_2FT_FUZZ			4
-
-#define ETP_2FT_XMIN			(  0 + ETP_2FT_FUZZ)
-#define ETP_2FT_XMAX			(288 - ETP_2FT_FUZZ)
-#define ETP_2FT_YMIN			(  0 + ETP_2FT_FUZZ)
-#define ETP_2FT_YMAX			(192 - ETP_2FT_FUZZ)
-
 struct elantech_data {
 	unsigned char reg_10;
 	unsigned char reg_11;
-- 
1.7.4.1


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

* [PATCH v4 3/8] Input: elantech - use firmware provided x, y ranges
  2011-08-29  8:28 ` JJ Ding
                   ` (2 preceding siblings ...)
  (?)
@ 2011-08-29  8:28 ` JJ Ding
  -1 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

With newer hardware, the touchpad provides range info.
Let's use it.

Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Acked-by: Daniel Kurtz <djkurtz@chromium.org>
---
 drivers/input/mouse/elantech.c |   71 +++++++++++++++++++++++++++++++--------
 drivers/input/mouse/elantech.h |    3 +-
 2 files changed, 58 insertions(+), 16 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index cd8e2e5..282b8b6 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -223,7 +223,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
 		input_report_abs(dev, ABS_X,
 			((packet[1] & 0x0c) << 6) | packet[2]);
 		input_report_abs(dev, ABS_Y,
-			ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3]));
+			etd->y_max - (((packet[1] & 0x03) << 8) | packet[3]));
 	}
 
 	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
@@ -233,7 +233,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
 	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
 
 	if (etd->fw_version < 0x020000 &&
-	    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
+	    (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
 		/* rocker up */
 		input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
 		/* rocker down */
@@ -298,7 +298,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 		 * byte 4:  .   .   .   .  y11 y10 y9  y8
 		 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
 		 */
-		y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]);
+		y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
 
 		pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
 		width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
@@ -313,7 +313,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 		 */
 		x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2;
 		/* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */
-		y1 = ETP_YMAX_V2 -
+		y1 = etd->y_max -
 			((((packet[0] & 0x20) << 3) | packet[2]) << 2);
 		/*
 		 * byte 3:  .   .  by8 bx8  .   .   .   .
@@ -321,7 +321,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 		 */
 		x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2;
 		/* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */
-		y2 = ETP_YMAX_V2 -
+		y2 = etd->y_max -
 			((((packet[3] & 0x20) << 3) | packet[5]) << 2);
 
 		/* Unknown so just report sensible values */
@@ -468,6 +468,41 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
 	return rc;
 }
 
+static void set_range(struct psmouse *psmouse, unsigned int *x_min,
+		     unsigned int *y_min, unsigned int *x_max,
+		     unsigned int *y_max)
+{
+	struct elantech_data *etd = psmouse->private;
+	int i;
+
+	switch (etd->hw_version) {
+	case 1:
+		*x_min = ETP_XMIN_V1;
+		*y_min = ETP_YMIN_V1;
+		*x_max = ETP_XMAX_V1;
+		*y_max = ETP_YMAX_V1;
+		break;
+
+	case 2:
+		if (etd->fw_version == 0x020800 ||
+		    etd->fw_version == 0x020b00 ||
+		    etd->fw_version == 0x020030) {
+			*x_min = ETP_XMIN_V2;
+			*y_min = ETP_YMIN_V2;
+			*x_max = ETP_XMAX_V2;
+			*y_max = ETP_YMAX_V2;
+		} else {
+			i = (etd->fw_version > 0x020800 &&
+			     etd->fw_version < 0x020900) ? 1 : 2;
+			*x_min = 0;
+			*y_min = 0;
+			*x_max = (etd->capabilities[1] - i) * 64;
+			*y_max = (etd->capabilities[2] - i) * 64;
+		}
+		break;
+	}
+}
+
 /*
  * Set the appropriate event bits for the input subsystem
  */
@@ -475,6 +510,9 @@ static void elantech_set_input_params(struct psmouse *psmouse)
 {
 	struct input_dev *dev = psmouse->dev;
 	struct elantech_data *etd = psmouse->private;
+	unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0;
+
+	set_range(psmouse, &x_min, &y_min, &x_max, &y_max);
 
 	__set_bit(EV_KEY, dev->evbit);
 	__set_bit(EV_ABS, dev->evbit);
@@ -492,18 +530,18 @@ static void elantech_set_input_params(struct psmouse *psmouse)
 	case 1:
 		/* Rocker button */
 		if (etd->fw_version < 0x020000 &&
-		    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
+		    (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
 			__set_bit(BTN_FORWARD, dev->keybit);
 			__set_bit(BTN_BACK, dev->keybit);
 		}
-		input_set_abs_params(dev, ABS_X, ETP_XMIN_V1, ETP_XMAX_V1, 0, 0);
-		input_set_abs_params(dev, ABS_Y, ETP_YMIN_V1, ETP_YMAX_V1, 0, 0);
+		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
 		break;
 
 	case 2:
 		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
-		input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0);
-		input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0);
+		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
 		if (etd->reports_pressure) {
 			input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
 					     ETP_PMAX_V2, 0, 0);
@@ -512,10 +550,12 @@ static void elantech_set_input_params(struct psmouse *psmouse)
 		}
 		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
 		input_mt_init_slots(dev, 2);
-		input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0);
-		input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
 		break;
 	}
+
+	etd->y_max = y_max;
 }
 
 struct elantech_attr_data {
@@ -769,13 +809,14 @@ int elantech_init(struct psmouse *psmouse)
 	pr_info("assuming hardware version %d, firmware version %d.%d.%d\n",
 		etd->hw_version, param[0], param[1], param[2]);
 
-	if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) {
+	if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY,
+	    etd->capabilities)) {
 		pr_err("failed to query capabilities.\n");
 		goto init_fail;
 	}
 	pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
-		param[0], param[1], param[2]);
-	etd->capabilities = param[0];
+		etd->capabilities[0], etd->capabilities[1],
+		etd->capabilities[2]);
 
 	/*
 	 * This firmware suffers from misreporting coordinates when
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index 1c5894e..b54ea27 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -93,13 +93,14 @@ struct elantech_data {
 	unsigned char reg_25;
 	unsigned char reg_26;
 	unsigned char debug;
-	unsigned char capabilities;
+	unsigned char capabilities[3];
 	bool paritycheck;
 	bool jumpy_cursor;
 	bool reports_pressure;
 	unsigned char hw_version;
 	unsigned int fw_version;
 	unsigned int single_finger_reports;
+	unsigned int y_max;
 	unsigned char parity[256];
 };
 
-- 
1.7.4.1


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

* [PATCH v4 4/8] Input: elantech - remove ETP_EDGE_FUZZ_V2
  2011-08-29  8:28 ` JJ Ding
@ 2011-08-29  8:28   ` JJ Ding
  -1 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

Don't try to be too clever and remove ETP_EDGE_FUZZ_V2. X, Y ranges
should be just the raw resolution of the device. Otherwise, they can
cause underflow on the Y axis.

Suggested-by: Éric Piel <eric.piel@tremplin-utc.net>
Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Acked-by: Daniel Kurtz <djkurtz@chromium.org>
---
 drivers/input/mouse/elantech.h |   15 ++++++---------
 1 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index b54ea27..d9e6144 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -66,16 +66,13 @@
 #define ETP_YMAX_V1			(384 - ETP_EDGE_FUZZ_V1)
 
 /*
- * It seems the resolution for hardware version 2 doubled.
- * Hence the X and Y ranges are doubled too.
- * The bezel around the pad also appears to be smaller
+ * The resolution for older v2 hardware doubled.
+ * (newer v2's firmware provides command so we can query)
  */
-#define ETP_EDGE_FUZZ_V2		8
-
-#define ETP_XMIN_V2			(   0 + ETP_EDGE_FUZZ_V2)
-#define ETP_XMAX_V2			(1152 - ETP_EDGE_FUZZ_V2)
-#define ETP_YMIN_V2			(   0 + ETP_EDGE_FUZZ_V2)
-#define ETP_YMAX_V2			( 768 - ETP_EDGE_FUZZ_V2)
+#define ETP_XMIN_V2			0
+#define ETP_XMAX_V2			1152
+#define ETP_YMIN_V2			0
+#define ETP_YMAX_V2			768
 
 #define ETP_PMIN_V2			0
 #define ETP_PMAX_V2			255
-- 
1.7.4.1


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

* [PATCH v4 4/8] Input: elantech - remove ETP_EDGE_FUZZ_V2
@ 2011-08-29  8:28   ` JJ Ding
  0 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

Don't try to be too clever and remove ETP_EDGE_FUZZ_V2. X, Y ranges
should be just the raw resolution of the device. Otherwise, they can
cause underflow on the Y axis.

Suggested-by: Éric Piel <eric.piel@tremplin-utc.net>
Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Acked-by: Daniel Kurtz <djkurtz@chromium.org>
---
 drivers/input/mouse/elantech.h |   15 ++++++---------
 1 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index b54ea27..d9e6144 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -66,16 +66,13 @@
 #define ETP_YMAX_V1			(384 - ETP_EDGE_FUZZ_V1)
 
 /*
- * It seems the resolution for hardware version 2 doubled.
- * Hence the X and Y ranges are doubled too.
- * The bezel around the pad also appears to be smaller
+ * The resolution for older v2 hardware doubled.
+ * (newer v2's firmware provides command so we can query)
  */
-#define ETP_EDGE_FUZZ_V2		8
-
-#define ETP_XMIN_V2			(   0 + ETP_EDGE_FUZZ_V2)
-#define ETP_XMAX_V2			(1152 - ETP_EDGE_FUZZ_V2)
-#define ETP_YMIN_V2			(   0 + ETP_EDGE_FUZZ_V2)
-#define ETP_YMAX_V2			( 768 - ETP_EDGE_FUZZ_V2)
+#define ETP_XMIN_V2			0
+#define ETP_XMAX_V2			1152
+#define ETP_YMIN_V2			0
+#define ETP_YMAX_V2			768
 
 #define ETP_PMIN_V2			0
 #define ETP_PMAX_V2			255
-- 
1.7.4.1

--
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] 23+ messages in thread

* [PATCH v4 5/8] Input: elantech - packet checking for v2 hardware
  2011-08-29  8:28 ` JJ Ding
                   ` (4 preceding siblings ...)
  (?)
@ 2011-08-29  8:28 ` JJ Ding
  -1 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

For v2 hardware, there is no real parity check, but we can still check
some constant bits for data integrity.

Also rename elantech_check_parity_v1 to elantech_packet_check_v1 to make
these packet checking function names consistent.

Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Acked-by: Daniel Kurtz <djkurtz@chromium.org>
---
 drivers/input/mouse/elantech.c |   39 ++++++++++++++++++++++++++++++++++-----
 1 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 282b8b6..008e8c2 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -350,7 +350,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 	input_sync(dev);
 }
 
-static int elantech_check_parity_v1(struct psmouse *psmouse)
+static int elantech_packet_check_v1(struct psmouse *psmouse)
 {
 	struct elantech_data *etd = psmouse->private;
 	unsigned char *packet = psmouse->packet;
@@ -374,6 +374,34 @@ static int elantech_check_parity_v1(struct psmouse *psmouse)
 	       etd->parity[packet[3]] == p3;
 }
 
+static int elantech_packet_check_v2(struct psmouse *psmouse)
+{
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+
+	/*
+	 * V2 hardware has two flavors. Older ones that do not report pressure,
+	 * and newer ones that reports pressure and width. With newer ones, all
+	 * packets (1, 2, 3 finger touch) have the same constant bits. With
+	 * older ones, 1/3 finger touch packets and 2 finger touch packets
+	 * have different constant bits.
+	 * With all three cases, if the constant bits are not exactly what I
+	 * expected, I consider them invalid.
+	 */
+	if (etd->reports_pressure)
+		return (packet[0] & 0x0c) == 0x04 &&
+		       (packet[3] & 0x0f) == 0x02;
+
+	if ((packet[0] & 0xc0) == 0x80)
+		return (packet[0] & 0x0c) == 0x0c &&
+		       (packet[3] & 0x0e) == 0x08;
+
+	return (packet[0] & 0x3c) == 0x3c &&
+	       (packet[1] & 0xf0) == 0x00 &&
+	       (packet[3] & 0x3e) == 0x38 &&
+	       (packet[4] & 0xf0) == 0x00;
+}
+
 /*
  * Process byte stream from mouse and handle complete packets
  */
@@ -389,14 +417,16 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
 
 	switch (etd->hw_version) {
 	case 1:
-		if (etd->paritycheck && !elantech_check_parity_v1(psmouse))
+		if (etd->paritycheck && !elantech_packet_check_v1(psmouse))
 			return PSMOUSE_BAD_DATA;
 
 		elantech_report_absolute_v1(psmouse);
 		break;
 
 	case 2:
-		/* We don't know how to check parity in protocol v2 */
+		if (etd->paritycheck && !elantech_packet_check_v2(psmouse))
+			return PSMOUSE_BAD_DATA;
+
 		elantech_report_absolute_v2(psmouse);
 		break;
 	}
@@ -795,8 +825,7 @@ int elantech_init(struct psmouse *psmouse)
 		etd->hw_version = 2;
 		/* For now show extra debug information */
 		etd->debug = 1;
-		/* Don't know how to do parity checking for version 2 */
-		etd->paritycheck = 0;
+		etd->paritycheck = 1;
 
 		if (etd->fw_version >= 0x020800)
 			etd->reports_pressure = true;
-- 
1.7.4.1


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

* [PATCH v4 6/8] Input: elantech - clean up elantech_init
  2011-08-29  8:28 ` JJ Ding
                   ` (5 preceding siblings ...)
  (?)
@ 2011-08-29  8:28 ` JJ Ding
  -1 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

Group property setting code into elantech_set_properties.

Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Acked-by: Daniel Kurtz <djkurtz@chromium.org>
---
 drivers/input/mouse/elantech.c |   69 ++++++++++++++++++++++-----------------
 1 files changed, 39 insertions(+), 30 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 008e8c2..2ae7c49 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -791,6 +791,42 @@ static int elantech_reconnect(struct psmouse *psmouse)
 }
 
 /*
+ * determine hardware version and set some properties according to it.
+ */
+static void elantech_set_properties(struct elantech_data *etd)
+{
+	/*
+	 * Assume every version greater than 0x020030 is new EeePC style
+	 * hardware with 6 byte packets, except 0x020600
+	 */
+	if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
+		etd->hw_version = 1;
+	else
+		etd->hw_version = 2;
+
+	/*
+	 * Turn on packet checking by default.
+	 */
+	etd->paritycheck = 1;
+
+	/*
+	 * This firmware suffers from misreporting coordinates when
+	 * a touch action starts causing the mouse cursor or scrolled page
+	 * to jump. Enable a workaround.
+	 */
+	etd->jumpy_cursor =
+		(etd->fw_version == 0x020022 || etd->fw_version == 0x020600);
+
+	if (etd->hw_version == 2) {
+		/* For now show extra debug information */
+		etd->debug = 1;
+
+		if (etd->fw_version >= 0x020800)
+			etd->reports_pressure = true;
+	}
+}
+
+/*
  * Initialize the touchpad and create sysfs entries
  */
 int elantech_init(struct psmouse *psmouse)
@@ -816,26 +852,9 @@ int elantech_init(struct psmouse *psmouse)
 	}
 
 	etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
-
-	/*
-	 * Assume every version greater than this is new EeePC style
-	 * hardware with 6 byte packets
-	 */
-	if (etd->fw_version >= 0x020030) {
-		etd->hw_version = 2;
-		/* For now show extra debug information */
-		etd->debug = 1;
-		etd->paritycheck = 1;
-
-		if (etd->fw_version >= 0x020800)
-			etd->reports_pressure = true;
-
-	} else {
-		etd->hw_version = 1;
-		etd->paritycheck = 1;
-	}
-
-	pr_info("assuming hardware version %d, firmware version %d.%d.%d\n",
+	elantech_set_properties(etd);
+	pr_info("assuming hardware version %d "
+		"(with firmware version 0x%02x%02x%02x)\n",
 		etd->hw_version, param[0], param[1], param[2]);
 
 	if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY,
@@ -847,16 +866,6 @@ int elantech_init(struct psmouse *psmouse)
 		etd->capabilities[0], etd->capabilities[1],
 		etd->capabilities[2]);
 
-	/*
-	 * This firmware suffers from misreporting coordinates when
-	 * a touch action starts causing the mouse cursor or scrolled page
-	 * to jump. Enable a workaround.
-	 */
-	if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) {
-		pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n");
-		etd->jumpy_cursor = true;
-	}
-
 	if (elantech_set_absolute_mode(psmouse)) {
 		pr_err("failed to put touchpad into absolute mode.\n");
 		goto init_fail;
-- 
1.7.4.1


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

* [PATCH v4 7/8] Input: elantech - add v3 hardware support
  2011-08-29  8:28 ` JJ Ding
                   ` (6 preceding siblings ...)
  (?)
@ 2011-08-29  8:28 ` JJ Ding
  -1 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

v3 hardware's packet format is almost identical to v2 (one/three finger touch),
except when sensing two finger touch, the hardware sends 12 bytes of data.

Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Acked-by: Daniel Kurtz <djkurtz@chromium.org>
Reviewed-and-Tested-by: Seth Forshee <seth.forshee@canonical.com>
---
 Documentation/input/elantech.txt |  117 +++++++++++++++++++---
 drivers/input/mouse/elantech.c   |  204 ++++++++++++++++++++++++++++++++++---
 drivers/input/mouse/elantech.h   |   12 +++
 3 files changed, 304 insertions(+), 29 deletions(-)

diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt
index bce9941..cee08ee 100644
--- a/Documentation/input/elantech.txt
+++ b/Documentation/input/elantech.txt
@@ -16,15 +16,22 @@ Contents
 
  1. Introduction
  2. Extra knobs
- 3. Hardware version 1
-    3.1 Registers
-    3.2 Native relative mode 4 byte packet format
-    3.3 Native absolute mode 4 byte packet format
- 4. Hardware version 2
+ 3. Differentiating hardware versions
+ 4. Hardware version 1
     4.1 Registers
-    4.2 Native absolute mode 6 byte packet format
-        4.2.1 One finger touch
-        4.2.2 Two finger touch
+    4.2 Native relative mode 4 byte packet format
+    4.3 Native absolute mode 4 byte packet format
+ 5. Hardware version 2
+    5.1 Registers
+    5.2 Native absolute mode 6 byte packet format
+        5.2.1 Parity checking and packet re-synchronization
+        5.2.2 One/Three finger touch
+        5.2.3 Two finger touch
+ 6. Hardware version 3
+    6.1 Registers
+    6.2 Native absolute mode 6 byte packet format
+        6.2.1 One/Three finger touch
+        6.2.2 Two finger touch
 
 
 
@@ -375,7 +382,7 @@ For all the other ones, there are just a few constant bits:
 
 In case an error is detected, all the packets are shifted by one (and packet[0] is discarded).
 
-5.2.1 One/Three finger touch
+5.2.2 One/Three finger touch
       ~~~~~~~~~~~~~~~~
 
 byte 0:
@@ -384,7 +391,7 @@ byte 0:
 	 n1  n0  w3  w2   .   .   R   L
 
          L, R = 1 when Left, Right mouse button pressed
-         n1..n0 = numbers of fingers on touchpad
+         n1..n0 = number of fingers on touchpad
 
 byte 1:
 
@@ -432,7 +439,7 @@ byte 5:
          y11..y0 = absolute y value (vertical)
 
 
-4.2.2 Two finger touch
+5.2.3 Two finger touch
       ~~~~~~~~~~~~~~~~
 
 Note that the two pairs of coordinates are not exactly the coordinates of the
@@ -446,7 +453,7 @@ byte 0:
         n1  n0  ay8 ax8  .   .   R   L
 
          L, R = 1 when Left, Right mouse button pressed
-         n1..n0 = numbers of fingers on touchpad
+         n1..n0 = number of fingers on touchpad
 
 byte 1:
 
@@ -480,3 +487,89 @@ byte 5:
         by7 by8 by5 by4 by3 by2 by1 by0
 
          by8..by0 = upper-right finger absolute y value
+
+/////////////////////////////////////////////////////////////////////////////
+
+6. Hardware version 3
+   ==================
+
+6.1 Registers
+    ~~~~~~~~~
+* reg_10
+
+   bit   7   6   5   4   3   2   1   0
+         0   0   0   0   0   0   0   A
+
+         A: 1 = enable absolute tracking
+
+6.2 Native absolute mode 6 byte packet format
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1 and 3 finger touch shares the same 6-byte packet format, except that
+3 finger touch only reports the position of the center of all three fingers.
+
+Firmware would send 12 bytes of data for 2 finger touch.
+
+Note on debounce:
+In case the box has unstable power supply or other electricity issues, or
+when number of finger changes, F/W would send "debounce packet" to inform
+driver that the hardware is in debounce status.
+The debouce packet has the following signature:
+    byte 0: 0xc4
+    byte 1: 0xff
+    byte 2: 0xff
+    byte 3: 0x02
+    byte 4: 0xff
+    byte 5: 0xff
+When we encounter this kind of packet, we just ignore it.
+
+6.2.1 One/Three finger touch
+      ~~~~~~~~~~~~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+        n1  n0  w3  w2   0   1   R   L
+
+        L, R = 1 when Left, Right mouse button pressed
+        n1..n0 = number of fingers on touchpad
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+        p7  p6  p5  p4 x11 x10  x9  x8
+
+byte 2:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x11..x0 = absolute x value (horizontal)
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+         0   0  w1  w0   0   0   1   0
+
+         w3..w0 = width of the finger touch
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+        p3  p1  p2  p0  y11 y10 y9  y8
+
+        p7..p0 = pressure
+
+byte 5:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y11..y0 = absolute y value (vertical)
+
+6.2.2 Two finger touch
+      ~~~~~~~~~~~~~~~~
+
+The packet format is exactly the same for two finger touch, except the hardware
+sends two 6 byte packets. The first packet contains data for the first finger,
+the second packet has data for the second finger. So for two finger touch a
+total of 12 bytes are sent.
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 2ae7c49..c4ceefd 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -108,6 +108,16 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
 			rc = -1;
 		}
 		break;
+
+	case 3:
+		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, reg) ||
+		    elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
+			rc = -1;
+		}
+		break;
 	}
 
 	if (rc)
@@ -154,6 +164,18 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
 			rc = -1;
 		}
 		break;
+
+	case 3:
+		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, reg) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, val) ||
+		    elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+			rc = -1;
+		}
+		break;
 	}
 
 	if (rc)
@@ -350,6 +372,84 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 	input_sync(dev);
 }
 
+/*
+ * Interpret complete data packets and report absolute mode input events for
+ * hardware version 3. (12 byte packets for two fingers)
+ */
+static void elantech_report_absolute_v3(struct psmouse *psmouse,
+					int packet_type)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+	unsigned int width = 0, pres = 0;
+
+	/* byte 0: n1  n0   .   .   .   .   R   L */
+	fingers = (packet[0] & 0xc0) >> 6;
+
+	switch (fingers) {
+	case 3:
+	case 1:
+		/*
+		 * byte 1:  .   .   .   .  x11 x10 x9  x8
+		 * byte 2: x7  x6  x5  x4  x4  x2  x1  x0
+		 */
+		x1 = ((packet[1] & 0x0f) << 8) | packet[2];
+		/*
+		 * byte 4:  .   .   .   .  y11 y10 y9  y8
+		 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
+		 */
+		y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+		break;
+
+	case 2:
+		if (packet_type == PACKET_V3_HEAD) {
+			/*
+			 * byte 1:   .    .    .    .  ax11 ax10 ax9  ax8
+			 * byte 2: ax7  ax6  ax5  ax4  ax3  ax2  ax1  ax0
+			 */
+			etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2];
+			/*
+			 * byte 4:   .    .    .    .  ay11 ay10 ay9  ay8
+			 * byte 5: ay7  ay6  ay5  ay4  ay3  ay2  ay1  ay0
+			 */
+			etd->prev_y = etd->y_max -
+				(((packet[4] & 0x0f) << 8) | packet[5]);
+			/*
+			 * wait for next packet
+			 */
+			return;
+		}
+
+		/* packet_type == PACKET_V3_TAIL */
+		x1 = etd->prev_x;
+		y1 = etd->prev_y;
+		x2 = ((packet[1] & 0x0f) << 8) | packet[2];
+		y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+		break;
+	}
+
+	pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+	width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
+
+	input_report_key(dev, BTN_TOUCH, fingers != 0);
+	if (fingers != 0) {
+		input_report_abs(dev, ABS_X, x1);
+		input_report_abs(dev, ABS_Y, y1);
+	}
+	elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
+	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
+	input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
+	input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
+	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
+	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+	input_report_abs(dev, ABS_PRESSURE, pres);
+	input_report_abs(dev, ABS_TOOL_WIDTH, width);
+
+	input_sync(dev);
+}
+
 static int elantech_packet_check_v1(struct psmouse *psmouse)
 {
 	struct elantech_data *etd = psmouse->private;
@@ -403,11 +503,37 @@ static int elantech_packet_check_v2(struct psmouse *psmouse)
 }
 
 /*
+ * We check the constant bits to determine what packet type we get,
+ * so packet checking is mandatory for v3 hardware.
+ */
+static int elantech_packet_check_v3(struct psmouse *psmouse)
+{
+	const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
+	unsigned char *packet = psmouse->packet;
+
+	/*
+	 * check debounce first, it has the same signature in byte 0
+	 * and byte 3 as PACKET_V3_HEAD.
+	 */
+	if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
+		return PACKET_DEBOUNCE;
+
+	if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
+		return PACKET_V3_HEAD;
+
+	if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
+		return PACKET_V3_TAIL;
+
+	return PACKET_UNKNOWN;
+}
+
+/*
  * Process byte stream from mouse and handle complete packets
  */
 static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
 {
 	struct elantech_data *etd = psmouse->private;
+	int packet_type;
 
 	if (psmouse->pktcnt < psmouse->pktsize)
 		return PSMOUSE_GOOD_DATA;
@@ -429,6 +555,18 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
 
 		elantech_report_absolute_v2(psmouse);
 		break;
+
+	case 3:
+		packet_type = elantech_packet_check_v3(psmouse);
+		/* ignore debounce */
+		if (packet_type == PACKET_DEBOUNCE)
+			return PSMOUSE_FULL_PACKET;
+
+		if (packet_type == PACKET_UNKNOWN)
+			return PSMOUSE_BAD_DATA;
+
+		elantech_report_absolute_v3(psmouse, packet_type);
+		break;
 	}
 
 	return PSMOUSE_FULL_PACKET;
@@ -463,8 +601,15 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
 		    elantech_write_reg(psmouse, 0x11, etd->reg_11) ||
 		    elantech_write_reg(psmouse, 0x21, etd->reg_21)) {
 			rc = -1;
-			break;
 		}
+		break;
+
+	case 3:
+		etd->reg_10 = 0x0b;
+		if (elantech_write_reg(psmouse, 0x10, etd->reg_10))
+			rc = -1;
+
+		break;
 	}
 
 	if (rc == 0) {
@@ -498,11 +643,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
 	return rc;
 }
 
-static void set_range(struct psmouse *psmouse, unsigned int *x_min,
+static int set_range(struct psmouse *psmouse, unsigned int *x_min,
 		     unsigned int *y_min, unsigned int *x_max,
 		     unsigned int *y_max)
 {
 	struct elantech_data *etd = psmouse->private;
+	unsigned char param[3];
 	int i;
 
 	switch (etd->hw_version) {
@@ -530,19 +676,30 @@ static void set_range(struct psmouse *psmouse, unsigned int *x_min,
 			*y_max = (etd->capabilities[2] - i) * 64;
 		}
 		break;
+
+	case 3:
+		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+			return -1;
+
+		*x_max = (0x0f & param[0]) << 8 | param[1];
+		*y_max = (0xf0 & param[0]) << 4 | param[2];
+		break;
 	}
+
+	return 0;
 }
 
 /*
  * Set the appropriate event bits for the input subsystem
  */
-static void elantech_set_input_params(struct psmouse *psmouse)
+static int elantech_set_input_params(struct psmouse *psmouse)
 {
 	struct input_dev *dev = psmouse->dev;
 	struct elantech_data *etd = psmouse->private;
 	unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0;
 
-	set_range(psmouse, &x_min, &y_min, &x_max, &y_max);
+	if (set_range(psmouse, &x_min, &y_min, &x_max, &y_max))
+		return -1;
 
 	__set_bit(EV_KEY, dev->evbit);
 	__set_bit(EV_ABS, dev->evbit);
@@ -570,6 +727,9 @@ static void elantech_set_input_params(struct psmouse *psmouse)
 
 	case 2:
 		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
+		/* fall through */
+	case 3:
 		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
 		if (etd->reports_pressure) {
@@ -578,7 +738,6 @@ static void elantech_set_input_params(struct psmouse *psmouse)
 			input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
 					     ETP_WMAX_V2, 0, 0);
 		}
-		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
 		input_mt_init_slots(dev, 2);
 		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
@@ -586,6 +745,8 @@ static void elantech_set_input_params(struct psmouse *psmouse)
 	}
 
 	etd->y_max = y_max;
+
+	return 0;
 }
 
 struct elantech_attr_data {
@@ -727,7 +888,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
 	 * Report this in case there are Elantech models that use a different
 	 * set of magic numbers
 	 */
-	if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) {
+	if (param[0] != 0x3c || param[1] != 0x03 ||
+	    (param[2] != 0xc8 && param[2] != 0x00)) {
 		pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
 			 param[0], param[1], param[2]);
 		return -1;
@@ -793,16 +955,16 @@ static int elantech_reconnect(struct psmouse *psmouse)
 /*
  * determine hardware version and set some properties according to it.
  */
-static void elantech_set_properties(struct elantech_data *etd)
+static int elantech_set_properties(struct elantech_data *etd)
 {
-	/*
-	 * Assume every version greater than 0x020030 is new EeePC style
-	 * hardware with 6 byte packets, except 0x020600
-	 */
 	if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
 		etd->hw_version = 1;
-	else
+	else if (etd->fw_version < 0x150600)
 		etd->hw_version = 2;
+	else if ((etd->fw_version & 0x0f0000) >> 16 == 5)
+		etd->hw_version = 3;
+	else
+		return -1;
 
 	/*
 	 * Turn on packet checking by default.
@@ -817,13 +979,15 @@ static void elantech_set_properties(struct elantech_data *etd)
 	etd->jumpy_cursor =
 		(etd->fw_version == 0x020022 || etd->fw_version == 0x020600);
 
-	if (etd->hw_version == 2) {
+	if (etd->hw_version > 1) {
 		/* For now show extra debug information */
 		etd->debug = 1;
 
 		if (etd->fw_version >= 0x020800)
 			etd->reports_pressure = true;
 	}
+
+	return 0;
 }
 
 /*
@@ -850,9 +1014,12 @@ int elantech_init(struct psmouse *psmouse)
 		pr_err("failed to query firmware version.\n");
 		goto init_fail;
 	}
-
 	etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
-	elantech_set_properties(etd);
+
+	if (elantech_set_properties(etd)) {
+		pr_err("unknown hardware version, aborting...\n");
+		goto init_fail;
+	}
 	pr_info("assuming hardware version %d "
 		"(with firmware version 0x%02x%02x%02x)\n",
 		etd->hw_version, param[0], param[1], param[2]);
@@ -871,7 +1038,10 @@ int elantech_init(struct psmouse *psmouse)
 		goto init_fail;
 	}
 
-	elantech_set_input_params(psmouse);
+	if (elantech_set_input_params(psmouse)) {
+		pr_err("failed to query touchpad range.\n");
+		goto init_fail;
+	}
 
 	error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
 				   &elantech_attr_group);
@@ -883,7 +1053,7 @@ int elantech_init(struct psmouse *psmouse)
 	psmouse->protocol_handler = elantech_process_byte;
 	psmouse->disconnect = elantech_disconnect;
 	psmouse->reconnect = elantech_reconnect;
-	psmouse->pktsize = etd->hw_version == 2 ? 6 : 4;
+	psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
 
 	return 0;
 
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index d9e6144..236c33c 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -16,6 +16,7 @@
 /*
  * Command values for Synaptics style queries
  */
+#define ETP_FW_ID_QUERY			0x00
 #define ETP_FW_VERSION_QUERY		0x01
 #define ETP_CAPABILITIES_QUERY		0x02
 
@@ -24,6 +25,7 @@
  */
 #define ETP_REGISTER_READ		0x10
 #define ETP_REGISTER_WRITE		0x11
+#define ETP_REGISTER_READWRITE		0x00
 
 /*
  * Hardware version 2 custom PS/2 command value
@@ -79,6 +81,14 @@
 #define ETP_WMIN_V2			0
 #define ETP_WMAX_V2			15
 
+/*
+ * v3 hardware has 2 kinds of packet types.
+ */
+#define PACKET_UNKNOWN			0x01
+#define PACKET_DEBOUNCE			0x02
+#define PACKET_V3_HEAD			0x03
+#define PACKET_V3_TAIL			0x04
+
 struct elantech_data {
 	unsigned char reg_10;
 	unsigned char reg_11;
@@ -98,6 +108,8 @@ struct elantech_data {
 	unsigned int fw_version;
 	unsigned int single_finger_reports;
 	unsigned int y_max;
+	unsigned int prev_x;
+	unsigned int prev_y;
 	unsigned char parity[256];
 };
 
-- 
1.7.4.1


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

* [PATCH v4 8/8] Input: elantech - add v4 hardware support
  2011-08-29  8:28 ` JJ Ding
                   ` (7 preceding siblings ...)
  (?)
@ 2011-08-29  8:28 ` JJ Ding
  2011-08-30 13:50   ` Tom _Lin
  2011-08-31 12:50     ` Éric Piel
  -1 siblings, 2 replies; 23+ messages in thread
From: JJ Ding @ 2011-08-29  8:28 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Seth Forshee, Dmitry Torokhov, Aaron Huang, Tom Lin,
	Éric Piel, Daniel Kurtz, Chase Douglas, Henrik Rydberg,
	Alessandro Rubini, JJ Ding

v4 hardware is a true multitouch capable touchpad (up to 5 fingers).
The packet format is quite complex, please see protocol document for
reference.

Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
---
 Documentation/input/elantech.txt |  170 ++++++++++++++++++++++++++
 drivers/input/mouse/elantech.c   |  247 ++++++++++++++++++++++++++++++++++----
 drivers/input/mouse/elantech.h   |   29 ++++-
 3 files changed, 420 insertions(+), 26 deletions(-)

diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt
index cee08ee..f63115a 100644
--- a/Documentation/input/elantech.txt
+++ b/Documentation/input/elantech.txt
@@ -32,6 +32,12 @@ Contents
     6.2 Native absolute mode 6 byte packet format
         6.2.1 One/Three finger touch
         6.2.2 Two finger touch
+ 7. Hardware version 4
+    7.1 Registers
+    7.2 Native absolute mode 6 byte packet format
+        7.2.1 Status packet
+        7.2.2 Head packet
+        7.2.3 Motion packet
 
 
 
@@ -573,3 +579,167 @@ The packet format is exactly the same for two finger touch, except the hardware
 sends two 6 byte packets. The first packet contains data for the first finger,
 the second packet has data for the second finger. So for two finger touch a
 total of 12 bytes are sent.
+
+/////////////////////////////////////////////////////////////////////////////
+
+7. Hardware version 4
+   ==================
+
+7.1 Registers
+    ~~~~~~~~~
+* reg_07
+
+   bit   7   6   5   4   3   2   1   0
+         0   0   0   0   0   0   0   A
+
+         A: 1 = enable absolute tracking
+
+7.2 Native absolute mode 6 byte packet format
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers.
+Unfortunately, due to PS/2's limited bandwidth, its packet format is rather
+complex.
+
+Whenever the numbers or identities of the fingers changes, the hardware sends a
+status packet to indicate how many and which fingers is on touchpad, followed by
+head packets or motion packets. A head packet contains data of finger id, finger
+position (absolute x, y values), width, and presure. A motion packet contains
+two fingers' position delta.
+
+For example, when status packet tells there are 2 fingers on touchpad, then we
+can expect two following head packets. If the finger status doesn't change,
+the following packets would be motion packets, only sending delta of finger
+position, until we receive a status packet.
+
+One exception is one finger touch. when a status packet tells us there is only
+one finger, the hardware would just send head packets afterwards.
+
+7.2.1 Status packet
+      ~~~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+         .   .   .   .   0   1   R   L
+
+         L, R = 1 when Left, Right mouse button pressed
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+         .   .   . ft4 ft3 ft2 ft1 ft0
+
+         ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad
+
+byte 2: not used
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+         .   .   .   1   0   0   0   0
+
+         constant bits
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+         p   .   .   .   .   .   .   .
+
+         p = 1 for palm
+
+byte 5: not used
+
+7.2.2 Head packet
+      ~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+        w3  w2  w1  w0   0   1   R   L
+
+        L, R = 1 when Left, Right mouse button pressed
+        w3..w0 = finger width (spans how many trace lines)
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+        p7  p6  p5  p4 x11 x10  x9  x8
+
+byte 2:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x11..x0 = absolute x value (horizontal)
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+       id2 id1 id0   1   0   0   0   1
+
+       id2..id0 = finger id
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+        p3  p1  p2  p0  y11 y10 y9  y8
+
+        p7..p0 = pressure
+
+byte 5:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y11..y0 = absolute y value (vertical)
+
+7.2.3 Motion packet
+      ~~~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+       id2 id1 id0   w   0   1   R   L
+
+       L, R = 1 when Left, Right mouse button pressed
+       id2..id0 = finger id
+       w = 1 when delta overflows (> 127 or < -128), in this case
+       firmware sends us (delta x / 5) and (delta y  / 5)
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x7..x0 = delta x (two's complement)
+
+byte 2:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y7..y0 = delta y (two's complement)
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+       id2 id1 id0   1   0   0   1   0
+
+       id2..id0 = finger id
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x7..x0 = delta x (two's complement)
+
+byte 5:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y7..y0 = delta y (two's complement)
+
+        byte 0 ~ 2 for one finger
+        byte 3 ~ 5 for another
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index c4ceefd..0d3936d 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -84,12 +84,6 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
 	unsigned char param[3];
 	int rc = 0;
 
-	if (reg < 0x10 || reg > 0x26)
-		return -1;
-
-	if (reg > 0x11 && reg < 0x20)
-		return -1;
-
 	switch (etd->hw_version) {
 	case 1:
 		if (psmouse_sliced_command(psmouse, ETP_REGISTER_READ) ||
@@ -109,7 +103,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
 		}
 		break;
 
-	case 3:
+	case 3 ... 4:
 		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
 		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
 		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
@@ -122,8 +116,10 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
 
 	if (rc)
 		pr_err("failed to read register 0x%02x.\n", reg);
-	else
+	else if (etd->hw_version != 4)
 		*val = param[0];
+	else
+		*val = param[1];
 
 	return rc;
 }
@@ -137,12 +133,6 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
 	struct elantech_data *etd = psmouse->private;
 	int rc = 0;
 
-	if (reg < 0x10 || reg > 0x26)
-		return -1;
-
-	if (reg > 0x11 && reg < 0x20)
-		return -1;
-
 	switch (etd->hw_version) {
 	case 1:
 		if (psmouse_sliced_command(psmouse, ETP_REGISTER_WRITE) ||
@@ -176,6 +166,20 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
 			rc = -1;
 		}
 		break;
+
+	case 4:
+		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, reg) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, val) ||
+		    elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+			rc = -1;
+		}
+		break;
 	}
 
 	if (rc)
@@ -409,12 +413,12 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
 			 * byte 1:   .    .    .    .  ax11 ax10 ax9  ax8
 			 * byte 2: ax7  ax6  ax5  ax4  ax3  ax2  ax1  ax0
 			 */
-			etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2];
+			etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2];
 			/*
 			 * byte 4:   .    .    .    .  ay11 ay10 ay9  ay8
 			 * byte 5: ay7  ay6  ay5  ay4  ay3  ay2  ay1  ay0
 			 */
-			etd->prev_y = etd->y_max -
+			etd->mt[0].y = etd->y_max -
 				(((packet[4] & 0x0f) << 8) | packet[5]);
 			/*
 			 * wait for next packet
@@ -423,8 +427,8 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
 		}
 
 		/* packet_type == PACKET_V3_TAIL */
-		x1 = etd->prev_x;
-		y1 = etd->prev_y;
+		x1 = etd->mt[0].x;
+		y1 = etd->mt[0].y;
 		x2 = ((packet[1] & 0x0f) << 8) | packet[2];
 		y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
 		break;
@@ -450,6 +454,129 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
 	input_sync(dev);
 }
 
+static void elantech_mt_sync(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	unsigned char *packet = psmouse->packet;
+
+	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
+	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+	input_mt_report_pointer_emulation(dev, true);
+	input_sync(dev);
+}
+
+static void process_packet_status(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	unsigned char *packet = psmouse->packet;
+	unsigned fingers;
+	int i;
+
+	/* notify finger state change */
+	fingers = packet[1] & 0x1f;
+	for (i = 0; i < ETP_MAX_FINGERS; i++) {
+		if ((fingers & (1 << i)) == 0) {
+			input_mt_slot(dev, i);
+			input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
+		}
+	}
+
+	elantech_mt_sync(psmouse);
+}
+
+static void process_packet_head(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	int id = ((packet[3] & 0xe0) >> 5) - 1;
+	int pres, traces;
+
+	if (id < 0)
+		return;
+
+	etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2];
+	etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+	pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+	traces = (packet[0] & 0xf0) >> 4;
+
+	input_mt_slot(dev, id);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+
+	input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
+	input_report_abs(dev, ABS_MT_PRESSURE, pres);
+	input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width);
+	/* report this for backwards compatibility */
+	input_report_abs(dev, ABS_TOOL_WIDTH, traces);
+
+	elantech_mt_sync(psmouse);
+}
+
+static void process_packet_motion(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0;
+	int id, sid;
+
+	id = ((packet[0] & 0xe0) >> 5) - 1;
+	if (id < 0)
+		return;
+
+	sid = ((packet[3] & 0xe0) >> 5) - 1;
+	weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1;
+	/*
+	 * Motion packets give us the delta of x, y values of specific fingers,
+	 * but in two's complement. Let the compiler do the conversion for us.
+	 * Also _enlarge_ the numbers to int, in case of overflow.
+	 */
+	delta_x1 = (signed char)packet[1];
+	delta_y1 = (signed char)packet[2];
+	delta_x2 = (signed char)packet[4];
+	delta_y2 = (signed char)packet[5];
+
+	etd->mt[id].x += delta_x1 * weight;
+	etd->mt[id].y -= delta_y1 * weight;
+	input_mt_slot(dev, id);
+	input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
+
+	if (sid >= 0) {
+		etd->mt[sid].x += delta_x2 * weight;
+		etd->mt[sid].y -= delta_y2 * weight;
+		input_mt_slot(dev, sid);
+		input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x);
+		input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y);
+	}
+
+	elantech_mt_sync(psmouse);
+}
+
+static void elantech_report_absolute_v4(struct psmouse *psmouse,
+					int packet_type)
+{
+	switch (packet_type) {
+	case PACKET_V4_STATUS:
+		process_packet_status(psmouse);
+		break;
+
+	case PACKET_V4_HEAD:
+		process_packet_head(psmouse);
+		break;
+
+	case PACKET_V4_MOTION:
+		process_packet_motion(psmouse);
+		break;
+
+	case PACKET_UNKNOWN:
+	default:
+		/* impossible to get here */
+		break;
+	}
+}
+
 static int elantech_packet_check_v1(struct psmouse *psmouse)
 {
 	struct elantech_data *etd = psmouse->private;
@@ -504,7 +631,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse)
 
 /*
  * We check the constant bits to determine what packet type we get,
- * so packet checking is mandatory for v3 hardware.
+ * so packet checking is mandatory for v3 and later hardware.
  */
 static int elantech_packet_check_v3(struct psmouse *psmouse)
 {
@@ -527,6 +654,25 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
 	return PACKET_UNKNOWN;
 }
 
+static int elantech_packet_check_v4(struct psmouse *psmouse)
+{
+	unsigned char *packet = psmouse->packet;
+
+	if ((packet[0] & 0x0c) == 0x04 &&
+	    (packet[3] & 0x1f) == 0x11)
+		return PACKET_V4_HEAD;
+
+	if ((packet[0] & 0x0c) == 0x04 &&
+	    (packet[3] & 0x1f) == 0x12)
+		return PACKET_V4_MOTION;
+
+	if ((packet[0] & 0x0c) == 0x04 &&
+	    (packet[3] & 0x1f) == 0x10)
+		return PACKET_V4_STATUS;
+
+	return PACKET_UNKNOWN;
+}
+
 /*
  * Process byte stream from mouse and handle complete packets
  */
@@ -567,6 +713,14 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
 
 		elantech_report_absolute_v3(psmouse, packet_type);
 		break;
+
+	case 4:
+		packet_type = elantech_packet_check_v4(psmouse);
+		if (packet_type == PACKET_UNKNOWN)
+			return PSMOUSE_BAD_DATA;
+
+		elantech_report_absolute_v4(psmouse, packet_type);
+		break;
 	}
 
 	return PSMOUSE_FULL_PACKET;
@@ -610,6 +764,13 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
 			rc = -1;
 
 		break;
+
+	case 4:
+		etd->reg_07 = 0x01;
+		if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
+			rc = -1;
+
+		goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */
 	}
 
 	if (rc == 0) {
@@ -637,6 +798,7 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
 		}
 	}
 
+ skip_readback_reg_10:
 	if (rc)
 		pr_err("failed to initialise registers.\n");
 
@@ -645,10 +807,11 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
 
 static int set_range(struct psmouse *psmouse, unsigned int *x_min,
 		     unsigned int *y_min, unsigned int *x_max,
-		     unsigned int *y_max)
+		     unsigned int *y_max, unsigned int *width)
 {
 	struct elantech_data *etd = psmouse->private;
 	unsigned char param[3];
+	unsigned char traces = 0;
 	int i;
 
 	switch (etd->hw_version) {
@@ -677,12 +840,16 @@ static int set_range(struct psmouse *psmouse, unsigned int *x_min,
 		}
 		break;
 
+	case 4:
+		traces = etd->capabilities[1];
+		/* pass through */
 	case 3:
 		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
 			return -1;
 
 		*x_max = (0x0f & param[0]) << 8 | param[1];
 		*y_max = (0xf0 & param[0]) << 4 | param[2];
+		*width = *x_max / (traces - 1);
 		break;
 	}
 
@@ -696,9 +863,9 @@ static int elantech_set_input_params(struct psmouse *psmouse)
 {
 	struct input_dev *dev = psmouse->dev;
 	struct elantech_data *etd = psmouse->private;
-	unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0;
+	unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
 
-	if (set_range(psmouse, &x_min, &y_min, &x_max, &y_max))
+	if (set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
 		return -1;
 
 	__set_bit(EV_KEY, dev->evbit);
@@ -742,9 +909,37 @@ static int elantech_set_input_params(struct psmouse *psmouse)
 		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
 		break;
+
+	case 4:
+		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+		/* For X to recognize me as touchpad. */
+		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
+		/*
+		 * range of pressure and width is the same as v2,
+		 * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
+		 */
+		input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
+				     ETP_PMAX_V2, 0, 0);
+		input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
+				     ETP_WMAX_V2, 0, 0);
+		/* Multitouch capable pad, up to 5 fingers. */
+		input_mt_init_slots(dev, ETP_MAX_FINGERS);
+		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+		input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
+				     ETP_PMAX_V2, 0, 0);
+		/*
+		 * The firmware reports how many trace lines the finger spans,
+		 * convert to surface unit as Protocol-B requires.
+		 */
+		input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0,
+				     ETP_WMAX_V2 * width, 0, 0);
+		break;
 	}
 
 	etd->y_max = y_max;
+	etd->width = width;
 
 	return 0;
 }
@@ -816,6 +1011,7 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse,
 			    elantech_show_int_attr,			\
 			    elantech_set_int_attr)
 
+ELANTECH_INT_ATTR(reg_07, 0x07);
 ELANTECH_INT_ATTR(reg_10, 0x10);
 ELANTECH_INT_ATTR(reg_11, 0x11);
 ELANTECH_INT_ATTR(reg_20, 0x20);
@@ -829,6 +1025,7 @@ ELANTECH_INT_ATTR(debug, 0);
 ELANTECH_INT_ATTR(paritycheck, 0);
 
 static struct attribute *elantech_attrs[] = {
+	&psmouse_attr_reg_07.dattr.attr,
 	&psmouse_attr_reg_10.dattr.attr,
 	&psmouse_attr_reg_11.dattr.attr,
 	&psmouse_attr_reg_20.dattr.attr,
@@ -957,12 +1154,16 @@ static int elantech_reconnect(struct psmouse *psmouse)
  */
 static int elantech_set_properties(struct elantech_data *etd)
 {
+	int ver = (etd->fw_version & 0x0f0000) >> 16;
+
 	if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
 		etd->hw_version = 1;
 	else if (etd->fw_version < 0x150600)
 		etd->hw_version = 2;
-	else if ((etd->fw_version & 0x0f0000) >> 16 == 5)
+	else if (ver == 5)
 		etd->hw_version = 3;
+	else if (ver == 6)
+		etd->hw_version = 4;
 	else
 		return -1;
 
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index 236c33c..7ecaef0 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -82,14 +82,37 @@
 #define ETP_WMAX_V2			15
 
 /*
- * v3 hardware has 2 kinds of packet types.
+ * v3 hardware has 2 kinds of packet types,
+ * v4 hardware has 3.
  */
 #define PACKET_UNKNOWN			0x01
 #define PACKET_DEBOUNCE			0x02
 #define PACKET_V3_HEAD			0x03
 #define PACKET_V3_TAIL			0x04
+#define PACKET_V4_HEAD			0x05
+#define PACKET_V4_MOTION		0x06
+#define PACKET_V4_STATUS		0x07
+
+/*
+ * track up to 5 fingers for v4 hardware
+ */
+#define ETP_MAX_FINGERS			5
+
+/*
+ * weight value for v4 hardware
+ */
+#define ETP_WEIGHT_VALUE		5
+
+/*
+ * The base position for one finger, v4 hardware
+ */
+struct finger_pos {
+	unsigned int x;
+	unsigned int y;
+};
 
 struct elantech_data {
+	unsigned char reg_07;
 	unsigned char reg_10;
 	unsigned char reg_11;
 	unsigned char reg_20;
@@ -108,8 +131,8 @@ struct elantech_data {
 	unsigned int fw_version;
 	unsigned int single_finger_reports;
 	unsigned int y_max;
-	unsigned int prev_x;
-	unsigned int prev_y;
+	unsigned int width;
+	struct finger_pos mt[ETP_MAX_FINGERS];
 	unsigned char parity[256];
 };
 
-- 
1.7.4.1


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

* Re: [PATCH v4 8/8] Input: elantech - add v4 hardware support
  2011-08-29  8:28 ` [PATCH v4 8/8] Input: elantech - add v4 " JJ Ding
@ 2011-08-30 13:50   ` Tom _Lin
  2011-08-31 12:50     ` Éric Piel
  1 sibling, 0 replies; 23+ messages in thread
From: Tom _Lin @ 2011-08-30 13:50 UTC (permalink / raw)
  To: JJ Ding
  Cc: linux-input, linux-kernel, Seth Forshee, Dmitry Torokhov,
	Aaron Huang, Éric Piel, Daniel Kurtz, Chase Douglas,
	Henrik Rydberg, Alessandro Rubini

Hi JJ
On Mon, 2011-08-29 at 16:28 +0800, JJ Ding wrote:
> v4 hardware is a true multitouch capable touchpad (up to 5 fingers).
> The packet format is quite complex, please see protocol document for
> reference.
> 
> Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
> ---
>  Documentation/input/elantech.txt |  170 ++++++++++++++++++++++++++
>  drivers/input/mouse/elantech.c   |  247 ++++++++++++++++++++++++++++++++++----
>  drivers/input/mouse/elantech.h   |   29 ++++-
>  3 files changed, 420 insertions(+), 26 deletions(-)
> 
> diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt
> index cee08ee..f63115a 100644
> --- a/Documentation/input/elantech.txt
> +++ b/Documentation/input/elantech.txt
> @@ -32,6 +32,12 @@ Contents
>      6.2 Native absolute mode 6 byte packet format
>          6.2.1 One/Three finger touch
>          6.2.2 Two finger touch
> + 7. Hardware version 4
> +    7.1 Registers
> +    7.2 Native absolute mode 6 byte packet format
> +        7.2.1 Status packet
> +        7.2.2 Head packet
> +        7.2.3 Motion packet
>  
> 
> 
> @@ -573,3 +579,167 @@ The packet format is exactly the same for two finger touch, except the hardware
>  sends two 6 byte packets. The first packet contains data for the first finger,
>  the second packet has data for the second finger. So for two finger touch a
>  total of 12 bytes are sent.
> +
> +/////////////////////////////////////////////////////////////////////////////
> +
> +7. Hardware version 4
> +   ==================
> +
> +7.1 Registers
> +    ~~~~~~~~~
> +* reg_07
> +
> +   bit   7   6   5   4   3   2   1   0
> +         0   0   0   0   0   0   0   A
> +
> +         A: 1 = enable absolute tracking
> +
> +7.2 Native absolute mode 6 byte packet format
> +    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers.
> +Unfortunately, due to PS/2's limited bandwidth, its packet format is rather
> +complex.
> +
> +Whenever the numbers or identities of the fingers changes, the hardware sends a
> +status packet to indicate how many and which fingers is on touchpad, followed by
> +head packets or motion packets. A head packet contains data of finger id, finger
> +position (absolute x, y values), width, and presure. A motion packet contains
> +two fingers' position delta.
> +
> +For example, when status packet tells there are 2 fingers on touchpad, then we
> +can expect two following head packets. If the finger status doesn't change,
> +the following packets would be motion packets, only sending delta of finger
> +position, until we receive a status packet.
> +
> +One exception is one finger touch. when a status packet tells us there is only
> +one finger, the hardware would just send head packets afterwards.
> +
> +7.2.1 Status packet
> +      ~~~~~~~~~~~~~
> +
> +byte 0:
> +
> +   bit   7   6   5   4   3   2   1   0
> +         .   .   .   .   0   1   R   L
> +
> +         L, R = 1 when Left, Right mouse button pressed
> +
> +byte 1:
> +
> +   bit   7   6   5   4   3   2   1   0
> +         .   .   . ft4 ft3 ft2 ft1 ft0
> +
> +         ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad
> +
> +byte 2: not used
> +
> +byte 3:
> +
> +   bit   7   6   5   4   3   2   1   0
> +         .   .   .   1   0   0   0   0
> +
> +         constant bits
> +
> +byte 4:
> +
> +   bit   7   6   5   4   3   2   1   0
> +         p   .   .   .   .   .   .   .
> +
> +         p = 1 for palm
> +
> +byte 5: not used
> +
> +7.2.2 Head packet
> +      ~~~~~~~~~~~
> +
> +byte 0:
> +
> +   bit   7   6   5   4   3   2   1   0
> +        w3  w2  w1  w0   0   1   R   L
> +
> +        L, R = 1 when Left, Right mouse button pressed
> +        w3..w0 = finger width (spans how many trace lines)
> +
> +byte 1:
> +
> +   bit   7   6   5   4   3   2   1   0
> +        p7  p6  p5  p4 x11 x10  x9  x8
> +
> +byte 2:
> +
> +   bit   7   6   5   4   3   2   1   0
> +        x7  x6  x5  x4  x3  x2  x1  x0
> +
> +        x11..x0 = absolute x value (horizontal)
> +
> +byte 3:
> +
> +   bit   7   6   5   4   3   2   1   0
> +       id2 id1 id0   1   0   0   0   1
> +
> +       id2..id0 = finger id
> +
> +byte 4:
> +
> +   bit   7   6   5   4   3   2   1   0
> +        p3  p1  p2  p0  y11 y10 y9  y8
> +
> +        p7..p0 = pressure
> +
> +byte 5:
> +
> +   bit   7   6   5   4   3   2   1   0
> +        y7  y6  y5  y4  y3  y2  y1  y0
> +
> +        y11..y0 = absolute y value (vertical)
> +
> +7.2.3 Motion packet
> +      ~~~~~~~~~~~~~
> +
> +byte 0:
> +
> +   bit   7   6   5   4   3   2   1   0
> +       id2 id1 id0   w   0   1   R   L
> +
> +       L, R = 1 when Left, Right mouse button pressed
> +       id2..id0 = finger id
> +       w = 1 when delta overflows (> 127 or < -128), in this case
> +       firmware sends us (delta x / 5) and (delta y  / 5)
> +
> +byte 1:
> +
> +   bit   7   6   5   4   3   2   1   0
> +        x7  x6  x5  x4  x3  x2  x1  x0
> +
> +        x7..x0 = delta x (two's complement)
> +
> +byte 2:
> +
> +   bit   7   6   5   4   3   2   1   0
> +        y7  y6  y5  y4  y3  y2  y1  y0
> +
> +        y7..y0 = delta y (two's complement)
> +
> +byte 3:
> +
> +   bit   7   6   5   4   3   2   1   0
> +       id2 id1 id0   1   0   0   1   0
> +
> +       id2..id0 = finger id
> +
> +byte 4:
> +
> +   bit   7   6   5   4   3   2   1   0
> +        x7  x6  x5  x4  x3  x2  x1  x0
> +
> +        x7..x0 = delta x (two's complement)
> +
> +byte 5:
> +
> +   bit   7   6   5   4   3   2   1   0
> +        y7  y6  y5  y4  y3  y2  y1  y0
> +
> +        y7..y0 = delta y (two's complement)
> +
> +        byte 0 ~ 2 for one finger
> +        byte 3 ~ 5 for another
> diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
> index c4ceefd..0d3936d 100644
> --- a/drivers/input/mouse/elantech.c
> +++ b/drivers/input/mouse/elantech.c
> @@ -84,12 +84,6 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
>  	unsigned char param[3];
>  	int rc = 0;
>  
> -	if (reg < 0x10 || reg > 0x26)
> -		return -1;
> -
> -	if (reg > 0x11 && reg < 0x20)
> -		return -1;
> -
>  	switch (etd->hw_version) {
>  	case 1:
>  		if (psmouse_sliced_command(psmouse, ETP_REGISTER_READ) ||
> @@ -109,7 +103,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
>  		}
>  		break;
>  
> -	case 3:
> +	case 3 ... 4:
>  		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
>  		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
>  		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> @@ -122,8 +116,10 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
>  
>  	if (rc)
>  		pr_err("failed to read register 0x%02x.\n", reg);
> -	else
> +	else if (etd->hw_version != 4)
>  		*val = param[0];
> +	else
> +		*val = param[1];
>  
>  	return rc;
>  }
> @@ -137,12 +133,6 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
>  	struct elantech_data *etd = psmouse->private;
>  	int rc = 0;
>  
> -	if (reg < 0x10 || reg > 0x26)
> -		return -1;
> -
> -	if (reg > 0x11 && reg < 0x20)
> -		return -1;
> -
>  	switch (etd->hw_version) {
>  	case 1:
>  		if (psmouse_sliced_command(psmouse, ETP_REGISTER_WRITE) ||
> @@ -176,6 +166,20 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
>  			rc = -1;
>  		}
>  		break;
> +
> +	case 4:
> +		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> +		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
> +		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> +		    elantech_ps2_command(psmouse, NULL, reg) ||
> +		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> +		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
> +		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> +		    elantech_ps2_command(psmouse, NULL, val) ||
> +		    elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
> +			rc = -1;
> +		}
> +		break;
>  	}
>  
>  	if (rc)
> @@ -409,12 +413,12 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
>  			 * byte 1:   .    .    .    .  ax11 ax10 ax9  ax8
>  			 * byte 2: ax7  ax6  ax5  ax4  ax3  ax2  ax1  ax0
>  			 */
> -			etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2];
> +			etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2];
>  			/*
>  			 * byte 4:   .    .    .    .  ay11 ay10 ay9  ay8
>  			 * byte 5: ay7  ay6  ay5  ay4  ay3  ay2  ay1  ay0
>  			 */
> -			etd->prev_y = etd->y_max -
> +			etd->mt[0].y = etd->y_max -
>  				(((packet[4] & 0x0f) << 8) | packet[5]);
>  			/*
>  			 * wait for next packet
> @@ -423,8 +427,8 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
>  		}
>  
>  		/* packet_type == PACKET_V3_TAIL */
> -		x1 = etd->prev_x;
> -		y1 = etd->prev_y;
> +		x1 = etd->mt[0].x;
> +		y1 = etd->mt[0].y;
>  		x2 = ((packet[1] & 0x0f) << 8) | packet[2];
>  		y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
>  		break;
> @@ -450,6 +454,129 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
>  	input_sync(dev);
>  }
>  
> +static void elantech_mt_sync(struct psmouse *psmouse)
> +{
> +	struct input_dev *dev = psmouse->dev;
> +	unsigned char *packet = psmouse->packet;
> +
> +	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
> +	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
> +	input_mt_report_pointer_emulation(dev, true);
> +	input_sync(dev);
> +}
> +
> +static void process_packet_status(struct psmouse *psmouse)
> +{
> +	struct input_dev *dev = psmouse->dev;
> +	unsigned char *packet = psmouse->packet;
> +	unsigned fingers;
> +	int i;
> +
> +	/* notify finger state change */
> +	fingers = packet[1] & 0x1f;
> +	for (i = 0; i < ETP_MAX_FINGERS; i++) {
> +		if ((fingers & (1 << i)) == 0) {
> +			input_mt_slot(dev, i);
> +			input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
> +		}
> +	}
> +
> +	elantech_mt_sync(psmouse);
> +}
> +
> +static void process_packet_head(struct psmouse *psmouse)
> +{
> +	struct input_dev *dev = psmouse->dev;
> +	struct elantech_data *etd = psmouse->private;
> +	unsigned char *packet = psmouse->packet;
> +	int id = ((packet[3] & 0xe0) >> 5) - 1;
> +	int pres, traces;
> +
> +	if (id < 0)
> +		return;
> +
> +	etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2];
> +	etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
> +	pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
> +	traces = (packet[0] & 0xf0) >> 4;
> +
> +	input_mt_slot(dev, id);
> +	input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
> +
> +	input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
> +	input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
> +	input_report_abs(dev, ABS_MT_PRESSURE, pres);
> +	input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width);
> +	/* report this for backwards compatibility */
> +	input_report_abs(dev, ABS_TOOL_WIDTH, traces);
> +
> +	elantech_mt_sync(psmouse);
> +}
> +
> +static void process_packet_motion(struct psmouse *psmouse)
> +{
> +	struct input_dev *dev = psmouse->dev;
> +	struct elantech_data *etd = psmouse->private;
> +	unsigned char *packet = psmouse->packet;
> +	int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0;
> +	int id, sid;
> +
> +	id = ((packet[0] & 0xe0) >> 5) - 1;
> +	if (id < 0)
> +		return;
> +
> +	sid = ((packet[3] & 0xe0) >> 5) - 1;
> +	weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1;
> +	/*
> +	 * Motion packets give us the delta of x, y values of specific fingers,
> +	 * but in two's complement. Let the compiler do the conversion for us.
> +	 * Also _enlarge_ the numbers to int, in case of overflow.
> +	 */
> +	delta_x1 = (signed char)packet[1];
> +	delta_y1 = (signed char)packet[2];
> +	delta_x2 = (signed char)packet[4];
> +	delta_y2 = (signed char)packet[5];
> +
> +	etd->mt[id].x += delta_x1 * weight;
> +	etd->mt[id].y -= delta_y1 * weight;
> +	input_mt_slot(dev, id);
> +	input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
> +	input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
> +
> +	if (sid >= 0) {
> +		etd->mt[sid].x += delta_x2 * weight;
> +		etd->mt[sid].y -= delta_y2 * weight;
> +		input_mt_slot(dev, sid);
> +		input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x);
> +		input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y);
> +	}
> +
> +	elantech_mt_sync(psmouse);
> +}
> +
> +static void elantech_report_absolute_v4(struct psmouse *psmouse,
> +					int packet_type)
> +{
> +	switch (packet_type) {
> +	case PACKET_V4_STATUS:
> +		process_packet_status(psmouse);
> +		break;
> +
> +	case PACKET_V4_HEAD:
> +		process_packet_head(psmouse);
> +		break;
> +
> +	case PACKET_V4_MOTION:
> +		process_packet_motion(psmouse);
> +		break;
> +
> +	case PACKET_UNKNOWN:
		  elantech_packet_dump(psmouse->packet, psmosue->pktsize);
You could add this function here.
We will get detail data for debug when data type is PACKET_UNKNOWN.
> +	default:
> +		/* impossible to get here */
> +		break;
> +	}
> +}
> +
>  static int elantech_packet_check_v1(struct psmouse *psmouse)
>  {
>  	struct elantech_data *etd = psmouse->private;
> @@ -504,7 +631,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse)
>  
>  /*
>   * We check the constant bits to determine what packet type we get,
> - * so packet checking is mandatory for v3 hardware.
> + * so packet checking is mandatory for v3 and later hardware.
>   */
>  static int elantech_packet_check_v3(struct psmouse *psmouse)
>  {
> @@ -527,6 +654,25 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
>  	return PACKET_UNKNOWN;
>  }
>  
> +static int elantech_packet_check_v4(struct psmouse *psmouse)
> +{
> +	unsigned char *packet = psmouse->packet;
> +
> +	if ((packet[0] & 0x0c) == 0x04 &&
> +	    (packet[3] & 0x1f) == 0x11)
> +		return PACKET_V4_HEAD;
> +
> +	if ((packet[0] & 0x0c) == 0x04 &&
> +	    (packet[3] & 0x1f) == 0x12)
> +		return PACKET_V4_MOTION;
> +
> +	if ((packet[0] & 0x0c) == 0x04 &&
> +	    (packet[3] & 0x1f) == 0x10)
> +		return PACKET_V4_STATUS;
> +
> +	return PACKET_UNKNOWN;
> +}
> +
>  /*
>   * Process byte stream from mouse and handle complete packets
>   */
> @@ -567,6 +713,14 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
>  
>  		elantech_report_absolute_v3(psmouse, packet_type);
>  		break;
> +
> +	case 4:
> +		packet_type = elantech_packet_check_v4(psmouse);
> +		if (packet_type == PACKET_UNKNOWN)
> +			return PSMOUSE_BAD_DATA;
> +
> +		elantech_report_absolute_v4(psmouse, packet_type);
> +		break;
>  	}
>  
>  	return PSMOUSE_FULL_PACKET;
> @@ -610,6 +764,13 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
>  			rc = -1;
>  
>  		break;
> +
> +	case 4:
> +		etd->reg_07 = 0x01;
> +		if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
> +			rc = -1;
> +
> +		goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */
>  	}
>  
>  	if (rc == 0) {
> @@ -637,6 +798,7 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
>  		}
>  	}
>  
> + skip_readback_reg_10:
>  	if (rc)
>  		pr_err("failed to initialise registers.\n");
>  
> @@ -645,10 +807,11 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
>  
>  static int set_range(struct psmouse *psmouse, unsigned int *x_min,
>  		     unsigned int *y_min, unsigned int *x_max,
> -		     unsigned int *y_max)
> +		     unsigned int *y_max, unsigned int *width)
>  {
>  	struct elantech_data *etd = psmouse->private;
>  	unsigned char param[3];
> +	unsigned char traces = 0;
>  	int i;
>  
>  	switch (etd->hw_version) {
> @@ -677,12 +840,16 @@ static int set_range(struct psmouse *psmouse, unsigned int *x_min,
>  		}
>  		break;
>  
> +	case 4:
> +		traces = etd->capabilities[1];
> +		/* pass through */
>  	case 3:
>  		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
>  			return -1;
>  
>  		*x_max = (0x0f & param[0]) << 8 | param[1];
>  		*y_max = (0xf0 & param[0]) << 4 | param[2];
> +		*width = *x_max / (traces - 1);
>  		break;
>  	}
>  
> @@ -696,9 +863,9 @@ static int elantech_set_input_params(struct psmouse *psmouse)
>  {
>  	struct input_dev *dev = psmouse->dev;
>  	struct elantech_data *etd = psmouse->private;
> -	unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0;
> +	unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
>  
> -	if (set_range(psmouse, &x_min, &y_min, &x_max, &y_max))
> +	if (set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
>  		return -1;
>  
>  	__set_bit(EV_KEY, dev->evbit);
> @@ -742,9 +909,37 @@ static int elantech_set_input_params(struct psmouse *psmouse)
>  		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
>  		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
>  		break;
> +
> +	case 4:
> +		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
> +		/* For X to recognize me as touchpad. */
> +		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
> +		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
> +		/*
> +		 * range of pressure and width is the same as v2,
> +		 * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
> +		 */
> +		input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
> +				     ETP_PMAX_V2, 0, 0);
> +		input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
> +				     ETP_WMAX_V2, 0, 0);
> +		/* Multitouch capable pad, up to 5 fingers. */
> +		input_mt_init_slots(dev, ETP_MAX_FINGERS);
> +		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
> +		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
> +		input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
> +				     ETP_PMAX_V2, 0, 0);
> +		/*
> +		 * The firmware reports how many trace lines the finger spans,
> +		 * convert to surface unit as Protocol-B requires.
> +		 */
> +		input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0,
> +				     ETP_WMAX_V2 * width, 0, 0);
> +		break;
>  	}
>  
>  	etd->y_max = y_max;
> +	etd->width = width;
>  
>  	return 0;
>  }
> @@ -816,6 +1011,7 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse,
>  			    elantech_show_int_attr,			\
>  			    elantech_set_int_attr)
>  
> +ELANTECH_INT_ATTR(reg_07, 0x07);
>  ELANTECH_INT_ATTR(reg_10, 0x10);
>  ELANTECH_INT_ATTR(reg_11, 0x11);
>  ELANTECH_INT_ATTR(reg_20, 0x20);
> @@ -829,6 +1025,7 @@ ELANTECH_INT_ATTR(debug, 0);
>  ELANTECH_INT_ATTR(paritycheck, 0);
>  
>  static struct attribute *elantech_attrs[] = {
> +	&psmouse_attr_reg_07.dattr.attr,
>  	&psmouse_attr_reg_10.dattr.attr,
>  	&psmouse_attr_reg_11.dattr.attr,
>  	&psmouse_attr_reg_20.dattr.attr,
> @@ -957,12 +1154,16 @@ static int elantech_reconnect(struct psmouse *psmouse)
>   */
>  static int elantech_set_properties(struct elantech_data *etd)
>  {
> +	int ver = (etd->fw_version & 0x0f0000) >> 16;
> +
>  	if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
>  		etd->hw_version = 1;
>  	else if (etd->fw_version < 0x150600)
>  		etd->hw_version = 2;
> -	else if ((etd->fw_version & 0x0f0000) >> 16 == 5)
> +	else if (ver == 5)
>  		etd->hw_version = 3;
> +	else if (ver == 6)
> +		etd->hw_version = 4;
>  	else
>  		return -1;
>  
> diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
> index 236c33c..7ecaef0 100644
> --- a/drivers/input/mouse/elantech.h
> +++ b/drivers/input/mouse/elantech.h
> @@ -82,14 +82,37 @@
>  #define ETP_WMAX_V2			15
>  
>  /*
> - * v3 hardware has 2 kinds of packet types.
> + * v3 hardware has 2 kinds of packet types,
> + * v4 hardware has 3.
>   */
>  #define PACKET_UNKNOWN			0x01
>  #define PACKET_DEBOUNCE			0x02
>  #define PACKET_V3_HEAD			0x03
>  #define PACKET_V3_TAIL			0x04
> +#define PACKET_V4_HEAD			0x05
> +#define PACKET_V4_MOTION		0x06
> +#define PACKET_V4_STATUS		0x07
> +
> +/*
> + * track up to 5 fingers for v4 hardware
> + */
> +#define ETP_MAX_FINGERS			5
> +
> +/*
> + * weight value for v4 hardware
> + */
> +#define ETP_WEIGHT_VALUE		5
> +
> +/*
> + * The base position for one finger, v4 hardware
> + */
> +struct finger_pos {
> +	unsigned int x;
> +	unsigned int y;
> +};
>  
>  struct elantech_data {
> +	unsigned char reg_07;
>  	unsigned char reg_10;
>  	unsigned char reg_11;
>  	unsigned char reg_20;
> @@ -108,8 +131,8 @@ struct elantech_data {
>  	unsigned int fw_version;
>  	unsigned int single_finger_reports;
>  	unsigned int y_max;
> -	unsigned int prev_x;
> -	unsigned int prev_y;
> +	unsigned int width;
> +	struct finger_pos mt[ETP_MAX_FINGERS];
>  	unsigned char parity[256];
>  };
>  



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

* Re: [PATCH v4 0/8] Input: elantech: add support for newer hardware
  2011-08-29  8:28 ` JJ Ding
                   ` (8 preceding siblings ...)
  (?)
@ 2011-08-31  9:43 ` JJ Ding
  2011-08-31 21:10   ` Dmitry Torokhov
  -1 siblings, 1 reply; 23+ messages in thread
From: JJ Ding @ 2011-08-31  9:43 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Seth Forshee, Aaron Huang, Tom Lin, Éric Piel, Daniel Kurtz,
	Chase Douglas, Henrik Rydberg, Alessandro Rubini, linux-input,
	linux-kernel

Hi Dmitry,

What do you think about the series?
Do you think these patches all right for upstream?
Or do you have any other concerns about the chages?
Please let me know and I will fix it.
Thnak you.

jj

On Mon, 29 Aug 2011 16:28:51 +0800, JJ Ding <jj_ding@emc.com.tw> wrote:
> Hi Lists,
> 
> This is a series of patches to add support for newer generations of ELAN
> touchpad.
> 
> Patches #1~#6 are essentially fixes and cleanups that pave the way for
> patch #7 and patch #8, which really adds code for v3 and v4 hardware.
> 
> Any comments, suggestoins are welcome.
> 
> Note:
> Please review patch #8, which adds support for the latest touchpads from ELAN.
> This is a true multi-touch capable touchpad that can track up to 5 fingers.
> Support is implemented using MT-B protocol. I used synaptics and multitouch X
> driver to test this driver, both worked fine.
> 
> Thank you very much.
> 
> Changes since v1:
> - drop EC workaround patch.
> - add patch #2, make ST and MT have the same range, as Dmitry suggested.
> - add patch #4, remove ETP_EDGE_FUZZ_V2, as Éric suggested.
> - rename all packet checking functions so they are consistent.
> - some code cleanup, and don't report ABS_[XY] when fingers == 0, as Seth suggested.
> - add document for v3 debounce, and now check debounce in elantech_packet_check_v3.
> 
> Changes since v2:
> - fix v3 hardware packet checking (reported by Seth and fix by Dmitry.)
> 
> Changes since v3:
> - fix a tiny style problem (useless space on end-of-line, reported by Seth)
> - v3 hardware can track 2 fingers well, so do not set INPUT_PROP_SEMI_MT on v3
>   (As suggested earlier by Éric.)
> - add patch #8, which adds support for v4 hardware.
> 
> JJ Ding (8):
>   Input: elantech - correct x, y value range for v2 hardware
>   Input: elantech - get rid of ETP_2FT_* in elantech.h
>   Input: elantech - use firmware provided x, y ranges
>   Input: elantech - remove ETP_EDGE_FUZZ_V2
>   Input: elantech - packet checking for v2 hardware
>   Input: elantech - clean up elantech_init
>   Input: elantech - add v3 hardware support
>   Input: elantech - add v4 hardware support
> 
>  Documentation/input/elantech.txt |  295 +++++++++++++++++-
>  drivers/input/mouse/elantech.c   |  614 ++++++++++++++++++++++++++++++++-----
>  drivers/input/mouse/elantech.h   |   56 +++-
>  3 files changed, 849 insertions(+), 116 deletions(-)
> 
> -- 
> 1.7.4.1
> 

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

* Re: [PATCH v4 8/8] Input: elantech - add v4 hardware support
  2011-08-29  8:28 ` [PATCH v4 8/8] Input: elantech - add v4 " JJ Ding
@ 2011-08-31 12:50     ` Éric Piel
  2011-08-31 12:50     ` Éric Piel
  1 sibling, 0 replies; 23+ messages in thread
From: Éric Piel @ 2011-08-31 12:50 UTC (permalink / raw)
  To: JJ Ding
  Cc: linux-input, linux-kernel, Seth Forshee, Dmitry Torokhov,
	Aaron Huang, Tom Lin, Daniel Kurtz, Chase Douglas,
	Henrik Rydberg, Alessandro Rubini

Op 29-08-11 10:28, JJ Ding schreef:
> v4 hardware is a true multitouch capable touchpad (up to 5 fingers).
> The packet format is quite complex, please see protocol document for
> reference.
Hi,

It's great that you add support for another version!

Looks good. Just a few comment (inline).

Cheers,
Éric


>
> Signed-off-by: JJ Ding<jj_ding@emc.com.tw>
> ---
>   Documentation/input/elantech.txt |  170 ++++++++++++++++++++++++++
>   drivers/input/mouse/elantech.c   |  247 ++++++++++++++++++++++++++++++++++----
>   drivers/input/mouse/elantech.h   |   29 ++++-
>   3 files changed, 420 insertions(+), 26 deletions(-)
>
> diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt
> index cee08ee..f63115a 100644
> --- a/Documentation/input/elantech.txt
> +++ b/Documentation/input/elantech.txt
> @@ -32,6 +32,12 @@ Contents
>       6.2 Native absolute mode 6 byte packet format
>           6.2.1 One/Three finger touch
>           6.2.2 Two finger touch
> + 7. Hardware version 4
> +    7.1 Registers
> +    7.2 Native absolute mode 6 byte packet format
> +        7.2.1 Status packet
> +        7.2.2 Head packet
> +        7.2.3 Motion packet
>
>
>
> @@ -573,3 +579,167 @@ The packet format is exactly the same for two finger touch, except the hardware
>   sends two 6 byte packets. The first packet contains data for the first finger,
>   the second packet has data for the second finger. So for two finger touch a
>   total of 12 bytes are sent.
> +
> +/////////////////////////////////////////////////////////////////////////////
> +
> +7. Hardware version 4
> +   ==================
> +
> +7.1 Registers
> +    ~~~~~~~~~
> +* reg_07
> +
> +   bit   7   6   5   4   3   2   1   0
> +         0   0   0   0   0   0   0   A
> +
> +         A: 1 = enable absolute tracking
> +
> +7.2 Native absolute mode 6 byte packet format
> +    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers.
> +Unfortunately, due to PS/2's limited bandwidth, its packet format is rather
> +complex.
> +
> +Whenever the numbers or identities of the fingers changes, the hardware sends a
> +status packet to indicate how many and which fingers is on touchpad, followed by
> +head packets or motion packets. A head packet contains data of finger id, finger
> +position (absolute x, y values), width, and presure. A motion packet contains
Typo: pres_s_ure

> +two fingers' position delta.
> +
:
> diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
> index c4ceefd..0d3936d 100644
> --- a/drivers/input/mouse/elantech.c
> +++ b/drivers/input/mouse/elantech.c
> @@ -84,12 +84,6 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
>   	unsigned char param[3];
>   	int rc = 0;
>
> -	if (reg<  0x10 || reg>  0x26)
> -		return -1;
> -
> -	if (reg>  0x11&&  reg<  0x20)
> -		return -1;
> -
You could still leave a check of reg being between 0x07 and 0x26, it's
better than nothing.

:
>
> +static void elantech_mt_sync(struct psmouse *psmouse)
> +{
> +	struct input_dev *dev = psmouse->dev;
> +	unsigned char *packet = psmouse->packet;
> +
> +	input_report_key(dev, BTN_LEFT, packet[0]&  0x01);
> +	input_report_key(dev, BTN_RIGHT, packet[0]&  0x02);
> +	input_mt_report_pointer_emulation(dev, true);
> +	input_sync(dev);
> +}
The function naming is a bit strange. If you put _mt_, I expect there is 
only code related to multitouch. Maybe rename to:
elantech_input_sync_v4()


> +
> +static void process_packet_status(struct psmouse *psmouse)
:
> +static void process_packet_head(struct psmouse *psmouse)
:
> +static void process_packet_motion(struct psmouse *psmouse)
Maybe rename these function to *_v4(), so that it's clear it's not for 
v3 hardware or any other version.

:
> @@ -645,10 +807,11 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
>
>   static int set_range(struct psmouse *psmouse, unsigned int *x_min,
>   		     unsigned int *y_min, unsigned int *x_max,
> -		     unsigned int *y_max)
> +		     unsigned int *y_max, unsigned int *width)
>   {
>   	struct elantech_data *etd = psmouse->private;
>   	unsigned char param[3];
> +	unsigned char traces = 0;
Don't initialize it.

>   	int i;
>
>   	switch (etd->hw_version) {
> @@ -677,12 +840,16 @@ static int set_range(struct psmouse *psmouse, unsigned int *x_min,
>   		}
>   		break;
>
> +	case 4:
> +		traces = etd->capabilities[1];
> +		/* pass through */
>   	case 3:
>   		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
>   			return -1;
>
>   		*x_max = (0x0f&  param[0])<<  8 | param[1];
>   		*y_max = (0xf0&  param[0])<<  4 | param[2];
> +		*width = *x_max / (traces - 1);
>   		break;
>   	}
width is used only for firmware 4, right? If so then this code is too 
tricky. Order normally the cases, and duplicate the few common lines. 
Maintainability is more important than saving a couple of bytes :-)

Also, what happens if the firmware returns 1 in  etd->capabilities[1]? 
Make sure a division by zero is _impossible_. Please add a check on sane 
values for "traces", and bail out if it's not within these limits:
	if ((traces < 2) || (traces > *x_max))
		return -1;

Éric


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

* Re: [PATCH v4 8/8] Input: elantech - add v4 hardware support
@ 2011-08-31 12:50     ` Éric Piel
  0 siblings, 0 replies; 23+ messages in thread
From: Éric Piel @ 2011-08-31 12:50 UTC (permalink / raw)
  To: JJ Ding
  Cc: linux-input, linux-kernel, Seth Forshee, Dmitry Torokhov,
	Aaron Huang, Tom Lin, Daniel Kurtz, Chase Douglas,
	Henrik Rydberg, Alessandro Rubini

Op 29-08-11 10:28, JJ Ding schreef:
> v4 hardware is a true multitouch capable touchpad (up to 5 fingers).
> The packet format is quite complex, please see protocol document for
> reference.
Hi,

It's great that you add support for another version!

Looks good. Just a few comment (inline).

Cheers,
Éric


>
> Signed-off-by: JJ Ding<jj_ding@emc.com.tw>
> ---
>   Documentation/input/elantech.txt |  170 ++++++++++++++++++++++++++
>   drivers/input/mouse/elantech.c   |  247 ++++++++++++++++++++++++++++++++++----
>   drivers/input/mouse/elantech.h   |   29 ++++-
>   3 files changed, 420 insertions(+), 26 deletions(-)
>
> diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt
> index cee08ee..f63115a 100644
> --- a/Documentation/input/elantech.txt
> +++ b/Documentation/input/elantech.txt
> @@ -32,6 +32,12 @@ Contents
>       6.2 Native absolute mode 6 byte packet format
>           6.2.1 One/Three finger touch
>           6.2.2 Two finger touch
> + 7. Hardware version 4
> +    7.1 Registers
> +    7.2 Native absolute mode 6 byte packet format
> +        7.2.1 Status packet
> +        7.2.2 Head packet
> +        7.2.3 Motion packet
>
>
>
> @@ -573,3 +579,167 @@ The packet format is exactly the same for two finger touch, except the hardware
>   sends two 6 byte packets. The first packet contains data for the first finger,
>   the second packet has data for the second finger. So for two finger touch a
>   total of 12 bytes are sent.
> +
> +/////////////////////////////////////////////////////////////////////////////
> +
> +7. Hardware version 4
> +   ==================
> +
> +7.1 Registers
> +    ~~~~~~~~~
> +* reg_07
> +
> +   bit   7   6   5   4   3   2   1   0
> +         0   0   0   0   0   0   0   A
> +
> +         A: 1 = enable absolute tracking
> +
> +7.2 Native absolute mode 6 byte packet format
> +    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers.
> +Unfortunately, due to PS/2's limited bandwidth, its packet format is rather
> +complex.
> +
> +Whenever the numbers or identities of the fingers changes, the hardware sends a
> +status packet to indicate how many and which fingers is on touchpad, followed by
> +head packets or motion packets. A head packet contains data of finger id, finger
> +position (absolute x, y values), width, and presure. A motion packet contains
Typo: pres_s_ure

> +two fingers' position delta.
> +
:
> diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
> index c4ceefd..0d3936d 100644
> --- a/drivers/input/mouse/elantech.c
> +++ b/drivers/input/mouse/elantech.c
> @@ -84,12 +84,6 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
>   	unsigned char param[3];
>   	int rc = 0;
>
> -	if (reg<  0x10 || reg>  0x26)
> -		return -1;
> -
> -	if (reg>  0x11&&  reg<  0x20)
> -		return -1;
> -
You could still leave a check of reg being between 0x07 and 0x26, it's
better than nothing.

:
>
> +static void elantech_mt_sync(struct psmouse *psmouse)
> +{
> +	struct input_dev *dev = psmouse->dev;
> +	unsigned char *packet = psmouse->packet;
> +
> +	input_report_key(dev, BTN_LEFT, packet[0]&  0x01);
> +	input_report_key(dev, BTN_RIGHT, packet[0]&  0x02);
> +	input_mt_report_pointer_emulation(dev, true);
> +	input_sync(dev);
> +}
The function naming is a bit strange. If you put _mt_, I expect there is 
only code related to multitouch. Maybe rename to:
elantech_input_sync_v4()


> +
> +static void process_packet_status(struct psmouse *psmouse)
:
> +static void process_packet_head(struct psmouse *psmouse)
:
> +static void process_packet_motion(struct psmouse *psmouse)
Maybe rename these function to *_v4(), so that it's clear it's not for 
v3 hardware or any other version.

:
> @@ -645,10 +807,11 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
>
>   static int set_range(struct psmouse *psmouse, unsigned int *x_min,
>   		     unsigned int *y_min, unsigned int *x_max,
> -		     unsigned int *y_max)
> +		     unsigned int *y_max, unsigned int *width)
>   {
>   	struct elantech_data *etd = psmouse->private;
>   	unsigned char param[3];
> +	unsigned char traces = 0;
Don't initialize it.

>   	int i;
>
>   	switch (etd->hw_version) {
> @@ -677,12 +840,16 @@ static int set_range(struct psmouse *psmouse, unsigned int *x_min,
>   		}
>   		break;
>
> +	case 4:
> +		traces = etd->capabilities[1];
> +		/* pass through */
>   	case 3:
>   		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
>   			return -1;
>
>   		*x_max = (0x0f&  param[0])<<  8 | param[1];
>   		*y_max = (0xf0&  param[0])<<  4 | param[2];
> +		*width = *x_max / (traces - 1);
>   		break;
>   	}
width is used only for firmware 4, right? If so then this code is too 
tricky. Order normally the cases, and duplicate the few common lines. 
Maintainability is more important than saving a couple of bytes :-)

Also, what happens if the firmware returns 1 in  etd->capabilities[1]? 
Make sure a division by zero is _impossible_. Please add a check on sane 
values for "traces", and bail out if it's not within these limits:
	if ((traces < 2) || (traces > *x_max))
		return -1;

Éric

--
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] 23+ messages in thread

* Re: [PATCH v4 0/8] Input: elantech: add support for newer hardware
  2011-08-29  8:28 ` JJ Ding
@ 2011-08-31 12:54   ` Éric Piel
  -1 siblings, 0 replies; 23+ messages in thread
From: Éric Piel @ 2011-08-31 12:54 UTC (permalink / raw)
  To: JJ Ding
  Cc: linux-input, linux-kernel, Seth Forshee, Dmitry Torokhov,
	Aaron Huang, Tom Lin, Daniel Kurtz, Chase Douglas,
	Henrik Rydberg, Alessandro Rubini

Op 29-08-11 10:28, JJ Ding schreef:
> Hi Lists,
>
> This is a series of patches to add support for newer generations of ELAN
> touchpad.
>
> Patches #1~#6 are essentially fixes and cleanups that pave the way for
> patch #7 and patch #8, which really adds code for v3 and v4 hardware.
>
> Any comments, suggestoins are welcome.
>
Hello,
IMHO, this patch series is starting to look really good.

For patches 1-7 you have my:

Acked-by: Éric Piel <eric.piel@tremplin-utc.net>

I've just some little comments on patch 8.

I'll try find the time to test on my laptop (with touchpad firmware 
version 2) this weekend.

Cheers,
Éric

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

* Re: [PATCH v4 0/8] Input: elantech: add support for newer hardware
@ 2011-08-31 12:54   ` Éric Piel
  0 siblings, 0 replies; 23+ messages in thread
From: Éric Piel @ 2011-08-31 12:54 UTC (permalink / raw)
  To: JJ Ding
  Cc: linux-input, linux-kernel, Seth Forshee, Dmitry Torokhov,
	Aaron Huang, Tom Lin, Daniel Kurtz, Chase Douglas,
	Henrik Rydberg, Alessandro Rubini

Op 29-08-11 10:28, JJ Ding schreef:
> Hi Lists,
>
> This is a series of patches to add support for newer generations of ELAN
> touchpad.
>
> Patches #1~#6 are essentially fixes and cleanups that pave the way for
> patch #7 and patch #8, which really adds code for v3 and v4 hardware.
>
> Any comments, suggestoins are welcome.
>
Hello,
IMHO, this patch series is starting to look really good.

For patches 1-7 you have my:

Acked-by: Éric Piel <eric.piel@tremplin-utc.net>

I've just some little comments on patch 8.

I'll try find the time to test on my laptop (with touchpad firmware 
version 2) this weekend.

Cheers,
Éric
--
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] 23+ messages in thread

* Re: [PATCH v4 0/8] Input: elantech: add support for newer hardware
  2011-08-31  9:43 ` [PATCH v4 0/8] Input: elantech: add support for newer hardware JJ Ding
@ 2011-08-31 21:10   ` Dmitry Torokhov
  2011-09-01  1:38     ` JJ Ding
  0 siblings, 1 reply; 23+ messages in thread
From: Dmitry Torokhov @ 2011-08-31 21:10 UTC (permalink / raw)
  To: JJ Ding
  Cc: Seth Forshee, Aaron Huang, Tom Lin, Éric Piel, Daniel Kurtz,
	Chase Douglas, Henrik Rydberg, Alessandro Rubini, linux-input,
	linux-kernel

Hi JJ,

On Wed, Aug 31, 2011 at 05:43:59PM +0800, JJ Ding wrote:
> Hi Dmitry,
> 
> What do you think about the series?
> Do you think these patches all right for upstream?
> Or do you have any other concerns about the chages?
> Please let me know and I will fix it.

I believe the patches are mostly OK, however I am in a middle of house
move so I'll give final review some time next week, during LPC.

Thanks.

-- 
Dmitry

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

* Re: [PATCH v4 8/8] Input: elantech - add v4 hardware support
  2011-08-31 12:50     ` Éric Piel
@ 2011-09-01  1:31       ` JJ Ding
  -1 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-09-01  1:31 UTC (permalink / raw)
  To: Éric Piel
  Cc: linux-input, linux-kernel, Seth Forshee, Dmitry Torokhov,
	Aaron Huang, Tom Lin, Daniel Kurtz, Chase Douglas,
	Henrik Rydberg, Alessandro Rubini

Hi Éric,

Thanks for your comments.
Reply below inline, thank you.

jj

On Wed, 31 Aug 2011 14:50:59 +0200, Éric Piel <E.A.B.Piel@tudelft.nl> wrote:
> Op 29-08-11 10:28, JJ Ding schreef:
> > v4 hardware is a true multitouch capable touchpad (up to 5 fingers).
> > The packet format is quite complex, please see protocol document for
> > reference.
> Hi,
> 
> It's great that you add support for another version!
> 
> Looks good. Just a few comment (inline).
> 
> Cheers,
> Éric
> 
> 
> >
> > Signed-off-by: JJ Ding<jj_ding@emc.com.tw>
> > ---
> >   Documentation/input/elantech.txt |  170 ++++++++++++++++++++++++++
> >   drivers/input/mouse/elantech.c   |  247 ++++++++++++++++++++++++++++++++++----
> >   drivers/input/mouse/elantech.h   |   29 ++++-
> >   3 files changed, 420 insertions(+), 26 deletions(-)
> >
> > diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt
> > index cee08ee..f63115a 100644
> > --- a/Documentation/input/elantech.txt
> > +++ b/Documentation/input/elantech.txt
> > @@ -32,6 +32,12 @@ Contents
> >       6.2 Native absolute mode 6 byte packet format
> >           6.2.1 One/Three finger touch
> >           6.2.2 Two finger touch
> > + 7. Hardware version 4
> > +    7.1 Registers
> > +    7.2 Native absolute mode 6 byte packet format
> > +        7.2.1 Status packet
> > +        7.2.2 Head packet
> > +        7.2.3 Motion packet
> >
> >
> >
> > @@ -573,3 +579,167 @@ The packet format is exactly the same for two finger touch, except the hardware
> >   sends two 6 byte packets. The first packet contains data for the first finger,
> >   the second packet has data for the second finger. So for two finger touch a
> >   total of 12 bytes are sent.
> > +
> > +/////////////////////////////////////////////////////////////////////////////
> > +
> > +7. Hardware version 4
> > +   ==================
> > +
> > +7.1 Registers
> > +    ~~~~~~~~~
> > +* reg_07
> > +
> > +   bit   7   6   5   4   3   2   1   0
> > +         0   0   0   0   0   0   0   A
> > +
> > +         A: 1 = enable absolute tracking
> > +
> > +7.2 Native absolute mode 6 byte packet format
> > +    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > +v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers.
> > +Unfortunately, due to PS/2's limited bandwidth, its packet format is rather
> > +complex.
> > +
> > +Whenever the numbers or identities of the fingers changes, the hardware sends a
> > +status packet to indicate how many and which fingers is on touchpad, followed by
> > +head packets or motion packets. A head packet contains data of finger id, finger
> > +position (absolute x, y values), width, and presure. A motion packet contains
> Typo: pres_s_ure
Fixed.
> > +two fingers' position delta.
> > +
> :
> > diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
> > index c4ceefd..0d3936d 100644
> > --- a/drivers/input/mouse/elantech.c
> > +++ b/drivers/input/mouse/elantech.c
> > @@ -84,12 +84,6 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
> >   	unsigned char param[3];
> >   	int rc = 0;
> >
> > -	if (reg<  0x10 || reg>  0x26)
> > -		return -1;
> > -
> > -	if (reg>  0x11&&  reg<  0x20)
> > -		return -1;
> > -
> You could still leave a check of reg being between 0x07 and 0x26, it's
> better than nothing.
OK, I will add them back. 
> :
> >
> > +static void elantech_mt_sync(struct psmouse *psmouse)
> > +{
> > +	struct input_dev *dev = psmouse->dev;
> > +	unsigned char *packet = psmouse->packet;
> > +
> > +	input_report_key(dev, BTN_LEFT, packet[0]&  0x01);
> > +	input_report_key(dev, BTN_RIGHT, packet[0]&  0x02);
> > +	input_mt_report_pointer_emulation(dev, true);
> > +	input_sync(dev);
> > +}
> The function naming is a bit strange. If you put _mt_, I expect there is 
> only code related to multitouch. Maybe rename to:
> elantech_input_sync_v4()
Changed.
> 
> > +
> > +static void process_packet_status(struct psmouse *psmouse)
> :
> > +static void process_packet_head(struct psmouse *psmouse)
> :
> > +static void process_packet_motion(struct psmouse *psmouse)
> Maybe rename these function to *_v4(), so that it's clear it's not for 
> v3 hardware or any other version.
Changed.
> :
> > @@ -645,10 +807,11 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
> >
> >   static int set_range(struct psmouse *psmouse, unsigned int *x_min,
> >   		     unsigned int *y_min, unsigned int *x_max,
> > -		     unsigned int *y_max)
> > +		     unsigned int *y_max, unsigned int *width)
> >   {
> >   	struct elantech_data *etd = psmouse->private;
> >   	unsigned char param[3];
> > +	unsigned char traces = 0;
> Don't initialize it.
Fixed.
> 
> >   	int i;
> >
> >   	switch (etd->hw_version) {
> > @@ -677,12 +840,16 @@ static int set_range(struct psmouse *psmouse, unsigned int *x_min,
> >   		}
> >   		break;
> >
> > +	case 4:
> > +		traces = etd->capabilities[1];
> > +		/* pass through */
> >   	case 3:
> >   		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
> >   			return -1;
> >
> >   		*x_max = (0x0f&  param[0])<<  8 | param[1];
> >   		*y_max = (0xf0&  param[0])<<  4 | param[2];
> > +		*width = *x_max / (traces - 1);
> >   		break;
> >   	}
> width is used only for firmware 4, right? If so then this code is too 
> tricky. Order normally the cases, and duplicate the few common lines. 
> Maintainability is more important than saving a couple of bytes :-)
Yes, width is only used for firmware 4. I will change this for better
maintainability.
> Also, what happens if the firmware returns 1 in  etd->capabilities[1]? 
> Make sure a division by zero is _impossible_. Please add a check on sane 
> values for "traces", and bail out if it's not within these limits:
> 	if ((traces < 2) || (traces > *x_max))
> 		return -1;
Thanks for reminding me this. I will fix it.
> Éric
> 
> --
> 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] 23+ messages in thread

* Re: [PATCH v4 8/8] Input: elantech - add v4 hardware support
@ 2011-09-01  1:31       ` JJ Ding
  0 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-09-01  1:31 UTC (permalink / raw)
  To: Éric Piel
  Cc: linux-input, linux-kernel, Seth Forshee, Dmitry Torokhov,
	Aaron Huang, Tom Lin, Daniel Kurtz, Chase Douglas,
	Henrik Rydberg, Alessandro Rubini

Hi Éric,

Thanks for your comments.
Reply below inline, thank you.

jj

On Wed, 31 Aug 2011 14:50:59 +0200, Éric Piel <E.A.B.Piel@tudelft.nl> wrote:
> Op 29-08-11 10:28, JJ Ding schreef:
> > v4 hardware is a true multitouch capable touchpad (up to 5 fingers).
> > The packet format is quite complex, please see protocol document for
> > reference.
> Hi,
> 
> It's great that you add support for another version!
> 
> Looks good. Just a few comment (inline).
> 
> Cheers,
> Éric
> 
> 
> >
> > Signed-off-by: JJ Ding<jj_ding@emc.com.tw>
> > ---
> >   Documentation/input/elantech.txt |  170 ++++++++++++++++++++++++++
> >   drivers/input/mouse/elantech.c   |  247 ++++++++++++++++++++++++++++++++++----
> >   drivers/input/mouse/elantech.h   |   29 ++++-
> >   3 files changed, 420 insertions(+), 26 deletions(-)
> >
> > diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt
> > index cee08ee..f63115a 100644
> > --- a/Documentation/input/elantech.txt
> > +++ b/Documentation/input/elantech.txt
> > @@ -32,6 +32,12 @@ Contents
> >       6.2 Native absolute mode 6 byte packet format
> >           6.2.1 One/Three finger touch
> >           6.2.2 Two finger touch
> > + 7. Hardware version 4
> > +    7.1 Registers
> > +    7.2 Native absolute mode 6 byte packet format
> > +        7.2.1 Status packet
> > +        7.2.2 Head packet
> > +        7.2.3 Motion packet
> >
> >
> >
> > @@ -573,3 +579,167 @@ The packet format is exactly the same for two finger touch, except the hardware
> >   sends two 6 byte packets. The first packet contains data for the first finger,
> >   the second packet has data for the second finger. So for two finger touch a
> >   total of 12 bytes are sent.
> > +
> > +/////////////////////////////////////////////////////////////////////////////
> > +
> > +7. Hardware version 4
> > +   ==================
> > +
> > +7.1 Registers
> > +    ~~~~~~~~~
> > +* reg_07
> > +
> > +   bit   7   6   5   4   3   2   1   0
> > +         0   0   0   0   0   0   0   A
> > +
> > +         A: 1 = enable absolute tracking
> > +
> > +7.2 Native absolute mode 6 byte packet format
> > +    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > +v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers.
> > +Unfortunately, due to PS/2's limited bandwidth, its packet format is rather
> > +complex.
> > +
> > +Whenever the numbers or identities of the fingers changes, the hardware sends a
> > +status packet to indicate how many and which fingers is on touchpad, followed by
> > +head packets or motion packets. A head packet contains data of finger id, finger
> > +position (absolute x, y values), width, and presure. A motion packet contains
> Typo: pres_s_ure
Fixed.
> > +two fingers' position delta.
> > +
> :
> > diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
> > index c4ceefd..0d3936d 100644
> > --- a/drivers/input/mouse/elantech.c
> > +++ b/drivers/input/mouse/elantech.c
> > @@ -84,12 +84,6 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
> >   	unsigned char param[3];
> >   	int rc = 0;
> >
> > -	if (reg<  0x10 || reg>  0x26)
> > -		return -1;
> > -
> > -	if (reg>  0x11&&  reg<  0x20)
> > -		return -1;
> > -
> You could still leave a check of reg being between 0x07 and 0x26, it's
> better than nothing.
OK, I will add them back. 
> :
> >
> > +static void elantech_mt_sync(struct psmouse *psmouse)
> > +{
> > +	struct input_dev *dev = psmouse->dev;
> > +	unsigned char *packet = psmouse->packet;
> > +
> > +	input_report_key(dev, BTN_LEFT, packet[0]&  0x01);
> > +	input_report_key(dev, BTN_RIGHT, packet[0]&  0x02);
> > +	input_mt_report_pointer_emulation(dev, true);
> > +	input_sync(dev);
> > +}
> The function naming is a bit strange. If you put _mt_, I expect there is 
> only code related to multitouch. Maybe rename to:
> elantech_input_sync_v4()
Changed.
> 
> > +
> > +static void process_packet_status(struct psmouse *psmouse)
> :
> > +static void process_packet_head(struct psmouse *psmouse)
> :
> > +static void process_packet_motion(struct psmouse *psmouse)
> Maybe rename these function to *_v4(), so that it's clear it's not for 
> v3 hardware or any other version.
Changed.
> :
> > @@ -645,10 +807,11 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
> >
> >   static int set_range(struct psmouse *psmouse, unsigned int *x_min,
> >   		     unsigned int *y_min, unsigned int *x_max,
> > -		     unsigned int *y_max)
> > +		     unsigned int *y_max, unsigned int *width)
> >   {
> >   	struct elantech_data *etd = psmouse->private;
> >   	unsigned char param[3];
> > +	unsigned char traces = 0;
> Don't initialize it.
Fixed.
> 
> >   	int i;
> >
> >   	switch (etd->hw_version) {
> > @@ -677,12 +840,16 @@ static int set_range(struct psmouse *psmouse, unsigned int *x_min,
> >   		}
> >   		break;
> >
> > +	case 4:
> > +		traces = etd->capabilities[1];
> > +		/* pass through */
> >   	case 3:
> >   		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
> >   			return -1;
> >
> >   		*x_max = (0x0f&  param[0])<<  8 | param[1];
> >   		*y_max = (0xf0&  param[0])<<  4 | param[2];
> > +		*width = *x_max / (traces - 1);
> >   		break;
> >   	}
> width is used only for firmware 4, right? If so then this code is too 
> tricky. Order normally the cases, and duplicate the few common lines. 
> Maintainability is more important than saving a couple of bytes :-)
Yes, width is only used for firmware 4. I will change this for better
maintainability.
> Also, what happens if the firmware returns 1 in  etd->capabilities[1]? 
> Make sure a division by zero is _impossible_. Please add a check on sane 
> values for "traces", and bail out if it's not within these limits:
> 	if ((traces < 2) || (traces > *x_max))
> 		return -1;
Thanks for reminding me this. I will fix it.
> Éric
> 
> --
> 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
--
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] 23+ messages in thread

* Re: [PATCH v4 0/8] Input: elantech: add support for newer hardware
  2011-08-31 21:10   ` Dmitry Torokhov
@ 2011-09-01  1:38     ` JJ Ding
  0 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-09-01  1:38 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Seth Forshee, Aaron Huang, Tom Lin, Éric Piel, Daniel Kurtz,
	Chase Douglas, Henrik Rydberg, Alessandro Rubini, linux-input,
	linux-kernel

Hi Dmitry,

Thank you for letting me know.

jj

On Wed, 31 Aug 2011 14:10:06 -0700, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> Hi JJ,
> 
> On Wed, Aug 31, 2011 at 05:43:59PM +0800, JJ Ding wrote:
> > Hi Dmitry,
> > 
> > What do you think about the series?
> > Do you think these patches all right for upstream?
> > Or do you have any other concerns about the chages?
> > Please let me know and I will fix it.
> 
> I believe the patches are mostly OK, however I am in a middle of house
> move so I'll give final review some time next week, during LPC.
> 
> Thanks.
> 
> -- 
> Dmitry

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

* Re: [PATCH v4 0/8] Input: elantech: add support for newer hardware
  2011-08-31 12:54   ` Éric Piel
@ 2011-09-01  1:39     ` JJ Ding
  -1 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-09-01  1:39 UTC (permalink / raw)
  To: Éric Piel
  Cc: linux-input, linux-kernel, Seth Forshee, Dmitry Torokhov,
	Aaron Huang, Tom Lin, Daniel Kurtz, Chase Douglas,
	Henrik Rydberg, Alessandro Rubini

Hi Éric,

Thnaks for the reviewing and testing.

jj

On Wed, 31 Aug 2011 14:54:07 +0200, Éric Piel <E.A.B.Piel@tudelft.nl> wrote:
> Op 29-08-11 10:28, JJ Ding schreef:
> > Hi Lists,
> >
> > This is a series of patches to add support for newer generations of ELAN
> > touchpad.
> >
> > Patches #1~#6 are essentially fixes and cleanups that pave the way for
> > patch #7 and patch #8, which really adds code for v3 and v4 hardware.
> >
> > Any comments, suggestoins are welcome.
> >
> Hello,
> IMHO, this patch series is starting to look really good.
> 
> For patches 1-7 you have my:
> 
> Acked-by: Éric Piel <eric.piel@tremplin-utc.net>
> 
> I've just some little comments on patch 8.
> 
> I'll try find the time to test on my laptop (with touchpad firmware 
> version 2) this weekend.
> 
> Cheers,
> Éric

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

* Re: [PATCH v4 0/8] Input: elantech: add support for newer hardware
@ 2011-09-01  1:39     ` JJ Ding
  0 siblings, 0 replies; 23+ messages in thread
From: JJ Ding @ 2011-09-01  1:39 UTC (permalink / raw)
  To: Éric Piel
  Cc: linux-input, linux-kernel, Seth Forshee, Dmitry Torokhov,
	Aaron Huang, Tom Lin, Daniel Kurtz, Chase Douglas,
	Henrik Rydberg, Alessandro Rubini

Hi Éric,

Thnaks for the reviewing and testing.

jj

On Wed, 31 Aug 2011 14:54:07 +0200, Éric Piel <E.A.B.Piel@tudelft.nl> wrote:
> Op 29-08-11 10:28, JJ Ding schreef:
> > Hi Lists,
> >
> > This is a series of patches to add support for newer generations of ELAN
> > touchpad.
> >
> > Patches #1~#6 are essentially fixes and cleanups that pave the way for
> > patch #7 and patch #8, which really adds code for v3 and v4 hardware.
> >
> > Any comments, suggestoins are welcome.
> >
> Hello,
> IMHO, this patch series is starting to look really good.
> 
> For patches 1-7 you have my:
> 
> Acked-by: Éric Piel <eric.piel@tremplin-utc.net>
> 
> I've just some little comments on patch 8.
> 
> I'll try find the time to test on my laptop (with touchpad firmware 
> version 2) this weekend.
> 
> Cheers,
> Éric
--
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] 23+ messages in thread

end of thread, other threads:[~2011-09-01  1:37 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-29  8:28 [PATCH v4 0/8] Input: elantech: add support for newer hardware JJ Ding
2011-08-29  8:28 ` JJ Ding
2011-08-29  8:28 ` [PATCH v4 1/8] Input: elantech - correct x, y value range for v2 hardware JJ Ding
2011-08-29  8:28 ` [PATCH v4 2/8] Input: elantech - get rid of ETP_2FT_* in elantech.h JJ Ding
2011-08-29  8:28 ` [PATCH v4 3/8] Input: elantech - use firmware provided x, y ranges JJ Ding
2011-08-29  8:28 ` [PATCH v4 4/8] Input: elantech - remove ETP_EDGE_FUZZ_V2 JJ Ding
2011-08-29  8:28   ` JJ Ding
2011-08-29  8:28 ` [PATCH v4 5/8] Input: elantech - packet checking for v2 hardware JJ Ding
2011-08-29  8:28 ` [PATCH v4 6/8] Input: elantech - clean up elantech_init JJ Ding
2011-08-29  8:28 ` [PATCH v4 7/8] Input: elantech - add v3 hardware support JJ Ding
2011-08-29  8:28 ` [PATCH v4 8/8] Input: elantech - add v4 " JJ Ding
2011-08-30 13:50   ` Tom _Lin
2011-08-31 12:50   ` Éric Piel
2011-08-31 12:50     ` Éric Piel
2011-09-01  1:31     ` JJ Ding
2011-09-01  1:31       ` JJ Ding
2011-08-31  9:43 ` [PATCH v4 0/8] Input: elantech: add support for newer hardware JJ Ding
2011-08-31 21:10   ` Dmitry Torokhov
2011-09-01  1:38     ` JJ Ding
2011-08-31 12:54 ` Éric Piel
2011-08-31 12:54   ` Éric Piel
2011-09-01  1:39   ` JJ Ding
2011-09-01  1:39     ` JJ Ding

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.