On Wed, 17 Mar 2021 at 07:41:53 +0100, Anton Lindqvist wrote:
> I'm wondering if the umt device is detached more than once since it
> claims multiple report ids. I ran into the same problem while developing
> uhidpp:
>
> https://github.com/openbsd/src/blob/master/sys/dev/usb/uhidpp.c#L437-L443
>
> Also, the output of `show registers` in ddb would be helpful.
>
Something like this is probably needed (maybe also for
uhidev_activate):
diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
index d777cfb6e45..86231615432 100644
--- sys/dev/usb/uhidev.c
+++ sys/dev/usb/uhidev.c
@@ -403,7 +403,7 @@ int
uhidev_detach(struct device *self, int flags)
{
struct uhidev_softc *sc = (struct uhidev_softc *)self;
- int i, rv = 0;
+ int i, j, rv = 0;
DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags));
@@ -420,19 +420,19 @@ uhidev_detach(struct device *self, int flags)
if (sc->sc_repdesc != NULL)
free(sc->sc_repdesc, M_USBDEV, sc->sc_repdesc_size);
- /*
- * XXX Check if we have only one children claiming all the Report
- * IDs, this is a hack since we need a dev -> Report ID mapping
- * for uhidev_intr().
- */
- if (sc->sc_nrepid > 1 && sc->sc_subdevs[0] != NULL &&
- sc->sc_subdevs[0] == sc->sc_subdevs[1])
- return (config_detach(&sc->sc_subdevs[0]->sc_dev, flags));
-
for (i = 0; i < sc->sc_nrepid; i++) {
- if (sc->sc_subdevs[i] != NULL) {
- rv |= config_detach(&sc->sc_subdevs[i]->sc_dev, flags);
- sc->sc_subdevs[i] = NULL;
+ if (sc->sc_subdevs[i] == NULL)
+ continue;
+
+ rv |= config_detach(&sc->sc_subdevs[i]->sc_dev, flags);
+
+ /*
+ * Nullify without detaching any other instances of this device
+ * found on other report ids
+ */
+ for (j = 0; j < sc->sc_nrepid; j++) {
+ if (sc->sc_subdevs[i] == sc->sc_subdevs[j])
+ sc->sc_subdevs[j] = NULL;
}
}