From owner-freebsd-x11@FreeBSD.ORG Sun Nov 30 11:12:07 2014 Return-Path: Delivered-To: freebsd-x11@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 9A20049C for ; Sun, 30 Nov 2014 11:12:07 +0000 (UTC) Received: from mail-vc0-x233.google.com (mail-vc0-x233.google.com [IPv6:2607:f8b0:400c:c03::233]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4AD917CA for ; Sun, 30 Nov 2014 11:12:07 +0000 (UTC) Received: by mail-vc0-f179.google.com with SMTP id le20so3962627vcb.10 for ; Sun, 30 Nov 2014 03:12:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:subject :content-type; bh=ACepHa/0OjaNyx0iLMfxzBySa51jyOHHDHYoFgBezWQ=; b=pZHzKgqtXHOan62Z7XE2FFE6/ZI7k27HHG3seQFjOMHrqNEKY8wJr8lvUdJ+8NIhwt i+wu+5xYUYvKNXfCoGATRubsAiKPYsQfcfXXejLvoBGnfC2wQZ/evshh/KU0FsgpUyKG vgUBow/aa09SIwafvyhQHbhbME0NXh/3G8jqFW3a+XkMQBY2O9lgsZXmZIjcQnGonMNl 67bAtoUR7HhVJQ50gpPzqqtkNkTPXUy3+QMnChF+A6FDtIs7Ojx/ELMxz+c538bfmQUm LgLXiMmELQfK27fBNhmXqjA1Vl4ZyoZq8yGMhnHY7J+CPtXaQ1rZZTkhca+wFDPv0GbP xmVQ== X-Received: by 10.220.199.70 with SMTP id er6mr25474867vcb.68.1417345926347; Sun, 30 Nov 2014 03:12:06 -0800 (PST) Received: from ?IPv6:2001:470:1f15:b1f:7092:eb2c:e77c:5043? ([2001:470:1f15:b1f:7092:eb2c:e77c:5043]) by mx.google.com with ESMTPSA id e4sm2968405vdc.2.2014.11.30.03.12.04 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 30 Nov 2014 03:12:05 -0800 (PST) Message-ID: <547AFB83.1040705@gmail.com> Date: Sun, 30 Nov 2014 12:12:03 +0100 From: =?UTF-8?B?SmFuIEtva2Vtw7xsbGVy?= User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 MIME-Version: 1.0 To: freebsd-x11@freebsd.org Subject: [PATCH] psm.c: Better support for Synaptics guest device (pointing sticks on Thinkpads) Content-Type: multipart/mixed; boundary="------------070205070402080805040807" X-BeenThere: freebsd-x11@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: X11 on FreeBSD -- maintaining and support List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 30 Nov 2014 11:12:07 -0000 This is a multi-part message in MIME format. --------------070205070402080805040807 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit 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? --------------070205070402080805040807 Content-Type: text/x-patch; name="synaptics-guest-device.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="synaptics-guest-device.patch" 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); --------------070205070402080805040807--