Module Name:    src
Committed By:   riastradh
Date:           Mon Mar 28 12:44:17 UTC 2022

Modified Files:
        src/sys/dev/usb: uatp.c ucycom.c uhid.c uhidev.c uhidev.h ukbd.c ums.c
            uthum.c uts.c

Log Message:
uhidev(9): Make uhidev state opaque.

This makes the API simpler and clearer and gives us more latitude to
fix bugs in the state management without breaking the ABI.

XXX kernel ABI change to signature of uhidev_get_report_desc and
uhidev_open, and to struct uhidev_attach_arg, requires bump for
uhidev driver modules


To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/sys/dev/usb/uatp.c
cvs rdiff -u -r1.54 -r1.55 src/sys/dev/usb/ucycom.c
cvs rdiff -u -r1.122 -r1.123 src/sys/dev/usb/uhid.c
cvs rdiff -u -r1.89 -r1.90 src/sys/dev/usb/uhidev.c
cvs rdiff -u -r1.25 -r1.26 src/sys/dev/usb/uhidev.h
cvs rdiff -u -r1.158 -r1.159 src/sys/dev/usb/ukbd.c
cvs rdiff -u -r1.102 -r1.103 src/sys/dev/usb/ums.c
cvs rdiff -u -r1.22 -r1.23 src/sys/dev/usb/uthum.c
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/usb/uts.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/uatp.c
diff -u src/sys/dev/usb/uatp.c:1.28 src/sys/dev/usb/uatp.c:1.29
--- src/sys/dev/usb/uatp.c:1.28	Mon Mar 28 12:43:12 2022
+++ src/sys/dev/usb/uatp.c	Mon Mar 28 12:44:17 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: uatp.c,v 1.28 2022/03/28 12:43:12 riastradh Exp $	*/
+/*	$NetBSD: uatp.c,v 1.29 2022/03/28 12:44:17 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
@@ -146,7 +146,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.28 2022/03/28 12:43:12 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.29 2022/03/28 12:44:17 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -301,7 +301,7 @@ static void geyser34_initialize(struct u
 static int geyser34_finalize(struct uatp_softc *);
 static void geyser34_deferred_reset(struct uatp_softc *);
 static void geyser34_reset_task(void *);
-static void uatp_intr(struct uhidev *, void *, unsigned int);
+static void uatp_intr(void *, void *, unsigned int);
 static bool base_sample_softc_flag(const struct uatp_softc *, const uint8_t *);
 static bool base_sample_input_flag(const struct uatp_softc *, const uint8_t *);
 static void read_sample_1(uint8_t *, uint8_t *, const uint8_t *);
@@ -486,7 +486,8 @@ static const struct uatp_knobs default_k
 };
 
 struct uatp_softc {
-	struct uhidev sc_hdev;		/* uhidev(9) parent.  */
+	device_t sc_dev;
+	struct uhidev *sc_hdev;		/* uhidev(9) parent.  */
 	struct usbd_device *sc_udev;	/* USB device.  */
 	device_t sc_wsmousedev;		/* Attached wsmouse device.  */
 	const struct uatp_parameters *sc_parameters;
@@ -691,7 +692,7 @@ find_uatp_descriptor(const struct uhidev
 static device_t
 uatp_dev(const struct uatp_softc *sc)
 {
-	return sc->sc_hdev.sc_dev;
+	return sc->sc_dev;
 }
 
 static uint8_t *
@@ -931,12 +932,8 @@ uatp_attach(device_t parent, device_t se
 	int report_size, input_size;
 	struct wsmousedev_attach_args a;
 
-	/* Set up uhidev state.  (Why doesn't uhidev do most of this?)  */
-	sc->sc_hdev.sc_dev = self;
-	sc->sc_hdev.sc_intr = uatp_intr;
-	sc->sc_hdev.sc_parent = uha->parent;
-	sc->sc_hdev.sc_report_id = uha->reportid;
-
+	sc->sc_dev = self;
+	sc->sc_hdev = uha->parent;
 	sc->sc_udev = uha->uiaa->uiaa_device;
 
 	/* Identify ourselves to dmesg.  */
@@ -948,7 +945,7 @@ uatp_attach(device_t parent, device_t se
 	    "vendor 0x%04x, product 0x%04x, report id %d\n",
 	    (unsigned int)uha->uiaa->uiaa_vendor,
 	    (unsigned int)uha->uiaa->uiaa_product,
-	    (int)uha->reportid);
+	    uha->reportid);
 
 	uhidev_get_report_desc(uha->parent, &report_descriptor, &report_size);
 	input_size = hid_report_size(report_descriptor, report_size, hid_input,
@@ -1251,8 +1248,8 @@ uatp_enable(void *v)
 	tap_enable(sc);
 	uatp_clear_position(sc);
 
-	DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_open(%p)\n", &sc->sc_hdev));
-	return uhidev_open(&sc->sc_hdev);
+	DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_open(%p)\n", sc->sc_hdev));
+	return uhidev_open(sc->sc_hdev, &uatp_intr, sc);
 }
 
 static void
@@ -1270,8 +1267,8 @@ uatp_disable(void *v)
 	tap_disable(sc);
 	sc->sc_status &=~ UATP_ENABLED;
 
-	DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_close(%p)\n", &sc->sc_hdev));
-	uhidev_close(&sc->sc_hdev);
+	DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_close(%p)\n", sc->sc_hdev));
+	uhidev_close(sc->sc_hdev);
 }
 
 static int
@@ -1399,15 +1396,15 @@ geyser34_reset_task(void *arg)
 /* Interrupt handler */
 
 static void
-uatp_intr(struct uhidev *addr, void *ibuf, unsigned int len)
+uatp_intr(void *cookie, void *ibuf, unsigned int len)
 {
-	struct uatp_softc *sc = (struct uatp_softc *)addr;
+	struct uatp_softc *sc = cookie;
 	uint8_t *input;
 	int dx, dy, dz, dw;
 	uint32_t buttons;
 
 	DPRINTF(sc, UATP_DEBUG_INTR, ("softc %p, ibuf %p, len %u\n",
-	    addr, ibuf, len));
+	    sc, ibuf, len));
 
 	/*
 	 * Some devices break packets up into chunks, so we accumulate

Index: src/sys/dev/usb/ucycom.c
diff -u src/sys/dev/usb/ucycom.c:1.54 src/sys/dev/usb/ucycom.c:1.55
--- src/sys/dev/usb/ucycom.c:1.54	Mon Mar 28 12:43:30 2022
+++ src/sys/dev/usb/ucycom.c	Mon Mar 28 12:44:17 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ucycom.c,v 1.54 2022/03/28 12:43:30 riastradh Exp $	*/
+/*	$NetBSD: ucycom.c,v 1.55 2022/03/28 12:44:17 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.54 2022/03/28 12:43:30 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.55 2022/03/28 12:44:17 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -117,7 +117,8 @@ int	ucycomdebug = 20;
 #define UCYCOM_ORESET	0x08
 
 struct ucycom_softc {
-	struct uhidev		sc_hdev;
+	device_t		sc_dev;
+	struct uhidev		*sc_hdev;
 	struct usbd_device	*sc_udev;
 
 	struct usb_task		sc_task;
@@ -176,7 +177,7 @@ Static int ucycomparam(struct tty *, str
 Static void ucycomstart(struct tty *);
 Static void ucycomstarttask(void *);
 Static void ucycomwritecb(struct usbd_xfer *, void *, usbd_status);
-Static void ucycom_intr(struct uhidev *, void *, u_int);
+Static void ucycom_intr(void *, void *, u_int);
 Static int ucycom_configure(struct ucycom_softc *, uint32_t, uint8_t);
 Static void tiocm_to_ucycom(struct ucycom_softc *, u_long, int);
 Static int ucycom_to_tiocm(struct ucycom_softc *);
@@ -222,10 +223,8 @@ ucycom_attach(device_t parent, device_t 
 	int size, repid;
 	void *desc;
 
-	sc->sc_hdev.sc_dev = self;
-	sc->sc_hdev.sc_intr = ucycom_intr;
-	sc->sc_hdev.sc_parent = uha->parent;
-	sc->sc_hdev.sc_report_id = uha->reportid;
+	sc->sc_dev = self;
+	sc->sc_hdev = uha->parent;
 	sc->sc_udev = uha->uiaa->uiaa_device;
 	sc->sc_init_state = UCYCOM_INIT_NONE;
 
@@ -280,7 +279,7 @@ ucycom_detach(device_t self, int flags)
 		mutex_spin_exit(&tty_lock);
 	}
 	/* Wait for processes to go away. */
-	usb_detach_waitold(sc->sc_hdev.sc_dev);
+	usb_detach_waitold(sc->sc_dev);
 	splx(s);
 
 	/* locate the major number */
@@ -358,7 +357,7 @@ ucycomopen(dev_t dev, int flag, int mode
 		return EIO;
 	if (sc->sc_init_state != UCYCOM_INIT_INITED)
 		return ENXIO;
-	if (!device_is_active(sc->sc_hdev.sc_dev))
+	if (!device_is_active(sc->sc_dev))
 		return ENXIO;
 
 	tp = sc->sc_tty;
@@ -375,7 +374,7 @@ ucycomopen(dev_t dev, int flag, int mode
 
 		tp->t_dev = dev;
 
-		err = uhidev_open(&sc->sc_hdev);
+		err = uhidev_open(sc->sc_hdev, &ucycom_intr, sc);
 		if (err) {
 			/* Any cleanup? */
 			splx(s);
@@ -617,7 +616,7 @@ ucycomstarttask(void *cookie)
 	usbd_status err;
 
 	/* What can we do on error? */
-	err = uhidev_write_async(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen, 0,
+	err = uhidev_write_async(sc->sc_hdev, sc->sc_obuf, sc->sc_olen, 0,
 	    USBD_NO_TIMEOUT, ucycomwritecb, sc);
 
 #ifdef UCYCOM_DEBUG
@@ -942,7 +941,7 @@ ucycom_configure(struct ucycom_softc *sc
 	report[2] = (baud >> 16) & 0xff;
 	report[3] = (baud >> 24) & 0xff;
 	report[4] = cfg;
-	err = uhidev_set_report(&sc->sc_hdev, UHID_FEATURE_REPORT,
+	err = uhidev_set_report(sc->sc_hdev, UHID_FEATURE_REPORT,
 	    report, sc->sc_flen);
 	if (err != 0) {
 		DPRINTF(("%s\n", usbd_errstr(err)));
@@ -959,9 +958,9 @@ ucycom_configure(struct ucycom_softc *sc
 }
 
 Static void
-ucycom_intr(struct uhidev *addr, void *ibuf, u_int len)
+ucycom_intr(void *cookie, void *ibuf, u_int len)
 {
-	struct ucycom_softc *sc = (struct ucycom_softc *)addr;
+	struct ucycom_softc *sc = cookie;
 	struct tty *tp = sc->sc_tty;
 	int (*rint)(int , struct tty *) = tp->t_linesw->l_rint;
 	uint8_t *cp = ibuf;
@@ -1005,8 +1004,7 @@ ucycom_intr(struct uhidev *addr, void *i
 		DPRINTFN(7,("ucycom_intr: char=0x%02x\n", *cp));
 		if ((*rint)(*cp++, tp) == -1) {
 			/* XXX what should we do? */
-			aprint_error_dev(sc->sc_hdev.sc_dev,
-			    "lost a character\n");
+			aprint_error_dev(sc->sc_dev, "lost a character\n");
 			break;
 		}
 	}
@@ -1124,7 +1122,7 @@ ucycom_set_status(struct ucycom_softc *s
 	memset(sc->sc_obuf, 0, sc->sc_olen);
 	sc->sc_obuf[0] = sc->sc_mcr;
 
-	err = uhidev_write(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen);
+	err = uhidev_write(sc->sc_hdev, sc->sc_obuf, sc->sc_olen);
 	if (err) {
 		DPRINTF(("ucycom_set_status: err=%d\n", err));
 	}
@@ -1137,7 +1135,7 @@ ucycom_get_cfg(struct ucycom_softc *sc)
 	int err, cfg, baud;
 	uint8_t report[5];
 
-	err = uhidev_get_report(&sc->sc_hdev, UHID_FEATURE_REPORT,
+	err = uhidev_get_report(sc->sc_hdev, UHID_FEATURE_REPORT,
 	    report, sc->sc_flen);
 	if (err) {
 		DPRINTF(("%s: failed\n", __func__));
@@ -1163,7 +1161,7 @@ ucycom_cleanup(struct ucycom_softc *sc)
 
 	obuf = sc->sc_obuf;
 	sc->sc_obuf = NULL;
-	uhidev_close(&sc->sc_hdev);
+	uhidev_close(sc->sc_hdev);
 
 	if (obuf != NULL)
 		kmem_free(obuf, sc->sc_olen);

Index: src/sys/dev/usb/uhid.c
diff -u src/sys/dev/usb/uhid.c:1.122 src/sys/dev/usb/uhid.c:1.123
--- src/sys/dev/usb/uhid.c:1.122	Mon Mar 28 12:43:12 2022
+++ src/sys/dev/usb/uhid.c	Mon Mar 28 12:44:17 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: uhid.c,v 1.122 2022/03/28 12:43:12 riastradh Exp $	*/
+/*	$NetBSD: uhid.c,v 1.123 2022/03/28 12:44:17 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004, 2008, 2012 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.122 2022/03/28 12:43:12 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.123 2022/03/28 12:44:17 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -85,8 +85,10 @@ int	uhiddebug = 0;
 #endif
 
 struct uhid_softc {
-	struct uhidev sc_hdev;
+	device_t sc_dev;
+	struct uhidev *sc_hdev;
 	struct usbd_device *sc_udev;
+	uint8_t sc_report_id;
 
 	kmutex_t sc_lock;
 	kcondvar_t sc_cv;
@@ -144,7 +146,7 @@ const struct cdevsw uhid_cdevsw = {
 	.d_flag = D_OTHER
 };
 
-static void uhid_intr(struct uhidev *, void *, u_int);
+static void uhid_intr(void *, void *, u_int);
 
 static int	uhid_match(device_t, cfdata_t, void *);
 static void	uhid_attach(device_t, device_t, void *);
@@ -176,13 +178,12 @@ uhid_attach(device_t parent, device_t se
 	int size, repid;
 	void *desc;
 
-	sc->sc_hdev.sc_dev = self;
-	selinit(&sc->sc_rsel);
-	sc->sc_hdev.sc_intr = uhid_intr;
-	sc->sc_hdev.sc_parent = uha->parent;
-	sc->sc_hdev.sc_report_id = uha->reportid;
-
+	sc->sc_dev = self;
+	sc->sc_hdev = uha->parent;
 	sc->sc_udev = uha->uiaa->uiaa_device;
+	sc->sc_report_id = uha->reportid;
+
+	selinit(&sc->sc_rsel);
 
 	uhidev_get_report_desc(uha->parent, &desc, &size);
 	repid = uha->reportid;
@@ -232,9 +233,9 @@ uhid_detach(device_t self, int flags)
 }
 
 static void
-uhid_intr(struct uhidev *addr, void *data, u_int len)
+uhid_intr(void *cookie, void *data, u_int len)
 {
-	struct uhid_softc *sc = (struct uhid_softc *)addr;
+	struct uhid_softc *sc = cookie;
 
 #ifdef UHID_DEBUG
 	if (uhiddebug > 5) {
@@ -306,7 +307,7 @@ uhidopen(dev_t dev, int flag, int mode, 
 	mutex_exit(&proc_lock);
 
 	/* Open the uhidev -- after this point we can get interrupts.  */
-	error = uhidev_open(&sc->sc_hdev);
+	error = uhidev_open(sc->sc_hdev, &uhid_intr, sc);
 	if (error)
 		goto fail1;
 
@@ -354,7 +355,7 @@ uhidcancel(dev_t dev, int flag, int mode
 	cv_broadcast(&sc->sc_cv);
 	mutex_exit(&sc->sc_lock);
 
-	uhidev_stop(&sc->sc_hdev);
+	uhidev_stop(sc->sc_hdev);
 
 	return 0;
 }
@@ -379,7 +380,7 @@ uhidclose(dev_t dev, int flag, int mode,
 	mutex_exit(&sc->sc_lock);
 
 	/* Prevent further interrupts.  */
-	uhidev_close(&sc->sc_hdev);
+	uhidev_close(sc->sc_hdev);
 
 	/* Hang up all select/poll.  */
 	selnotify(&sc->sc_rsel, POLLHUP, 0);
@@ -422,10 +423,10 @@ uhidread(dev_t dev, struct uio *uio, int
 	DPRINTFN(1, ("uhidread\n"));
 	if (atomic_load_relaxed(&sc->sc_state) & UHID_IMMED) {
 		DPRINTFN(1, ("uhidread immed\n"));
-		extra = sc->sc_hdev.sc_report_id != 0;
+		extra = sc->sc_report_id != 0;
 		if (sc->sc_isize + extra > sizeof(buffer))
 			return ENOBUFS;
-		err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
+		err = uhidev_get_report(sc->sc_hdev, UHID_INPUT_REPORT,
 					buffer, sc->sc_isize + extra);
 		if (err)
 			return EIO;
@@ -489,7 +490,7 @@ uhidwrite(dev_t dev, struct uio *uio, in
 	if (uhiddebug > 5) {
 		uint32_t i;
 
-		DPRINTF(("%s: outdata[%d] =", device_xname(sc->sc_hdev.sc_dev),
+		DPRINTF(("%s: outdata[%d] =", device_xname(sc->sc_dev),
 		    error));
 		for (i = 0; i < size; i++)
 			DPRINTF((" %02x", sc->sc_obuf[i]));
@@ -498,13 +499,13 @@ uhidwrite(dev_t dev, struct uio *uio, in
 #endif
 	if (!error) {
 		if (sc->sc_raw)
-			err = uhidev_write(&sc->sc_hdev, sc->sc_obuf, size);
+			err = uhidev_write(sc->sc_hdev, sc->sc_obuf, size);
 		else
-			err = uhidev_set_report(&sc->sc_hdev,
+			err = uhidev_set_report(sc->sc_hdev,
 			    UHID_OUTPUT_REPORT, sc->sc_obuf, size);
 		if (err) {
 			DPRINTF(("%s: err = %d\n",
-			    device_xname(sc->sc_hdev.sc_dev), err));
+			    device_xname(sc->sc_dev), err));
 			error = EIO;
 		}
 	}
@@ -581,7 +582,7 @@ uhidioctl(dev_t dev, u_long cmd, void *a
 		break;
 
 	case USB_GET_REPORT_DESC:
-		uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
+		uhidev_get_report_desc(sc->sc_hdev, &desc, &size);
 		rd = (struct usb_ctl_report_desc *)addr;
 		size = uimin(size, sizeof(rd->ucrd_data));
 		rd->ucrd_size = size;
@@ -590,10 +591,10 @@ uhidioctl(dev_t dev, u_long cmd, void *a
 
 	case USB_SET_IMMED:
 		if (*(int *)addr) {
-			extra = sc->sc_hdev.sc_report_id != 0;
+			extra = sc->sc_report_id != 0;
 			if (sc->sc_isize + extra > sizeof(buffer))
 				return ENOBUFS;
-			err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
+			err = uhidev_get_report(sc->sc_hdev, UHID_INPUT_REPORT,
 						buffer, sc->sc_isize + extra);
 			if (err)
 				return EOPNOTSUPP;
@@ -618,10 +619,10 @@ uhidioctl(dev_t dev, u_long cmd, void *a
 		default:
 			return EINVAL;
 		}
-		extra = sc->sc_hdev.sc_report_id != 0;
+		extra = sc->sc_report_id != 0;
 		if (size + extra > sizeof(re->ucr_data))
 			return ENOBUFS;
-		err = uhidev_get_report(&sc->sc_hdev, re->ucr_report,
+		err = uhidev_get_report(sc->sc_hdev, re->ucr_report,
 		    re->ucr_data, size + extra);
 		if (extra)
 			memmove(re->ucr_data, re->ucr_data+1, size);
@@ -646,14 +647,14 @@ uhidioctl(dev_t dev, u_long cmd, void *a
 		}
 		if (size > sizeof(re->ucr_data))
 			return ENOBUFS;
-		err = uhidev_set_report(&sc->sc_hdev, re->ucr_report,
+		err = uhidev_set_report(sc->sc_hdev, re->ucr_report,
 		    re->ucr_data, size);
 		if (err)
 			return EIO;
 		break;
 
 	case USB_GET_REPORT_ID:
-		*(int *)addr = sc->sc_hdev.sc_report_id;
+		*(int *)addr = sc->sc_report_id;
 		break;
 
 	case USB_GET_DEVICE_DESC:

Index: src/sys/dev/usb/uhidev.c
diff -u src/sys/dev/usb/uhidev.c:1.89 src/sys/dev/usb/uhidev.c:1.90
--- src/sys/dev/usb/uhidev.c:1.89	Mon Mar 28 12:44:06 2022
+++ src/sys/dev/usb/uhidev.c	Mon Mar 28 12:44:17 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: uhidev.c,v 1.89 2022/03/28 12:44:06 riastradh Exp $	*/
+/*	$NetBSD: uhidev.c,v 1.90 2022/03/28 12:44:17 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.89 2022/03/28 12:44:06 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.90 2022/03/28 12:44:17 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -88,7 +88,18 @@ struct uhidev_softc {
 	void *sc_repdesc;
 
 	u_int sc_nrepid;
-	device_t *sc_subdevs;
+	struct uhidev {
+		struct uhidev_softc *sc_parent;
+		device_t	sc_dev;
+		void		(*sc_intr)(void *, void *, u_int);
+		void		*sc_cookie;
+		krndsource_t	sc_rndsource;
+		int		sc_in_rep_size;
+		uint8_t		sc_report_id;
+		uint8_t		sc_state;
+#define	UHIDEV_OPEN	0x01	/* device is open */
+#define	UHIDEV_STOPPED	0x02	/* xfers are stopped */
+	} *sc_subdevs;
 
 	kmutex_t sc_lock;
 	kcondvar_t sc_cv;
@@ -169,7 +180,6 @@ uhidev_attach(device_t parent, device_t 
 	usb_endpoint_descriptor_t *ed;
 	struct uhidev_attach_arg uha;
 	device_t dev;
-	struct uhidev *csc;
 	int maxinpktsize, size, nrepid, repid, repsz;
 	int *repsizes;
 	int i;
@@ -405,40 +415,35 @@ uhidev_attach(device_t parent, device_t 
 
 	DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize));
 
-	uha.parent = sc;
 	for (repid = 0; repid < nrepid; repid++) {
+		struct uhidev *scd = &sc->sc_subdevs[repid];
+
+		scd->sc_parent = sc;
+		scd->sc_report_id = repid;
+		scd->sc_in_rep_size = repsizes[repid];
+
 		DPRINTF(("uhidev_match: try repid=%d\n", repid));
 		if (hid_report_size(desc, size, hid_input, repid) == 0 &&
 		    hid_report_size(desc, size, hid_output, repid) == 0 &&
 		    hid_report_size(desc, size, hid_feature, repid) == 0) {
 			;	/* already NULL in sc->sc_subdevs[repid] */
 		} else {
+			uha.parent = scd;
 			uha.reportid = repid;
 			locs[UHIDBUSCF_REPORTID] = repid;
 
 			dev = config_found(self, &uha, uhidevprint,
 			    CFARGS(.submatch = config_stdsubmatch,
 				   .locators = locs));
-			sc->sc_subdevs[repid] = dev;
-			if (dev != NULL) {
-				csc = device_private(dev);
-				csc->sc_in_rep_size = repsizes[repid];
-#ifdef DIAGNOSTIC
-				DPRINTF(("uhidev_match: repid=%d dev=%p\n",
-					 repid, dev));
-				if (csc->sc_intr == NULL) {
-					kmem_free(repsizes,
-					    nrepid * sizeof(*repsizes));
-					aprint_error_dev(self,
-					    "sc_intr == NULL\n");
-					return;
-				}
-#endif
-				rnd_attach_source(&csc->rnd_source,
-						  device_xname(dev),
-						  RND_TYPE_TTY,
-						  RND_FLAG_DEFAULT);
-			}
+			sc->sc_subdevs[repid].sc_dev = dev;
+			if (dev == NULL)
+				continue;
+			/*
+			 * XXXSMP -- could be detached in the middle of
+			 * sleeping for allocation in rnd_attach_source
+			 */
+			rnd_attach_source(&scd->sc_rndsource,
+			    device_xname(dev), RND_TYPE_TTY, RND_FLAG_DEFAULT);
 		}
 	}
 	kmem_free(repsizes, nrepid * sizeof(*repsizes));
@@ -495,19 +500,26 @@ uhidev_childdet(device_t self, device_t 
 	struct uhidev_softc *sc = device_private(self);
 
 	for (i = 0; i < sc->sc_nrepid; i++) {
-		if (sc->sc_subdevs[i] == child)
+		if (sc->sc_subdevs[i].sc_dev == child)
 			break;
 	}
 	KASSERT(i < sc->sc_nrepid);
-	sc->sc_subdevs[i] = NULL;
+	sc->sc_subdevs[i].sc_dev = NULL;
+	/*
+	 * XXXSMP -- could be reattached in the middle of sleeping for
+	 * lock on sources to delete this in rnd_attach_source
+	 *
+	 * (Actually this can't happen right now because there's no
+	 * rescan method, but if there were, it could.)
+	 */
+	rnd_detach_source(&sc->sc_subdevs[i].sc_rndsource);
 }
 
 static int
 uhidev_detach(device_t self, int flags)
 {
 	struct uhidev_softc *sc = device_private(self);
-	int i, rv;
-	struct uhidev *csc;
+	int rv;
 
 	DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags));
 
@@ -524,28 +536,12 @@ uhidev_detach(device_t self, int flags)
 	 * DETACH_FORCE and the children will not have the option of
 	 * refusing detachment.
 	 */
-	for (i = 0; i < sc->sc_nrepid; i++) {
-		if (sc->sc_subdevs[i] == NULL)
-			continue;
-		/*
-		 * XXX rnd_detach_source should go in uhidev_childdet,
-		 * but the struct krndsource lives in the child's
-		 * softc, which is gone by the time of childdet.  The
-		 * parent uhidev_softc should be changed to allocate
-		 * the struct krndsource, not the child.
-		 */
-		csc = device_private(sc->sc_subdevs[i]);
-		rnd_detach_source(&csc->rnd_source);
-		rv = config_detach(sc->sc_subdevs[i], flags);
-		if (rv) {
-			rnd_attach_source(&csc->rnd_source,
-			    device_xname(sc->sc_dev),
-			    RND_TYPE_TTY, RND_FLAG_DEFAULT);
-			mutex_enter(&sc->sc_lock);
-			sc->sc_dying = 0;
-			mutex_exit(&sc->sc_lock);
-			return rv;
-		}
+	rv = config_detach_children(self, flags);
+	if (rv) {
+		mutex_enter(&sc->sc_lock);
+		sc->sc_dying = 0;
+		mutex_exit(&sc->sc_lock);
+		return rv;
 	}
 
 	KASSERTMSG(sc->sc_refcnt == 0,
@@ -579,7 +575,6 @@ static void
 uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status)
 {
 	struct uhidev_softc *sc = addr;
-	device_t cdev;
 	struct uhidev *scd;
 	u_char *p;
 	u_int rep;
@@ -618,12 +613,9 @@ uhidev_intr(struct usbd_xfer *xfer, void
 		printf("uhidev_intr: bad repid %d\n", rep);
 		return;
 	}
-	cdev = sc->sc_subdevs[rep];
-	if (!cdev)
-		return;
-	scd = device_private(cdev);
+	scd = &sc->sc_subdevs[rep];
 	DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=%#x\n",
-		    rep, scd, scd ? scd->sc_state : 0));
+		    rep, scd, scd->sc_state));
 	if (!(atomic_load_acquire(&scd->sc_state) & UHIDEV_OPEN))
 		return;
 #ifdef UHIDEV_DEBUG
@@ -637,13 +629,15 @@ uhidev_intr(struct usbd_xfer *xfer, void
 			device_xname(sc->sc_dev)));
 		return;
 	}
-	rnd_add_uint32(&scd->rnd_source, (uintptr_t)(sc->sc_ibuf));
-	scd->sc_intr(scd, p, cc);
+	rnd_add_uint32(&scd->sc_rndsource, (uintptr_t)(sc->sc_ibuf));
+	scd->sc_intr(scd->sc_cookie, p, cc);
 }
 
 void
-uhidev_get_report_desc(struct uhidev_softc *sc, void **desc, int *size)
+uhidev_get_report_desc(struct uhidev *scd, void **desc, int *size)
 {
+	struct uhidev_softc *sc = scd->sc_parent;
+
 	*desc = sc->sc_repdesc;
 	*size = sc->sc_repdesc_size;
 }
@@ -904,7 +898,8 @@ uhidev_close_pipes(struct uhidev_softc *
 }
 
 int
-uhidev_open(struct uhidev *scd)
+uhidev_open(struct uhidev *scd, void (*intr)(void *, void *, u_int),
+    void *cookie)
 {
 	struct uhidev_softc *sc = scd->sc_parent;
 	int error;
@@ -923,6 +918,8 @@ uhidev_open(struct uhidev *scd)
 		error = EBUSY;
 		goto out;
 	}
+	scd->sc_intr = intr;
+	scd->sc_cookie = cookie;
 	atomic_store_release(&scd->sc_state, scd->sc_state | UHIDEV_OPEN);
 
 	/* Open the pipes which are shared by all report ids.  */
@@ -1067,9 +1064,19 @@ uhidev_close(struct uhidev *scd)
 	 * We must drop the lock while doing this, because
 	 * uhidev_write_callback takes the lock in softint context and
 	 * it could deadlock with the xcall softint.
+	 *
+	 * It is safe to drop the lock now before zeroing sc_intr and
+	 * sc_cookie because the driver is obligated not to reopen
+	 * until after uhidev_close returns.
 	 */
 	mutex_exit(&sc->sc_lock);
 	xc_barrier(XC_HIGHPRI);
+	mutex_enter(&sc->sc_lock);
+	KASSERT((scd->sc_state & UHIDEV_OPEN) == 0);
+	scd->sc_intr = NULL;
+	scd->sc_cookie = NULL;
+
+	mutex_exit(&sc->sc_lock);
 }
 
 usbd_status

Index: src/sys/dev/usb/uhidev.h
diff -u src/sys/dev/usb/uhidev.h:1.25 src/sys/dev/usb/uhidev.h:1.26
--- src/sys/dev/usb/uhidev.h:1.25	Mon Mar 28 12:43:39 2022
+++ src/sys/dev/usb/uhidev.h	Mon Mar 28 12:44:17 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: uhidev.h,v 1.25 2022/03/28 12:43:39 riastradh Exp $	*/
+/*	$NetBSD: uhidev.h,v 1.26 2022/03/28 12:44:17 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -33,34 +33,18 @@
 #ifndef	_DEV_USB_UHIDEV_H_
 #define	_DEV_USB_UHIDEV_H_
 
-#include <sys/device.h>
-#include <sys/rndsource.h>
-
 #include <dev/usb/usbdi.h>
 
-struct uhidev_softc;
-
-struct uhidev {
-	device_t sc_dev;		/* base device */
-	struct uhidev_softc *sc_parent;
-	uByte sc_report_id;
-	uint8_t sc_state;	/* read/written under sc_parent->sc_lock */
-#define	UHIDEV_OPEN	0x01	/* device is open */
-#define	UHIDEV_STOPPED	0x02	/* xfers are stopped */
-	int sc_in_rep_size;
-	void (*sc_intr)(struct uhidev *, void *, u_int);
-	krndsource_t     rnd_source;
-};
+struct uhidev;
 
 struct uhidev_attach_arg {
 	struct usbif_attach_arg *uiaa;
-	struct uhidev_softc *parent;
+	struct uhidev *parent;
 	int reportid;
-	int reportsize;
 };
 
-void uhidev_get_report_desc(struct uhidev_softc *, void **, int *);
-int uhidev_open(struct uhidev *);
+void uhidev_get_report_desc(struct uhidev *, void **, int *);
+int uhidev_open(struct uhidev *, void (*)(void *, void *, unsigned), void *);
 void uhidev_stop(struct uhidev *);
 void uhidev_close(struct uhidev *);
 usbd_status uhidev_set_report(struct uhidev *, int, void *, int);

Index: src/sys/dev/usb/ukbd.c
diff -u src/sys/dev/usb/ukbd.c:1.158 src/sys/dev/usb/ukbd.c:1.159
--- src/sys/dev/usb/ukbd.c:1.158	Mon Mar 28 12:43:12 2022
+++ src/sys/dev/usb/ukbd.c	Mon Mar 28 12:44:17 2022
@@ -1,4 +1,4 @@
-/*      $NetBSD: ukbd.c,v 1.158 2022/03/28 12:43:12 riastradh Exp $        */
+/*      $NetBSD: ukbd.c,v 1.159 2022/03/28 12:44:17 riastradh Exp $        */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.158 2022/03/28 12:43:12 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.159 2022/03/28 12:44:17 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -235,9 +235,11 @@ Static const uint8_t ukbd_trtab[256] = {
 #define KEY_ERROR 0x01
 
 struct ukbd_softc {
-	struct uhidev sc_hdev;
+	device_t sc_dev;
+	struct uhidev *sc_hdev;
 	struct usbd_device *sc_udev;
 	struct usbd_interface *sc_iface;
+	int sc_report_id;
 
 	struct ukbd_data sc_ndata;
 	struct ukbd_data sc_odata;
@@ -340,7 +342,7 @@ const struct wskbd_consops ukbd_consops 
 
 Static const char *ukbd_parse_desc(struct ukbd_softc *);
 
-Static void	ukbd_intr(struct uhidev *, void *, u_int);
+Static void	ukbd_intr(void *, void *, u_int);
 Static void	ukbd_decode(struct ukbd_softc *, struct ukbd_data *);
 Static void	ukbd_delayed_decode(void *);
 
@@ -408,12 +410,11 @@ ukbd_attach(device_t parent, device_t se
 	const char *parseerr;
 	struct wskbddev_attach_args a;
 
-	sc->sc_hdev.sc_dev = self;
-	sc->sc_hdev.sc_intr = ukbd_intr;
-	sc->sc_hdev.sc_parent = uha->parent;
-	sc->sc_hdev.sc_report_id = uha->reportid;
+	sc->sc_dev = self;
+	sc->sc_hdev = uha->parent;
 	sc->sc_udev = uha->uiaa->uiaa_device;
 	sc->sc_iface = uha->uiaa->uiaa_iface;
+	sc->sc_report_id = uha->reportid;
 	sc->sc_flags = 0;
 
 	aprint_naive("\n");
@@ -514,7 +515,7 @@ ukbd_enable(void *v, int on)
 	/* Should only be called to change state */
 	if ((sc->sc_flags & FLAG_ENABLED) != 0 && on != 0) {
 #ifdef DIAGNOSTIC
-		aprint_error_dev(sc->sc_hdev.sc_dev, "bad call on=%d\n", on);
+		aprint_error_dev(sc->sc_dev, "bad call on=%d\n", on);
 #endif
 		return EBUSY;
 	}
@@ -522,10 +523,10 @@ ukbd_enable(void *v, int on)
 	DPRINTF(("%s: sc=%p on=%d\n", __func__, sc, on));
 	if (on) {
 		sc->sc_flags |= FLAG_ENABLED;
-		return uhidev_open(&sc->sc_hdev);
+		return uhidev_open(sc->sc_hdev, &ukbd_intr, sc);
 	} else {
 		sc->sc_flags &= ~FLAG_ENABLED;
-		uhidev_close(&sc->sc_hdev);
+		uhidev_close(sc->sc_hdev);
 		return 0;
 	}
 }
@@ -573,7 +574,7 @@ ukbd_detach(device_t self, int flags)
 		 * XXX console, if there are any other keyboards.
 		 */
 		printf("%s: was console keyboard\n",
-		       device_xname(sc->sc_hdev.sc_dev));
+		       device_xname(sc->sc_dev));
 		wskbd_cndetach();
 		ukbd_is_console = 1;
 	}
@@ -587,8 +588,8 @@ ukbd_detach(device_t self, int flags)
 	    USB_TASKQ_DRIVER, NULL);
 
 	/* The console keyboard does not get a disable call, so check pipe. */
-	if (sc->sc_hdev.sc_state & UHIDEV_OPEN)
-		uhidev_close(&sc->sc_hdev);
+	if (sc->sc_flags & FLAG_ENABLED)
+		uhidev_close(sc->sc_hdev);
 
 	return rv;
 }
@@ -608,8 +609,7 @@ ukbd_translate_keycodes(struct ukbd_soft
 			for (tp = tab; tp->from; tp++)
 				if (tp->from == i) {
 					if (tp->to & IS_PMF) {
-						pmf_event_inject(
-						    sc->sc_hdev.sc_dev,
+						pmf_event_inject(sc->sc_dev,
 						    tp->to & 0xff);
 					} else
 						setbit(ud->keys, tp->to);
@@ -641,9 +641,9 @@ ukbd_translate_modifier(struct ukbd_soft
 }
 
 void
-ukbd_intr(struct uhidev *addr, void *ibuf, u_int len)
+ukbd_intr(void *cookie, void *ibuf, u_int len)
 {
-	struct ukbd_softc *sc = (struct ukbd_softc *)addr;
+	struct ukbd_softc *sc = cookie;
 	struct ukbd_data *ud = &sc->sc_ndata;
 	int i;
 
@@ -768,7 +768,7 @@ ukbd_decode(struct ukbd_softc *sc, struc
 	 */
 	if (ukbdtrace) {
 		struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex];
-		p->unit = device_unit(sc->sc_hdev.sc_dev);
+		p->unit = device_unit(sc->sc_dev);
 		microtime(&p->tv);
 		p->ud = *ud;
 		if (++ukbdtraceindex >= UKBDTRACESIZE)
@@ -923,7 +923,7 @@ ukbd_set_leds_task(void *v)
 	if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1)
 		res |= 1 << sc->sc_capsloc.pos;
 
-	uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1);
+	uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1);
 }
 
 #if defined(WSDISPLAY_COMPAT_RAWKBD) && defined(UKBD_REPEAT)
@@ -1059,7 +1059,7 @@ ukbd_parse_desc(struct ukbd_softc *sc)
 	void *desc;
 	int ikey;
 
-	uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
+	uhidev_get_report_desc(sc->sc_hdev, &desc, &size);
 	ikey = 0;
 	sc->sc_nkeycode = 0;
 	d = hid_start_parse(desc, size, hid_input);
@@ -1077,7 +1077,7 @@ ukbd_parse_desc(struct ukbd_softc *sc)
 
 		if (h.kind != hid_input || (h.flags & HIO_CONST) ||
 		    HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
-		    h.report_ID != sc->sc_hdev.sc_report_id)
+		    h.report_ID != sc->sc_report_id)
 			continue;
 		DPRINTF(("%s: ikey=%d usage=%#x flags=%#x pos=%d size=%d "
 		    "cnt=%d\n", __func__, ikey, h.usage, h.flags, h.loc.pos,
@@ -1120,13 +1120,13 @@ ukbd_parse_desc(struct ukbd_softc *sc)
 	hid_end_parse(d);
 
 	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
-		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_numloc, NULL);
+	    sc->sc_report_id, hid_output, &sc->sc_numloc, NULL);
 	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
-		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_capsloc, NULL);
+	    sc->sc_report_id, hid_output, &sc->sc_capsloc, NULL);
 	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
-		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_scroloc, NULL);
+	    sc->sc_report_id, hid_output, &sc->sc_scroloc, NULL);
 	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_COMPOSE),
-		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_compose, NULL);
+	    sc->sc_report_id, hid_output, &sc->sc_compose, NULL);
 
 	return NULL;
 }

Index: src/sys/dev/usb/ums.c
diff -u src/sys/dev/usb/ums.c:1.102 src/sys/dev/usb/ums.c:1.103
--- src/sys/dev/usb/ums.c:1.102	Mon Mar 28 12:43:12 2022
+++ src/sys/dev/usb/ums.c	Mon Mar 28 12:44:17 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ums.c,v 1.102 2022/03/28 12:43:12 riastradh Exp $	*/
+/*	$NetBSD: ums.c,v 1.103 2022/03/28 12:44:17 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1998, 2017 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ums.c,v 1.102 2022/03/28 12:43:12 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ums.c,v 1.103 2022/03/28 12:44:17 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -75,7 +75,7 @@ int	umsdebug = 0;
 #define UMSUNIT(s)	(minor(s))
 
 struct ums_softc {
-	struct uhidev sc_hdev;
+	struct uhidev *sc_hdev;
 	struct usbd_device *sc_udev;
 	struct hidms sc_ms;
 
@@ -85,7 +85,7 @@ struct ums_softc {
 	char	sc_dying;
 };
 
-Static void ums_intr(struct uhidev *, void *, u_int);
+Static void ums_intr(void *, void *, u_int);
 
 Static int	ums_enable(void *);
 Static void	ums_disable(void *);
@@ -146,10 +146,7 @@ ums_attach(device_t parent, device_t sel
 
 	aprint_naive("\n");
 
-	sc->sc_hdev.sc_dev = self;
-	sc->sc_hdev.sc_intr = ums_intr;
-	sc->sc_hdev.sc_parent = uha->parent;
-	sc->sc_hdev.sc_report_id = uha->reportid;
+	sc->sc_hdev = uha->parent;
 	sc->sc_udev = uha->uiaa->uiaa_device;
 
 	quirks = usbd_get_quirks(sc->sc_udev)->uq_flags;
@@ -218,7 +215,7 @@ ums_attach(device_t parent, device_t sel
 			while (hid_get_item(d, &item)) {
 				if (item.kind != hid_input
 				    || HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP
-				    || item.report_ID != sc->sc_hdev.sc_report_id)
+				    || item.report_ID != uha->reportid)
 					continue;
 				if (HID_GET_USAGE(item.usage) == HUG_X) {
 					sc->sc_ms.sc_calibcoords.minx = item.logical_minimum;
@@ -238,7 +235,7 @@ ums_attach(device_t parent, device_t sel
 	hidms_attach(self, &sc->sc_ms, &ums_accessops);
 
 	if (sc->sc_alwayson) {
-		error = uhidev_open(&sc->sc_hdev);
+		error = uhidev_open(sc->sc_hdev, &ums_intr, sc);
 		if (error != 0) {
 			aprint_error_dev(self,
 			    "WARNING: couldn't open always-on device\n");
@@ -279,7 +276,7 @@ ums_detach(device_t self, int flags)
 	DPRINTF(("ums_detach: sc=%p flags=%d\n", sc, flags));
 
 	if (sc->sc_alwayson)
-		uhidev_close(&sc->sc_hdev);
+		uhidev_close(sc->sc_hdev);
 
 	/* No need to do reference counting of ums, wsmouse has all the goo. */
 	if (sc->sc_ms.hidms_wsmousedev != NULL)
@@ -291,9 +288,9 @@ ums_detach(device_t self, int flags)
 }
 
 Static void
-ums_intr(struct uhidev *addr, void *ibuf, u_int len)
+ums_intr(void *cookie, void *ibuf, u_int len)
 {
-	struct ums_softc *sc = (struct ums_softc *)addr;
+	struct ums_softc *sc = cookie;
 
 	if (sc->sc_enabled)
 		hidms_intr(&sc->sc_ms, ibuf, len);
@@ -317,7 +314,7 @@ ums_enable(void *v)
 	sc->sc_ms.hidms_buttons = 0;
 
 	if (!sc->sc_alwayson) {
-		error = uhidev_open(&sc->sc_hdev);
+		error = uhidev_open(sc->sc_hdev, &ums_intr, sc);
 		if (error)
 			sc->sc_enabled = 0;
 	}
@@ -341,7 +338,7 @@ ums_disable(void *v)
 	if (sc->sc_enabled) {
 		sc->sc_enabled = 0;
 		if (!sc->sc_alwayson)
-			uhidev_close(&sc->sc_hdev);
+			uhidev_close(sc->sc_hdev);
 	}
 }
 

Index: src/sys/dev/usb/uthum.c
diff -u src/sys/dev/usb/uthum.c:1.22 src/sys/dev/usb/uthum.c:1.23
--- src/sys/dev/usb/uthum.c:1.22	Mon Mar 28 12:43:12 2022
+++ src/sys/dev/usb/uthum.c	Mon Mar 28 12:44:17 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: uthum.c,v 1.22 2022/03/28 12:43:12 riastradh Exp $   */
+/*	$NetBSD: uthum.c,v 1.23 2022/03/28 12:44:17 riastradh Exp $   */
 /*	$OpenBSD: uthum.c,v 1.6 2010/01/03 18:43:02 deraadt Exp $   */
 
 /*
@@ -22,7 +22,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uthum.c,v 1.22 2022/03/28 12:43:12 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uthum.c,v 1.23 2022/03/28 12:44:17 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -74,7 +74,8 @@ static const uint8_t cmd_end[8] =
 #define UTHUM_TYPE_TEMPER	2
 
 struct uthum_softc {
-	struct uhidev		 sc_hdev;
+	device_t		 sc_dev;
+	struct uhidev *		 sc_hdev;
 	struct usbd_device *	 sc_udev;
 	u_char			 sc_dying;
 	uint16_t		 sc_flag;
@@ -109,7 +110,6 @@ static int uthum_temper_temp(uint8_t, ui
 static int uthum_sht1x_temp(uint8_t, uint8_t);
 static int uthum_sht1x_rh(unsigned int, int);
 
-static void uthum_intr(struct uhidev *, void *, u_int);
 static void uthum_refresh(struct sysmon_envsys *, envsys_data_t *);
 
 
@@ -134,11 +134,9 @@ uthum_attach(device_t parent, device_t s
 	int size, repid;
 	void *desc;
 
+	sc->sc_dev = self;
+	sc->sc_hdev = uha->parent;
 	sc->sc_udev = dev;
-	sc->sc_hdev.sc_dev = self;
-	sc->sc_hdev.sc_intr = uthum_intr;
-	sc->sc_hdev.sc_parent = uha->parent;
-	sc->sc_hdev.sc_report_id = uha->reportid;
 	sc->sc_num_sensors = 0;
 
 	aprint_normal("\n");
@@ -149,8 +147,7 @@ uthum_attach(device_t parent, device_t s
 	sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
 	sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);
 
-	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
-	    sc->sc_hdev.sc_dev);
+	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
 
 	if (sc->sc_flen < 32) {
 		/* not sensor interface, just attach */
@@ -230,8 +227,7 @@ uthum_detach(device_t self, int flags)
 	if (sc->sc_sme != NULL)
 		sysmon_envsys_unregister(sc->sc_sme);
 
-	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
-	    sc->sc_hdev.sc_dev);
+	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
 
 	return rv;
 }
@@ -249,12 +245,6 @@ uthum_activate(device_t self, enum devac
 	return 0;
 }
 
-static void
-uthum_intr(struct uhidev *addr, void *ibuf, u_int len)
-{
-	/* do nothing */
-}
-
 static int
 uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf,
 	size_t len, int need_delay)
@@ -272,24 +262,24 @@ uthum_read_data(struct uthum_softc *sc, 
 	/* issue query */
 	memset(cmdbuf, 0, sizeof(cmdbuf));
 	memcpy(cmdbuf, cmd_start, sizeof(cmd_start));
-	if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT,
+	if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
 	    cmdbuf, olen))
 		return EIO;
 
 	memset(cmdbuf, 0, sizeof(cmdbuf));
 	cmdbuf[0] = target_cmd;
-	if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT,
+	if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
 	    cmdbuf, olen))
 		return EIO;
 
 	memset(cmdbuf, 0, sizeof(cmdbuf));
 	for (i = 0; i < 7; i++) {
-		if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT,
+		if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
 		    cmdbuf, olen))
 			return EIO;
 	}
 	memcpy(cmdbuf, cmd_end, sizeof(cmd_end));
-	if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT,
+	if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
 	    cmdbuf, olen))
 		return EIO;
 
@@ -299,7 +289,7 @@ uthum_read_data(struct uthum_softc *sc, 
 
 	/* get answer */
 	flen = uimin(sc->sc_flen, sizeof(report));
-	if (uhidev_get_report(&sc->sc_hdev, UHID_FEATURE_REPORT,
+	if (uhidev_get_report(sc->sc_hdev, UHID_FEATURE_REPORT,
 	    report, flen))
 		return EIO;
 	memcpy(buf, report, len);

Index: src/sys/dev/usb/uts.c
diff -u src/sys/dev/usb/uts.c:1.14 src/sys/dev/usb/uts.c:1.15
--- src/sys/dev/usb/uts.c:1.14	Sat Aug  7 16:19:17 2021
+++ src/sys/dev/usb/uts.c	Mon Mar 28 12:44:17 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: uts.c,v 1.14 2021/08/07 16:19:17 thorpej Exp $	*/
+/*	$NetBSD: uts.c,v 1.15 2022/03/28 12:44:17 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uts.c,v 1.14 2021/08/07 16:19:17 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uts.c,v 1.15 2022/03/28 12:44:17 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -72,7 +72,8 @@ int	utsdebug = 0;
 
 
 struct uts_softc {
-	struct uhidev sc_hdev;
+	device_t sc_dev;
+	struct uhidev *sc_hdev;
 
 	struct hid_location sc_loc_x, sc_loc_y, sc_loc_z;
 	struct hid_location sc_loc_btn;
@@ -92,7 +93,7 @@ struct uts_softc {
 
 #define TSCREEN_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
 
-Static void	uts_intr(struct uhidev *, void *, u_int);
+Static void	uts_intr(void *, void *, u_int);
 
 Static int	uts_enable(void *);
 Static void	uts_disable(void *);
@@ -146,10 +147,8 @@ uts_attach(device_t parent, device_t sel
 
 	aprint_normal("\n");
 
-	sc->sc_hdev.sc_dev = self;
-	sc->sc_hdev.sc_intr = uts_intr;
-	sc->sc_hdev.sc_parent = uha->parent;
-	sc->sc_hdev.sc_report_id = uha->reportid;
+	sc->sc_dev = self;
+	sc->sc_hdev = uha->parent;
 
 	uhidev_get_report_desc(uha->parent, &desc, &size);
 
@@ -159,7 +158,7 @@ uts_attach(device_t parent, device_t sel
 	/* requires HID usage Generic_Desktop:X */
 	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
 		uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
-		aprint_error_dev(sc->sc_hdev.sc_dev,
+		aprint_error_dev(sc->sc_dev,
 		    "touchscreen has no X report\n");
 		return;
 	}
@@ -170,7 +169,7 @@ uts_attach(device_t parent, device_t sel
 	case HIO_RELATIVE:
 		break;
 	default:
-		aprint_error_dev(sc->sc_hdev.sc_dev,
+		aprint_error_dev(sc->sc_dev,
 		    "X report 0x%04x not supported\n", flags);
 		return;
 	}
@@ -178,7 +177,7 @@ uts_attach(device_t parent, device_t sel
 	/* requires HID usage Generic_Desktop:Y */
 	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
 		uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
-		aprint_error_dev(sc->sc_hdev.sc_dev,
+		aprint_error_dev(sc->sc_dev,
 		    "touchscreen has no Y report\n");
 		return;
 	}
@@ -189,15 +188,15 @@ uts_attach(device_t parent, device_t sel
 	case HIO_RELATIVE:
 		break;
 	default:
-		aprint_error_dev(sc->sc_hdev.sc_dev,
+		aprint_error_dev(sc->sc_dev,
 		    "Y report 0x%04x not supported\n", flags);
 		return;
 	}
 
 	/* requires HID usage Digitizer:Tip_Switch */
 	if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH),
-	    uha->reportid, hid_input, &sc->sc_loc_btn, 0)) {
-		aprint_error_dev(sc->sc_hdev.sc_dev,
+		uha->reportid, hid_input, &sc->sc_loc_btn, 0)) {
+		aprint_error_dev(sc->sc_dev,
 		    "touchscreen has no tip switch report\n");
 		return;
 	}
@@ -211,10 +210,10 @@ uts_attach(device_t parent, device_t sel
 			 * ELAN touchscreens error out here but still return
 			 * valid data
 			 */
-			aprint_debug_dev(sc->sc_hdev.sc_dev,
+			aprint_debug_dev(sc->sc_dev,
 			    "ELAN touchscreen found, working around bug.\n");
 		} else {
-			aprint_error_dev(sc->sc_hdev.sc_dev,
+			aprint_error_dev(sc->sc_dev,
 			    "touchscreen has no range report\n");
 			return;
 		}
@@ -247,7 +246,7 @@ uts_attach(device_t parent, device_t sel
 		while (hid_get_item(d, &item)) {
 			if (item.kind != hid_input
 			    || HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP
-			    || item.report_ID != sc->sc_hdev.sc_report_id)
+			    || item.report_ID != uha->reportid)
 				continue;
 			if (HID_GET_USAGE(item.usage) == HUG_X) {
 				sc->sc_calibcoords.minx = item.logical_minimum;
@@ -322,7 +321,7 @@ uts_enable(void *v)
 	sc->sc_enabled = 1;
 	sc->sc_buttons = 0;
 
-	return uhidev_open(&sc->sc_hdev);
+	return uhidev_open(sc->sc_hdev, &uts_intr, sc);
 }
 
 Static void
@@ -339,7 +338,7 @@ uts_disable(void *v)
 #endif
 
 	sc->sc_enabled = 0;
-	uhidev_close(&sc->sc_hdev);
+	uhidev_close(sc->sc_hdev);
 }
 
 Static int
@@ -363,9 +362,9 @@ uts_ioctl(void *v, u_long cmd, void *dat
 }
 
 Static void
-uts_intr(struct uhidev *addr, void *ibuf, u_int len)
+uts_intr(void *cookie, void *ibuf, u_int len)
 {
-	struct uts_softc *sc = (struct uts_softc *)addr;
+	struct uts_softc *sc = cookie;
 	int dx, dy, dz;
 	uint32_t buttons = 0;
 	int flags, s;

Reply via email to