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.

Modified files:

Index: src/sys/dev/pckbport/synaptics.c
diff -u src/sys/dev/pckbport/synaptics.c:1.31 src/sys/dev/pckbport/synaptics.c:1.32
--- src/sys/dev/pckbport/synaptics.c:1.31	Tue Feb 25 13:30:10 2014
+++ src/sys/dev/pckbport/synaptics.c	Thu May 22 21:11:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: synaptics.c,v 1.31 2014/02/25 18:30:10 pooka Exp $	*/
+/*	$NetBSD: synaptics.c,v 1.32 2014/05/23 01:11:29 christos Exp $	*/
 
 /*
  * Copyright (c) 2005, Steve C. Woodford
@@ -48,7 +48,7 @@
 #include "opt_pms.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: synaptics.c,v 1.31 2014/02/25 18:30:10 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: synaptics.c,v 1.32 2014/05/23 01:11:29 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -131,6 +131,93 @@ static int synaptics_max_speed_x_nodenum
 static int synaptics_max_speed_y_nodenum;
 static int synaptics_movement_threshold_nodenum;
 
+static void
+pms_synaptics_probe_extended(struct pms_softc *psc)
+{
+	struct synaptics_softc *sc = &psc->u.synaptics;
+	u_char cmd[1], resp[3];
+	int res;
+
+	aprint_debug_dev(psc->sc_dev,
+	    "synaptics_probe: Capabilities 0x%04x.\n", sc->caps);
+	if (sc->caps & SYNAPTICS_CAP_PASSTHROUGH)
+		sc->flags |= SYN_FLAG_HAS_PASSTHROUGH;
+
+	if (sc->caps & SYNAPTICS_CAP_PALMDETECT)
+		sc->flags |= SYN_FLAG_HAS_PALM_DETECT;
+
+	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) + 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) {
+			int buttons = (resp[1] >> 4);
+			aprint_debug_dev(psc->sc_dev,
+			    "%s: Extended Buttons: %d.\n", __func__, buttons);
+
+			aprint_debug_dev(psc->sc_dev, "%s: Extended "
+			    "Capabilities: 0x%02x 0x%02x 0x%02x.\n", __func__,
+			    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, "%s: Continued "
+			    "Capabilities 0x%02x 0x%02x 0x%02x.\n", __func__,
+			    resp[0], resp[1], resp[2]);
+			switch (clickpad_type) {
+			case 1:
+				sc->flags |= SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD;
+				break;
+			case 2:
+				sc->flags |= SYN_FLAG_HAS_TWO_BUTTON_CLICKPAD;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+}
+
 int
 pms_synaptics_probe_init(void *vsc)
 {
@@ -200,39 +287,17 @@ pms_synaptics_probe_init(void *vsc)
 		sc->flags |= SYN_FLAG_HAS_BUTTONS_4_5;
 
 	if (sc->caps & SYNAPTICS_CAP_EXTENDED) {
-		aprint_debug_dev(psc->sc_dev,
-		    "synaptics_probe: Capabilities 0x%04x.\n", sc->caps);
-		if (sc->caps & SYNAPTICS_CAP_PASSTHROUGH)
-			sc->flags |= SYN_FLAG_HAS_PASSTHROUGH;
-
-		if (sc->caps & SYNAPTICS_CAP_PALMDETECT)
-			sc->flags |= SYN_FLAG_HAS_PALM_DETECT;
-
-		if (sc->caps & SYNAPTICS_CAP_MULTIDETECT)
-			sc->flags |= SYN_FLAG_HAS_MULTI_FINGER;
-
-		/* Ask about extra buttons to detect up/down. */
-		if (sc->caps & SYNAPTICS_CAP_EXTNUM) {
-			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)
-				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;
-			}
-		}
+		pms_synaptics_probe_extended(psc);
 	}
 
 	if (sc->flags) {
 		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 +318,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 +361,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.
 		 */
@@ -621,6 +706,8 @@ pms_synaptics_parse(struct pms_softc *ps
 	struct synaptics_softc *sc = &psc->u.synaptics;
 	struct synaptics_packet sp;
 
+	memset(&sp, 0, sizeof(sp));
+
 	/* Absolute X/Y coordinates of finger */
 	sp.sp_x = psc->packet[4] + ((psc->packet[1] & 0x0f) << 8) +
 	   ((psc->packet[3] & 0x10) << 8);
@@ -658,6 +745,12 @@ pms_synaptics_parse(struct pms_softc *ps
 		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. */
@@ -861,12 +954,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.
@@ -880,9 +978,16 @@ synaptics_gesture_detect(struct synaptic
 		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) {
 		/*
@@ -893,13 +998,19 @@ synaptics_gesture_detect(struct synaptic
 		 * 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.
 			 */

Index: src/sys/dev/pckbport/synapticsreg.h
diff -u src/sys/dev/pckbport/synapticsreg.h:1.7 src/sys/dev/pckbport/synapticsreg.h:1.8
--- src/sys/dev/pckbport/synapticsreg.h:1.7	Sat Sep 10 14:38:20 2011
+++ src/sys/dev/pckbport/synapticsreg.h	Thu May 22 21:11:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: synapticsreg.h,v 1.7 2011/09/10 18:38:20 jakllsch Exp $	*/
+/*	$NetBSD: synapticsreg.h,v 1.8 2014/05/23 01:11:29 christos Exp $	*/
 
 /*
  * Copyright (c) 2005, Steve C. Woodford
@@ -35,45 +35,47 @@
  *
  */
 
-#ifndef _DEV_PCKBCPORT_SYNAPTICSREG_H_
-#define _DEV_PCKBCPORT_SYNAPTICSREG_H_
+#ifndef	_DEV_PCKBCPORT_SYNAPTICSREG_H_
+#define	_DEV_PCKBCPORT_SYNAPTICSREG_H_
 
 /* Synaptics information queries. */
-#define SYNAPTICS_IDENTIFY_TOUCHPAD	0x0
-#define SYNAPTICS_READ_MODE		0x1
-#define SYNAPTICS_READ_CAPABILITIES	0x2
-#define SYNAPTICS_READ_MODEL_ID		0x3
-#define SYNAPTICS_EXTENDED_QUERY	0x9
+#define	SYNAPTICS_IDENTIFY_TOUCHPAD	0x0
+#define	SYNAPTICS_READ_MODE		0x1
+#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
-#define SYNAPTICS_CMD_CLIENT_CMD	0x28
+#define	SYNAPTICS_CMD_SET_MODE2		0x14
+#define	SYNAPTICS_CMD_CLIENT_CMD	0x28
 
 /* Magic numbers. */
-#define SYNAPTICS_MIN_VERSION		45 /* 4.5 */
-#define SYNAPTICS_MAGIC_BYTE		0x47
+#define	SYNAPTICS_MIN_VERSION		45 /* 4.5 */
+#define	SYNAPTICS_MAGIC_BYTE		0x47
 
 /* Capability bits. */
-#define SYNAPTICS_CAP_EXTENDED		(1 << 15)
-#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_SLEEP		(1 << 4)
-#define SYNAPTICS_CAP_4BUTTON		(1 << 3)
-#define SYNAPTICS_CAP_MULTIDETECT	(1 << 1)
-#define SYNAPTICS_CAP_PALMDETECT	(1 << 0)
+#define	SYNAPTICS_CAP_EXTENDED		(1 << 15)
+#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)
+#define	SYNAPTICS_CAP_PALMDETECT	(1 << 0)
 
 /* Mode bits. */
-#define SYNAPTICS_MODE_ABSOLUTE		(1 << 7)
-#define SYNAPTICS_MODE_RATE		(1 << 6)
-#define SYNAPTICS_MODE_SLEEP		(1 << 3)
-#define SYNAPTICS_MODE_GEST		(1 << 2)
-#define SYNAPTICS_MODE_4BYTE_CLIENT	(1 << 1)
-#define SYNAPTICS_MODE_W		(1)
+#define	SYNAPTICS_MODE_ABSOLUTE		(1 << 7)
+#define	SYNAPTICS_MODE_RATE		(1 << 6)
+#define	SYNAPTICS_MODE_SLEEP		(1 << 3)
+#define	SYNAPTICS_MODE_GEST		(1 << 2)
+#define	SYNAPTICS_MODE_4BYTE_CLIENT	(1 << 1)
+#define	SYNAPTICS_MODE_W		(1)
 
 /* Extended mode button masks. */
-#define SYN_1BUTMASK			0x1
-#define SYN_2BUTMASK			0x1
+#define	SYN_1BUTMASK			0x1
+#define	SYN_2BUTMASK			0x1
 
 /* Touchpad edge boundaries (Recommended values from Synaptics documentation) */
 #define	SYNAPTICS_EDGE_LEFT		1632

Index: src/sys/dev/pckbport/synapticsvar.h
diff -u src/sys/dev/pckbport/synapticsvar.h:1.5 src/sys/dev/pckbport/synapticsvar.h:1.6
--- src/sys/dev/pckbport/synapticsvar.h:1.5	Sat Sep 10 14:38:20 2011
+++ src/sys/dev/pckbport/synapticsvar.h	Thu May 22 21:11:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: synapticsvar.h,v 1.5 2011/09/10 18:38:20 jakllsch Exp $	*/
+/*	$NetBSD: synapticsvar.h,v 1.6 2014/05/23 01:11:29 christos Exp $	*/
 
 /*
  * Copyright (c) 2005, Steve C. Woodford
@@ -42,12 +42,18 @@ struct synaptics_softc {
 	int	caps;
 
 	int	flags;
-#define	SYN_FLAG_HAS_MIDDLE_BUTTON	(1 << 0)
-#define	SYN_FLAG_HAS_BUTTONS_4_5	(1 << 1)
-#define	SYN_FLAG_HAS_UP_DOWN_BUTTONS	(1 << 2)
-#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_MIDDLE_BUTTON		(1 << 0)
+#define	SYN_FLAG_HAS_BUTTONS_4_5		(1 << 1)
+#define	SYN_FLAG_HAS_UP_DOWN_BUTTONS		(1 << 2)
+#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;
 

Reply via email to