Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Handle more UAC2 descriptors and add debug output.



details:   https://anonhg.NetBSD.org/src/rev/04cb149a09ee
branches:  trunk
changeset: 374200:04cb149a09ee
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Mon Apr 10 15:14:50 2023 +0000

description:
Handle more UAC2 descriptors and add debug output.
Fix handling of clock sources (mix.wIndex wasn't set).

UAC2 can use separate clock sources (and thus sample rates) for each terminal.
That doesn't match the audio(4) model where sample rates are part of an audio
format and global. For now, try to match clocks for input and output terminals
separately.

diffstat:

 sys/dev/usb/uaudio.c    |  374 ++++++++++++++++++++++++++++++++++++-----------
 sys/dev/usb/uaudioreg.h |   99 +++++++++++-
 2 files changed, 377 insertions(+), 96 deletions(-)

diffs (truncated from 852 to 300 lines):

diff -r ebcd4cfb80ff -r 04cb149a09ee sys/dev/usb/uaudio.c
--- a/sys/dev/usb/uaudio.c      Mon Apr 10 15:04:49 2023 +0000
+++ b/sys/dev/usb/uaudio.c      Mon Apr 10 15:14:50 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uaudio.c,v 1.177 2023/04/03 16:00:17 mlelstv Exp $     */
+/*     $NetBSD: uaudio.c,v 1.178 2023/04/10 15:14:50 mlelstv Exp $     */
 
 /*
  * Copyright (c) 1999, 2012 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.177 2023/04/03 16:00:17 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.178 2023/04/10 15:14:50 mlelstv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -222,6 +222,7 @@ struct uaudio_softc {
        device_t        sc_audiodev;
        int             sc_nratectls;   /* V2 sample rates */
        int             sc_ratectls[AUFMT_MAX_FREQUENCIES];
+       int             sc_ratemode[AUFMT_MAX_FREQUENCIES];
        struct audio_format *sc_formats;
        int             sc_nformats;
        u_int           sc_channel_config;
@@ -239,8 +240,8 @@ struct terminal_list {
 struct io_terminal {
        union {
                const uaudio_cs_descriptor_t *desc;
-               const struct usb_audio_input_terminal *it;
-               const struct usb_audio_output_terminal *ot;
+               const union usb_audio_input_terminal *it;
+               const union usb_audio_output_terminal *ot;
                const struct usb_audio_mixer_unit *mu;
                const struct usb_audio_selector_unit *su;
                const struct usb_audio_feature_unit *fu;
@@ -287,10 +288,11 @@ Static void       uaudio_mixer_add_ctl(struct 
 Static char    *uaudio_id_name
        (struct uaudio_softc *, const struct io_terminal *, int);
 #ifdef UAUDIO_DEBUG
-Static void    uaudio_dump_cluster(const struct usb_audio_cluster *);
+Static void    uaudio_dump_cluster
+       (struct uaudio_softc *, const union usb_audio_cluster *);
 #endif
-Static struct usb_audio_cluster uaudio_get_cluster
-       (int, const struct io_terminal *);
+Static union usb_audio_cluster uaudio_get_cluster
+       (struct uaudio_softc *, int, const struct io_terminal *);
 Static void    uaudio_add_input
        (struct uaudio_softc *, const struct io_terminal *, int);
 Static void    uaudio_add_output
@@ -323,11 +325,11 @@ Static void       uaudio_add_clksel
 Static struct terminal_list *uaudio_merge_terminal_list
        (const struct io_terminal *);
 Static struct terminal_list *uaudio_io_terminaltype
-       (int, struct io_terminal *, int);
+       (struct uaudio_softc *, int, struct io_terminal *, int);
 Static usbd_status uaudio_identify
        (struct uaudio_softc *, const usb_config_descriptor_t *);
 Static u_int uaudio_get_rates
-       (struct uaudio_softc *, u_int *, u_int);
+       (struct uaudio_softc *, int, u_int *, u_int);
 Static void uaudio_build_formats
        (struct uaudio_softc *);
 
@@ -643,7 +645,6 @@ uaudio_mixer_add_ctl(struct uaudio_softc
                DPRINTF("adding %s\n", mc->ctlname);
        }
        len = sizeof(*mc) * (sc->sc_nctls + 1);
-KASSERT(len > 0);
        nmc = kmem_alloc(len, KM_SLEEP);
        /* Copy old data, if there was any */
        if (sc->sc_nctls != 0) {
@@ -697,8 +698,14 @@ KASSERT(len > 0);
                mc->mul = r->maxval - r->minval;
                res = r->resval;
        } else { /* UAUDIO_VERSION2 */
-               count = (uint16_t)uaudio_get(sc, V2_RANGES, UT_READ_CLASS_INTERFACE,
-                                mc->wValue[0], mc->wIndex, 2);
+               count = (uint16_t)uaudio_get(sc, V2_RANGES,
+                   UT_READ_CLASS_INTERFACE,
+                   mc->wValue[0], mc->wIndex, 2);
+
+               if (count == 0 || count == (uint16_t)-1) {
+                       DPRINTF("invalid range count %zu\n", count);
+                       return;
+               }
 
                if (count > 1) {
                        r = kmem_alloc(sizeof(struct range) * count,
@@ -814,19 +821,47 @@ uaudio_id_name(struct uaudio_softc *sc,
 
 #ifdef UAUDIO_DEBUG
 Static void
-uaudio_dump_cluster(const struct usb_audio_cluster *cl)
+uaudio_dump_cluster(struct uaudio_softc *sc, const union usb_audio_cluster *cl)
 {
-       static const char *channel_names[16] = {
+       static const char *channel_v1_names[16] = {
                "LEFT", "RIGHT", "CENTER", "LFE",
                "LEFT_SURROUND", "RIGHT_SURROUND", "LEFT_CENTER", "RIGHT_CENTER",
                "SURROUND", "LEFT_SIDE", "RIGHT_SIDE", "TOP",
                "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15",
        };
-       int cc, i, first;
-
-       cc = UGETW(cl->wChannelConfig);
-       printf("cluster: bNrChannels=%u wChannelConfig=%#.4x",
-                 cl->bNrChannels, cc);
+       static const char *channel_v2_names[32] = {
+               "LEFT", "RIGHT", "CENTER", "LFE",
+               "BACK_LEFT", "BACK_RIGHT", "FLC", "FRC",
+               "BACK_CENTER", "SIDE_LEFT", "SIDE_RIGHT", "TOP CENTER",
+               "TFL", "TFC", "TFR", "TBL", "TBC", "TBR",
+               "TFLC", "TFRC", "LLFE", "RLFE", "TSL", "TSR",
+               "BC", "BLC", "BRC",
+               "RESERVED27", "RESERVED28", "RESERVED29", "RESERVED30",
+               "RAW_DATA"
+       };
+       const char **channel_names;
+       uint32_t cc;
+       int i, first, icn;
+
+       switch (sc->sc_version) {
+       case UAUDIO_VERSION1:
+               channel_names = channel_v1_names;
+               cc = UGETW(cl->v1.wChannelConfig);
+               icn = cl->v1.iChannelNames;
+               printf("cluster: bNrChannels=%u wChannelConfig=%#.4x",
+                         cl->v1.bNrChannels, cc);
+               break;
+       case UAUDIO_VERSION2:
+               channel_names = channel_v2_names;
+               cc = UGETDW(cl->v2.bmChannelConfig);
+               icn = cl->v2.iChannelNames;
+               printf("cluster: bNrChannels=%u bmChannelConfig=%#.8x",
+                         cl->v2.bNrChannels, cc);
+               break;
+       default:
+               return;
+       }
+
        first = TRUE;
        for (i = 0; cc != 0; i++) {
                if (cc & 1) {
@@ -835,14 +870,14 @@ uaudio_dump_cluster(const struct usb_aud
                }
                cc = cc >> 1;
        }
-       printf("> iChannelNames=%u", cl->iChannelNames);
+       printf("> iChannelNames=%u", icn);
 }
 #endif
 
-Static struct usb_audio_cluster
-uaudio_get_cluster(int id, const struct io_terminal *iot)
+Static union usb_audio_cluster
+uaudio_get_cluster(struct uaudio_softc *sc, int id, const struct io_terminal *iot)
 {
-       struct usb_audio_cluster r;
+       union usb_audio_cluster r;
        const uaudio_cs_descriptor_t *dp;
        int i;
 
@@ -850,17 +885,27 @@ uaudio_get_cluster(int id, const struct 
                dp = iot[id].d.desc;
                if (dp == 0)
                        goto bad;
+
                switch (dp->bDescriptorSubtype) {
                case UDESCSUB_AC_INPUT:
-                       r.bNrChannels = iot[id].d.it->bNrChannels;
-                       USETW(r.wChannelConfig, UGETW(iot[id].d.it->wChannelConfig));
-                       r.iChannelNames = iot[id].d.it->iChannelNames;
+                       switch (sc->sc_version) {
+                       case UAUDIO_VERSION1:
+                               r.v1.bNrChannels = iot[id].d.it->v1.bNrChannels;
+                               USETW(r.v1.wChannelConfig, UGETW(iot[id].d.it->v1.wChannelConfig));
+                               r.v1.iChannelNames = iot[id].d.it->v1.iChannelNames;
+                               break;
+                       case UAUDIO_VERSION2:
+                               r.v2.bNrChannels = iot[id].d.it->v2.bNrChannels;
+                               USETDW(r.v2.bmChannelConfig, UGETW(iot[id].d.it->v2.bmChannelConfig));
+                               r.v2.iChannelNames = iot[id].d.it->v2.iChannelNames;
+                               break;
+                       }
                        return r;
                case UDESCSUB_AC_OUTPUT:
-                       id = iot[id].d.ot->bSourceId;
+                       id = iot[id].d.ot->v1.bSourceId;
                        break;
                case UDESCSUB_AC_MIXER:
-                       r = *(const struct usb_audio_cluster *)
+                       r = *(const union usb_audio_cluster *)
                                &iot[id].d.mu->baSourceId[iot[id].d.mu->bNrInPins];
                        return r;
                case UDESCSUB_AC_SELECTOR:
@@ -871,11 +916,11 @@ uaudio_get_cluster(int id, const struct 
                        id = iot[id].d.fu->bSourceId;
                        break;
                case UDESCSUB_AC_PROCESSING:
-                       r = *(const struct usb_audio_cluster *)
+                       r = *(const union usb_audio_cluster *)
                                &iot[id].d.pu->baSourceId[iot[id].d.pu->bNrInPins];
                        return r;
                case UDESCSUB_AC_EXTENSION:
-                       r = *(const struct usb_audio_cluster *)
+                       r = *(const union usb_audio_cluster *)
                                &iot[id].d.eu->baSourceId[iot[id].d.eu->bNrInPins];
                        return r;
                default:
@@ -892,21 +937,39 @@ uaudio_get_cluster(int id, const struct 
 Static void
 uaudio_add_input(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
 {
-       const struct usb_audio_input_terminal *d;
+       const union usb_audio_input_terminal *d;
 
        d = iot[id].d.it;
+       switch (sc->sc_version) {
+       case UAUDIO_VERSION1:
 #ifdef UAUDIO_DEBUG
-       DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x "
-                   "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
-                   "iChannelNames=%d iTerminal=%d\n",
-                   d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
-                   d->bNrChannels, UGETW(d->wChannelConfig),
-                   d->iChannelNames, d->iTerminal);
+               DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x "
+                           "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
+                           "iChannelNames=%d iTerminal=%d\n",
+                           d->v1.bTerminalId, UGETW(d->v1.wTerminalType), d->v1.bAssocTerminal,
+                           d->v1.bNrChannels, UGETW(d->v1.wChannelConfig),
+                           d->v1.iChannelNames, d->v1.iTerminal);
 #endif
-       /* If USB input terminal, record wChannelConfig */
-       if ((UGETW(d->wTerminalType) & 0xff00) != 0x0100)
-               return;
-       sc->sc_channel_config = UGETW(d->wChannelConfig);
+               /* If USB input terminal, record wChannelConfig */
+               if ((UGETW(d->v1.wTerminalType) & 0xff00) != 0x0100)
+                       return;
+               sc->sc_channel_config = UGETW(d->v1.wChannelConfig);
+               break;
+       case UAUDIO_VERSION2:
+#ifdef UAUDIO_DEBUG
+               DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x "
+                           "bAssocTerminal=%d bNrChannels=%d bmChannelConfig=%x "
+                           "iChannelNames=%d bCSourceId=%d iTerminal=%d\n",
+                           d->v2.bTerminalId, UGETW(d->v2.wTerminalType), d->v2.bAssocTerminal,
+                           d->v2.bNrChannels, UGETDW(d->v2.bmChannelConfig),
+                           d->v2.iChannelNames, d->v2.bCSourceId, d->v2.iTerminal);
+#endif
+               /* If USB input terminal, record wChannelConfig */
+               if ((UGETW(d->v2.wTerminalType) & 0xff00) != 0x0100)
+                       return;
+               sc->sc_channel_config = UGETDW(d->v2.bmChannelConfig);
+               break;
+       }
 }
 
 Static void
@@ -914,13 +977,23 @@ uaudio_add_output(struct uaudio_softc *s
     const struct io_terminal *iot, int id)
 {
 #ifdef UAUDIO_DEBUG
-       const struct usb_audio_output_terminal *d;
+       const union usb_audio_output_terminal *d;
 
        d = iot[id].d.ot;
-       DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x "
-                   "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
-                   d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
-                   d->bSourceId, d->iTerminal);
+       switch (sc->sc_version) {
+       case UAUDIO_VERSION1:
+               DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x "
+                           "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
+                           d->v1.bTerminalId, UGETW(d->v1.wTerminalType), d->v1.bAssocTerminal,
+                           d->v1.bSourceId, d->v1.iTerminal);
+               break;
+       case UAUDIO_VERSION2:
+               DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x "
+                           "bAssocTerminal=%d bSourceId=%d bCSourceId=%d, iTerminal=%d\n",
+                           d->v2.bTerminalId, UGETW(d->v2.wTerminalType), d->v2.bAssocTerminal,
+                           d->v2.bSourceId, d->v2.bCSourceId, d->v2.iTerminal);
+               break;
+       }
 #endif
 }
 
@@ -928,7 +1001,7 @@ Static void
 uaudio_add_mixer(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
 {
        const struct usb_audio_mixer_unit *d;
-       const struct usb_audio_mixer_unit_1 *d1;
+       const union usb_audio_mixer_unit_1 *d1;
        int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k;
        const uByte *bm;



Home | Main Index | Thread Index | Old Index