All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Éric Piel" <E.A.B.Piel@tudelft.nl>
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Henrik Rydberg <rydberg@euromail.se>,
	Chris Bagwell <chris@cnpbagwell.com>,
	"linux-input@vger.kernel.org" <linux-input@vger.kernel.org>,
	Florian Ragwitz <rafl@debian.org>
Subject: [PATCH 08/10] elantech: track finger to distinguish coordinates in 2-finger report
Date: Mon, 09 Aug 2010 00:53:52 +0200	[thread overview]
Message-ID: <4C5F3580.2090805@tudelft.nl> (raw)
In-Reply-To: <4C5F34F4.7030503@tudelft.nl>

The elantech hardware is limited when reporting two fingers. It just
reports the minimum and maximum coordinates of the rectangle containing
the fingers.

As multitouch protocol requires at least to report the correct position
of each finger, we track the finger position when there is only one
finger to distinguish which corner of the rectangle corresponds to the
actual position of the fingers. When there are three fingers, only the
minimum position is reported, so we just don't track it and hope the
last tracked position has the most likelihood to be correct.

It works fine, at least as long as the two fingers don't get
horizontally or vertically aligned, after what it's back to random.
This also allows to avoid so "jumps" in the single-touch protocol.

Signed-off-by: Éric Piel <eric.piel@tremplin-utc.net>
---
 drivers/input/mouse/elantech.c |   75 ++++++++++++++++++++++++++++++++--------
 drivers/input/mouse/elantech.h |    2 +
 2 files changed, 62 insertions(+), 15 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 7fa4f29..1dd7e7c 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -242,6 +242,45 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
 	input_sync(dev);
 }
 
+/* Store the current position of the finger, for tracking when 2 fingers */
+static void track_one_finger(struct elantech_data *etd, unsigned int x, unsigned int y)
+{
+	etd->prev_x = x;
+	etd->prev_y = y;
+}
+
+/* Ensure that argument a contains a value closest to ref than b */
+static void find_closest_and_swap(unsigned int *ref, unsigned int *a, unsigned int *b)
+{
+	int dist_a = abs(*ref - *a);
+	int dist_b = abs(*ref - *b);
+	int tmp;
+	if (dist_b < dist_a) {
+		tmp = *a;
+		*a = *b;
+		*b = tmp;
+	}
+	*ref = *a;
+}
+
+/*
+ * Track the coordinates reported and swap the values to improve the likelihood
+ * that the coordinates correspond to the real positions of the two fingers.
+ */
+static void
+track_two_fingers(struct elantech_data *etd,
+		  unsigned int *x1, unsigned int *y1, unsigned int *x2, unsigned int *y2)
+{
+	/*
+	 * As the hardware can only report the coordinates without knowing which one
+	 * corresponds to which finger, we try to guess according to the last known
+	 * position, when using only one finger.
+	 */
+	find_closest_and_swap(&etd->prev_x, x1, x2);
+	find_closest_and_swap(&etd->prev_y, y1, y2);
+}
+
+
 /*
  * Interpret complete data packets and report absolute mode input events for
  * hardware version 2. (6 byte packets)
@@ -251,7 +290,7 @@ 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;
-	int fingers, x1, y1, x2, y2, width = 0, pres = 0;
+	unsigned int fingers, x1, y1, x2, y2, width = 0, pres = 0;
 
 	/* byte 0: n1  n0   .   .   .   .   R   L */
 	fingers = (packet[0] & 0xc0) >> 6;
@@ -285,6 +324,10 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 		input_report_abs(dev, ABS_X, x1);
 		input_report_abs(dev, ABS_Y, y1);
 
+		/* Only track if we are sure it's real finger coodinates */
+		if (fingers == 1)
+			track_one_finger(etd, x1, y1);
+
 		pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
 		width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
 		break;
@@ -296,37 +339,39 @@ 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_2FT_YMAX - (((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]);
+		y2 = (ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5])) << 2;
+
+		track_two_fingers(etd, &x1, &y1, &x2, &y2);
 		/* Multitouch */
-		input_report_abs(dev, ABS_MT_POSITION_X, x1 << 2);
-		input_report_abs(dev, ABS_MT_POSITION_Y, y1 << 2);
+		input_report_abs(dev, ABS_MT_POSITION_X, x1);
+		input_report_abs(dev, ABS_MT_POSITION_Y, y1);
 		input_mt_sync(dev);
-		input_report_abs(dev, ABS_MT_POSITION_X, x2 << 2);
-		input_report_abs(dev, ABS_MT_POSITION_Y, y2 << 2);
+		input_report_abs(dev, ABS_MT_POSITION_X, x2);
+		input_report_abs(dev, ABS_MT_POSITION_Y, y2);
 		input_mt_sync(dev);
 		/*
 		 * 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);
+		input_report_abs(dev, ABS_X, x1);
+		input_report_abs(dev, ABS_Y, y1);
 		/*
 		 * For compatibility with the proprietary X Elantech driver
 		 * report both coordinates as hat coordinates
 		 */
-		input_report_abs(dev, ABS_HAT0X, x1);
-		input_report_abs(dev, ABS_HAT0Y, y1);
-		input_report_abs(dev, ABS_HAT1X, x2);
-		input_report_abs(dev, ABS_HAT1Y, y2);
+		input_report_abs(dev, ABS_HAT0X, x1 >> 2);
+		input_report_abs(dev, ABS_HAT0Y, y1 >> 2);
+		input_report_abs(dev, ABS_HAT1X, x2 >> 2);
+		input_report_abs(dev, ABS_HAT1Y, y2 >> 2);
 
 		/* Unknown so just report sensible values */
 		pres = 127;
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index f6e3be5..fa9a6b4 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -111,6 +111,8 @@ struct elantech_data {
 	unsigned char hw_version;
 	unsigned int  fw_version;
 	unsigned char parity[256];
+	unsigned int prev_x;
+	unsigned int prev_y;
 };
 
 enum paritycheck_types {
-- 
1.7.2.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

  parent reply	other threads:[~2010-08-08 22:55 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-21 20:59 [PATCH 0/7] elantech: various improvements for 6-byte protocol Éric Piel
2010-06-21 21:01 ` [PATCH 1/7] elantech: Describe further the protocol Éric Piel
2010-06-21 21:02 ` [PATCH 2/7] [NEEDS TEST] elantech: discard the first 2 positions reports for some firmwares Éric Piel
2010-06-21 21:03 ` [PATCH 3/7] elantech: distinguish various hardware/firmware versions Éric Piel
2010-06-21 21:04 ` [PATCH 4/7] elantech: implement data check for 6-byte protocol Éric Piel
2010-06-21 21:05 ` [PATCH 6/7] elantech: export pressure and width when supported Éric Piel
2010-06-21 21:06 ` [PATCH 7/7] elantech: average the two coordinates when 2 fingers Éric Piel
2010-07-21  3:36   ` Dmitry Torokhov
2010-07-30 18:55     ` Éric Piel
2010-07-30 21:01       ` Henrik Rydberg
2010-07-30 21:41         ` Éric Piel
2010-07-31  9:28           ` Henrik Rydberg
2010-07-31  9:33             ` Dmitry Torokhov
2010-07-31 12:49               ` Henrik Rydberg
2010-07-31 23:00                 ` Éric Piel
2010-08-01  7:52                   ` Henrik Rydberg
2010-07-31 19:56           ` Chris Bagwell
     [not found]         ` <AANLkTi=cEEx-5eQPbRYvMMaECvXKQ+i-e0Eaw_g4JY7=@mail.gmail.com>
2010-07-31 23:04           ` Éric Piel
2010-08-01  9:37             ` Henrik Rydberg
2010-08-01 11:28               ` Éric Piel
2010-08-01 13:57                 ` Henrik Rydberg
2010-08-02  8:17                   ` Éric Piel
2010-08-02 10:02                     ` Henrik Rydberg
2010-08-02 11:12                       ` Éric Piel
2010-08-02 11:22                         ` Henrik Rydberg
2010-08-02 11:33                           ` Éric Piel
2010-08-02 11:46                             ` Henrik Rydberg
2010-08-02 12:13                               ` Éric Piel
2010-08-02 12:29                                 ` Henrik Rydberg
2010-08-02 12:46                                   ` Éric Piel
2010-08-02 13:03                                     ` Henrik Rydberg
2010-08-02 13:23                                       ` Éric Piel
2010-08-02 14:12                                         ` Henrik Rydberg
2010-08-02 16:39                                       ` Dmitry Torokhov
2010-08-02 17:15                                         ` Henrik Rydberg
2010-08-08 22:51                                         ` Éric Piel
2010-08-08 22:52                                           ` [PATCH 07/10] elantech: Report multitouch with proper ABS_MT messages Éric Piel
2010-08-08 22:53                                           ` Éric Piel [this message]
2010-08-08 22:54                                           ` [PATCH 09/10] elantech: remove support for proprietary X driver Éric Piel
2010-08-08 22:55                                           ` [PATCH 10/10] elantech: don't take into account the border size in the calculations Éric Piel
2010-08-02 16:26                           ` [PATCH 7/7] elantech: average the two coordinates when 2 fingers Dmitry Torokhov
2010-08-02 17:05                             ` Henrik Rydberg
2010-08-01  7:36           ` Henrik Rydberg
2010-06-21 21:07 ` [PATCH 5/7] elantech: report position also with 3 fingers Éric Piel
2010-07-21  3:38   ` Dmitry Torokhov
2010-07-30 18:37     ` Éric Piel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4C5F3580.2090805@tudelft.nl \
    --to=e.a.b.piel@tudelft.nl \
    --cc=chris@cnpbagwell.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=rafl@debian.org \
    --cc=rydberg@euromail.se \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.