public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Peter Osterlund <petero2@telia.com>
To: Dmitry Torokhov <dtor_core@ameritech.net>
Cc: linux-kernel@vger.kernel.org, Vojtech Pavlik <vojtech@suse.cz>
Subject: Re: [RFT/PATCH 2.6] ALPS touchpad driver
Date: 28 Jul 2004 21:22:17 +0200	[thread overview]
Message-ID: <m3u0vsszrq.fsf@telia.com> (raw)
In-Reply-To: <200407110045.08208.dtor_core@ameritech.net>

Dmitry Torokhov <dtor_core@ameritech.net> writes:

> I lifted some code off tpconfig and merged it with Peter's/Neil's ALPS driver.
> The driver will try to auto-detect presence of an ALPS touchpad by issuing
> E6/E7 requests and matching responses with known ALPS signatures. It will
> also try disabling hardware tapping so taps could be controlled by either
> userspace drivers (X/GPM) or future version of mousedev (2.6.8 I hope will
> have it).

I now have a computer with an ALPS touchpad, and your patch works
better than the old patch, even though there are some issues.
Auto-detection works:

        alps.c: E6 report: 00 00 64
        alps.c: E7 report: 73 02 0a
        alps.c: E6 report: 00 00 64
        alps.c: E7 report: 73 02 0a
        alps.c: Status: 15 01 0a
        ALPS Touchpad (Glidepoint) detected
          Disabling hardware tapping
        alps.c: Status: 11 01 0a
        input: AlpsPS/2 ALPS TouchPad on isa0060/serio4

However, fast double taps are no longer detected. The second tap is
simply ignored. I added this printk:

	printk("time:%lu x:%3d y:%3d z:%3d %d%d%d %d%d%d %d%d%d\n",
	       jiffies, x, y, z,
	       (packet[0] & 0x04) != 0, (packet[0] & 0x02) != 0, (packet[0] & 0x01) != 0,
	       (packet[2] & 0x04) != 0, (packet[2] & 0x02) != 0, (packet[2] & 0x01) != 0,
	       (packet[3] & 0x04) != 0, (packet[3] & 0x02) != 0, (packet[3] & 0x01) != 0);

to alps_process_packet() and made some tests:

A single tap gives:

        time:2836613 x:469 y:445 z: 16 111 010 000
        time:2836714 x:469 y:445 z:  0 111 000 000

Note that taps always generate z==16, and they always appear to be
100ms long. Apparently the touchpad firmware is still trying to be
clever instead of just reporting the measured x/y/z values.
Unfortunately a fast double tap generates exactly the same response.
The second tap is not detected.

A slightly longer tap (>100ms I think) gives:

        time:2947819 x:575 y:466 z: 79 111 010 000
        time:2947911 x:575 y:466 z: 52 111 010 000
        time:2947931 x:575 y:466 z:  0 111 000 000
        time:2947991 x:575 y:466 z: 16 111 010 000
        time:2948092 x:575 y:466 z:  0 111 000 000

This gets translated to a double click by the X driver (assuming
FingerHigh<16), even though I only tapped once.

If I hold the finger even longer on the pad before releasing it
(>~180ms I think), the touchpad reports:

        time:3180578 x:656 y:432 z: 78 111 010 000
        time:3180728 x:656 y:432 z: 71 111 010 000
        time:3180737 x:656 y:432 z: 42 111 010 000
        time:3180746 x:656 y:432 z:  0 111 000 000

Now it doesn't try to be clever, and instead reports the true x/y/z
values.

I tried the windows driver, and it correctly detects fast double taps,
which makes me think it is not using the "hardware tapping off" mode.
Therefore, it made some tests with hardware tapping enabled.

A short single tap now gives:

        time:3850310 x:574 y:402 z:  0 111 001 000
        time:3850410 x:574 y:402 z:  0 111 000 000

Ie, z==0 but the gesture bit is set to 1 for 100ms.

A fast double tap gives:

        time:3951723 x:589 y:359 z:  0 111 001 000
        time:3951865 x:589 y:359 z:  0 111 000 000
        time:3951883 x:617 y:354 z:  0 111 001 000
        time:3951905 x:617 y:354 z:  0 111 000 000

which is good, since it no longer looks identical to a single tap.

A longer tap gives:

        time:4161527 x:506 y:480 z: 90 111 010 000
        time:4161560 x:506 y:480 z: 68 111 010 000
        time:4161579 x:506 y:480 z:  0 111 000 000

So, it looks like it would be enough to convert the gesture bit to
some sufficiently large Z value. However, that's not enough, because a
tap-and-drag (touch-release-touch-drag-release) operation gives:

        time:4221184 x:502 y:444 z:  0 111 001 000
        time:4221312 x:542 y:365 z: 73 111 011 000
        time:4221324 x:540 y:368 z: 74 111 011 000
        ...
        time:4221543 x:511 y:419 z: 24 111 011 000
        time:4221554 x:511 y:419 z:  0 111 001 000
        time:4221577 x:511 y:419 z:  0 111 000 000

Note that there is no indication from the hardware that the finger was
released and then touched again between the first and second lines.
This case can be handled too by the driver, by detecting when the
state changes from "!fin && ges" to "fin && ges". With that logic
added, the driver can undo most of the damage caused by hardware tap
emulation, but sometimes there are delays between state changes which
I haven't completely understood yet. Setting MaxTapTime >= 210 in the
X driver seems to make it work quite well though.

The above analysis leads to the patch below. The static variable
obviously has to go in the final version. This patch is only to
illustrate the logic/ugliness needed to make my touchpad behave
reasonably.

---

 linux-petero/drivers/input/mouse/alps.c |   28 +++++++++++++++++++++++++---
 1 files changed, 25 insertions(+), 3 deletions(-)

diff -puN drivers/input/mouse/alps.c~alps-test drivers/input/mouse/alps.c
--- linux/drivers/input/mouse/alps.c~alps-test	2004-07-27 23:15:40.000000000 +0200
+++ linux-petero/drivers/input/mouse/alps.c	2004-07-28 20:53:06.993329536 +0200
@@ -80,6 +80,8 @@ static void alps_process_packet(struct p
 	struct input_dev *dev = &psmouse->dev;
 	int x, y, z;
 	int left = 0, right = 0, middle = 0;
+	int ges, fin;
+	static int prev_fin;
 
 	input_regs(dev, regs);
 
@@ -87,6 +89,27 @@ static void alps_process_packet(struct p
 	y = (packet[4] & 0x7f) | ((packet[3] & 0x70)<<(7-4));
 	z = packet[5];
 
+	printk("time:%lu x:%3d y:%3d z:%3d %d%d%d %d%d%d %d%d%d\n",
+	       jiffies, x, y, z,
+	       (packet[0] & 0x04) != 0, (packet[0] & 0x02) != 0, (packet[0] & 0x01) != 0,
+	       (packet[2] & 0x04) != 0, (packet[2] & 0x02) != 0, (packet[2] & 0x01) != 0,
+	       (packet[3] & 0x04) != 0, (packet[3] & 0x02) != 0, (packet[3] & 0x01) != 0);
+
+	ges = packet[2] & 1;
+	fin = packet[2] & 2;
+
+	if (ges && !fin)
+		z = 40;
+
+	if (ges && fin && !prev_fin) {
+		input_report_abs(dev, ABS_X, x);
+		input_report_abs(dev, ABS_Y, y);
+		input_report_abs(dev, ABS_PRESSURE, 0);
+		input_report_key(dev, BTN_TOOL_FINGER, 0);
+		input_sync(dev);
+	}
+	prev_fin = fin;
+
 	if (z > 30) input_report_key(dev, BTN_TOUCH, 1);
 	if (z < 25) input_report_key(dev, BTN_TOUCH, 0);
 
@@ -97,7 +120,6 @@ static void alps_process_packet(struct p
 	input_report_abs(dev, ABS_PRESSURE, z);
 	input_report_key(dev, BTN_TOOL_FINGER, z > 0);
 
-	left  |= (packet[2]     ) & 1;
 	left  |= (packet[3]     ) & 1;
 	right |= (packet[3] >> 1) & 1;
 	if (packet[0] == 0xff) {
@@ -289,7 +311,7 @@ static int alps_reconnect(struct psmouse
 		return -1;
 
 	if ((model == ALPS_MODEL_DUALPOINT ? param[2] : param[0]) & 0x04)
-		alps_tap_mode(psmouse, model, 0);
+		alps_tap_mode(psmouse, model, 1);
 
 	if (alps_absolute_mode(psmouse)) {
 		printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
@@ -322,7 +344,7 @@ int alps_init(struct psmouse *psmouse)
 
 	if ((model == ALPS_MODEL_DUALPOINT ? param[2] : param[0]) & 0x04) {
 		printk(KERN_INFO "  Disabling hardware tapping\n");
-		if (alps_tap_mode(psmouse, model, 0))
+		if (alps_tap_mode(psmouse, model, 1))
 			printk(KERN_WARNING "alps.c: Failed to disable hardware tapping\n");
 	}
 
_

-- 
Peter Osterlund - petero2@telia.com
http://w1.894.telia.com/~u89404340

  reply	other threads:[~2004-07-28 19:23 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-07-11  5:45 [RFT/PATCH 2.6] ALPS touchpad driver Dmitry Torokhov
2004-07-28 19:22 ` Peter Osterlund [this message]
2004-09-17 18:25   ` Stephen Hemminger

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=m3u0vsszrq.fsf@telia.com \
    --to=petero2@telia.com \
    --cc=dtor_core@ameritech.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=vojtech@suse.cz \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox