From ba9ca4db980ab8e6dcf3fc3b889908ded605b595 Mon Sep 17 00:00:00 2001 From: ratchov Date: Tue, 23 Jul 2024 08:59:21 +0000 Subject: [PATCH] uaudio: Fix confusion between interface numbers and interface indexes There is rare hardware for which the interface numbers and indexes are not equal. Such devices couldn't attach because the driver claimed the wrong interface. --- sys/dev/usb/uaudio.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/sys/dev/usb/uaudio.c b/sys/dev/usb/uaudio.c index b213c5e2196..8e8fd3f29bb 100644 --- a/sys/dev/usb/uaudio.c +++ b/sys/dev/usb/uaudio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uaudio.c,v 1.174 2023/12/10 06:32:14 ratchov Exp $ */ +/* $OpenBSD: uaudio.c,v 1.175 2024/07/23 08:59:21 ratchov Exp $ */ /* * Copyright (c) 2018 Alexandre Ratchov * @@ -2702,6 +2702,22 @@ uaudio_fixup_params(struct uaudio_softc *sc) } } +int +uaudio_iface_index(struct uaudio_softc *sc, int ifnum) +{ + int i, nifaces; + + nifaces = sc->udev->cdesc->bNumInterfaces; + + for (i = 0; i < nifaces; i++) { + if (sc->udev->ifaces[i].idesc->bInterfaceNumber == ifnum) + return i; + } + + printf("%s: %d: invalid interface number\n", __func__, ifnum); + return -1; +} + /* * Parse all descriptors and build configuration of the device. */ @@ -2711,6 +2727,7 @@ 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; + int i; while (p->rptr != p->wptr) { if (!uaudio_getdesc(p, &dp)) @@ -2736,7 +2753,8 @@ uaudio_process_conf(struct uaudio_softc *sc, struct uaudio_blob *p) switch (subclass) { case UISUBCLASS_AUDIOCONTROL: - if (usbd_iface_claimed(sc->udev, ifnum)) { + i = uaudio_iface_index(sc, ifnum); + if (i != -1 && usbd_iface_claimed(sc->udev, i)) { DPRINTF("%s: %d: AC already claimed\n", __func__, ifnum); break; } @@ -2748,7 +2766,8 @@ uaudio_process_conf(struct uaudio_softc *sc, struct uaudio_blob *p) return 0; break; case UISUBCLASS_AUDIOSTREAM: - if (usbd_iface_claimed(sc->udev, ifnum)) { + i = uaudio_iface_index(sc, ifnum); + if (i != -1 && usbd_iface_claimed(sc->udev, i)) { DPRINTF("%s: %d: AS already claimed\n", __func__, ifnum); break; } @@ -2768,10 +2787,19 @@ done: * 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); + for (a = sc->alts; a != NULL; a = a->next) { + i = uaudio_iface_index(sc, a->ifnum); + if (i != -1) { + DPRINTF("%s: claim: %d at %d\n", __func__, a->ifnum, i); + usbd_claim_iface(sc->udev, i); + } + } - usbd_claim_iface(sc->udev, sc->ctl_ifnum); + i = uaudio_iface_index(sc, sc->ctl_ifnum); + if (i != -1) { + DPRINTF("%s: claim: ac %d at %d\n", __func__, sc->ctl_ifnum, i); + usbd_claim_iface(sc->udev, i); + } return 1; } -- 2.20.1