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; } }