svn commit: r255153 - in head/sys: dev/atkbdc sys

Jean-Sebastien Pedron dumbbell at FreeBSD.org
Mon Sep 2 19:15:21 UTC 2013


Author: dumbbell
Date: Mon Sep  2 19:15:20 2013
New Revision: 255153
URL: http://svnweb.freebsd.org/changeset/base/255153

Log:
  psm: Add support for middle and extended buttons on Synaptics touchpads
  
  PR:		kern/170834
  Submitted by:	Brandon Gooch <jamesbrandongooch at gmail.com>
  Tested by:	Artyom Mirgorodskiy <artyom.mirgorodsky at gmail.com>
  MFC after:	1 month

Modified:
  head/sys/dev/atkbdc/psm.c
  head/sys/sys/mouse.h

Modified: head/sys/dev/atkbdc/psm.c
==============================================================================
--- head/sys/dev/atkbdc/psm.c	Mon Sep  2 18:25:18 2013	(r255152)
+++ head/sys/dev/atkbdc/psm.c	Mon Sep  2 19:15:20 2013	(r255153)
@@ -2601,14 +2601,14 @@ proc_synaptics(struct psm_softc *sc, pac
 	static int guest_buttons;
 	int w, x0, y0;
 
-	/* TouchPad PS/2 absolute mode message format
+	/* TouchPad PS/2 absolute mode message format with capFourButtons:
 	 *
 	 *  Bits:        7   6   5   4   3   2   1   0 (LSB)
 	 *  ------------------------------------------------
 	 *  ipacket[0]:  1   0  W3  W2   0  W1   R   L
 	 *  ipacket[1]: Yb  Ya  Y9  Y8  Xb  Xa  X9  X8
 	 *  ipacket[2]: Z7  Z6  Z5  Z4  Z3  Z2  Z1  Z0
-	 *  ipacket[3]:  1   1  Yc  Xc   0  W0   D   U
+	 *  ipacket[3]:  1   1  Yc  Xc   0  W0 D^R U^L
 	 *  ipacket[4]: X7  X6  X5  X4  X3  X2  X1  X0
 	 *  ipacket[5]: Y7  Y6  Y5  Y4  Y3  Y2  Y1  Y0
 	 *
@@ -2622,6 +2622,21 @@ proc_synaptics(struct psm_softc *sc, pac
 	 *  Y: y position
 	 *  Z: pressure
 	 *
+	 * Without capFourButtons but with nExtendeButtons and/or capMiddle
+	 *
+	 *  Bits:        7   6   5   4      3      2      1      0 (LSB)
+	 *  ------------------------------------------------------
+	 *  ipacket[3]:  1   1  Yc  Xc      0     W0    E^R    M^L
+	 *  ipacket[4]: X7  X6  X5  X4  X3|b7  X2|b5  X1|b3  X0|b1
+	 *  ipacket[5]: Y7  Y6  Y5  Y4  Y3|b8  Y2|b6  Y1|b4  Y0|b2
+	 *
+	 * Legend:
+	 *  M: Middle physical mouse button
+	 *  E: Extended mouse buttons reported instead of low bits of X and Y
+	 *  b1-b8: Extended mouse buttons
+	 *    Only ((nExtendedButtons + 1) >> 1) bits are used in packet
+	 *    4 and 5, for reading X and Y value they should be zeroed.
+	 *
 	 * Absolute reportable limits:    0 - 6143.
 	 * Typical bezel limits:       1472 - 5472.
 	 * Typical edge marings:       1632 - 5312.
@@ -2675,8 +2690,10 @@ proc_synaptics(struct psm_softc *sc, pac
 		w = 4;
 	}
 
-	/* Handle packets from the guest device */
-	/* XXX Documentation? */
+	/*
+	 * Handle packets from the guest device. See:
+	 * Synaptics PS/2 TouchPad Interfacing Guide, Section 5.1
+	 */
 	if (w == 3 && sc->synhw.capPassthrough) {
 		*x = ((pb->ipacket[1] & 0x10) ?
 		    pb->ipacket[4] - 256 : pb->ipacket[4]);
@@ -2704,36 +2721,49 @@ proc_synaptics(struct psm_softc *sc, pac
 		touchpad_buttons |= MOUSE_BUTTON3DOWN;
 
 	if (sc->synhw.capExtended && sc->synhw.capFourButtons) {
-		if ((pb->ipacket[3] & 0x01) && (pb->ipacket[0] & 0x01) == 0)
+		if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x01)
 			touchpad_buttons |= MOUSE_BUTTON4DOWN;
-		if ((pb->ipacket[3] & 0x02) && (pb->ipacket[0] & 0x02) == 0)
+		if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x02)
 			touchpad_buttons |= MOUSE_BUTTON5DOWN;
-	}
-
-	/*
-	 * In newer pads - bit 0x02 in the third byte of
-	 * the packet indicates that we have an extended
-	 * button press.
-	 */
-	/* XXX Documentation? */
-	if (pb->ipacket[3] & 0x02) {
-		/*
-		 * if directional_scrolls is not 1, we treat any of
-		 * the scrolling directions as middle-click.
-		 */
-		if (sc->syninfo.directional_scrolls) {
-			if (pb->ipacket[4] & 0x01)
-				touchpad_buttons |= MOUSE_BUTTON4DOWN;
-			if (pb->ipacket[5] & 0x01)
-				touchpad_buttons |= MOUSE_BUTTON5DOWN;
-			if (pb->ipacket[4] & 0x02)
-				touchpad_buttons |= MOUSE_BUTTON6DOWN;
-			if (pb->ipacket[5] & 0x02)
-				touchpad_buttons |= MOUSE_BUTTON7DOWN;
-		} else {
-			if ((pb->ipacket[4] & 0x0F) ||
-			    (pb->ipacket[5] & 0x0F))
+	} else if (sc->synhw.capExtended && sc->synhw.capMiddle) {
+		/* Middle Button */
+		if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)
+			touchpad_buttons |= MOUSE_BUTTON2DOWN;
+	} else if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) {
+		/* Extended Buttons */
+		if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x02) {
+			if (sc->syninfo.directional_scrolls) {
+				if (pb->ipacket[4] & 0x01)
+					touchpad_buttons |= MOUSE_BUTTON4DOWN;
+				if (pb->ipacket[5] & 0x01)
+					touchpad_buttons |= MOUSE_BUTTON5DOWN;
+				if (pb->ipacket[4] & 0x02)
+					touchpad_buttons |= MOUSE_BUTTON6DOWN;
+				if (pb->ipacket[5] & 0x02)
+					touchpad_buttons |= MOUSE_BUTTON7DOWN;
+			} else {
 				touchpad_buttons |= MOUSE_BUTTON2DOWN;
+			}
+
+			/*
+			 * Zero out bits used by extended buttons to avoid
+			 * misinterpretation of the data absolute position.
+			 *
+			 * The bits represented by
+			 *
+			 *     (nExtendedButtons + 1) >> 1
+			 *
+			 * will be masked out in both bytes.
+			 * The mask for n bits is computed with the formula
+			 *
+			 *     (1 << n) - 1
+			 */
+			int maskedbits = 0;
+			int mask = 0;
+			maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1;
+			mask = (1 << maskedbits) - 1;
+			pb->ipacket[4] &= ~(mask);
+			pb->ipacket[5] &= ~(mask);
 		}
 	}
 
@@ -4440,15 +4470,20 @@ enable_synaptics(KBDC kbdc, struct psm_s
 	buttons = 0;
 	synhw.capExtended = (status[0] & 0x80) != 0;
 	if (synhw.capExtended) {
-		synhw.capPassthrough = (status[2] & 0x80) != 0;
-		synhw.capSleep       = (status[2] & 0x10) != 0;
-		synhw.capFourButtons = (status[2] & 0x08) != 0;
-		synhw.capMultiFinger = (status[2] & 0x02) != 0;
-		synhw.capPalmDetect  = (status[2] & 0x01) != 0;
+		synhw.nExtendedQueries = (status[0] & 0x70) != 0;
+		synhw.capMiddle        = (status[0] & 0x04) != 0;
+		synhw.capPassthrough   = (status[2] & 0x80) != 0;
+		synhw.capSleep         = (status[2] & 0x10) != 0;
+		synhw.capFourButtons   = (status[2] & 0x08) != 0;
+		synhw.capMultiFinger   = (status[2] & 0x02) != 0;
+		synhw.capPalmDetect    = (status[2] & 0x01) != 0;
 
 		if (verbose >= 2) {
 			printf("  Extended capabilities:\n");
 			printf("   capExtended: %d\n", synhw.capExtended);
+			printf("   capMiddle: %d\n", synhw.capMiddle);
+			printf("   nExtendedQueries: %d\n",
+			    synhw.nExtendedQueries);
 			printf("   capPassthrough: %d\n", synhw.capPassthrough);
 			printf("   capSleep: %d\n", synhw.capSleep);
 			printf("   capFourButtons: %d\n", synhw.capFourButtons);
@@ -4457,16 +4492,27 @@ enable_synaptics(KBDC kbdc, struct psm_s
 		}
 
 		/*
-		 * If we have bits set in status[0] & 0x70, then we can load
+		 * If nExtendedQueries is 1 or greater, then the TouchPad
+		 * supports this number of extended queries. We can load
 		 * more information about buttons using query 0x09.
 		 */
-		if ((status[0] & 0x70) != 0) {
+		if (synhw.capExtended && synhw.nExtendedQueries) {
 			if (mouse_ext_command(kbdc, 0x09) == 0)
 				return (FALSE);
 			if (get_mouse_status(kbdc, status, 0, 3) != 3)
 				return (FALSE);
-			buttons = (status[1] & 0xf0) >> 4;
+			synhw.nExtendedButtons = (status[1] & 0xf0) >> 4;
+			/*
+			 * Add the number of extended buttons to the total
+			 * button support count, including the middle button
+			 * if capMiddle support bit is set.
+			 */
+			buttons = synhw.nExtendedButtons + synhw.capMiddle;
 		} else
+			/*
+			 * If the capFourButtons support bit is set,
+			 * add a fourth button to the total button count.
+			 */
 			buttons = synhw.capFourButtons ? 1 : 0;
 	}
 	if (verbose >= 2) {
@@ -4477,6 +4523,12 @@ enable_synaptics(KBDC kbdc, struct psm_s
 	}
 
 	/*
+	 * Add the default number of 3 buttons to the total
+	 * count of supported buttons reported above.
+	 */
+	buttons += 3;
+
+	/*
 	 * Read the mode byte.
 	 *
 	 * XXX: Note the Synaptics documentation also defines the first
@@ -4503,7 +4555,6 @@ enable_synaptics(KBDC kbdc, struct psm_s
 	/* "Commit" the Set Mode Byte command sent above. */
 	set_mouse_sampling_rate(kbdc, 20);
 
-	buttons += 3;
 	VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons));
 
 	if (sc != NULL) {

Modified: head/sys/sys/mouse.h
==============================================================================
--- head/sys/sys/mouse.h	Mon Sep  2 18:25:18 2013	(r255152)
+++ head/sys/sys/mouse.h	Mon Sep  2 19:15:20 2013	(r255153)
@@ -101,12 +101,15 @@ typedef struct synapticshw {
 	int capPen;
 	int infoSimplC;
 	int infoGeometry;
+	int nExtendedButtons;
 	int capExtended;
+	int nExtendedQueries;
+	int capMiddle;
+	int capPassthrough;
 	int capSleep;
 	int capFourButtons;
 	int capMultiFinger;
 	int capPalmDetect;
-	int capPassthrough;
 } synapticshw_t;
 
 /* iftype */


More information about the svn-src-head mailing list