Looks fine to me. I made some tests on a T420, with explicitly
triggered resets, and the detection and the "reset task" worked
as expected. There are noticeable delays, but I don't think
optimizing would be worth the effort (if it happens too often,
you may want to repair or exchange your touchpad).
Maybe we can generalize that later. Very rarely, I observe a
similar phenomenon with my Elantech-v4 touchpad (two not-in-sync
messages, then data reporting stops, which is to be expected
after a PS/2 reset).
But here is a little puzzle: There are no constant bits in
byte 2 and 3 and byte 5 and 6 of Absolute Mode packets, so
theoretically [0xaa, 0x00] may be a valid part of a packet,
starting at byte 2 or byte 5 (there is no overlap on other
positions). Is there a simple and sound way to exclude false
positive errors? Or can we simply ignore it because it's
improbable enough or impossible? (If not, a change of the
logic could be necessary: don't interrupt the normal processing
when the sequence is detected, and check the state of the
device in pms_reset_task).
On 10/29/2017 09:35 AM, Anton Lindqvist wrote:
> Hi,
> Every now and then, my Synaptics touchpad stops working and no further
> interrupts are received for the device. The following message appears in
> the log:
>
> pms0: not in sync yet, discard input (state = 0)
>
> Examining the bytes received prior to the halt reveals the sequence
> [0xaa, 0x00] which denotes a Synaptics reset announcement[1]. This
> sequence is sent after the touchpad experienced a loss of power and the
> device is reset. Since any altered setting prior to the reset is lost
> the device must be re-enabled in order to continue functioning. The
> simplest(?) way is to disable and then enable the device (many thanks to
> bru@ for helping out with this part).
>
> Testing this diff on hardware equipped with a Synaptics touchpad would be much
> appreciated. Even if you never experienced a reset in order make sure no
> regression is introduced.
>
> In addition, I'm looking for feedback and OKs.
>
> [1]
> https://www.aquaphoenix.com/hardware/ledlamp/reference/synaptics_touchpad_interfacing_guide.pdf#page=32
>
> Index: pms.c
> ===
> RCS file: /cvs/src/sys/dev/pckbc/pms.c,v
> retrieving revision 1.81
> diff -u -p -r1.81 pms.c
> --- pms.c 28 Oct 2017 14:31:29 - 1.81
> +++ pms.c 28 Oct 2017 16:55:22 -
> @@ -30,6 +30,7 @@
> #include
> #include
> #include
> +#include
>
> #include
>
> @@ -88,6 +89,8 @@ struct synaptics_softc {
>
> int mode;
>
> + int annstate; /* announcement state */
> +
> int mask;
> #define SYNAPTICS_MASK_NEWABS_STRICT 0xc8
> #define SYNAPTICS_MASK_NEWABS_RELAXED0xc0
> @@ -158,6 +161,8 @@ struct pms_softc {/* driver status inf
> #define PMS_DEV_PRIMARY 0x01
> #define PMS_DEV_SECONDARY0x02
>
> + struct task sc_reset_task;
> +
> int poll;
> int inputstate;
>
> @@ -255,6 +260,7 @@ int pms_reset(struct pms_softc *);
> int pms_dev_enable(struct pms_softc *);
> int pms_dev_disable(struct pms_softc *);
> void pms_protocol_lookup(struct pms_softc *);
> +void pms_reset_task(void *);
>
> int pms_enable_intelli(struct pms_softc *);
>
> @@ -293,6 +299,7 @@ int synaptics_set_mode(struct pms_softc
> int synaptics_query(struct pms_softc *, int, int *);
> int synaptics_get_hwinfo(struct pms_softc *);
> void synaptics_sec_proc(struct pms_softc *);
> +int synaptics_is_reset(struct pms_softc *, int);
>
> int alps_sec_proc(struct pms_softc *);
> int alps_get_hwinfo(struct pms_softc *);
> @@ -542,6 +549,32 @@ pms_protocol_lookup(struct pms_softc *sc
> DPRINTF("%s: protocol type %d\n", DEVNAME(sc), sc->protocol->type);
> }
>
> +void
> +pms_reset_task(void *v)
> +{
> + struct pms_softc *sc = v;
> +
> + rw_enter_write(&sc->sc_state_lock);
> +
> + /* Do nothing if the device already is disabled. */
> + if (sc->sc_state == PMS_STATE_DISABLED)
> + goto done;
> +
> +#ifdef DIAGNOSTIC
> + printf("%s: device reset\n", DEVNAME(sc));
> +#endif
> + if (sc->sc_sec_wsmousedev != NULL)
> + pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_SECONDARY);
> + pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_PRIMARY);
> +
> + pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_PRIMARY);
> + if (sc->sc_sec_wsmousedev != NULL)
> + pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_SECONDARY);
> +
> +done:
> + rw_exit_write(&sc->sc_state_lock);
> +}
> +
> int
> pms_enable_intelli(struct pms_softc *sc)
> {
> @@ -679,6 +712,8 @@ pmsattach(struct device *parent, struct
>*/
> sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
>
> + task_set(&sc->sc_reset_task, pms_reset_task, sc);
> +
> sc->poll = 1;
> sc->sc_dev_enable = 0;
>
> @@ -850,9 +885,11 @@ pmsinput(void *vsc,