Date: Sat, 29 Jun 2019 12:49:53 +0000 (UTC) From: Vladimir Kondratyev <wulf@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r349540 - in stable/12: share/man/man4 sys/dev/atkbdc Message-ID: <201906291249.x5TCnrUZ014411@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: wulf Date: Sat Jun 29 12:49:52 2019 New Revision: 349540 URL: https://svnweb.freebsd.org/changeset/base/349540 Log: MFC r346455-r346458, r348520, r348529, r348817, r348818 r346455: psm(4): Add support for 4 and 5 finger touches in synaptics driver While 4-th and 5-th finger positions are not exported through PS/2 interface, total number of touches is reported by MT trackpads. r346456: psm(4): do not process gestures when palm is present Ignoring of gesture processing when the palm is detected helps to reduce some of the erratic pointer behavior. This fixes regression introduced in r317814 Reported by: Ben LeMasurier <ben@crypt.ly> r346457: psm(4): respect tap_disabled configuration with enabled Extended support This fixes a bug where, even when hw.psm.tap_enabled=0, touchpad taps were processed. tap_enabled has three states: unconfigured, disabled, and enabled (-1, 0, 1). To respect PR kern/139272, taps are ignored only when explicity disabled. Submitted by: Ben LeMasurier <ben@crypt.ly> (initial version) r346458: psm(4): give names to synaptics commands Submitted by: Ben LeMasurier <ben@crypt.ly> r348520: psm(4): Add Elantech touchpad IC type 15 found on Thinkpad L480 laptops PR: 238291 Submitted by: Andrey Kosachenko <andrey.kosachenko@gmail.com> r348529: psm(4): Add natural scrolling support to sysmouse protocol This change enables natural scrolling with two finger scroll enabled and when user is using a trackpad (mouse and trackpoint are not affected). Depending on trackpad model it can be activated with setting of hw.psm.synaptics.natural_scroll or hw.psm.elantech.natural_scroll sysctl values to 1. Evdev protocol is not affected by this change too. Tune userland client e.g. libinput to enable natural scrolling in that case. Submitted by: nyan_myuji.xyz Reviewed by: wulf Differential Revision: https://reviews.freebsd.org/D20447 r348817: psm(4): Fix Elantech trackpoint support. Sign bits for X and Y motion data were taken from wrong places. PR: 238291 Reported by: Andrey Kosachenko <andrey.kosachenko@gmail.com> Tested by: Andrey Kosachenko <andrey.kosachenko@gmail.com> r348818: psm(4): Add extra sanity checks to Elantech trackpoint packet parser. Add strict checks for unused bit states in Elantech trackpoint packet parser to filter out spurious events produces by some hardware which are detected as trackpoint packets. See comment on r328191 for example. Tested by: Andrey Kosachenko <andrey.kosachenko@gmail.com> Modified: stable/12/share/man/man4/psm.4 stable/12/sys/dev/atkbdc/psm.c Directory Properties: stable/12/ (props changed) Modified: stable/12/share/man/man4/psm.4 ============================================================================== --- stable/12/share/man/man4/psm.4 Sat Jun 29 12:19:57 2019 (r349539) +++ stable/12/share/man/man4/psm.4 Sat Jun 29 12:49:52 2019 (r349540) @@ -354,8 +354,8 @@ Tap and drag gestures can be disabled by setting to .Em 0 at boot-time. -Currently, this is only supported on Synaptics touchpads with Extended -support disabled. +Currently, this is supported on Synaptics touchpads regardless of Extended +support state and on Elantech touchpads with Extended support enabled. The behaviour may be changed after boot by setting the sysctl with the same name and by restarting .Xr moused 8 Modified: stable/12/sys/dev/atkbdc/psm.c ============================================================================== --- stable/12/sys/dev/atkbdc/psm.c Sat Jun 29 12:19:57 2019 (r349539) +++ stable/12/sys/dev/atkbdc/psm.c Sat Jun 29 12:49:52 2019 (r349540) @@ -178,6 +178,22 @@ typedef struct packetbuf { #define PSM_PACKETQUEUE 128 #endif +/* + * Synaptics command definitions. + */ +#define SYNAPTICS_READ_IDENTITY 0x00 +#define SYNAPTICS_READ_MODES 0x01 +#define SYNAPTICS_READ_CAPABILITIES 0x02 +#define SYNAPTICS_READ_MODEL_ID 0x03 +#define SYNAPTICS_READ_SERIAL_PREFIX 0x06 +#define SYNAPTICS_READ_SERIAL_SUFFIX 0x07 +#define SYNAPTICS_READ_RESOLUTIONS 0x08 +#define SYNAPTICS_READ_EXTENDED 0x09 +#define SYNAPTICS_READ_CAPABILITIES_CONT 0x0c +#define SYNAPTICS_READ_MAX_COORDS 0x0d +#define SYNAPTICS_READ_DELUXE_LED 0x0e +#define SYNAPTICS_READ_MIN_COORDS 0x0f + typedef struct synapticsinfo { struct sysctl_ctx_list sysctl_ctx; struct sysctl_oid *sysctl_tree; @@ -219,6 +235,7 @@ typedef struct synapticsinfo { int softbutton3_x; int max_x; int max_y; + int natural_scroll; } synapticsinfo_t; typedef struct synapticspacket { @@ -554,6 +571,8 @@ enum { SYNAPTICS_SYSCTL_SOFTBUTTONS_Y = SYN_OFFSET(softbuttons_y), SYNAPTICS_SYSCTL_SOFTBUTTON2_X = SYN_OFFSET(softbutton2_x), SYNAPTICS_SYSCTL_SOFTBUTTON3_X = SYN_OFFSET(softbutton3_x), + SYNAPTICS_SYSCTL_NATURAL_SCROLL = SYN_OFFSET(natural_scroll), +#define SYNAPTICS_SYSCTL_LAST SYNAPTICS_SYSCTL_NATURAL_SCROLL }; /* packet formatting function */ @@ -1119,7 +1138,7 @@ doopen(struct psm_softc *sc, int command_byte) "active multiplexing mode.\n", sc->unit); } - mouse_ext_command(sc->kbdc, 1); + mouse_ext_command(sc->kbdc, SYNAPTICS_READ_MODES); get_mouse_status(sc->kbdc, stat, 0, 3); if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) || stat[1] == 0x47) && @@ -1830,7 +1849,7 @@ psm_register_synaptics(device_t dev) if (sc->synhw.capClickPad && sc->synhw.topButtonPad) evdev_support_prop(evdev_a, INPUT_PROP_TOPBUTTONPAD); evdev_support_key(evdev_a, BTN_TOUCH); - evdev_support_nfingers(evdev_a, 3); + evdev_support_nfingers(evdev_a, sc->synhw.capReportsV ? 5 : 3); psm_support_abs_bulk(evdev_a, synaptics_absinfo_st); if (sc->synhw.capAdvancedGestures || sc->synhw.capReportsV) psm_support_abs_bulk(evdev_a, synaptics_absinfo_mt); @@ -3212,8 +3231,9 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, { static int touchpad_buttons; static int guest_buttons; + static int ew_finger_count; static finger_t f[PSM_FINGERS]; - int w, id, nfingers, ewcode, extended_buttons, clickpad_pressed; + int w, id, nfingers, palm, ewcode, extended_buttons, clickpad_pressed; extended_buttons = 0; @@ -3372,6 +3392,9 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, (pb->ipacket[1] & 0x01)) + 8, .flags = PSM_FINGER_FUZZY, }; + break; + case 2: + ew_finger_count = pb->ipacket[1] & 0x0f; default: break; } @@ -3379,6 +3402,11 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, goto SYNAPTICS_END; case 1: + if (sc->synhw.capReportsV && ew_finger_count > 3) { + nfingers = ew_finger_count; + break; + } + /* FALLTHROUGH */ case 0: nfingers = w + 2; break; @@ -3568,12 +3596,16 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, ms->button = touchpad_buttons; - psmgestures(sc, &f[0], nfingers, ms); + palm = psmpalmdetect(sc, &f[0], nfingers); + + /* Palm detection doesn't terminate the current action. */ + if (!palm) + psmgestures(sc, &f[0], nfingers, ms); + for (id = 0; id < PSM_FINGERS; id++) psmsmoother(sc, &f[id], id, ms, x, y); - /* Palm detection doesn't terminate the current action. */ - if (psmpalmdetect(sc, &f[0], nfingers)) { + if (palm) { *x = *y = *z = 0; ms->button = ms->obutton; return (0); @@ -3807,9 +3839,15 @@ psmgestures(struct psm_softc *sc, finger_t *fingers, i gest->in_vscroll = 0; /* Compute tap timeout. */ - gest->taptimeout.tv_sec = tap_timeout / 1000000; - gest->taptimeout.tv_usec = tap_timeout % 1000000; - timevaladd(&gest->taptimeout, &sc->lastsoftintr); + if (tap_enabled != 0) { + gest->taptimeout = (struct timeval) { + .tv_sec = tap_timeout / 1000000, + .tv_usec = tap_timeout % 1000000, + }; + timevaladd( + &gest->taptimeout, &sc->lastsoftintr); + } else + timevalclear(&gest->taptimeout); sc->flags |= PSM_FLAGS_FINGERDOWN; @@ -4098,6 +4136,7 @@ psmsmoother(struct psm_softc *sc, finger_t *f, int smo int len, weight_prev_x, weight_prev_y; int div_max_x, div_max_y, div_x, div_y; int is_fuzzy; + int natural_scroll; /* Read sysctl. */ /* XXX Verify values? */ @@ -4125,6 +4164,7 @@ psmsmoother(struct psm_softc *sc, finger_t *f, int smo two_finger_scroll = sc->syninfo.two_finger_scroll; max_x = sc->syninfo.max_x; max_y = sc->syninfo.max_y; + natural_scroll = sc->syninfo.natural_scroll; is_fuzzy = (f->flags & PSM_FINGER_FUZZY) != 0; @@ -4286,14 +4326,24 @@ psmsmoother(struct psm_softc *sc, finger_t *f, int smo smoother_id, dx, dy, dxp, dyp)); break; case 1: /* Vertical scrolling. */ - if (dyp != 0) - ms->button |= (dyp > 0) ? - MOUSE_BUTTON4DOWN : MOUSE_BUTTON5DOWN; + if (dyp != 0) { + if (two_finger_scroll && natural_scroll) + ms->button |= (dyp > 0) ? + MOUSE_BUTTON5DOWN : MOUSE_BUTTON4DOWN; + else + ms->button |= (dyp > 0) ? + MOUSE_BUTTON4DOWN : MOUSE_BUTTON5DOWN; + } break; case 2: /* Horizontal scrolling. */ - if (dxp != 0) - ms->button |= (dxp > 0) ? - MOUSE_BUTTON7DOWN : MOUSE_BUTTON6DOWN; + if (dxp != 0) { + if (two_finger_scroll && natural_scroll) + ms->button |= (dxp > 0) ? + MOUSE_BUTTON6DOWN : MOUSE_BUTTON7DOWN; + else + ms->button |= (dxp > 0) ? + MOUSE_BUTTON7DOWN : MOUSE_BUTTON6DOWN; + } break; } @@ -4315,7 +4365,7 @@ proc_elantech(struct psm_softc *sc, packetbuf_t *pb, m { static int touchpad_button, trackpoint_button; finger_t fn, f[ELANTECH_MAX_FINGERS]; - int pkt, id, scale, i, nfingers, mask; + int pkt, id, scale, i, nfingers, mask, palm; if (!elantech_support) return (0); @@ -4625,7 +4675,7 @@ proc_elantech(struct psm_softc *sc, packetbuf_t *pb, m case ELANTECH_PKT_TRACKPOINT: /* 7 6 5 4 3 2 1 0 (LSB) * ------------------------------------------- - * ipacket[0]: 0 0 SX SY 0 M R L + * ipacket[0]: 0 0 SY SX 0 M R L * ipacket[1]: ~SX 0 0 0 0 0 0 0 * ipacket[2]: ~SY 0 0 0 0 0 0 0 * ipacket[3]: 0 0 ~SY ~SX 0 1 1 0 @@ -4636,22 +4686,32 @@ proc_elantech(struct psm_softc *sc, packetbuf_t *pb, m * over 9 bits with SX/SY the relative top bit and * X7..X0 and Y7..Y0 the lower bits. */ - *x = (pb->ipacket[0] & 0x20) ? - pb->ipacket[4] - 256 : pb->ipacket[4]; - *y = (pb->ipacket[0] & 0x10) ? - pb->ipacket[5] - 256 : pb->ipacket[5]; + if (!(pb->ipacket[0] & 0xC8) && !(pb->ipacket[1] & 0x7F) && + !(pb->ipacket[2] & 0x7F) && !(pb->ipacket[3] & 0xC9) && + !(pb->ipacket[0] & 0x10) != !(pb->ipacket[1] & 0x80) && + !(pb->ipacket[0] & 0x10) != !(pb->ipacket[3] & 0x10) && + !(pb->ipacket[0] & 0x20) != !(pb->ipacket[2] & 0x80) && + !(pb->ipacket[0] & 0x20) != !(pb->ipacket[3] & 0x20)) { - trackpoint_button = - ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | - ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | - ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); + *x = (pb->ipacket[0] & MOUSE_PS2_XNEG) ? + pb->ipacket[4] - 256 : pb->ipacket[4]; + *y = (pb->ipacket[0] & MOUSE_PS2_YNEG) ? + pb->ipacket[5] - 256 : pb->ipacket[5]; + + trackpoint_button = + ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | + ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | + ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); #ifdef EVDEV_SUPPORT - evdev_push_rel(sc->evdev_r, REL_X, *x); - evdev_push_rel(sc->evdev_r, REL_Y, -*y); - evdev_push_mouse_btn(sc->evdev_r, trackpoint_button); - evdev_sync(sc->evdev_r); + evdev_push_rel(sc->evdev_r, REL_X, *x); + evdev_push_rel(sc->evdev_r, REL_Y, -*y); + evdev_push_mouse_btn(sc->evdev_r, trackpoint_button); + evdev_sync(sc->evdev_r); #endif - ms->button = touchpad_button | trackpoint_button; + ms->button = touchpad_button | trackpoint_button; + } else + VLOG(3, (LOG_DEBUG, "elantech: " + "unexpected trackpoint packet skipped\n")); return (0); case ELANTECH_PKT_NOP: @@ -4704,10 +4764,14 @@ proc_elantech(struct psm_softc *sc, packetbuf_t *pb, m ms->button = touchpad_button | trackpoint_button; + /* Palm detection doesn't terminate the current action. */ + palm = psmpalmdetect(sc, &f[0], nfingers); + /* Send finger 1 position to gesture processor */ - if (PSM_FINGER_IS_SET(f[0]) || PSM_FINGER_IS_SET(f[1]) || - nfingers == 0) + if ((PSM_FINGER_IS_SET(f[0]) || PSM_FINGER_IS_SET(f[1]) || + nfingers == 0) && !palm) psmgestures(sc, &f[0], imin(nfingers, 3), ms); + /* Send fingers positions to movement smoothers */ for (id = 0; id < PSM_FINGERS; id++) if (PSM_FINGER_IS_SET(f[id]) || !(mask & (1 << id))) @@ -4722,8 +4786,7 @@ proc_elantech(struct psm_softc *sc, packetbuf_t *pb, m } sc->elanaction.mask = mask; - /* Palm detection doesn't terminate the current action. */ - if (psmpalmdetect(sc, &f[0], nfingers)) { + if (palm) { *x = *y = *z = 0; ms->button = ms->obutton; return (0); @@ -5602,7 +5665,7 @@ synaptics_sysctl(SYSCTL_HANDLER_ARGS) int error, arg; if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 || - oidp->oid_arg2 > SYNAPTICS_SYSCTL_SOFTBUTTON3_X) + oidp->oid_arg2 > SYNAPTICS_SYSCTL_LAST) return (EINVAL); sc = oidp->oid_arg1; @@ -5691,6 +5754,7 @@ synaptics_sysctl(SYSCTL_HANDLER_ARGS) return (EINVAL); break; case SYNAPTICS_SYSCTL_TOUCHPAD_OFF: + case SYNAPTICS_SYSCTL_NATURAL_SCROLL: if (arg < 0 || arg > 1) return (EINVAL); break; @@ -6083,6 +6147,15 @@ synaptics_sysctl_create_tree(struct psm_softc *sc, con synaptics_sysctl, "I", "Turn off touchpad"); + /* hw.psm.synaptics.natural_scroll. */ + sc->syninfo.natural_scroll = 0; + SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, + "natural_scroll", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, SYNAPTICS_SYSCTL_NATURAL_SCROLL, + synaptics_sysctl, "I", + "Enable natural scrolling"); + sc->syninfo.softbuttons_y = 0; sc->syninfo.softbutton2_x = 0; sc->syninfo.softbutton3_x = 0; @@ -6136,7 +6209,7 @@ synaptics_set_mode(struct psm_softc *sc, int mode_byte */ if ((sc->synhw.capAdvancedGestures || sc->synhw.capReportsV) && sc->hw.model == MOUSE_MODEL_SYNAPTICS && !(mode_byte & (1 << 5))) { - mouse_ext_command(sc->kbdc, 3); + mouse_ext_command(sc->kbdc, SYNAPTICS_READ_MODEL_ID); set_mouse_sampling_rate(sc->kbdc, 0xc8); } } @@ -6216,7 +6289,7 @@ enable_synaptics(struct psm_softc *sc, enum probearg a set_mouse_scaling(kbdc, 1); /* Identify the Touchpad version. */ - if (mouse_ext_command(kbdc, 0) == 0) + if (mouse_ext_command(kbdc, SYNAPTICS_READ_IDENTITY) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); @@ -6237,7 +6310,7 @@ enable_synaptics(struct psm_softc *sc, enum probearg a } /* Get the Touchpad model information. */ - if (mouse_ext_command(kbdc, 3) == 0) + if (mouse_ext_command(kbdc, SYNAPTICS_READ_MODEL_ID) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); @@ -6268,7 +6341,7 @@ enable_synaptics(struct psm_softc *sc, enum probearg a } /* Read the extended capability bits. */ - if (mouse_ext_command(kbdc, 2) == 0) + if (mouse_ext_command(kbdc, SYNAPTICS_READ_CAPABILITIES) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); @@ -6299,7 +6372,7 @@ enable_synaptics(struct psm_softc *sc, enum probearg a if (!set_mouse_scaling(kbdc, 1)) return (FALSE); - if (mouse_ext_command(kbdc, 0x08) == 0) + if (mouse_ext_command(kbdc, SYNAPTICS_READ_RESOLUTIONS) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); @@ -6336,7 +6409,8 @@ enable_synaptics(struct psm_softc *sc, enum probearg a if (synhw.nExtendedQueries >= 1) { if (!set_mouse_scaling(kbdc, 1)) return (FALSE); - if (mouse_ext_command(kbdc, 0x09) == 0) + if (mouse_ext_command(kbdc, + SYNAPTICS_READ_EXTENDED) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); @@ -6375,7 +6449,8 @@ enable_synaptics(struct psm_softc *sc, enum probearg a if (synhw.nExtendedQueries >= 4) { if (!set_mouse_scaling(kbdc, 1)) return (FALSE); - if (mouse_ext_command(kbdc, 0x0c) == 0) + if (mouse_ext_command(kbdc, + SYNAPTICS_READ_CAPABILITIES_CONT) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); @@ -6396,7 +6471,8 @@ enable_synaptics(struct psm_softc *sc, enum probearg a if (synhw.capReportsMax) { if (!set_mouse_scaling(kbdc, 1)) return (FALSE); - if (mouse_ext_command(kbdc, 0x0d) == 0) + if (mouse_ext_command(kbdc, + SYNAPTICS_READ_MAX_COORDS) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); @@ -6417,7 +6493,8 @@ enable_synaptics(struct psm_softc *sc, enum probearg a if (synhw.capReportsMin) { if (!set_mouse_scaling(kbdc, 1)) return (FALSE); - if (mouse_ext_command(kbdc, 0x0f) == 0) + if (mouse_ext_command(kbdc, + SYNAPTICS_READ_MIN_COORDS) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); @@ -6520,7 +6597,7 @@ enable_synaptics(struct psm_softc *sc, enum probearg a * byte of the response to this query to be a constant 0x3b, this * does not appear to be true for Touchpads with guest devices. */ - if (mouse_ext_command(kbdc, 1) == 0) + if (mouse_ext_command(kbdc, SYNAPTICS_READ_MODES) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); @@ -7071,7 +7148,7 @@ enable_elantech(struct psm_softc *sc, enum probearg ar { static const int ic2hw[] = /*IC: 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - { 0, 0, 2, 0, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0 }; + { 0, 0, 2, 0, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }; static const int fw_sizes[][3] = { /* FW.vers MaxX MaxY */ { 0x020030, 1152, 768 },
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201906291249.x5TCnrUZ014411>