hms(4): improve scroll with IICHID_SAMPLING

The current quirk is designed to discard duplicated data read from
the chip.  Problem is, it also discards real events when they happen
to be identical, which is the case with scroll wheel events;
differently from X/Y they always move by fixed offset.  This results
in two-finger scroll that would stop mid-way that could be fixed by
manually setting dev.hms.0.drift_thresh to 0.

To fix that, don't discard duplicates when there's wheel movement.
For users with actual duplicates problem this will result in scroll
suddenly becoming quite inertial, but it will stop moving at any touch,
so shouldn't be terrible.

PR:		kern/276709
Reviewed By:	wulf
Differential Revision:	https://reviews.freebsd.org/D47640
This commit is contained in:
Edward Tomasz Napierala 2024-11-25 15:08:10 +00:00
parent ccb973da1f
commit c0a5ee953f

View File

@ -122,6 +122,7 @@ struct hms_softc {
hid_size_t isize;
uint32_t drift_cnt;
uint32_t drift_thresh;
struct hid_location wheel_loc;
#endif
};
@ -131,6 +132,7 @@ hms_intr(void *context, void *buf, hid_size_t len)
{
struct hidmap *hm = context;
struct hms_softc *sc = device_get_softc(hm->dev);
int32_t wheel;
if (len > sc->isize)
len = sc->isize;
@ -140,8 +142,18 @@ hms_intr(void *context, void *buf, hid_size_t len)
* to return last report data in sampling mode even after touch has
* been ended. That results in cursor drift. Filter out such a
* reports through comparing with previous one.
*
* Except this results in dropping consecutive mouse wheel events,
* because differently from cursor movement they always move by the
* same amount. So, don't do it when there's mouse wheel movement.
*/
if (len == sc->last_irsize && memcmp(buf, sc->last_ir, len) == 0) {
if (sc->wheel_loc.size != 0)
wheel = hid_get_data(buf, len, &sc->wheel_loc);
else
wheel = 0;
if (len == sc->last_irsize && memcmp(buf, sc->last_ir, len) == 0 &&
wheel == 0) {
sc->drift_cnt++;
if (sc->drift_thresh != 0 && sc->drift_cnt >= sc->drift_thresh)
return;
@ -285,9 +297,25 @@ hms_attach(device_t dev)
/* Count number of input usages of variable type mapped to buttons */
for (hi = sc->hm.hid_items;
hi < sc->hm.hid_items + sc->hm.nhid_items;
hi++)
hi++) {
if (hi->type == HIDMAP_TYPE_VARIABLE && hi->evtype == EV_KEY)
nbuttons++;
#ifdef IICHID_SAMPLING
/*
* Make note of which part of the report descriptor is the wheel.
*/
if (hi->type == HIDMAP_TYPE_VARIABLE &&
hi->evtype == EV_REL && hi->code == REL_WHEEL) {
sc->wheel_loc = hi->loc;
/*
* Account for the leading Report ID byte
* if it is a multi-report device.
*/
if (hi->id != 0)
sc->wheel_loc.pos += 8;
}
#endif
}
/* announce information about the mouse */
device_printf(dev, "%d buttons and [%s%s%s%s%s] coordinates ID=%u\n",