From owner-freebsd-current@FreeBSD.ORG Sun Apr 19 18:46:25 2015 Return-Path: Delivered-To: freebsd-current@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 CA98F655 for ; Sun, 19 Apr 2015 18:46:25 +0000 (UTC) Received: from mail-wi0-x232.google.com (mail-wi0-x232.google.com [IPv6:2a00:1450:400c:c05::232]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 52191DEB for ; Sun, 19 Apr 2015 18:46:25 +0000 (UTC) Received: by wizk4 with SMTP id k4so74958359wiz.1 for ; Sun, 19 Apr 2015 11:46:23 -0700 (PDT) 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:references :in-reply-to:content-type; bh=78ucYaBhHPKABVUbbebiva4ue0mOmnqG6vnKQ3s0yZA=; b=XO/4Q2/ZTCcytz5Ua0nN2h2W4GJCRnu0Ysd9vm14KmCbKY3kmi7hUdCp7saRLnY9ug nx3xW+jsgSyyvtNgI4mk6++9jEF/rjGlJIMFAD70KvsQX7EqGkAX+GkHp+eiepsxkMnw 3VqAaqZRn10a0eCMGJxQ5YC6eFlMP5WZ5BaLPYrZmXO09LNUU9WXczGH7Ch6pUkC31h4 9DTfIOj2YWN5u0D9L10FDgC7mMvNA8ShzLW0PFjoKeDbnr2rKHWuPCUroFB0yGt/iRRf DrbcWZN3IwVd/aUmwiGmw6R4BrN3x5/ED9Nlhb6e6pEXL0yoncbs1RQVN4Db0LgTv5Mq ZhlA== X-Received: by 10.180.106.70 with SMTP id gs6mr18543678wib.36.1429469183909; Sun, 19 Apr 2015 11:46:23 -0700 (PDT) Received: from ?IPv6:2001:470:1f15:b1f:2c4b:3537:2f58:deab? ([2001:470:1f15:b1f:2c4b:3537:2f58:deab]) by mx.google.com with ESMTPSA id z12sm24021588wjw.39.2015.04.19.11.46.21 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 19 Apr 2015 11:46:22 -0700 (PDT) Message-ID: <5533F7FC.3060609@gmail.com> Date: Sun, 19 Apr 2015 20:46:20 +0200 From: =?windows-1252?Q?Jan_Kokem=FCller?= User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 MIME-Version: 1.0 To: freebsd-current@freebsd.org Subject: Re: Call For Testers: Synaptics touchpads References: <1849381.HnoQVUIgNM@akita> In-Reply-To: <1849381.HnoQVUIgNM@akita> Content-Type: multipart/mixed; boundary="------------000106070501010702030604" X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 19 Apr 2015 18:46:25 -0000 This is a multi-part message in MIME format. --------------000106070501010702030604 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit On 08.04.2015 09:19, Rui Paulo wrote: > The attached patch adds support for newer touchpad features and implements two > finger scrolling. Hi, thanks for bringing two finger scrolling to the psm driver! I've attached a patch of some more improvements and fixes. I hope some of this stuff can make it into the driver: - Two finger scrolling support for "semi-MT" touchpads. Those include many of the older Synaptics touchpads before "true" multitouch support (indicated by capMultiFinger). Semi-MT touchpads can report a second finger position, but the X or Y coordinate may be swapped with some coordinate of the first finger. This is a result of how the hardware works internally. Therefore, all that can be reliably extracted is the bounding box of the two finger positions. Semi-MT touchpads can be recognized by the capAdvancedGestures capability bit. After setting the mode byte, advanced gestures mode has to be enabled. Then, data packets compatible with the capMultiFinger format are sent, so the same two finger scrolling code can be leveraged. Enabling advanced gestures mode on true multitouch touchpads should be harmless. Linux seems to always enable advanced gestures mode. I don't have a real multitouch touchpad for testing though. - Put mode setting logic into own functions synaptics_preferred_mode() and synaptics_set_mode() to have this in one place. synaptics_passthrough_on() and synaptics_passthrough_off() currently always use 0xc1 as the mode byte, which may be wrong for touchpads that don't have capExtended (sorry, my fault). - Expose X and Y resolution of touchpad to userland. Also expose minimum and maximum X and Y coordinates. This is useful for programs in userspace that read raw PSM packets (with PSM_LEVEL_NATIVE enabled) and need to interpret the coordinates. - Also send "extended w mode" packets (see section 3.2.9 of 511-000275-01_RevB.pdf) to userspace if PSM_LEVEL_NATIVE is enabled. This is useful for userspace programs/drivers such as xf86-input-synaptics that can handle these packets. - Fix parsing of nExtendedQueries, and request extended/continued capability bits depending on this value. - capReportsMax, capClearPad, capAdvancedGestures and capCoveredPad must be extracted from status[0] and not status[2], I think. Two finger scrolling works reasonably well with my semi-MT touchpad (Lenovo T420). However, it is very sensitive if I move my fingers very slowly. I wonder if this is because it's a semi-MT touchpad or if I have to tweak some setting. Also sometimes, if I move my fingers up, it scrolls down, and vice versa. Maybe this is a result of how dxp and dyp are calculated with the abs() function? Cheers, Jan --------------000106070501010702030604 Content-Type: text/x-patch; name="synaptics-improvements.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="synaptics-improvements.patch" diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index e8a2a93..4e41eef 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -483,6 +483,8 @@ 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 int synaptics_preferred_mode(struct psm_softc *sc); +static void synaptics_set_mode(struct psm_softc *sc, int mode_byte); static struct { int model; @@ -933,14 +935,8 @@ doopen(struct psm_softc *sc, int command_byte) get_mouse_status(sc->kbdc, stat, 0, 3); if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) || stat[1] == 0x47) && - stat[2] == 0x40) { - /* Set the mode byte -- request wmode where - * available */ - if (sc->synhw.capExtended) - mouse_ext_command(sc->kbdc, 0xc1); - else - mouse_ext_command(sc->kbdc, 0xc0); - set_mouse_sampling_rate(sc->kbdc, 20); + stat[2] == 0x40) { + synaptics_set_mode(sc, synaptics_preferred_mode(sc)); VLOG(5, (LOG_DEBUG, "psm%d: Synaptis Absolute Mode " "hopefully restored\n", sc->unit)); @@ -2176,6 +2172,20 @@ psmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, (*(int *)addr > PSM_LEVEL_MAX)) return (EINVAL); sc->mode.level = *(int *)addr; + + if (sc->hw.model == MOUSE_MODEL_SYNAPTICS) { + /* + * If we are entering PSM_LEVEL_NATIVE, we want to + * enable sending of "extended W mode" packets to + * userland. Reset the mode of the touchpad so that the + * change in the level is picked up. + */ + error = block_mouse_data(sc, &command_byte); + if (error) + return (error); + synaptics_set_mode(sc, synaptics_preferred_mode(sc)); + unblock_mouse_data(sc, command_byte); + } break; case MOUSE_GETSTATUS: @@ -2864,7 +2874,8 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, /* Palm detection. */ if (!( - (sc->synhw.capMultiFinger && (w == 0 || w == 1)) || + ((sc->synhw.capMultiFinger || + sc->synhw.capAdvancedGestures) && (w == 0 || w == 1)) || (sc->synhw.capPalmDetect && w >= 4 && w <= max_width) || (!sc->synhw.capPalmDetect && *z <= max_pressure) || (sc->synhw.capPen && w == 2))) { @@ -4191,7 +4202,8 @@ synaptics_sysctl_create_tree(struct psm_softc *sc) * physical area reserved for scrolling or when * there's no multi finger support. */ - if (sc->synhw.verticalScroll || sc->synhw.capMultiFinger == 0) + if (sc->synhw.verticalScroll || (sc->synhw.capMultiFinger == 0 && + sc->synhw.capAdvancedGestures == 0)) sc->syninfo.two_finger_scroll = 0; else sc->syninfo.two_finger_scroll = 1; @@ -4493,6 +4505,43 @@ synaptics_sysctl_create_tree(struct psm_softc *sc) } static int +synaptics_preferred_mode(struct psm_softc *sc) { + int mode_byte; + + mode_byte = 0xc0; + + /* request wmode where available */ + if (sc->synhw.capExtended) + mode_byte |= 1; + + /* + * Disable gesture processing when native packets are requested. This + * enables sending of encapsulated "extended W mode" packets. + */ + if (sc->mode.level == PSM_LEVEL_NATIVE) + mode_byte |= (1 << 2); + + return mode_byte; +} + +static void +synaptics_set_mode(struct psm_softc *sc, int mode_byte) { + mouse_ext_command(sc->kbdc, mode_byte); + + /* "Commit" the Set Mode Byte command sent above. */ + set_mouse_sampling_rate(sc->kbdc, 20); + + /* + * Enable advanced gestures mode if supported and we are not entering + * passthrough mode. + */ + if (sc->synhw.capAdvancedGestures && !(mode_byte & (1 << 5))) { + mouse_ext_command(sc->kbdc, 3); + set_mouse_sampling_rate(sc->kbdc, 0xc8); + } +} + +static int enable_synaptics(KBDC kbdc, struct psm_softc *sc) { synapticshw_t synhw; @@ -4575,7 +4624,7 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) buttons = 0; synhw.capExtended = (status[0] & 0x80) != 0; if (synhw.capExtended) { - synhw.nExtendedQueries = (status[0] & 0x70) != 0; + synhw.nExtendedQueries = (status[0] & 0x70) >> 4; synhw.capMiddle = (status[0] & 0x04) != 0; synhw.capPassthrough = (status[2] & 0x80) != 0; synhw.capLowPower = (status[2] & 0x40) != 0; @@ -4587,6 +4636,16 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) synhw.capMultiFinger = (status[2] & 0x02) != 0; synhw.capPalmDetect = (status[2] & 0x01) != 0; + if (!set_mouse_scaling(kbdc, 1)) + return (FALSE); + if (mouse_ext_command(kbdc, 0x08) == 0) + return (FALSE); + if (get_mouse_status(kbdc, status, 0, 3) != 3) + return (FALSE); + + synhw.infoXupmm = status[0]; + synhw.infoYupmm = status[2]; + if (verbose >= 2) { printf(" Extended capabilities:\n"); printf(" capExtended: %d\n", synhw.capExtended); @@ -4602,6 +4661,8 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) printf(" capBallistics: %d\n", synhw.capBallistics); printf(" capMultiFinger: %d\n", synhw.capMultiFinger); printf(" capPalmDetect: %d\n", synhw.capPalmDetect); + printf(" infoXupmm: %d\n", synhw.infoXupmm); + printf(" infoYupmm: %d\n", synhw.infoYupmm); } /* @@ -4609,7 +4670,9 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) * supports this number of extended queries. We can load * more information about buttons using query 0x09. */ - if (synhw.capExtended && synhw.nExtendedQueries) { + if (synhw.nExtendedQueries >= 1) { + if (!set_mouse_scaling(kbdc, 1)) + return (FALSE); if (mouse_ext_command(kbdc, 0x09) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) @@ -4618,6 +4681,7 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) synhw.horizontalScroll = (status[0] & 0x02) != 0; synhw.verticalWheel = (status[0] & 0x08) != 0; synhw.nExtendedButtons = (status[1] & 0xf0) >> 4; + synhw.capEWmode = (status[0] & 0x04) != 0; if (verbose >= 2) { printf(" Extended model ID:\n"); printf(" verticalScroll: %d\n", @@ -4628,6 +4692,8 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) synhw.verticalWheel); printf(" nExtendedButtons: %d\n", synhw.nExtendedButtons); + printf(" capEWmode: %d\n", + synhw.capEWmode); } /* * Add the number of extended buttons to the total @@ -4641,7 +4707,97 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) * add a fourth button to the total button count. */ buttons = synhw.capFourButtons ? 1 : 0; + + /* Read the continued capabilities bits. */ + if (synhw.nExtendedQueries >= 4) { + if (!set_mouse_scaling(kbdc, 1)) + return (FALSE); + if (mouse_ext_command(kbdc, 0x0c) == 0) + return (FALSE); + if (get_mouse_status(kbdc, status, 0, 3) != 3) + return (FALSE); + + synhw.capClickPad = (status[1] & 0x01) << 1; + synhw.capClickPad |= (status[0] & 0x10) != 0; + synhw.capDeluxeLEDs = (status[1] & 0x02) != 0; + synhw.noAbsoluteFilter = (status[1] & 0x04) != 0; + synhw.capReportsV = (status[1] & 0x08) != 0; + synhw.capUniformClickPad = (status[1] & 0x10) != 0; + synhw.capReportsMin = (status[1] & 0x20) != 0; + synhw.capInterTouch = (status[1] & 0x40) != 0; + synhw.capReportsMax = (status[0] & 0x02) != 0; + synhw.capClearPad = (status[0] & 0x04) != 0; + synhw.capAdvancedGestures = (status[0] & 0x08) != 0; + synhw.capCoveredPad = (status[0] & 0x80) != 0; + + if (synhw.capReportsMax) { + if (!set_mouse_scaling(kbdc, 1)) + return (FALSE); + if (mouse_ext_command(kbdc, 0x0d) == 0) + return (FALSE); + if (get_mouse_status(kbdc, status, 0, 3) != 3) + return (FALSE); + + synhw.maximumXCoord = (status[0] << 5) | + ((status[1] & 0x0f) << 1); + synhw.maximumYCoord = (status[2] << 5) | + ((status[1] & 0xf0) >> 3); + } + if (synhw.capReportsMin) { + if (!set_mouse_scaling(kbdc, 1)) + return (FALSE); + if (mouse_ext_command(kbdc, 0x0f) == 0) + return (FALSE); + if (get_mouse_status(kbdc, status, 0, 3) != 3) + return (FALSE); + + synhw.minimumXCoord = (status[0] << 5) | + ((status[1] & 0x0f) << 1); + synhw.minimumYCoord = (status[2] << 5) | + ((status[1] & 0xf0) >> 3); + } + + if (verbose >= 2) { + printf(" Continued capabilities:\n"); + printf(" capClickPad: %d\n", + synhw.capClickPad); + printf(" capDeluxeLEDs: %d\n", + synhw.capDeluxeLEDs); + printf(" noAbsoluteFilter: %d\n", + synhw.noAbsoluteFilter); + printf(" capReportsV: %d\n", + synhw.capReportsV); + printf(" capUniformClickPad: %d\n", + synhw.capUniformClickPad); + printf(" capReportsMin: %d\n", + synhw.capReportsMin); + printf(" capInterTouch: %d\n", + synhw.capInterTouch); + printf(" capReportsMax: %d\n", + synhw.capReportsMax); + printf(" capClearPad: %d\n", + synhw.capClearPad); + printf(" capAdvancedGestures: %d\n", + synhw.capAdvancedGestures); + printf(" capCoveredPad: %d\n", + synhw.capCoveredPad); + if (synhw.capReportsMax) { + printf(" maximumXCoord: %d\n", + synhw.maximumXCoord); + printf(" maximumYCoord: %d\n", + synhw.maximumYCoord); + } + if (synhw.capReportsMin) { + printf(" minimumXCoord: %d\n", + synhw.minimumXCoord); + printf(" minimumYCoord: %d\n", + synhw.minimumYCoord); + } + } + buttons += synhw.capClickPad; + } } + if (verbose >= 2) { if (synhw.capExtended) printf(" Additional Buttons: %d\n", buttons); @@ -4649,42 +4805,6 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) printf(" No extended capabilities\n"); } - /* Read the continued capabilities bits. */ - if (mouse_ext_command(kbdc, 0xc) != 0 && - get_mouse_status(kbdc, status, 0, 3) == 3) { - synhw.capClickPad = (status[1] & 0x01) << 1; - synhw.capClickPad |= (status[0] & 0x10) != 0; - synhw.capDeluxeLEDs = (status[1] & 0x02) != 0; - synhw.noAbsoluteFilter = (status[1] & 0x04) != 0; - synhw.capReportsV = (status[1] & 0x08) != 0; - synhw.capUniformClickPad = (status[1] & 0x10) != 0; - synhw.capReportsMin = (status[1] & 0x20) != 0; - synhw.capInterTouch = (status[1] & 0x40) != 0; - synhw.capReportsMax = (status[2] & 0x02) != 0; - synhw.capClearPad = (status[2] & 0x04) != 0; - synhw.capAdvancedGestures = (status[2] & 0x08) != 0; - synhw.capCoveredPad = (status[2] & 0x80) != 0; - - if (verbose >= 2) { - printf(" Continued capabilities:\n"); - printf(" capClickPad: %d\n", synhw.capClickPad); - printf(" capDeluxeLEDs: %d\n", synhw.capDeluxeLEDs); - printf(" noAbsoluteFilter: %d\n", - synhw.noAbsoluteFilter); - printf(" capReportsV: %d\n", synhw.capReportsV); - printf(" capUniformClickPad: %d\n", - synhw.capUniformClickPad); - printf(" capReportsMin: %d\n", synhw.capReportsMin); - printf(" capInterTouch: %d\n", synhw.capInterTouch); - printf(" capReportsMax: %d\n", synhw.capReportsMax); - printf(" capClearPad: %d\n", synhw.capClearPad); - printf(" capAdvancedGestures: %d\n", - synhw.capAdvancedGestures); - printf(" capCoveredPad: %d\n", synhw.capCoveredPad); - } - buttons += synhw.capClickPad; - } - /* * Add the default number of 3 buttons to the total * count of supported buttons reported above. @@ -4712,15 +4832,10 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) if (!synaptics_support) return (FALSE); - /* Set the mode byte; request wmode where available. */ - mouse_ext_command(kbdc, synhw.capExtended ? 0xc1 : 0xc0); - - /* "Commit" the Set Mode Byte command sent above. */ - set_mouse_sampling_rate(kbdc, 20); - VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons)); if (sc != NULL) { + synaptics_set_mode(sc, synaptics_preferred_mode(sc)); if (trackpoint_support && synhw.capPassthrough) { synaptics_passthrough_on(sc); enable_trackpoint(kbdc, sc); @@ -4737,30 +4852,17 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) 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); + VLOG(2, (LOG_NOTICE, "psm: setting pass-through mode.\n")); + synaptics_set_mode(sc, synaptics_preferred_mode(sc) | (1 << 5)); } 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); + synaptics_set_mode(sc, synaptics_preferred_mode(sc)); } /* IBM/Lenovo TrackPoint */ diff --git a/sys/sys/mouse.h b/sys/sys/mouse.h index 5329693..24d0ffc 100644 --- a/sys/sys/mouse.h +++ b/sys/sys/mouse.h @@ -128,6 +128,13 @@ typedef struct synapticshw { int verticalScroll; int horizontalScroll; int verticalWheel; + int capEWmode; + int minimumXCoord; + int minimumYCoord; + int maximumXCoord; + int maximumYCoord; + int infoXupmm; + int infoYupmm; } synapticshw_t; /* iftype */ --------------000106070501010702030604--