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 packet scheduling for high/super speed.



details:   https://anonhg.NetBSD.org/src/rev/d6f27f7f8638
branches:  trunk
changeset: 374279:d6f27f7f8638
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Sun Apr 16 19:26:20 2023 +0000

description:
Handle packet scheduling for high/super speed.
More UAC2 handling for input/output/feature/selector units.
Setting sample rate for UAC2 now works, still no support for clock selectors
and multipliers.
Added sysctl to set debug level.
Minor fixes.

diffstat:

 sys/dev/usb/uaudio.c    |  905 ++++++++++++++++++++++++++++++++---------------
 sys/dev/usb/uaudioreg.h |   44 ++-
 2 files changed, 647 insertions(+), 302 deletions(-)

diffs (truncated from 1790 to 300 lines):

diff -r db46fc1851d4 -r d6f27f7f8638 sys/dev/usb/uaudio.c
--- a/sys/dev/usb/uaudio.c      Sun Apr 16 18:37:16 2023 +0000
+++ b/sys/dev/usb/uaudio.c      Sun Apr 16 19:26:20 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uaudio.c,v 1.178 2023/04/10 15:14:50 mlelstv Exp $     */
+/*     $NetBSD: uaudio.c,v 1.179 2023/04/16 19:26:20 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.178 2023/04/10 15:14:50 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.179 2023/04/16 19:26:20 mlelstv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -59,6 +59,7 @@
 #include <sys/bus.h>
 #include <sys/cpu.h>
 #include <sys/atomic.h>
+#include <sys/sysctl.h>
 
 #include <sys/audioio.h>
 #include <dev/audio/audio_if.h>
@@ -99,8 +100,12 @@ int uaudiodebug = 0;
 #define DPRINTFN(n,x,y...)
 #endif
 
-#define UAUDIO_NCHANBUFS 6     /* number of outstanding request */
-#define UAUDIO_NFRAMES   10    /* ms of sound in each request */
+/* number of outstanding requests */
+#define UAUDIO_NCHANBUFS       6
+/* number of USB frames per request, also the number of ms */
+#define UAUDIO_NFRAMES         10
+/* number of microframes per requewst (high, super)  */
+#define UAUDIO_NFRAMES_HI      (UAUDIO_NFRAMES * USB_UFRAMES_PER_FRAME)
 
 
 #define MIX_MAX_CHAN 8
@@ -133,7 +138,6 @@ struct mixerctl {
        u_int           nranges;
        u_int           delta;
        u_int           mul;
-       u_int           high;
        uint8_t         class;
        char            ctlname[MAX_AUDIO_DEV_LEN];
        const char      *ctlunit;
@@ -147,6 +151,7 @@ struct as_info {
        uint8_t         attributes; /* Copy of bmAttributes of
                                     * usb_audio_streaming_endpoint_descriptor
                                     */
+       uint8_t         terminal;       /* connected Terminal ID */
        struct usbd_interface * ifaceh;
        const usb_interface_descriptor_t *idesc;
        const usb_endpoint_descriptor_audio_t *edesc;
@@ -177,12 +182,14 @@ struct chan {
        int     altidx;         /* currently used altidx */
 
        int     curchanbuf;
+       u_int   nframes;        /* UAUDIO_NFRAMES or UAUDIO_NFRAMES_HI */
+       u_int   nchanbufs;      /* 1..UAUDIO_NCHANBUFS */
        struct chanbuf {
                struct chan     *chan;
                struct usbd_xfer *xfer;
                u_char          *buffer;
-               uint16_t        sizes[UAUDIO_NFRAMES];
-               uint16_t        offsets[UAUDIO_NFRAMES];
+               uint16_t        sizes[UAUDIO_NFRAMES_HI];
+               uint16_t        offsets[UAUDIO_NFRAMES_HI];
                uint16_t        size;
        } chanbufs[UAUDIO_NCHANBUFS];
 
@@ -223,9 +230,13 @@ struct uaudio_softc {
        int             sc_nratectls;   /* V2 sample rates */
        int             sc_ratectls[AUFMT_MAX_FREQUENCIES];
        int             sc_ratemode[AUFMT_MAX_FREQUENCIES];
+       int             sc_playclock;
+       int             sc_recclock;
        struct audio_format *sc_formats;
        int             sc_nformats;
+       uint8_t         sc_clock[256];  /* map terminals to clocks */
        u_int           sc_channel_config;
+       u_int           sc_usb_frames_per_second;
        char            sc_dying;
        struct audio_device sc_adev;
 };
@@ -244,7 +255,7 @@ struct io_terminal {
                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;
+               const union usb_audio_feature_unit *fu;
                const struct usb_audio_processing_unit *pu;
                const struct usb_audio_extension_unit *eu;
                const struct usb_audio_clksrc_unit *cu;
@@ -254,6 +265,7 @@ struct io_terminal {
        struct terminal_list **inputs; /* list of source input terminals */
        struct terminal_list *output; /* list of destination output terminals */
        int direct;             /* directly connected to an output terminal */
+       uint8_t clock;
 };
 
 #define UAC_OUTPUT     0
@@ -286,7 +298,7 @@ Static const usb_interface_descriptor_t 
 
 Static void    uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *);
 Static char    *uaudio_id_name
-       (struct uaudio_softc *, const struct io_terminal *, int);
+       (struct uaudio_softc *, const struct io_terminal *, uint8_t);
 #ifdef UAUDIO_DEBUG
 Static void    uaudio_dump_cluster
        (struct uaudio_softc *, const union usb_audio_cluster *);
@@ -307,7 +319,7 @@ Static const char *uaudio_get_terminal_n
 Static int     uaudio_determine_class
        (const struct io_terminal *, struct mixerctl *);
 Static const char *uaudio_feature_name
-       (const struct io_terminal *, struct mixerctl *);
+       (const struct io_terminal *, uint8_t, int);
 Static void    uaudio_add_feature
        (struct uaudio_softc *, const struct io_terminal *, int);
 Static void    uaudio_add_processing_updown
@@ -348,6 +360,7 @@ Static void uaudio_set
 Static void    uaudio_ctl_set
        (struct uaudio_softc *, int, struct mixerctl *, int, int);
 
+Static usbd_status uaudio_speed(struct uaudio_softc *, int, int, uint8_t *, int);
 Static usbd_status uaudio_set_speed(struct uaudio_softc *, int, int, u_int);
 
 Static usbd_status uaudio_chan_open(struct uaudio_softc *, struct chan *);
@@ -357,7 +370,7 @@ Static usbd_status uaudio_chan_alloc_buf
        (struct uaudio_softc *, struct chan *);
 Static void    uaudio_chan_free_buffers(struct uaudio_softc *, struct chan *);
 Static void    uaudio_chan_init
-       (struct chan *, int, const struct audio_params *, int);
+       (struct chan *, int, const struct audio_params *, int, bool);
 Static void    uaudio_chan_set_param(struct chan *, u_char *, u_char *, int);
 Static void    uaudio_chan_ptransfer(struct chan *);
 Static void    uaudio_chan_pintr
@@ -414,7 +427,6 @@ static void uaudio_childdet(device_t, de
 static int uaudio_activate(device_t, enum devact);
 
 
-
 CFATTACH_DECL2_NEW(uaudio, sizeof(struct uaudio_softc),
     uaudio_match, uaudio_attach, uaudio_detach, uaudio_activate, NULL,
     uaudio_childdet);
@@ -510,6 +522,25 @@ uaudio_attach(device_t parent, device_t 
        sc->sc_playchan.altidx = -1;
        sc->sc_recchan.altidx = -1;
 
+       switch (sc->sc_udev->ud_speed) {
+       case USB_SPEED_LOW:
+       case USB_SPEED_FULL:
+               sc->sc_usb_frames_per_second = USB_FRAMES_PER_SECOND;
+               sc->sc_playchan.nframes =
+                   sc->sc_recchan.nframes = UAUDIO_NFRAMES;
+               break;
+       default: /* HIGH, SUPER, SUPER_PLUS, more ? */
+               sc->sc_usb_frames_per_second = USB_FRAMES_PER_SECOND * USB_UFRAMES_PER_FRAME;
+               sc->sc_playchan.nframes =
+                   sc->sc_recchan.nframes = UAUDIO_NFRAMES_HI;
+               break;
+       }
+       sc->sc_playchan.nchanbufs =
+           sc->sc_recchan.nchanbufs = UAUDIO_NCHANBUFS;
+
+       DPRINTF("usb fps %u, max channel frames %u, max channel buffers %u\n",
+           sc->sc_usb_frames_per_second, sc->sc_playchan.nframes, sc->sc_playchan.nchanbufs);
+
        if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
                sc->sc_altflags |= UA_NOFRAC;
 
@@ -785,11 +816,8 @@ uaudio_mixer_add_ctl(struct uaudio_softc
 
        if (mc->mul == 0)
                mc->mul = 1;
-       mc->delta = res * 255 / mc->mul;
-       if (mc->delta > 0 && mc->delta < 255)
-               mc->high = 255 / mc->delta * mc->delta;
-       else
-               mc->high = 255;
+
+       mc->delta = (res * 255 + mc->mul - 1) / mc->mul;
 
 #ifdef UAUDIO_DEBUG
        if (uaudiodebug > 2) {
@@ -811,11 +839,12 @@ uaudio_mixer_add_ctl(struct uaudio_softc
 
 Static char *
 uaudio_id_name(struct uaudio_softc *sc,
-    const struct io_terminal *iot, int id)
+    const struct io_terminal *iot, uint8_t id)
 {
        static char tbuf[32];
 
-       snprintf(tbuf, sizeof(tbuf), "i%d", id);
+       snprintf(tbuf, sizeof(tbuf), "i%u", id);
+
        return tbuf;
 }
 
@@ -879,6 +908,7 @@ uaudio_get_cluster(struct uaudio_softc *
 {
        union usb_audio_cluster r;
        const uaudio_cs_descriptor_t *dp;
+       u_int pins;
        int i;
 
        for (i = 0; i < 25; i++) { /* avoid infinite loops */
@@ -891,37 +921,78 @@ uaudio_get_cluster(struct uaudio_softc *
                        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));
+                               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));
+                               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:
+                       /* XXX This is not really right */
                        id = iot[id].d.ot->v1.bSourceId;
                        break;
                case UDESCSUB_AC_MIXER:
-                       r = *(const union usb_audio_cluster *)
-                               &iot[id].d.mu->baSourceId[iot[id].d.mu->bNrInPins];
+                       switch (sc->sc_version) {
+                       case UAUDIO_VERSION1:
+                               pins = iot[id].d.mu->bNrInPins;
+                               r.v1 = *(const struct usb_audio_v1_cluster *)
+                                   &iot[id].d.mu->baSourceId[pins];
+                               break;
+                       case UAUDIO_VERSION2:
+                               pins = iot[id].d.mu->bNrInPins;
+                               r.v2 = *(const struct usb_audio_v2_cluster *)
+                                   &iot[id].d.mu->baSourceId[pins];
+                               break;
+                       }
                        return r;
                case UDESCSUB_AC_SELECTOR:
                        /* XXX This is not really right */
                        id = iot[id].d.su->baSourceId[0];
                        break;
                case UDESCSUB_AC_FEATURE:
-                       id = iot[id].d.fu->bSourceId;
+                       /* XXX This is not really right */
+                       switch (sc->sc_version) {
+                       case UAUDIO_VERSION1:
+                               id = iot[id].d.fu->v1.bSourceId;
+                               break;
+                       case UAUDIO_VERSION2:
+                               id = iot[id].d.fu->v2.bSourceId;
+                               break;
+                       }
                        break;
                case UDESCSUB_AC_PROCESSING:
-                       r = *(const union usb_audio_cluster *)
-                               &iot[id].d.pu->baSourceId[iot[id].d.pu->bNrInPins];
+                       switch (sc->sc_version) {
+                       case UAUDIO_VERSION1:
+                               pins = iot[id].d.pu->bNrInPins;
+                               r.v1 = *(const struct usb_audio_v1_cluster *)
+                                   &iot[id].d.pu->baSourceId[pins];
+                               break;
+                       case UAUDIO_VERSION2:
+                               pins = iot[id].d.pu->bNrInPins;
+                               r.v2 = *(const struct usb_audio_v2_cluster *)
+                                   &iot[id].d.pu->baSourceId[pins];
+                               break;
+                       }
                        return r;
                case UDESCSUB_AC_EXTENSION:
-                       r = *(const union usb_audio_cluster *)
-                               &iot[id].d.eu->baSourceId[iot[id].d.eu->bNrInPins];
+                       switch (sc->sc_version) {
+                       case UAUDIO_VERSION1:
+                               pins = iot[id].d.eu->bNrInPins;
+                               r.v1 = *(const struct usb_audio_v1_cluster *)
+                                   &iot[id].d.eu->baSourceId[pins];
+                               break;
+                       case UAUDIO_VERSION2:
+                               pins = iot[id].d.eu->bNrInPins;
+                               r.v2 = *(const struct usb_audio_v2_cluster *)
+                                   &iot[id].d.eu->baSourceId[pins];
+                               break;
+                       }
                        return r;
                default:
                        goto bad;
@@ -951,9 +1022,10 @@ uaudio_add_input(struct uaudio_softc *sc



Home | Main Index | Thread Index | Old Index