NetBSD Problem Report #48831

From www@NetBSD.org  Thu May 22 08:13:21 2014
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	(using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 62EC5A584C
	for <gnats-bugs@gnats.NetBSD.org>; Thu, 22 May 2014 08:13:21 +0000 (UTC)
Message-Id: <20140522081319.81E18A64ED@mollari.NetBSD.org>
Date: Thu, 22 May 2014 08:13:19 +0000 (UTC)
From: joerg.grundmann@centertools.de
Reply-To: joerg.grundmann@centertools.de
To: gnats-bugs@NetBSD.org
Subject: Synaptics Touch pad (ClickPad) and Klick-by-tap-gestures do not work
X-Send-Pr-Version: www-1.0

>Number:         48831
>Category:       kern
>Synopsis:       Synaptics Touch pad (ClickPad) and Klick-by-tap-gestures do not work
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu May 22 08:15:01 +0000 2014
>Closed-Date:    Sun Jun 03 20:58:41 +0000 2018
>Last-Modified:  Sun Jun 03 20:58:41 +0000 2018
>Originator:     Jörg Grundmann
>Release:        NetBSD 6.1.3
>Organization:
CenterTools GmbH
>Environment:
NetBSD joerg-netbsd-613.centertools.net 6.1.3 NetBSD 6.1.3 (GENERIC) i386
>Description:
1.
Newer notebooks like the Lenovo ThinkPad L540 have a touch pad which has no physical keys but the whole touch pad can be pressed to generate a left mouse button klick. This is not handled in the current driver.

2.
When fixing this issue, I recognized that virtual clicks are not handled correctly (tapping on the touch pad).

This touch pad reports version 8.1
>How-To-Repeat:
1.
On console:
$ cat /dev/wsmouse

Move finger on the touch pad -> garbage on screen -> OK
Press the whole touch pad down -> Nothing happens

Alternative:
Start Xorg Server
Mouse move by moving finger on the touch pad works.
Pressing the touch pad down does not create a "click"

2.
Start Xorg Server
Try to do "clicks" by just tapping the touch pad with one finger
-> Nothing happens
>Fix:
The following patch fixes both problems:

diff --git a/sys/dev/pckbport/synaptics.c b/sys/dev/pckbport/synaptics.c
index 50949fa..c061745 100644
--- a/sys/dev/pckbport/synaptics.c
+++ b/sys/dev/pckbport/synaptics.c
@@ -211,20 +211,66 @@ pms_synaptics_probe_init(void *vsc)
 		if (sc->caps & SYNAPTICS_CAP_MULTIDETECT)
 			sc->flags |= SYN_FLAG_HAS_MULTI_FINGER;

+		if (sc->caps & SYNAPTICS_CAP_MULTIFINGERREPORT)
+			sc->flags |= SYN_FLAG_HAS_MULTI_FINGER_REPORT;
+
 		/* Ask about extra buttons to detect up/down. */
-		if (sc->caps & SYNAPTICS_CAP_EXTNUM) {
+		if ( ((sc->caps & SYNAPTICS_CAP_EXTNUM) + 0x08) >= SYNAPTICS_EXTENDED_QUERY) {
 			res = pms_sliced_command(psc->sc_kbctag,
 			    psc->sc_kbcslot, SYNAPTICS_EXTENDED_QUERY);
 			cmd[0] = PMS_SEND_DEV_STATUS;
 			res |= pckbport_poll_cmd(psc->sc_kbctag,
 			    psc->sc_kbcslot, cmd, 1, 3, resp, 0);
-			if (res == 0)
+			if (res == 0) {
+				int buttons = (resp[1] >> 4);
 				aprint_debug_dev(psc->sc_dev,
 				    "synaptics_probe: Extended "
-				    "Capabilities 0x%02x.\n", resp[1]);
-			if (!res && (resp[1] >> 4) >= 2) {
-				/* Yes. */
-				sc->flags |= SYN_FLAG_HAS_UP_DOWN_BUTTONS;
+				    "Buttons: %d.\n", buttons);
+
+				aprint_debug_dev(psc->sc_dev,
+				    "synaptics_probe: Extended "
+				    "Capabilities: 0x%02x 0x%02x 0x%02x.\n",
+				    resp[0], resp[1], resp[2]);
+				if (buttons >= 2) {
+					/* Yes. */
+					sc->flags |= SYN_FLAG_HAS_UP_DOWN_BUTTONS;
+				}
+				if ((resp[0] & 0x1)) {
+					/* Vertical scroll area */
+					sc->flags |= SYN_FLAG_HAS_VERTICAL_SCROLL;
+				}
+				if ((resp[0] & 0x2)) {
+					/* Horizontal scroll area */
+					sc->flags |= SYN_FLAG_HAS_HORIZONTAL_SCROLL;
+				}
+				if ((resp[0] & 0x4)) {
+					/* Extended W-Mode */
+					sc->flags |= SYN_FLAG_HAS_EXTENDED_WMODE;
+				}
+			}
+		}
+
+		/* Ask about click pad */
+		if ( ((sc->caps & SYNAPTICS_CAP_EXTNUM) + 0x08) >= SYNAPTICS_CONTINUED_CAPABILITIES) {
+			res = pms_sliced_command(psc->sc_kbctag,
+			    psc->sc_kbcslot, SYNAPTICS_CONTINUED_CAPABILITIES);
+			cmd[0] = PMS_SEND_DEV_STATUS;
+			res |= pckbport_poll_cmd(psc->sc_kbctag,
+			    psc->sc_kbcslot, cmd, 1, 3, resp, 0);
+			if (res == 0) {
+				u_char clickpad_type = (resp[1] & 0x1);
+				clickpad_type |= ((resp[0] >> 4) & 0x1);
+
+				aprint_debug_dev(psc->sc_dev,
+				    "synaptics_probe: Continued "
+				    "Capabilities 0x%02x 0x%02x 0x%02x.\n",
+				    resp[0], resp[1], resp[2]);
+				if (clickpad_type == 1) {
+					sc->flags |= SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD;
+				}
+				else if (clickpad_type == 2) {
+					sc->flags |= SYN_FLAG_HAS_TWO_BUTTON_CLICKPAD;
+				}
 			}
 		}
 	}
@@ -233,6 +279,10 @@ pms_synaptics_probe_init(void *vsc)
 		const char comma[] = ", ";
 		const char *sep = "";
 		aprint_normal_dev(psc->sc_dev, "");
+		if (sc->flags & SYN_FLAG_HAS_EXTENDED_WMODE) {
+			aprint_normal("%sExtended W mode", sep);
+			sep = comma;
+		}
 		if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) {
 			aprint_normal("%sPassthrough", sep);
 			sep = comma;
@@ -253,6 +303,26 @@ pms_synaptics_probe_init(void *vsc)
 			aprint_normal("%sPalm detect", sep);
 			sep = comma;
 		}
+		if (sc->flags & SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD) {
+			aprint_normal("%sOne button click pad", sep);
+			sep = comma;
+		}
+		if (sc->flags & SYN_FLAG_HAS_TWO_BUTTON_CLICKPAD) {
+			aprint_normal("%sTwo button click pad", sep);
+			sep = comma;
+		}
+		if (sc->flags & SYN_FLAG_HAS_VERTICAL_SCROLL) {
+			aprint_normal("%sVertical scroll", sep);
+			sep = comma;
+		}
+		if (sc->flags & SYN_FLAG_HAS_HORIZONTAL_SCROLL) {
+			aprint_normal("%sHorizontal scroll", sep);
+			sep = comma;
+		}
+		if (sc->flags & SYN_FLAG_HAS_MULTI_FINGER_REPORT) {
+			aprint_normal("%sMulti-finger Report", sep);
+			sep = comma;
+		}
 		if (sc->flags & SYN_FLAG_HAS_MULTI_FINGER)
 			aprint_normal("%sMulti-finger", sep);

@@ -276,7 +346,7 @@ pms_synaptics_enable(void *vsc)
 	int res;

 	if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) {
-		/* 
+		/*
 		 * Extended capability probes can confuse the passthrough device;
 		 * reset the touchpad now to cure that.
 		 */
@@ -626,6 +696,8 @@ pms_synaptics_parse(struct pms_softc *psc)
 	struct synaptics_softc *sc = &psc->u.synaptics;
 	struct synaptics_packet sp;

+	memset(&sp, 0, sizeof(struct synaptics_packet));
+
 	/* Absolute X/Y coordinates of finger */
 	sp.sp_x = psc->packet[4] + ((psc->packet[1] & 0x0f) << 8) +
 	   ((psc->packet[3] & 0x10) << 8);
@@ -663,6 +735,12 @@ pms_synaptics_parse(struct pms_softc *psc)
 		sp.sp_down = 0;
 	}

+	if(sc->flags & SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD) {
+		/* This is not correctly specified. Read this button press
+		 * from L/U bit.
+		 */
+		sp.sp_left = ((psc->packet[0] ^ psc->packet[3]) & 0x01) ? 1 : 0;
+	} else
 	/* Middle button. */
 	if (sc->flags & SYN_FLAG_HAS_MIDDLE_BUTTON) {
 		/* Old style Middle Button. */
@@ -866,12 +944,17 @@ static inline void
 synaptics_gesture_detect(struct synaptics_softc *sc,
     struct synaptics_packet *sp, int fingers)
 {
-	int gesture_len, gesture_move_x, gesture_move_y, gesture_buttons;
+	int gesture_len, gesture_buttons;
 	int set_buttons;

 	gesture_len = SYN_TIME(sc, sc->gesture_start_packet);
 	gesture_buttons = sc->gesture_buttons;

+	if (fingers > 0 && (fingers == sc->prev_fingers)) {
+		/* Finger is still present */
+		sc->gesture_move_x = abs(sc->gesture_start_x - sp->sp_x);
+		sc->gesture_move_y = abs(sc->gesture_start_y - sp->sp_y);
+	} else
 	if (fingers && sc->prev_fingers == 0) {
 		/*
 		 * Finger was just applied.
@@ -885,9 +968,16 @@ synaptics_gesture_detect(struct synaptics_softc *sc,
 		if (SYN_IS_SINGLE_TAP(sc->gesture_type))
 			sc->gesture_type |= SYN_GESTURE_DRAG;

-		sc->gesture_start_x = sp->sp_x;
-		sc->gesture_start_y = sp->sp_y;
+		sc->gesture_start_x = abs(sp->sp_x);
+		sc->gesture_start_y = abs(sp->sp_y);
+		sc->gesture_move_x = 0;
+		sc->gesture_move_y = 0;
 		sc->gesture_start_packet = sc->total_packets;
+
+#ifdef DIAGNOSTIC
+		aprint_debug("Finger applied: gesture_start_x: %d gesture_start_y: %d\n",
+			sc->gesture_start_x, sc->gesture_start_y);
+#endif
 	} else
 	if (fingers == 0 && sc->prev_fingers != 0) {
 		/*
@@ -898,13 +988,19 @@ synaptics_gesture_detect(struct synaptics_softc *sc,
 		 * detected (the pad may report coordinates for any
 		 * of the fingers).
 		 */
-		gesture_move_x = abs(sc->gesture_start_x - sp->sp_x);
-		gesture_move_y = abs(sc->gesture_start_y - sp->sp_y);
+
+#ifdef DIAGNOSTIC
+		aprint_debug("Finger removed: gesture_len: %d (%d)\n",
+			gesture_len, synaptics_gesture_length);
+		aprint_debug("gesture_move_x: %d (%d) sp_x: %d\n",
+			sc->gesture_move_x, synaptics_gesture_move, abs(sp->sp_x));
+		aprint_debug("gesture_move_y: %d (%d) sp_y: %d\n",
+			sc->gesture_move_y, synaptics_gesture_move, abs(sp->sp_y));
+#endif

 		if (gesture_len < synaptics_gesture_length &&
-		    (sc->prev_fingers > 1 ||
-		    (gesture_move_x < synaptics_gesture_move &&
-		     gesture_move_y < synaptics_gesture_move))) {
+		    ((sc->gesture_move_x < synaptics_gesture_move &&
+		     sc->gesture_move_y < synaptics_gesture_move))) {
 			/*
 			 * Looking good so far.
 			 */
diff --git a/sys/dev/pckbport/synapticsreg.h b/sys/dev/pckbport/synapticsreg.h
index 27d22f1..3642a28 100644
--- a/sys/dev/pckbport/synapticsreg.h
+++ b/sys/dev/pckbport/synapticsreg.h
@@ -44,6 +44,7 @@
 #define SYNAPTICS_READ_CAPABILITIES	0x2
 #define SYNAPTICS_READ_MODEL_ID		0x3
 #define SYNAPTICS_EXTENDED_QUERY	0x9
+#define SYNAPTICS_CONTINUED_CAPABILITIES 0x0c

 /* Synaptics special commands */
 #define SYNAPTICS_CMD_SET_MODE2		0x14
@@ -58,6 +59,7 @@
 #define SYNAPTICS_CAP_EXTNUM		(1 << 14 | 1 << 13 | 1 << 12)
 #define SYNAPTICS_CAP_MBUTTON		(1 << 10)
 #define SYNAPTICS_CAP_PASSTHROUGH	(1 << 7)
+#define SYNAPTICS_CAP_MULTIFINGERREPORT (1 << 5)
 #define SYNAPTICS_CAP_SLEEP		(1 << 4)
 #define SYNAPTICS_CAP_4BUTTON		(1 << 3)
 #define SYNAPTICS_CAP_MULTIDETECT	(1 << 1)
diff --git a/sys/dev/pckbport/synapticsvar.h b/sys/dev/pckbport/synapticsvar.h
index a548536..28b6c0c 100644
--- a/sys/dev/pckbport/synapticsvar.h
+++ b/sys/dev/pckbport/synapticsvar.h
@@ -48,6 +48,12 @@ struct synaptics_softc {
 #define	SYN_FLAG_HAS_PASSTHROUGH	(1 << 3)
 #define	SYN_FLAG_HAS_PALM_DETECT	(1 << 4)
 #define	SYN_FLAG_HAS_MULTI_FINGER	(1 << 5)
+#define SYN_FLAG_HAS_MULTI_FINGER_REPORT (1 << 6)
+#define SYN_FLAG_HAS_VERTICAL_SCROLL (1 << 7)
+#define SYN_FLAG_HAS_HORIZONTAL_SCROLL (1 << 8)
+#define SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD (1 << 9)
+#define SYN_FLAG_HAS_TWO_BUTTON_CLICKPAD (1 << 10)
+#define SYN_FLAG_HAS_EXTENDED_WMODE (1<<11)

 	u_int	total_packets;		/* Total number of packets received */
 #define	SYN_TIME(sc,c)	(((sc)->total_packets >= (c)) ?		\
@@ -58,6 +64,7 @@ struct synaptics_softc {
 	int	prev_fingers;

 	int	gesture_start_x, gesture_start_y;
+	int gesture_move_x, gesture_move_y;
 	u_int	gesture_start_packet;
 	u_int	gesture_tap_packet;


>Release-Note:

>Audit-Trail:
From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/48831 CVS commit: src/sys/dev/pckbport
Date: Thu, 22 May 2014 21:11:29 -0400

 Module Name:	src
 Committed By:	christos
 Date:		Fri May 23 01:11:29 UTC 2014

 Modified Files:
 	src/sys/dev/pckbport: synaptics.c synapticsreg.h synapticsvar.h

 Log Message:
 PR/48831: Jörg Grundmann: Synaptics Touch pad (ClickPad) and
 Klick-by-tap-gestures do not work


 To generate a diff of this commit:
 cvs rdiff -u -r1.31 -r1.32 src/sys/dev/pckbport/synaptics.c
 cvs rdiff -u -r1.7 -r1.8 src/sys/dev/pckbport/synapticsreg.h
 cvs rdiff -u -r1.5 -r1.6 src/sys/dev/pckbport/synapticsvar.h

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "David H. Gutteridge" <dhgutteridge@sympatico.ca>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: kern/48831: Synaptics Touch pad (ClickPad) and Klick-by-tap-gestures do not work
Date: Fri, 23 May 2014 21:08:40 -0400

 X.org's xf86-input-synaptics driver version 1.8.0 also has enhancements
 that may be relevant, see:

 =
 http://cgit.freedesktop.org/xorg/driver/xf86-input-synaptics/commit/?id=3D=
 f183c1c38778b659b4c75a0e2c532dd5a9f8d437

 (I don't know how significant this is, I've just been looking at the
 same sort of issue as it relates to my Lenovo ThinkPad Edge E531.)

 Dave=

State-Changed-From-To: open->closed
State-Changed-By: maya@NetBSD.org
State-Changed-When: Sun, 03 Jun 2018 20:58:41 +0000
State-Changed-Why:
Committed by christos. THanks for the patch, I've got a Synaptics touchpad myself which benefits from these changes :-)


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.43 2018/01/16 07:36:43 maya Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2017 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.