Skip interfaces already claimed by other uaudio(4) instances.
authorratchov <ratchov@openbsd.org>
Sun, 10 Dec 2023 06:32:14 +0000 (06:32 +0000)
committerratchov <ratchov@openbsd.org>
Sun, 10 Dec 2023 06:32:14 +0000 (06:32 +0000)
Fixes support of devices that attach multiple uaudio(4) drivers.

Every uaudio(4) instance parses the full set of device descriptors
because there are multiple interfaces per driver instance. If there is
a second uaudio(4) instance (i.e. a second control & stream interfaces
combo), the latter must skip the interfaces already used by the first
one (if it didn't, multiple uaudio(4) would try to use the same
interface and neither would work).

Help from and ok armani@.

sys/dev/usb/uaudio.c

index d8e300a..b213c5e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uaudio.c,v 1.173 2023/06/27 09:28:08 ratchov Exp $    */
+/*     $OpenBSD: uaudio.c,v 1.174 2023/12/10 06:32:14 ratchov Exp $    */
 /*
  * Copyright (c) 2018 Alexandre Ratchov <alex@caoua.org>
  *
@@ -2584,7 +2584,6 @@ uaudio_process_as(struct uaudio_softc *sc,
                }
        }
 
-
        while (p->rptr != p->wptr) {
                savep = p->rptr;
                if (!uaudio_getdesc(p, &dp))
@@ -2710,6 +2709,7 @@ int
 uaudio_process_conf(struct uaudio_softc *sc, struct uaudio_blob *p)
 {
        struct uaudio_blob dp;
+       struct uaudio_alt *a;
        unsigned int type, ifnum, altnum, nep, class, subclass;
 
        while (p->rptr != p->wptr) {
@@ -2736,7 +2736,10 @@ uaudio_process_conf(struct uaudio_softc *sc, struct uaudio_blob *p)
 
                switch (subclass) {
                case UISUBCLASS_AUDIOCONTROL:
-                       usbd_claim_iface(sc->udev, ifnum);
+                       if (usbd_iface_claimed(sc->udev, ifnum)) {
+                               DPRINTF("%s: %d: AC already claimed\n", __func__, ifnum);
+                               break;
+                       }
                        if (sc->unit_list != NULL) {
                                DPRINTF("%s: >1 AC ifaces\n", __func__);
                                goto done;
@@ -2745,7 +2748,10 @@ uaudio_process_conf(struct uaudio_softc *sc, struct uaudio_blob *p)
                                return 0;
                        break;
                case UISUBCLASS_AUDIOSTREAM:
-                       usbd_claim_iface(sc->udev, ifnum);
+                       if (usbd_iface_claimed(sc->udev, ifnum)) {
+                               DPRINTF("%s: %d: AS already claimed\n", __func__, ifnum);
+                               break;
+                       }
                        if (nep == 0) {
                                DPRINTF("%s: "
                                    "stop altnum %d\n", __func__, altnum);
@@ -2758,6 +2764,15 @@ uaudio_process_conf(struct uaudio_softc *sc, struct uaudio_blob *p)
 done:
        uaudio_fixup_params(sc);
 
+       /*
+        * Claim all interfaces we use. This prevents other uaudio(4)
+        * devices from trying to use them.
+        */
+       for (a = sc->alts; a != NULL; a = a->next)
+               usbd_claim_iface(sc->udev, a->ifnum);
+
+       usbd_claim_iface(sc->udev, sc->ctl_ifnum);
+
        return 1;
 }