All of lore.kernel.org
 help / color / mirror / Atom feed
From: George Pantalos <gpantalos@gmail.com>
To: Seth Forshee <seth.forshee@canonical.com>
Cc: linux-input@vger.kernel.org
Subject: Re: ALPS v4 Semi-mt Support
Date: Mon, 16 Apr 2012 17:24:55 +0300	[thread overview]
Message-ID: <1492453.bjpWEAk9kj@vaio> (raw)
In-Reply-To: <20120410215939.GE21994@thinkpad-t410>

> On Tue, Apr 10, 2012 at 10:21:13AM -0500, Seth Forshee wrote:
> > I definitely think your state processing could be improved. My
> > suggestion would be to treat multi_packet as a counter. Reset it to 0
> > when you see the sync bit is set, and increment it for each packet until
> > you have a full set of MT data. That way you know for sure which section
> > of the MT data you're working with for any given packet. But be prepared
> > to handle an incomplete packet sequence as well (I'm pretty sure I saw
> > some of these when I was working with a v4 touchpad).
> 
> I found an old patch I had from working on the semi-MT support
> previously that demonstrates the multi_packet-as-counter approach. I
> ported the relevant code on top of 3.4-rc2, cleaned it up, compile
> tested it, and pasted the resulting patch below.
> 
> Note that this is ignoring the ST coordinates except from the final
> packet of the MT sequence, which isn't ideal. A better approach might be
> to stash the ST data from each packet in alps_data, then when you have
> all three packets process the bitmaps and report all three ST points
> with the same set of MT data.

Hello Seth,

First of all, sorry for answering so late, I had no internet access for the 
past week.

Thank you for your comments and for posting your patch. You are of course 
correct in your remarks.

 I decided to try and improve upon your patch which has superior state 
processing. I followed your proposal initially and stashed the first and 
second packet ST data in alps_data and if bitmap fingers < 2 report all the ST 
data.
The problem with this approach is that it introduces a noticeable delay/lag in 
mouse pointer movement.

I then tried using the last_fingers approach.  This way we report ST data as 
they come but only if the last MT report had 1 finger present and we always 
(as far as I can tell) must have calculated bitmap finger count before 
reporting ST events. I have posted this patch below. I also observed jumpy 
behavior with the xf86-input-multitouch driver when the MT report had 1 
finger, so if bitmap fingers are 1 , it uses x,y instead of x1,y1.
This approach has the benefit of producing smooth pointer movement and 
accurately reporting MT events like the other approach.

To handle inconsistent data I used your patch to dump raw packets.  I noticed 
,as your documentation also states, that the condition (packet[6] & 0x40) 
could also be triggered by the second MT packet and then reset 
multi_packet to 0.
So I used the fact that byte 5 of the MT data, priv->multi_data [4] must 
always be 0x00. A kind of second sync byte to ensure we have correct MT 
reports. Unless the MT data is consistent we report nothing.

Thanks for your help and guidance.

--- linux-3.3/drivers/input/mouse/alps.c.orig	2012-04-15 21:45:18.083826446 
+0300
+++ linux-3.3/drivers/input/mouse/alps.c	2012-04-16 16:33:11.412181964 
+0300
@@ -604,10 +604,39 @@
 
 static void alps_process_packet_v4(struct psmouse *psmouse)
 {
+	struct alps_data *priv = psmouse->private;
 	unsigned char *packet = psmouse->packet;
 	struct input_dev *dev = psmouse->dev;
+	int offset;
 	int x, y, z;
 	int left, right;
+	int x1, y1, x2, y2;
+	int fingers = 0;
+	unsigned int x_bitmap, y_bitmap;
+
+	/*
+	 * v4 has a 6-byte encoding for bitmap data, but this data is
+	 * broken up between 3 normal packets. Use priv->multi_packet to
+	 * track our position in the bitmap packet.
+	 */
+	if ((packet[6] & 0x40) && (priv->multi_data[4] == 0x00)) {
+		/* sync, reset position */
+		priv->multi_packet = 0;
+	}
+
+	if (WARN_ON_ONCE(priv->multi_packet > 2))
+		return;
+
+	offset = 2 * priv->multi_packet;
+	priv->multi_data[offset] = packet[6];
+	priv->multi_data[offset + 1] = packet[7];
+
+	/*
+	 * The 5th byte of the MT data must always be 0x00.
+	 * Try to re-sync our position if MT data is inconsistent.
+	 */
+	if (priv->multi_data[4] != 0x00)
+		return;
 
 	left = packet[4] & 0x01;
 	right = packet[4] & 0x02;
@@ -617,22 +646,78 @@
 	y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
 	z = packet[5] & 0x7f;
 
-	if (z >= 64)
-		input_report_key(dev, BTN_TOUCH, 1);
-	else
-		input_report_key(dev, BTN_TOUCH, 0);
 
-	if (z > 0) {
-		input_report_abs(dev, ABS_X, x);
-		input_report_abs(dev, ABS_Y, y);
-	}
-	input_report_abs(dev, ABS_PRESSURE, z);
+	if (++priv->multi_packet > 2) {
+		priv->multi_packet = 0;
+
+		x_bitmap = ((priv->multi_data[2] & 0x1f) << 10) |
+			   ((priv->multi_data[3] & 0x60) << 3) |
+			   ((priv->multi_data[0] & 0x3f) << 2) |
+			   ((priv->multi_data[1] & 0x60) >> 5);
+		y_bitmap = ((priv->multi_data[5] & 0x01) << 10) |
+			   ((priv->multi_data[3] & 0x1f) << 5) |
+			   (priv->multi_data[1] & 0x1f);
+
+		fingers = alps_process_bitmap(x_bitmap, y_bitmap,
+					      &x1, &y1, &x2, &y2);
 
-	input_report_key(dev, BTN_TOOL_FINGER, z > 0);
-	input_report_key(dev, BTN_LEFT, left);
-	input_report_key(dev, BTN_RIGHT, right);
+		/*
+		 * If there were no contacts in the bitmap, use ST
+		 * points in MT reports.
+		 */
+		if (fingers < 2) {
+			x1 = x;
+			y1 = y;
+			fingers = z > 0 ? 1 : 0;
+		}
+
+		priv->last_fingers = fingers;
+
+		if (z >= 64)
+			input_report_key(dev, BTN_TOUCH, 1);
+		else
+			input_report_key(dev, BTN_TOUCH, 0);
+
+		alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
+
+		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_TOOL_QUADTAP, fingers == 4);
+
+		input_report_key(dev, BTN_LEFT, left);
+		input_report_key(dev, BTN_RIGHT, right);
+
+		if (z > 0) {
+			input_report_abs(dev, ABS_X, x);
+			input_report_abs(dev, ABS_Y, y);
+		}
+		input_report_abs(dev, ABS_PRESSURE, z);
+
+		input_sync(dev);
+	} else {
+		if (priv->last_fingers == 1) {
+			if (z >= 64)
+				input_report_key(dev, BTN_TOUCH, 1);
+			else
+				input_report_key(dev, BTN_TOUCH, 0);
+
+			alps_report_semi_mt_data(dev, 1, x, y, 0, 0);
+
+			input_report_key(dev, BTN_TOOL_FINGER, z > 0);
+
+			input_report_key(dev, BTN_LEFT, left);
+			input_report_key(dev, BTN_RIGHT, right);
+
+			if (z > 0) {
+				input_report_abs(dev, ABS_X, x);
+				input_report_abs(dev, ABS_Y, y);
+			}
+			input_report_abs(dev, ABS_PRESSURE, z);
 
-	input_sync(dev);
+			input_sync(dev);
+		}
+	}
 }
 
 static void alps_process_packet(struct psmouse *psmouse)
@@ -1557,6 +1642,7 @@
 		input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
 		break;
 	case ALPS_PROTO_V3:
+	case ALPS_PROTO_V4:
 		set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
 		input_mt_init_slots(dev1, 2);
 		input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, 
ALPS_V3_X_MAX, 0, 0);
@@ -1565,8 +1651,7 @@
 		set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit);
 		set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
 		set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
-		/* fall through */
-	case ALPS_PROTO_V4:
+
 		input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0);
 		input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0);
 		break;
--- linux-3.3/drivers/input/mouse/alps.h.orig	2012-04-16 
16:39:49.948823942 +0300
+++ linux-3.3/drivers/input/mouse/alps.h	2012-04-16 16:41:28.228817760 
+0300
@@ -39,6 +39,7 @@
 	int prev_fin;			/* Finger bit from previous packet */
 	int multi_packet;		/* Multi-packet data in progress */
 	unsigned char multi_data[6];	/* Saved multi-packet data */
+	int last_fingers;		/* Number of fingers from MT report*/
 	u8 quirks;
 	struct timer_list timer;
 };



  reply	other threads:[~2012-04-16 14:23 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-10 14:02 ALPS v4 Semi-mt Support George Pantalos
2012-04-10 15:21 ` Seth Forshee
2012-04-10 21:59   ` Seth Forshee
2012-04-16 14:24     ` George Pantalos [this message]
2012-04-16 21:24       ` Seth Forshee
2012-04-16 22:21         ` George Pantalos
2012-04-17 13:16           ` Seth Forshee
2012-04-17  0:52         ` George Pantalos
2012-04-17 15:22           ` Seth Forshee
  -- strict thread matches above, loose matches on Subject: below --
2012-04-10 14:01 George Pantalos

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=1492453.bjpWEAk9kj@vaio \
    --to=gpantalos@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=seth.forshee@canonical.com \
    /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.