Re: ims(4) touchscreen support for the SGB4E

Kirill A. Korinsky <[email protected]>
Newsgroups gmane.os.openbsd.tech
Message-ID <[email protected]>
On Tue, 26 May 2026 21:04:59 +0200,
Marcus Glocker <[email protected]> wrote:
> 
> Here's a status update for this diff:
> 
> - The DTS part (the power-on path for the Samsung touchscreen) was
>   committed this morning, so it's out of the picture for this diff now.
> 
> - I received a few test reports, all reporting no regressions.
> 
> What the diff does:
> 
> Today ihidev(4) doesn't handle empty packets for polling devices at
> all -- that's the
> 
> 	/*
> 	 * TODO: all fingers are up, should we pass to hid
> 	 * layer?
> 	 */
> 
> comment, which this diff completes with an edge-triggered check.
> ihidev(4) remembers the report-id of the last non-empty report.  When
> we have delivered a report for some report-id and then read an empty
> packet while polling, the device has gone idle (all contacts up).  We
> then hand that report-id's subdevice a zeroed report, so the upper
> layer can register the release.  The edge condition makes this fire
> once, on the transition, not on every idle poll.
> 
> Interrupt-driven devices are not affected -- their empty-packet path
> still just returns as before.
> 
> The zeroed report then reaches hidms.  For an interrupt-driven
> absolute device the real release report carries the exact coordinates;
> for our polled device the synthesized report carries 0,0.  Currently
> hidms just sets the new absolute coordinates, so for the polled
> device the 0,0 snaps the pointer to the upper-left corner.  To prevent
> that, we add a check in hidms:  if a button was pressed before and
> is now released, we skip setting the absolute coordinates on that
> report and leave the pointer where it was.  For an interrupt-driven
> device this is invisible -- the previous position is the same point
> the release report would have set -- and for the polled device it
> prevents the corner snap.
> 
> Importantly, this hidms check only does anything for devices that
> report absolute coordinates (HIDMS_ABSX/ABSY).  Relative pointers --
> ordinary mice and touchpads, that is nearly all ums(4) users -- skip
> it entirely, which is why the test reports (all relative devices) show
> no change.  The only absolute device exercising this path is the
> touchscreen.
> 
> On regression risk:
> 
> - For ihidev(4) I think it's close to zero:  we've only completed a
>   code path that wasn't implemented for polling devices, and
>   interrupt-driven devices are untouched.
> 
> - For hidms I think it's low as well:  we now hold the last position
>   on release instead of re-setting it to the position from the release
>   report, which is the same point, so there's no visible change for
>   existing absolute (interrupt-driven) devices and it's a no-op for
>   relative ones.  hidms_input() is used by ims(4) and ums(4); uwacom(4)
>   uses hidms for setup but parses input itself, so it is not affected.
>   If a regression does show up, the change is small and trivial to back
>   out.
> 
> Based on that, ok?
> 
>

Tested for about a week on my main daily driver. No regression to report,
but some feedback bellow.

> Index: sys/dev/hid/hidms.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/hid/hidms.c,v
> diff -u -p -u -p -r1.11 hidms.c
> --- sys/dev/hid/hidms.c	10 May 2024 10:49:10 -0000	1.11
> +++ sys/dev/hid/hidms.c	23 May 2026 14:30:24 -0000
> @@ -533,7 +533,7 @@ hidms_input(struct hidms *ms, uint8_t *d
>  {
>  	int dx, dy, dz, dw;
>  	u_int32_t buttons = 0;
> -	int i, s;
> +	int i, s, released;
>  
>  	DPRINTFN(5,("hidms_input: len=%d\n", len));
>  
> @@ -595,17 +595,26 @@ hidms_input(struct hidms *ms, uint8_t *d
>  	    buttons != ms->sc_buttons) {
>  		DPRINTFN(10, ("hidms_input: x:%d y:%d z:%d w:%d buttons:0x%x\n",
>  			dx, dy, dz, dw, buttons));
> +		released = (ms->sc_buttons != 0 && buttons == 0);
>  		ms->sc_buttons = buttons;
>  		if (ms->sc_wsmousedev != NULL) {
>  			s = spltty();
> +			/*
> +			 * A polled touchscreen reports finger-up as a zeroed
> +			 * packet; emitting its (0,0) as an absolute position
> +			 * would snap the pointer to the corner.  On a button
> +			 * release edge, hold the last position instead.
> +			 */
>  			if (ms->sc_flags & HIDMS_ABSX) {
> -				wsmouse_set(ms->sc_wsmousedev,
> -				    WSMOUSE_ABS_X, dx, 0);
> +				if (!released)
> +					wsmouse_set(ms->sc_wsmousedev,
> +					    WSMOUSE_ABS_X, dx, 0);
>  				dx = 0;
>  			}
>  			if (ms->sc_flags & HIDMS_ABSY) {
> -				wsmouse_set(ms->sc_wsmousedev,
> -				    WSMOUSE_ABS_Y, dy, 0);
> +				if (!released)
> +					wsmouse_set(ms->sc_wsmousedev,
> +					    WSMOUSE_ABS_Y, dy, 0);
>  				dy = 0;
>  			}
>  			WSMOUSE_INPUT(ms->sc_wsmousedev,


I think this hidms part is broader than the stated touchscreen fix.

The new released flag is true for every absolute HID device whose buttons
transition from nonzero to zero; it is not tied to the synthetic zeroed
report generated by the polled ihidev path, if I not mistaken.

Consequently, a real release report from an interrupt driven absolute
device, with valid final X/Y coordinates, will have those coordinates
suppressed, and the button release will be delivered at the previous stored
position.

Not sure does it bring any issue, or just impossible case.

> Index: sys/dev/i2c/ihidev.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/i2c/ihidev.c,v
> diff -u -p -u -p -r1.43 ihidev.c
> --- sys/dev/i2c/ihidev.c	23 May 2026 11:10:57 -0000	1.43
> +++ sys/dev/i2c/ihidev.c	23 May 2026 14:30:24 -0000
> @@ -142,6 +142,7 @@ ihidev_attach(struct device *parent, str
>  	sc->sc_tag = ia->ia_tag;
>  	sc->sc_addr = ia->ia_addr;
>  	sc->sc_hid_desc_addr = ia->ia_size;
> +	sc->sc_lastrepid = -1;
>  
>  	if (ihidev_hid_command(sc, I2C_HID_CMD_DESCR, NULL) ||
>  	    ihidev_hid_desc_parse(sc)) {
> @@ -159,10 +160,13 @@ ihidev_attach(struct device *parent, str
>  
>  	/* find largest report size and allocate memory for input buffer */
>  	sc->sc_isize = letoh16(sc->hid_desc.wMaxInputLength);
> +	sc->sc_repsizes = mallocarray(sc->sc_nrepid, sizeof(int),
> +	    M_DEVBUF, M_WAITOK | M_ZERO);
>  	for (repid = 0; repid < sc->sc_nrepid; repid++) {
>  		repsz = hid_report_size(sc->sc_report, sc->sc_reportlen,
>  		    hid_input, repid);
>  		repsizes[repid] = repsz;
> +		sc->sc_repsizes[repid] = repsz;
>  		if (repsz > sc->sc_isize)
>  			sc->sc_isize = repsz;
>  		if (repsz != 0)
> @@ -255,6 +259,9 @@ ihidev_detach(struct device *self, int f
>  	if (sc->sc_report != NULL)
>  		free(sc->sc_report, M_DEVBUF, sc->sc_reportlen);
>  
> +	if (sc->sc_repsizes != NULL)
> +		free(sc->sc_repsizes, M_DEVBUF, sc->sc_nrepid * sizeof(int));
> +
>  	return (0);
>  }
>  
> @@ -718,10 +725,21 @@ ihidev_intr(void *arg)
>  	psize = sc->sc_ibuf[0] | sc->sc_ibuf[1] << 8;
>  	if (psize <= 2 || psize > sc->sc_isize) {
>  		if (sc->sc_poll) {
> -			/*
> -			 * TODO: all fingers are up, should we pass to hid
> -			 * layer?
> -			 */
> +			/* empty packet: hand the last subdev a zeroed report
> +			 * once so it releases its contacts (polled finger-up) */
> +			int lrep = sc->sc_lastrepid;
> +			int rsz;
> +
> +			if (lrep >= 0 && lrep < sc->sc_nrepid &&
> +			    (scd = sc->sc_subdevs[lrep]) != NULL &&
> +			    (scd->sc_state & IHIDEV_OPEN) && !sc->sc_dying) {
> +				rsz = sc->sc_repsizes[lrep];
> +				if (rsz > 0 && rsz <= sc->sc_isize) {
> +					memset(sc->sc_ibuf, 0, rsz);
> +					scd->sc_intr(scd, sc->sc_ibuf, rsz);
> +				}
> +				sc->sc_lastrepid = -1;
> +			}
>  			sc->sc_fastpoll = 0;
>  			goto more_polling;
>  		} else

I think on an empty polled packet it sends a zeroed input report to
whichever subdevice last produced data.

So the behaviour applies to other polled I2C HID child, not only ims.

Not sure how safe it is.

> @@ -770,8 +788,10 @@ ihidev_intr(void *arg)
>  		return (1);
>  	}
>  
> -	if (!sc->sc_dying)
> +	if (!sc->sc_dying) {
> +		sc->sc_lastrepid = rep;
>  		scd->sc_intr(scd, p, psize);
> +	}
>  
>  	if (sc->sc_poll && (fast != sc->sc_fastpoll)) {
>  		DPRINTF(("%s: %s->%s polling\n", sc->sc_dev.dv_xname,
> Index: sys/dev/i2c/ihidev.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/i2c/ihidev.h,v
> diff -u -p -u -p -r1.11 ihidev.h
> --- sys/dev/i2c/ihidev.h	7 Jan 2025 19:26:14 -0000	1.11
> +++ sys/dev/i2c/ihidev.h	23 May 2026 14:30:24 -0000
> @@ -85,6 +85,8 @@ struct ihidev_softc {
>  
>  	u_int		sc_isize;
>  	u_char		*sc_ibuf;
> +	int		sc_lastrepid;	/* report id of last non-empty input */
> +	int		*sc_repsizes;	/* per-report input size, for poll path */
>  
>  	int		sc_refcnt;
>  
> 

-- 
wbr, Kirill
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.