Date: Sun, 30 Nov 2014 12:12:03 +0100 From: =?UTF-8?B?SmFuIEtva2Vtw7xsbGVy?= <jan.kokemueller@gmail.com> To: freebsd-x11@freebsd.org Subject: [PATCH] psm.c: Better support for Synaptics guest device (pointing sticks on Thinkpads) Message-ID: <547AFB83.1040705@gmail.com>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
Hi,
I've written a patch for psm.c that makes the hw.psm.trackpoint sysctls
work when using the TrackPoint as a Synaptics guest device. Not all
Thinkpads support turning off the Touchpad in the BIOS, for example the
SL510. The default settings of the TrackPoint are much too slow for me,
so I needed this functionality badly.
There is also a new "touchpad_off" sysctl that disables the Touchpad but
lets guest device inputs through.
Lastly I've adjusted the default TrackPoint sensitivity to match the
official documentation, this was probably a typo.
Comments?
[-- Attachment #2 --]
diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c
index 9a6ae72..1aeddf8 100644
--- a/sys/dev/atkbdc/psm.c
+++ b/sys/dev/atkbdc/psm.c
@@ -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 {
@@ -228,6 +229,7 @@ typedef struct synapticsinfo {
int vscroll_min_delta;
int vscroll_div_min;
int vscroll_div_max;
+ int touchpad_off;
} synapticsinfo_t;
typedef struct synapticspacket {
@@ -472,6 +474,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;
@@ -879,6 +885,10 @@ doinitialize(struct psm_softc *sc, mousemode_t *mode)
set_mouse_resolution(kbdc, mode->resolution);
set_mouse_scaling(kbdc, 1);
set_mouse_mode(kbdc);
+
+ /* trackpoint settings get lost on resume, restore them */
+ if (sc->tphw > 0)
+ set_trackpoint_parameters(sc);
}
/* Record sync on the next data packet we see. */
@@ -2713,6 +2723,12 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
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)
@@ -4004,6 +4020,7 @@ enable_4dplus(KBDC kbdc, struct psm_softc *sc)
return (TRUE);
}
+
/* Synaptics Touchpad */
static int
synaptics_sysctl(SYSCTL_HANDLER_ARGS)
@@ -4074,6 +4091,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);
}
@@ -4385,6 +4406,15 @@ synaptics_sysctl_create_tree(struct psm_softc *sc)
&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
@@ -4558,25 +4588,72 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc)
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 = 0xc1;
+ mode_byte |= (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)
+{
+ VLOG(2, (LOG_NOTICE, "psm: turning pass-through mode off.\n"));
+ set_mouse_scaling(sc->kbdc, 2);
+ set_mouse_scaling(sc->kbdc, 1);
+
+ int mode_byte = 0xc1;
+ 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);
}
@@ -4619,7 +4696,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);
@@ -4642,7 +4719,7 @@ trackpoint_sysctl_create_tree(struct psm_softc *sc)
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,
@@ -4750,6 +4827,25 @@ trackpoint_sysctl_create_tree(struct psm_softc *sc)
"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)
{
@@ -4770,23 +4866,12 @@ enable_trackpoint(KBDC kbdc, struct psm_softc *sc)
/* 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?547AFB83.1040705>
