Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Apr 2015 21:26:47 +0000 (UTC)
From:      Rui Paulo <rpaulo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r281709 - stable/10/sys/dev/atkbdc
Message-ID:  <201504182126.t3ILQlCd082838@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rpaulo
Date: Sat Apr 18 21:26:47 2015
New Revision: 281709
URL: https://svnweb.freebsd.org/changeset/base/281709

Log:
  MFC r281441:
    Add support for controlling the trackpoint when Synaptics is enabled.

Modified:
  stable/10/sys/dev/atkbdc/psm.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/atkbdc/psm.c
==============================================================================
--- stable/10/sys/dev/atkbdc/psm.c	Sat Apr 18 21:24:46 2015	(r281708)
+++ stable/10/sys/dev/atkbdc/psm.c	Sat Apr 18 21:26:47 2015	(r281709)
@@ -191,7 +191,8 @@ enum {
 	SYNAPTICS_SYSCTL_VSCROLL_VER_AREA,
 	SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA,
 	SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN,
-	SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX
+	SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX,
+	SYNAPTICS_SYSCTL_TOUCHPAD_OFF
 };
 
 typedef struct synapticsinfo {
@@ -229,6 +230,7 @@ typedef struct synapticsinfo {
 	int			 vscroll_min_delta;
 	int			 vscroll_div_min;
 	int			 vscroll_div_max;
+	int			 touchpad_off;
 } synapticsinfo_t;
 
 typedef struct synapticspacket {
@@ -474,6 +476,10 @@ static probefunc_t	enable_synaptics;
 static probefunc_t	enable_trackpoint;
 static probefunc_t	enable_versapad;
 
+static void set_trackpoint_parameters(struct psm_softc *sc);
+static void synaptics_passthrough_on(struct psm_softc *sc);
+static void synaptics_passthrough_off(struct psm_softc *sc);
+
 static struct {
 	int		model;
 	u_char		syncmask;
@@ -881,6 +887,13 @@ doinitialize(struct psm_softc *sc, mouse
 			    set_mouse_resolution(kbdc, mode->resolution);
 		set_mouse_scaling(kbdc, 1);
 		set_mouse_mode(kbdc);
+
+		/*
+		 * Trackpoint settings are lost on resume.
+		 * Restore them here.
+		 */
+		if (sc->tphw > 0)
+			set_trackpoint_parameters(sc);
 	}
 
 	/* Record sync on the next data packet we see. */
@@ -2715,6 +2728,12 @@ proc_synaptics(struct psm_softc *sc, pac
 		goto SYNAPTICS_END;
 	}
 
+	if (sc->syninfo.touchpad_off) {
+		*x = *y = *z = 0;
+		ms->button = ms->obutton;
+		goto SYNAPTICS_END;
+	}
+
 	/* Button presses */
 	touchpad_buttons = 0;
 	if (pb->ipacket[0] & 0x01)
@@ -4121,6 +4140,10 @@ synaptics_sysctl(SYSCTL_HANDLER_ARGS)
 		if (arg < -6143 || arg > 6143)
 			return (EINVAL);
 		break;
+        case SYNAPTICS_SYSCTL_TOUCHPAD_OFF:
+		if (arg < 0 || arg > 1)
+			return (EINVAL);
+		break;
 	default:
 		return (EINVAL);
 	}
@@ -4448,6 +4471,15 @@ synaptics_sysctl_create_tree(struct psm_
 	    &sc->syninfo.vscroll_div_max, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX,
 	    synaptics_sysctl, "I",
 	    "Divisor for slow scrolling");
+
+	/* hw.psm.synaptics.touchpad_off. */
+	sc->syninfo.touchpad_off = 0;
+	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
+	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
+	    "touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
+	    &sc->syninfo.touchpad_off, SYNAPTICS_SYSCTL_TOUCHPAD_OFF,
+	    synaptics_sysctl, "I",
+	    "Turn off touchpad");
 }
 
 static int
@@ -4671,25 +4703,75 @@ enable_synaptics(KBDC kbdc, struct psm_s
 	VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons));
 
 	if (sc != NULL) {
+		if (trackpoint_support && synhw.capPassthrough) {
+			synaptics_passthrough_on(sc);
+			enable_trackpoint(kbdc, sc);
+			synaptics_passthrough_off(sc);
+		}
 		/* Create sysctl tree. */
 		synaptics_sysctl_create_tree(sc);
-
 		sc->hw.buttons = buttons;
 	}
 
 	return (TRUE);
 }
 
+static void
+synaptics_passthrough_on(struct psm_softc *sc)
+{
+	int mode_byte;
+
+	mode_byte = 0xc1 | (1 << 5);
+	VLOG(2, (LOG_NOTICE, "psm: setting pass-through mode. %d\n",
+		mode_byte));
+	mouse_ext_command(sc->kbdc, mode_byte);
+
+	/* "Commit" the Set Mode Byte command sent above. */
+	set_mouse_sampling_rate(sc->kbdc, 20);
+}
+
+static void
+synaptics_passthrough_off(struct psm_softc *sc)
+{
+	int mode_byte;
+
+	mode_byte = 0xc1;
+	VLOG(2, (LOG_NOTICE, "psm: turning pass-through mode off.\n"));
+	set_mouse_scaling(sc->kbdc, 2);
+	set_mouse_scaling(sc->kbdc, 1);
+	mouse_ext_command(sc->kbdc, mode_byte);
+
+	/* "Commit" the Set Mode Byte command sent above. */
+	set_mouse_sampling_rate(sc->kbdc, 20);
+}
+
 /* IBM/Lenovo TrackPoint */
 static int
-trackpoint_command(KBDC kbdc, int cmd, int loc, int val)
+trackpoint_command(struct psm_softc *sc, int cmd, int loc, int val)
 {
 	const int seq[] = { 0xe2, cmd, loc, val };
 	int i;
 
-	for (i = 0; i < nitems(seq); i++)
-		if (send_aux_command(kbdc, seq[i]) != PSM_ACK)
+	if (sc->synhw.capPassthrough)
+		synaptics_passthrough_on(sc);
+
+	for (i = 0; i < nitems(seq); i++) {
+		if (sc->synhw.capPassthrough &&
+		    (seq[i] == 0xff || seq[i] == 0xe7))
+			if (send_aux_command(sc->kbdc, 0xe7) != PSM_ACK) {
+				synaptics_passthrough_off(sc);
+				return (EIO);
+			}
+		if (send_aux_command(sc->kbdc, seq[i]) != PSM_ACK) {
+			if (sc->synhw.capPassthrough)
+				synaptics_passthrough_off(sc);
 			return (EIO);
+		}
+	}
+
+	if (sc->synhw.capPassthrough)
+		synaptics_passthrough_off(sc);
+
 	return (0);
 }
 
@@ -4732,7 +4814,7 @@ trackpoint_sysctl(SYSCTL_HANDLER_ARGS)
 		return (0);
 	if (newval < 0 || newval > (tp[TPMASK] == 0 ? 255 : 1))
 		return (EINVAL);
-	error = trackpoint_command(sc->kbdc, tp[TPMASK] == 0 ? 0x81 : 0x47,
+	error = trackpoint_command(sc, tp[TPMASK] == 0 ? 0x81 : 0x47,
 	    tp[TPLOC], tp[TPMASK] == 0 ? newval : tp[TPMASK]);
 	if (error != 0)
 		return (error);
@@ -4755,7 +4837,7 @@ trackpoint_sysctl_create_tree(struct psm
 	    0, "IBM/Lenovo TrackPoint");
 
 	/* hw.psm.trackpoint.sensitivity */
-	sc->tpinfo.sensitivity = 0x64;
+	sc->tpinfo.sensitivity = 0x80;
 	SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
 	    SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
 	    "sensitivity", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
@@ -4863,6 +4945,25 @@ trackpoint_sysctl_create_tree(struct psm
 	    "Skip backups from drags");
 }
 
+static void
+set_trackpoint_parameters(struct psm_softc *sc)
+{
+	trackpoint_command(sc, 0x81, 0x4a, sc->tpinfo.sensitivity);
+	trackpoint_command(sc, 0x81, 0x60, sc->tpinfo.uplateau);
+	trackpoint_command(sc, 0x81, 0x4d, sc->tpinfo.inertia);
+	trackpoint_command(sc, 0x81, 0x57, sc->tpinfo.reach);
+	trackpoint_command(sc, 0x81, 0x58, sc->tpinfo.draghys);
+	trackpoint_command(sc, 0x81, 0x59, sc->tpinfo.mindrag);
+	trackpoint_command(sc, 0x81, 0x5a, sc->tpinfo.upthresh);
+	trackpoint_command(sc, 0x81, 0x5c, sc->tpinfo.threshold);
+	trackpoint_command(sc, 0x81, 0x5d, sc->tpinfo.jenks);
+	trackpoint_command(sc, 0x81, 0x5e, sc->tpinfo.ztime);
+	if (sc->tpinfo.pts == 0x01)
+		trackpoint_command(sc, 0x47, 0x2c, 0x01);
+	if (sc->tpinfo.skipback == 0x01)
+		trackpoint_command(sc, 0x47, 0x2d, 0x08);
+}
+
 static int
 enable_trackpoint(KBDC kbdc, struct psm_softc *sc)
 {
@@ -4883,23 +4984,14 @@ enable_trackpoint(KBDC kbdc, struct psm_
 		/* Create sysctl tree. */
 		trackpoint_sysctl_create_tree(sc);
 
-		trackpoint_command(kbdc, 0x81, 0x4a, sc->tpinfo.sensitivity);
-		trackpoint_command(kbdc, 0x81, 0x4d, sc->tpinfo.inertia);
-		trackpoint_command(kbdc, 0x81, 0x60, sc->tpinfo.uplateau);
-		trackpoint_command(kbdc, 0x81, 0x57, sc->tpinfo.reach);
-		trackpoint_command(kbdc, 0x81, 0x58, sc->tpinfo.draghys);
-		trackpoint_command(kbdc, 0x81, 0x59, sc->tpinfo.mindrag);
-		trackpoint_command(kbdc, 0x81, 0x5a, sc->tpinfo.upthresh);
-		trackpoint_command(kbdc, 0x81, 0x5c, sc->tpinfo.threshold);
-		trackpoint_command(kbdc, 0x81, 0x5d, sc->tpinfo.jenks);
-		trackpoint_command(kbdc, 0x81, 0x5e, sc->tpinfo.ztime);
-		if (sc->tpinfo.pts == 0x01)
-			trackpoint_command(kbdc, 0x47, 0x2c, 0x01);
-		if (sc->tpinfo.skipback == 0x01)
-			trackpoint_command(kbdc, 0x47, 0x2d, 0x08);
-
-		sc->hw.hwid = id;
-		sc->hw.buttons = 3;
+		/*
+		 * Don't overwrite hwid and buttons when we are
+		 * a guest device.
+		 */
+		if (!sc->synhw.capPassthrough) {
+			sc->hw.hwid = id;
+			sc->hw.buttons = 3;
+		}
 	}
 
 	return (TRUE);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504182126.t3ILQlCd082838>