Date: Mon, 19 Mar 2018 03:46:13 +0000 (UTC) From: Eitan Adler <eadler@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r331170 - in stable/11/sys: dev/atkbdc sys Message-ID: <201803190346.w2J3kDdR005800@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: eadler Date: Mon Mar 19 03:46:12 2018 New Revision: 331170 URL: https://svnweb.freebsd.org/changeset/base/331170 Log: MFC r328636: psm(4): Add support for HP EliteBook 1040 ForcePads. ForcePads do not have any physical buttons, instead they detect click based on finger pressure. Forcepads erroneously report button click if there are 2 or more fingers on the touchpad breaking multifinger gestures. To workaround this start reporting a click only after 4 consecutive single touch packets has been received. Skip these packets in case more contacts appear. PR: 223369 Modified: stable/11/sys/dev/atkbdc/psm.c stable/11/sys/sys/mouse.h Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/dev/atkbdc/psm.c ============================================================================== --- stable/11/sys/dev/atkbdc/psm.c Mon Mar 19 03:44:19 2018 (r331169) +++ stable/11/sys/dev/atkbdc/psm.c Mon Mar 19 03:46:12 2018 (r331170) @@ -132,6 +132,13 @@ __FBSDID("$FreeBSD$"); #define PSMCPNP_DRIVER_NAME "psmcpnp" +struct psmcpnp_softc { + enum { + PSMCPNP_GENERIC, + PSMCPNP_FORCEPAD, + } type; /* Based on PnP ID */ +}; + /* input queue */ #define PSM_BUFSIZE 960 #define PSM_SMALLBUFSIZE 240 @@ -416,6 +423,7 @@ struct psm_softc { /* Driver status information */ int squelch; /* level to filter movement at low speed */ int syncerrors; /* # of bytes discarded to synchronize */ int pkterrors; /* # of packets failed during quaranteen. */ + int fpcount; /* forcePad valid packet counter */ struct timeval inputtimeout; struct timeval lastsoftintr; /* time of last soft interrupt */ struct timeval lastinputerr; /* time last sync error happened */ @@ -3183,7 +3191,7 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, static int touchpad_buttons; static int guest_buttons; static finger_t f[PSM_FINGERS]; - int w, id, nfingers, ewcode, extended_buttons; + int w, id, nfingers, ewcode, extended_buttons, clickpad_pressed; extended_buttons = 0; @@ -3445,10 +3453,6 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, extended_buttons |= sc->extended_buttons; } } - /* Handle ClickPad */ - if (sc->synhw.capClickPad && - ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)) - touchpad_buttons |= MOUSE_BUTTON1DOWN; if (sc->synhw.capReportsV && nfingers > 1) f[0] = (finger_t) { @@ -3481,6 +3485,36 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2) nfingers = 0; + /* Handle ClickPad */ + if (sc->synhw.capClickPad) { + clickpad_pressed = (pb->ipacket[0] ^ pb->ipacket[3]) & 0x01; + if (sc->synhw.forcePad) { + /* + * Forcepads erroneously report button click if there + * are 2 or more fingers on the touchpad breaking + * multifinger gestures. To workaround this start + * reporting a click only after 4 consecutive single + * touch packets has been received. + * Skip these packets in case more contacts appear. + */ + switch (nfingers) { + case 0: + sc->fpcount = 0; + break; + case 1: + if (clickpad_pressed && sc->fpcount < INT_MAX) + ++sc->fpcount; + /* FALLTHROUGH */ + default: + if (!clickpad_pressed) + sc->fpcount = 0; + if (sc->fpcount >= sc->syninfo.window_min) + touchpad_buttons |= MOUSE_BUTTON1DOWN; + } + } else if (clickpad_pressed) + touchpad_buttons |= MOUSE_BUTTON1DOWN; + } + for (id = 0; id < PSM_FINGERS; id++) if (id >= nfingers) PSM_FINGER_RESET(f[id]); @@ -6004,6 +6038,8 @@ synaptics_set_mode(struct psm_softc *sc, int mode_byte static int enable_synaptics(struct psm_softc *sc, enum probearg arg) { + device_t psmcpnp; + struct psmcpnp_softc *psmcpnp_sc; KBDC kbdc = sc->kbdc; synapticshw_t synhw; int status[3]; @@ -6081,6 +6117,10 @@ enable_synaptics(struct psm_softc *sc, enum probearg a return (FALSE); } + psmcpnp = devclass_get_device(devclass_find(PSMCPNP_DRIVER_NAME), + sc->unit); + psmcpnp_sc = (psmcpnp != NULL) ? device_get_softc(psmcpnp) : NULL; + /* Set the different capabilities when they exist. */ buttons = 0; synhw.capExtended = (status[0] & 0x80) != 0; @@ -6235,6 +6275,20 @@ enable_synaptics(struct psm_softc *sc, enum probearg a synhw.minimumYCoord = 1408; } + /* + * ClickPad properties are not exported through PS/2 + * protocol. Detection is based on controller's PnP ID. + */ + if (synhw.capClickPad && psmcpnp_sc != NULL) { + switch (psmcpnp_sc->type) { + case PSMCPNP_FORCEPAD: + synhw.forcePad = 1; + break; + default: + break; + } + } + if (verbose >= 2) { printf(" Continued capabilities:\n"); printf(" capClickPad: %d\n", @@ -6271,6 +6325,10 @@ enable_synaptics(struct psm_softc *sc, enum probearg a printf(" minimumYCoord: %d\n", synhw.minimumYCoord); } + if (synhw.capClickPad) { + printf(" forcePad: %d\n", + synhw.forcePad); + } } buttons += synhw.capClickPad; } @@ -7096,7 +7154,7 @@ static device_method_t psmcpnp_methods[] = { static driver_t psmcpnp_driver = { PSMCPNP_DRIVER_NAME, psmcpnp_methods, - 1, /* no softc */ + sizeof(struct psmcpnp_softc), }; static struct isa_pnp_id psmcpnp_ids[] = { @@ -7116,6 +7174,13 @@ static struct isa_pnp_id psmcpnp_ids[] = { { 0 } }; +/* _HID list for quirk detection. Any device below has _CID from psmcpnp_ids */ +static struct isa_pnp_id forcepad_ids[] = { + { 0x0d302e4f, "HP PS/2 forcepad port" }, /* SYN300D, EB 1040 */ + { 0x14302e4f, "HP PS/2 forcepad port" }, /* SYN3014, EB 1040 */ + { 0 } +}; + static int create_a_copy(device_t atkbdc, device_t me) { @@ -7142,11 +7207,16 @@ create_a_copy(device_t atkbdc, device_t me) static int psmcpnp_probe(device_t dev) { + struct psmcpnp_softc *sc = device_get_softc(dev); struct resource *res; u_long irq; int rid; - if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids)) + if (ISA_PNP_PROBE(device_get_parent(dev), dev, forcepad_ids) == 0) + sc->type = PSMCPNP_FORCEPAD; + else if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids) == 0) + sc->type = PSMCPNP_GENERIC; + else return (ENXIO); /* Modified: stable/11/sys/sys/mouse.h ============================================================================== --- stable/11/sys/sys/mouse.h Mon Mar 19 03:44:19 2018 (r331169) +++ stable/11/sys/sys/mouse.h Mon Mar 19 03:46:12 2018 (r331170) @@ -135,6 +135,7 @@ typedef struct synapticshw { int maximumYCoord; int infoXupmm; int infoYupmm; + int forcePad; } synapticshw_t; /* iftype */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803190346.w2J3kDdR005800>