The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/usb/uaudio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: uaudio.c,v 1.91 2004/11/05 17:46:14 kent Exp $ */
    2 /*      $FreeBSD$: */
    3 
    4 /*-
    5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (lennart@augustsson.net) at
   10  * Carlstedt Research & Technology.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *        This product includes software developed by the NetBSD
   23  *        Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * USB audio specs: http://www.usb.org/developers/devclass_docs/audio10.pdf
   43  *                  http://www.usb.org/developers/devclass_docs/frmts10.pdf
   44  *                  http://www.usb.org/developers/devclass_docs/termt10.pdf
   45  */
   46 
   47 #include <sys/cdefs.h>
   48 #if defined(__NetBSD__) || defined(__OpenBSD__)
   49 __KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.91 2004/11/05 17:46:14 kent Exp $");
   50 #endif
   51 
   52 #include <sys/param.h>
   53 #include <sys/systm.h>
   54 #include <sys/kernel.h>
   55 #include <sys/malloc.h>
   56 #if defined(__NetBSD__) || defined(__OpenBSD__)
   57 #include <sys/device.h>
   58 #include <sys/ioctl.h>
   59 #endif
   60 #include <sys/tty.h>
   61 #include <sys/file.h>
   62 #include <sys/reboot.h>         /* for bootverbose */
   63 #include <sys/select.h>
   64 #include <sys/proc.h>
   65 #include <sys/vnode.h>
   66 #if defined(__NetBSD__) || defined(__OpenBSD__)
   67 #include <sys/device.h>
   68 #elif defined(__FreeBSD__)
   69 #include <sys/module.h>
   70 #include <sys/bus.h>
   71 #include <sys/conf.h>
   72 #endif
   73 #include <sys/poll.h>
   74 #if defined(__FreeBSD__)
   75 #include <sys/sysctl.h>
   76 #endif
   77 
   78 #if defined(__NetBSD__) || defined(__OpenBSD__)
   79 #include <sys/audioio.h>
   80 #include <dev/audio_if.h>
   81 #include <dev/audiovar.h>
   82 #include <dev/mulaw.h>
   83 #include <dev/auconv.h>
   84 #elif defined(__FreeBSD__)
   85 #include <dev/sound/pcm/sound.h>        /* XXXXX */
   86 #include <dev/sound/chip.h>
   87 #endif
   88 
   89 #include <dev/usb/usb.h>
   90 #include <dev/usb/usbdi.h>
   91 #include <dev/usb/usbdi_util.h>
   92 #include <dev/usb/usb_quirks.h>
   93 
   94 #if defined(__NetBSD__) || defined(__OpenBSD__)
   95 #include <dev/usb/uaudioreg.h>
   96 #elif defined(__FreeBSD__)
   97 #include <dev/sound/usb/uaudioreg.h>
   98 #include <dev/sound/usb/uaudio.h>
   99 #endif
  100 
  101 #if defined(__NetBSD__) || defined(__OpenBSD__)
  102 /* #define UAUDIO_DEBUG */
  103 #else
  104 /* #define USB_DEBUG */
  105 #endif
  106 /* #define UAUDIO_MULTIPLE_ENDPOINTS */
  107 #ifdef USB_DEBUG
  108 #define DPRINTF(x)      do { if (uaudiodebug) logprintf x; } while (0)
  109 #define DPRINTFN(n,x)   do { if (uaudiodebug>(n)) logprintf x; } while (0)
  110 int     uaudiodebug = 0;
  111 #if defined(__FreeBSD__)
  112 SYSCTL_NODE(_hw_usb, OID_AUTO, uaudio, CTLFLAG_RW, 0, "USB uaudio");
  113 SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, debug, CTLFLAG_RW,
  114            &uaudiodebug, 0, "uaudio debug level");
  115 #endif
  116 #else
  117 #define DPRINTF(x)
  118 #define DPRINTFN(n,x)
  119 #endif
  120 
  121 #define UAUDIO_NCHANBUFS 6      /* number of outstanding request */
  122 #if defined(__NetBSD__) || defined(__OpenBSD__)
  123 #define UAUDIO_NFRAMES   10     /* ms of sound in each request */
  124 #elif defined(__FreeBSD__)
  125 #define UAUDIO_NFRAMES   20     /* ms of sound in each request */
  126 #endif
  127 
  128 
  129 #define MIX_MAX_CHAN 8
  130 struct mixerctl {
  131         u_int16_t       wValue[MIX_MAX_CHAN]; /* using nchan */
  132         u_int16_t       wIndex;
  133         u_int8_t        nchan;
  134         u_int8_t        type;
  135 #define MIX_ON_OFF      1
  136 #define MIX_SIGNED_16   2
  137 #define MIX_UNSIGNED_16 3
  138 #define MIX_SIGNED_8    4
  139 #define MIX_SELECTOR    5
  140 #define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1)
  141 #define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16)
  142         int             minval, maxval;
  143         u_int           delta;
  144         u_int           mul;
  145 #if defined(__FreeBSD__) /* XXXXX */
  146         unsigned        ctl;
  147 #define MAX_SELECTOR_INPUT_PIN 256
  148         u_int8_t        slctrtype[MAX_SELECTOR_INPUT_PIN];
  149 #endif
  150         u_int8_t        class;
  151 #if !defined(__FreeBSD__)
  152         char            ctlname[MAX_AUDIO_DEV_LEN];
  153         char            *ctlunit;
  154 #endif
  155 };
  156 #define MAKE(h,l) (((h) << 8) | (l))
  157 
  158 struct as_info {
  159         u_int8_t        alt;
  160         u_int8_t        encoding;
  161         u_int8_t        attributes; /* Copy of bmAttributes of
  162                                      * usb_audio_streaming_endpoint_descriptor
  163                                      */
  164         usbd_interface_handle   ifaceh;
  165         const usb_interface_descriptor_t *idesc;
  166         const usb_endpoint_descriptor_audio_t *edesc;
  167         const usb_endpoint_descriptor_audio_t *edesc1;
  168         const struct usb_audio_streaming_type1_descriptor *asf1desc;
  169         int             sc_busy;        /* currently used */
  170 };
  171 
  172 struct chan {
  173 #if defined(__NetBSD__) || defined(__OpenBSD__)
  174         void    (*intr)(void *);        /* DMA completion intr handler */
  175         void    *arg;           /* arg for intr() */
  176 #else
  177         struct pcm_channel *pcm_ch;
  178 #endif
  179         usbd_pipe_handle pipe;
  180         usbd_pipe_handle sync_pipe;
  181 
  182         u_int   sample_size;
  183         u_int   sample_rate;
  184         u_int   bytes_per_frame;
  185         u_int   fraction;       /* fraction/1000 is the extra samples/frame */
  186         u_int   residue;        /* accumulates the fractional samples */
  187 
  188         u_char  *start;         /* upper layer buffer start */
  189         u_char  *end;           /* upper layer buffer end */
  190         u_char  *cur;           /* current position in upper layer buffer */
  191         int     blksize;        /* chunk size to report up */
  192         int     transferred;    /* transferred bytes not reported up */
  193 
  194         int     altidx;         /* currently used altidx */
  195 
  196         int     curchanbuf;
  197         struct chanbuf {
  198                 struct chan     *chan;
  199                 usbd_xfer_handle xfer;
  200                 u_char          *buffer;
  201                 u_int16_t       sizes[UAUDIO_NFRAMES];
  202                 u_int16_t       offsets[UAUDIO_NFRAMES];
  203                 u_int16_t       size;
  204         } chanbufs[UAUDIO_NCHANBUFS];
  205 
  206         struct uaudio_softc *sc; /* our softc */
  207 #if defined(__FreeBSD__)
  208         u_int32_t format;
  209         int     precision;
  210         int     channels;
  211 #endif
  212 };
  213 
  214 struct uaudio_softc {
  215         USBBASEDEVICE   sc_dev;         /* base device */
  216         usbd_device_handle sc_udev;     /* USB device */
  217         int             sc_ac_iface;    /* Audio Control interface */
  218         usbd_interface_handle   sc_ac_ifaceh;
  219         struct chan     sc_playchan;    /* play channel */
  220         struct chan     sc_recchan;     /* record channel */
  221         int             sc_nullalt;
  222         int             sc_audio_rev;
  223         struct as_info  *sc_alts;       /* alternate settings */
  224         int             sc_nalts;       /* # of alternate settings */
  225         int             sc_altflags;
  226 #define HAS_8           0x01
  227 #define HAS_16          0x02
  228 #define HAS_8U          0x04
  229 #define HAS_ALAW        0x08
  230 #define HAS_MULAW       0x10
  231 #define UA_NOFRAC       0x20            /* don't do sample rate adjustment */
  232 #define HAS_24          0x40
  233         int             sc_mode;        /* play/record capability */
  234         struct mixerctl *sc_ctls;       /* mixer controls */
  235         int             sc_nctls;       /* # of mixer controls */
  236         device_ptr_t    sc_audiodev;
  237         char            sc_dying;
  238 };
  239 
  240 struct terminal_list {
  241         int size;
  242         uint16_t terminals[1];
  243 };
  244 #define TERMINAL_LIST_SIZE(N)   (offsetof(struct terminal_list, terminals) \
  245                                 + sizeof(uint16_t) * (N))
  246 
  247 struct io_terminal {
  248         union {
  249                 const usb_descriptor_t *desc;
  250                 const struct usb_audio_input_terminal *it;
  251                 const struct usb_audio_output_terminal *ot;
  252                 const struct usb_audio_mixer_unit *mu;
  253                 const struct usb_audio_selector_unit *su;
  254                 const struct usb_audio_feature_unit *fu;
  255                 const struct usb_audio_processing_unit *pu;
  256                 const struct usb_audio_extension_unit *eu;
  257         } d;
  258         int inputs_size;
  259         struct terminal_list **inputs; /* list of source input terminals */
  260         struct terminal_list *output; /* list of destination output terminals */
  261         int direct;             /* directly connected to an output terminal */
  262 };
  263 
  264 #define UAC_OUTPUT      0
  265 #define UAC_INPUT       1
  266 #define UAC_EQUAL       2
  267 #define UAC_RECORD      3
  268 #define UAC_NCLASSES    4
  269 #ifdef USB_DEBUG
  270 #if defined(__FreeBSD__)
  271 #define AudioCinputs    "inputs"
  272 #define AudioCoutputs   "outputs"
  273 #define AudioCrecord    "record"
  274 #define AudioCequalization      "equalization"
  275 #endif
  276 Static const char *uac_names[] = {
  277         AudioCoutputs, AudioCinputs, AudioCequalization, AudioCrecord,
  278 };
  279 #endif
  280 
  281 Static usbd_status uaudio_identify_ac
  282         (struct uaudio_softc *, const usb_config_descriptor_t *);
  283 Static usbd_status uaudio_identify_as
  284         (struct uaudio_softc *, const usb_config_descriptor_t *);
  285 Static usbd_status uaudio_process_as
  286         (struct uaudio_softc *, const char *, int *, int,
  287          const usb_interface_descriptor_t *);
  288 
  289 Static void     uaudio_add_alt(struct uaudio_softc *, const struct as_info *);
  290 
  291 Static const usb_interface_descriptor_t *uaudio_find_iface
  292         (const char *, int, int *, int);
  293 
  294 Static void     uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *);
  295 
  296 #if defined(__NetBSD__) || defined(__OpenBSD__)
  297 Static char     *uaudio_id_name
  298         (struct uaudio_softc *, const struct io_terminal *, int);
  299 #endif
  300 
  301 #ifdef USB_DEBUG
  302 Static void     uaudio_dump_cluster(const struct usb_audio_cluster *);
  303 #endif
  304 Static struct usb_audio_cluster uaudio_get_cluster
  305         (int, const struct io_terminal *);
  306 Static void     uaudio_add_input
  307         (struct uaudio_softc *, const struct io_terminal *, int);
  308 Static void     uaudio_add_output
  309         (struct uaudio_softc *, const struct io_terminal *, int);
  310 Static void     uaudio_add_mixer
  311         (struct uaudio_softc *, const struct io_terminal *, int);
  312 Static void     uaudio_add_selector
  313         (struct uaudio_softc *, const struct io_terminal *, int);
  314 #ifdef USB_DEBUG
  315 Static const char *uaudio_get_terminal_name(int);
  316 #endif
  317 Static int      uaudio_determine_class
  318         (const struct io_terminal *, struct mixerctl *);
  319 #if defined(__FreeBSD__)
  320 Static const int uaudio_feature_name(const struct io_terminal *,
  321                     struct mixerctl *);
  322 #else
  323 Static const char *uaudio_feature_name
  324         (const struct io_terminal *, struct mixerctl *);
  325 #endif
  326 Static void     uaudio_add_feature
  327         (struct uaudio_softc *, const struct io_terminal *, int);
  328 Static void     uaudio_add_processing_updown
  329         (struct uaudio_softc *, const struct io_terminal *, int);
  330 Static void     uaudio_add_processing
  331         (struct uaudio_softc *, const struct io_terminal *, int);
  332 Static void     uaudio_add_extension
  333         (struct uaudio_softc *, const struct io_terminal *, int);
  334 Static struct terminal_list *uaudio_merge_terminal_list
  335         (const struct io_terminal *);
  336 Static struct terminal_list *uaudio_io_terminaltype
  337         (int, struct io_terminal *, int);
  338 Static usbd_status uaudio_identify
  339         (struct uaudio_softc *, const usb_config_descriptor_t *);
  340 
  341 Static int      uaudio_signext(int, int);
  342 #if defined(__NetBSD__) || defined(__OpenBSD__)
  343 Static int      uaudio_value2bsd(struct mixerctl *, int);
  344 #endif
  345 Static int      uaudio_bsd2value(struct mixerctl *, int);
  346 Static int      uaudio_get(struct uaudio_softc *, int, int, int, int, int);
  347 #if defined(__NetBSD__) || defined(__OpenBSD__)
  348 Static int      uaudio_ctl_get
  349         (struct uaudio_softc *, int, struct mixerctl *, int);
  350 #endif
  351 Static void     uaudio_set
  352         (struct uaudio_softc *, int, int, int, int, int, int);
  353 Static void     uaudio_ctl_set
  354         (struct uaudio_softc *, int, struct mixerctl *, int, int);
  355 
  356 Static usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int);
  357 
  358 Static usbd_status uaudio_chan_open(struct uaudio_softc *, struct chan *);
  359 Static void     uaudio_chan_close(struct uaudio_softc *, struct chan *);
  360 Static usbd_status uaudio_chan_alloc_buffers
  361         (struct uaudio_softc *, struct chan *);
  362 Static void     uaudio_chan_free_buffers(struct uaudio_softc *, struct chan *);
  363 
  364 #if defined(__NetBSD__) || defined(__OpenBSD__)
  365 Static void     uaudio_chan_init
  366         (struct chan *, int, const struct audio_params *, int);
  367 Static void     uaudio_chan_set_param(struct chan *, u_char *, u_char *, int);
  368 #endif
  369 
  370 Static void     uaudio_chan_ptransfer(struct chan *);
  371 Static void     uaudio_chan_pintr
  372         (usbd_xfer_handle, usbd_private_handle, usbd_status);
  373 
  374 Static void     uaudio_chan_rtransfer(struct chan *);
  375 Static void     uaudio_chan_rintr
  376         (usbd_xfer_handle, usbd_private_handle, usbd_status);
  377 
  378 #if defined(__NetBSD__) || defined(__OpenBSD__)
  379 Static int      uaudio_open(void *, int);
  380 Static void     uaudio_close(void *);
  381 Static int      uaudio_drain(void *);
  382 Static int      uaudio_query_encoding(void *, struct audio_encoding *);
  383 Static void     uaudio_get_minmax_rates
  384         (int, const struct as_info *, const struct audio_params *,
  385          int, u_long *, u_long *);
  386 Static int      uaudio_match_alt_sub
  387         (int, const struct as_info *, const struct audio_params *, int, u_long);
  388 Static int      uaudio_match_alt_chan
  389         (int, const struct as_info *, struct audio_params *, int);
  390 Static int      uaudio_match_alt
  391         (int, const struct as_info *, struct audio_params *, int);
  392 Static int      uaudio_set_params
  393         (void *, int, int, struct audio_params *, struct audio_params *);
  394 Static int      uaudio_round_blocksize(void *, int);
  395 Static int      uaudio_trigger_output
  396         (void *, void *, void *, int, void (*)(void *), void *,
  397          struct audio_params *);
  398 Static int      uaudio_trigger_input
  399         (void *, void *, void *, int, void (*)(void *), void *,
  400          struct audio_params *);
  401 Static int      uaudio_halt_in_dma(void *);
  402 Static int      uaudio_halt_out_dma(void *);
  403 Static int      uaudio_getdev(void *, struct audio_device *);
  404 Static int      uaudio_mixer_set_port(void *, mixer_ctrl_t *);
  405 Static int      uaudio_mixer_get_port(void *, mixer_ctrl_t *);
  406 Static int      uaudio_query_devinfo(void *, mixer_devinfo_t *);
  407 Static int      uaudio_get_props(void *);
  408 
  409 Static const struct audio_hw_if uaudio_hw_if = {
  410         uaudio_open,
  411         uaudio_close,
  412         uaudio_drain,
  413         uaudio_query_encoding,
  414         uaudio_set_params,
  415         uaudio_round_blocksize,
  416         NULL,
  417         NULL,
  418         NULL,
  419         NULL,
  420         NULL,
  421         uaudio_halt_out_dma,
  422         uaudio_halt_in_dma,
  423         NULL,
  424         uaudio_getdev,
  425         NULL,
  426         uaudio_mixer_set_port,
  427         uaudio_mixer_get_port,
  428         uaudio_query_devinfo,
  429         NULL,
  430         NULL,
  431         NULL,
  432         NULL,
  433         uaudio_get_props,
  434         uaudio_trigger_output,
  435         uaudio_trigger_input,
  436         NULL,
  437 };
  438 
  439 Static struct audio_device uaudio_device = {
  440         "USB audio",
  441         "",
  442         "uaudio"
  443 };
  444 
  445 #elif defined(__FreeBSD__)
  446 Static int      audio_attach_mi(device_t);
  447 Static int      uaudio_init_params(struct uaudio_softc * sc, struct chan *ch, int mode);
  448 
  449 /* for NetBSD compatibirity */
  450 #define AUMODE_PLAY     0x01
  451 #define AUMODE_RECORD   0x02
  452 
  453 #define AUDIO_PROP_FULLDUPLEX   0x01
  454 
  455 #define AUDIO_ENCODING_ULAW             1
  456 #define AUDIO_ENCODING_ALAW             2
  457 #define AUDIO_ENCODING_SLINEAR_LE       6
  458 #define AUDIO_ENCODING_SLINEAR_BE       7
  459 #define AUDIO_ENCODING_ULINEAR_LE       8
  460 #define AUDIO_ENCODING_ULINEAR_BE       9
  461 
  462 #endif  /* FreeBSD */
  463 
  464 
  465 #if defined(__NetBSD__) || defined(__OpenBSD__)
  466 
  467 USB_DECLARE_DRIVER(uaudio);
  468 
  469 #elif defined(__FreeBSD__)
  470 
  471 USB_DECLARE_DRIVER_INIT(uaudio,
  472                 DEVMETHOD(device_suspend, bus_generic_suspend),
  473                 DEVMETHOD(device_resume, bus_generic_resume),
  474                 DEVMETHOD(device_shutdown, bus_generic_shutdown),
  475                 DEVMETHOD(bus_print_child, bus_generic_print_child)
  476                 );
  477 #endif
  478 
  479 
  480 USB_MATCH(uaudio)
  481 {
  482         USB_MATCH_START(uaudio, uaa);
  483         usb_interface_descriptor_t *id;
  484 
  485         if (uaa->iface == NULL)
  486                 return (UMATCH_NONE);
  487 
  488         id = usbd_get_interface_descriptor(uaa->iface);
  489         /* Trigger on the control interface. */
  490         if (id == NULL ||
  491             id->bInterfaceClass != UICLASS_AUDIO ||
  492             id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL ||
  493             (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
  494                 return (UMATCH_NONE);
  495 
  496         return (UMATCH_IFACECLASS_IFACESUBCLASS);
  497 }
  498 
  499 USB_ATTACH(uaudio)
  500 {
  501         USB_ATTACH_START(uaudio, sc, uaa);
  502         usb_interface_descriptor_t *id;
  503         usb_config_descriptor_t *cdesc;
  504         char devinfo[1024];
  505         usbd_status err;
  506         int i, j, found;
  507 
  508 #if defined(__FreeBSD__)
  509         usbd_devinfo(uaa->device, 0, devinfo);
  510         USB_ATTACH_SETUP;
  511 #else
  512         usbd_devinfo(uaa->device, 0, devinfo, sizeof(devinfo));
  513 #endif
  514 
  515 #if !defined(__FreeBSD__)
  516         printf(": %s\n", devinfo);
  517 #endif
  518 
  519         sc->sc_udev = uaa->device;
  520 
  521         cdesc = usbd_get_config_descriptor(sc->sc_udev);
  522         if (cdesc == NULL) {
  523                 printf("%s: failed to get configuration descriptor\n",
  524                        USBDEVNAME(sc->sc_dev));
  525                 USB_ATTACH_ERROR_RETURN;
  526         }
  527 
  528         err = uaudio_identify(sc, cdesc);
  529         if (err) {
  530                 printf("%s: audio descriptors make no sense, error=%d\n",
  531                        USBDEVNAME(sc->sc_dev), err);
  532                 USB_ATTACH_ERROR_RETURN;
  533         }
  534 
  535         sc->sc_ac_ifaceh = uaa->iface;
  536         /* Pick up the AS interface. */
  537         for (i = 0; i < uaa->nifaces; i++) {
  538                 if (uaa->ifaces[i] == NULL)
  539                         continue;
  540                 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
  541                 if (id == NULL)
  542                         continue;
  543                 found = 0;
  544                 for (j = 0; j < sc->sc_nalts; j++) {
  545                         if (id->bInterfaceNumber ==
  546                             sc->sc_alts[j].idesc->bInterfaceNumber) {
  547                                 sc->sc_alts[j].ifaceh = uaa->ifaces[i];
  548                                 found = 1;
  549                         }
  550                 }
  551                 if (found)
  552                         uaa->ifaces[i] = NULL;
  553         }
  554 
  555         for (j = 0; j < sc->sc_nalts; j++) {
  556                 if (sc->sc_alts[j].ifaceh == NULL) {
  557                         printf("%s: alt %d missing AS interface(s)\n",
  558                             USBDEVNAME(sc->sc_dev), j);
  559                         USB_ATTACH_ERROR_RETURN;
  560                 }
  561         }
  562 
  563         printf("%s: audio rev %d.%02x\n", USBDEVNAME(sc->sc_dev),
  564                sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
  565 
  566         sc->sc_playchan.sc = sc->sc_recchan.sc = sc;
  567         sc->sc_playchan.altidx = -1;
  568         sc->sc_recchan.altidx = -1;
  569 
  570         if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
  571                 sc->sc_altflags |= UA_NOFRAC;
  572 
  573 #ifndef USB_DEBUG
  574         if (bootverbose)
  575 #endif
  576                 printf("%s: %d mixer controls\n", USBDEVNAME(sc->sc_dev),
  577                     sc->sc_nctls);
  578 
  579 #if !defined(__FreeBSD__)
  580         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  581                            USBDEV(sc->sc_dev));
  582 #endif
  583 
  584         DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
  585 #if defined(__OpenBSD__)
  586         audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
  587 #elif defined(__NetBSD__)
  588         sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
  589 #elif defined(__FreeBSD__)
  590         sc->sc_dying = 0;
  591         if (audio_attach_mi(sc->sc_dev)) {
  592                 printf("audio_attach_mi failed\n");
  593                 USB_ATTACH_ERROR_RETURN;
  594         }
  595 #endif
  596 
  597         USB_ATTACH_SUCCESS_RETURN;
  598 }
  599 
  600 #if defined(__NetBSD__) || defined(__OpenBSD__)
  601 int
  602 uaudio_activate(device_ptr_t self, enum devact act)
  603 {
  604         struct uaudio_softc *sc = (struct uaudio_softc *)self;
  605         int rv = 0;
  606 
  607         switch (act) {
  608         case DVACT_ACTIVATE:
  609                 return (EOPNOTSUPP);
  610                 break;
  611 
  612         case DVACT_DEACTIVATE:
  613                 if (sc->sc_audiodev != NULL)
  614                         rv = config_deactivate(sc->sc_audiodev);
  615                 sc->sc_dying = 1;
  616                 break;
  617         }
  618         return (rv);
  619 }
  620 #endif
  621 
  622 #if defined(__NetBSD__) || defined(__OpenBSD__)
  623 int
  624 uaudio_detach(device_ptr_t self, int flags)
  625 {
  626         struct uaudio_softc *sc = (struct uaudio_softc *)self;
  627         int rv = 0;
  628 
  629         /* Wait for outstanding requests to complete. */
  630         usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
  631 
  632         if (sc->sc_audiodev != NULL)
  633                 rv = config_detach(sc->sc_audiodev, flags);
  634 
  635         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  636                            USBDEV(sc->sc_dev));
  637 
  638         return (rv);
  639 }
  640 #elif defined(__FreeBSD__)
  641 
  642 USB_DETACH(uaudio)
  643 {
  644         USB_DETACH_START(uaudio, sc);
  645 
  646         sc->sc_dying = 1;
  647 
  648 #if 0 /* XXX */
  649         /* Wait for outstanding requests to complete. */
  650         usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
  651 #endif
  652 
  653         /* do nothing ? */
  654         return bus_generic_detach(sc->sc_dev);
  655 }
  656 #endif
  657 
  658 #if defined(__NetBSD__) || defined(__OpenBSD__)
  659 Static int
  660 uaudio_query_encoding(void *addr, struct audio_encoding *fp)
  661 {
  662         struct uaudio_softc *sc = addr;
  663         int flags = sc->sc_altflags;
  664         int idx;
  665 
  666         if (sc->sc_dying)
  667                 return (EIO);
  668 
  669         if (sc->sc_nalts == 0 || flags == 0)
  670                 return (ENXIO);
  671 
  672         idx = fp->index;
  673         switch (idx) {
  674         case 0:
  675                 strlcpy(fp->name, AudioEulinear, sizeof(fp->name));
  676                 fp->encoding = AUDIO_ENCODING_ULINEAR;
  677                 fp->precision = 8;
  678                 fp->flags = flags&HAS_8U ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
  679                 return (0);
  680         case 1:
  681                 strlcpy(fp->name, AudioEmulaw, sizeof(fp->name));
  682                 fp->encoding = AUDIO_ENCODING_ULAW;
  683                 fp->precision = 8;
  684                 fp->flags = flags&HAS_MULAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
  685                 return (0);
  686         case 2:
  687                 strlcpy(fp->name, AudioEalaw, sizeof(fp->name));
  688                 fp->encoding = AUDIO_ENCODING_ALAW;
  689                 fp->precision = 8;
  690                 fp->flags = flags&HAS_ALAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
  691                 return (0);
  692         case 3:
  693                 strlcpy(fp->name, AudioEslinear, sizeof(fp->name));
  694                 fp->encoding = AUDIO_ENCODING_SLINEAR;
  695                 fp->precision = 8;
  696                 fp->flags = flags&HAS_8 ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
  697                 return (0);
  698         case 4:
  699                 strlcpy(fp->name, AudioEslinear_le, sizeof(fp->name));
  700                 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
  701                 fp->precision = 16;
  702                 fp->flags = 0;
  703                 return (0);
  704         case 5:
  705                 strlcpy(fp->name, AudioEulinear_le, sizeof(fp->name));
  706                 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
  707                 fp->precision = 16;
  708                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  709                 return (0);
  710         case 6:
  711                 strlcpy(fp->name, AudioEslinear_be, sizeof(fp->name));
  712                 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
  713                 fp->precision = 16;
  714                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  715                 return (0);
  716         case 7:
  717                 strlcpy(fp->name, AudioEulinear_be, sizeof(fp->name));
  718                 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
  719                 fp->precision = 16;
  720                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  721                 return (0);
  722         default:
  723                 return (EINVAL);
  724         }
  725 }
  726 #endif
  727 
  728 Static const usb_interface_descriptor_t *
  729 uaudio_find_iface(const char *buf, int size, int *offsp, int subtype)
  730 {
  731         const usb_interface_descriptor_t *d;
  732 
  733         while (*offsp < size) {
  734                 d = (const void *)(buf + *offsp);
  735                 *offsp += d->bLength;
  736                 if (d->bDescriptorType == UDESC_INTERFACE &&
  737                     d->bInterfaceClass == UICLASS_AUDIO &&
  738                     d->bInterfaceSubClass == subtype)
  739                         return (d);
  740         }
  741         return (NULL);
  742 }
  743 
  744 Static void
  745 uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc)
  746 {
  747         int res;
  748         size_t len;
  749         struct mixerctl *nmc;
  750 
  751 #if defined(__FreeBSD__)
  752         if (mc->class < UAC_NCLASSES) {
  753                 DPRINTF(("%s: adding %s.%d\n",
  754                          __func__, uac_names[mc->class], mc->ctl));
  755         } else {
  756                 DPRINTF(("%s: adding %d\n", __func__, mc->ctl));
  757         }
  758 #else
  759         if (mc->class < UAC_NCLASSES) {
  760                 DPRINTF(("%s: adding %s.%s\n",
  761                          __func__, uac_names[mc->class], mc->ctlname));
  762         } else {
  763                 DPRINTF(("%s: adding %s\n", __func__, mc->ctlname));
  764         }
  765 #endif
  766         len = sizeof(*mc) * (sc->sc_nctls + 1);
  767         nmc = malloc(len, M_USBDEV, M_NOWAIT);
  768         if (nmc == NULL) {
  769                 printf("uaudio_mixer_add_ctl: no memory\n");
  770                 return;
  771         }
  772         /* Copy old data, if there was any */
  773         if (sc->sc_nctls != 0) {
  774                 memcpy(nmc, sc->sc_ctls, sizeof(*mc) * (sc->sc_nctls));
  775                 free(sc->sc_ctls, M_USBDEV);
  776         }
  777         sc->sc_ctls = nmc;
  778 
  779         mc->delta = 0;
  780         if (mc->type == MIX_ON_OFF) {
  781                 mc->minval = 0;
  782                 mc->maxval = 1;
  783         } else if (mc->type == MIX_SELECTOR) {
  784                 ;
  785         } else {
  786                 /* Determine min and max values. */
  787                 mc->minval = uaudio_signext(mc->type,
  788                         uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
  789                                    mc->wValue[0], mc->wIndex,
  790                                    MIX_SIZE(mc->type)));
  791                 mc->maxval = 1 + uaudio_signext(mc->type,
  792                         uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE,
  793                                    mc->wValue[0], mc->wIndex,
  794                                    MIX_SIZE(mc->type)));
  795                 mc->mul = mc->maxval - mc->minval;
  796                 if (mc->mul == 0)
  797                         mc->mul = 1;
  798                 res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
  799                                  mc->wValue[0], mc->wIndex,
  800                                  MIX_SIZE(mc->type));
  801                 if (res > 0)
  802                         mc->delta = (res * 255 + mc->mul/2) / mc->mul;
  803         }
  804 
  805         sc->sc_ctls[sc->sc_nctls++] = *mc;
  806 
  807 #ifdef USB_DEBUG
  808         if (uaudiodebug > 2) {
  809                 int i;
  810                 DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc->wValue[0]));
  811                 for (i = 1; i < mc->nchan; i++)
  812                         DPRINTF((",%04x", mc->wValue[i]));
  813 #if defined(__FreeBSD__)
  814                 DPRINTF((" wIndex=%04x type=%d ctl='%d' "
  815                          "min=%d max=%d\n",
  816                          mc->wIndex, mc->type, mc->ctl,
  817                          mc->minval, mc->maxval));
  818 #else
  819                 DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' "
  820                          "min=%d max=%d\n",
  821                          mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
  822                          mc->minval, mc->maxval));
  823 #endif
  824         }
  825 #endif
  826 }
  827 
  828 #if defined(__NetBSD__) || defined(__OpenBSD__)
  829 Static char *
  830 uaudio_id_name(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
  831 {
  832         static char buf[32];
  833         snprintf(buf, sizeof(buf), "i%d", id);
  834         return (buf);
  835 }
  836 #endif
  837 
  838 #ifdef USB_DEBUG
  839 Static void
  840 uaudio_dump_cluster(const struct usb_audio_cluster *cl)
  841 {
  842         static const char *channel_names[16] = {
  843                 "LEFT", "RIGHT", "CENTER", "LFE",
  844                 "LEFT_SURROUND", "RIGHT_SURROUND", "LEFT_CENTER", "RIGHT_CENTER",
  845                 "SURROUND", "LEFT_SIDE", "RIGHT_SIDE", "TOP",
  846                 "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15",
  847         };
  848         int cc, i, first;
  849 
  850         cc = UGETW(cl->wChannelConfig);
  851         logprintf("cluster: bNrChannels=%u wChannelConfig=0x%.4x",
  852                   cl->bNrChannels, cc);
  853         first = TRUE;
  854         for (i = 0; cc != 0; i++) {
  855                 if (cc & 1) {
  856                         logprintf("%c%s", first ? '<' : ',', channel_names[i]);
  857                         first = FALSE;
  858                 }
  859                 cc = cc >> 1;
  860         }
  861         logprintf("> iChannelNames=%u", cl->iChannelNames);
  862 }
  863 #endif
  864 
  865 Static struct usb_audio_cluster
  866 uaudio_get_cluster(int id, const struct io_terminal *iot)
  867 {
  868         struct usb_audio_cluster r;
  869         const usb_descriptor_t *dp;
  870         int i;
  871 
  872         for (i = 0; i < 25; i++) { /* avoid infinite loops */
  873                 dp = iot[id].d.desc;
  874                 if (dp == 0)
  875                         goto bad;
  876                 switch (dp->bDescriptorSubtype) {
  877                 case UDESCSUB_AC_INPUT:
  878                         r.bNrChannels = iot[id].d.it->bNrChannels;
  879                         USETW(r.wChannelConfig, UGETW(iot[id].d.it->wChannelConfig));
  880                         r.iChannelNames = iot[id].d.it->iChannelNames;
  881                         return (r);
  882                 case UDESCSUB_AC_OUTPUT:
  883                         id = iot[id].d.ot->bSourceId;
  884                         break;
  885                 case UDESCSUB_AC_MIXER:
  886                         r = *(const struct usb_audio_cluster *)
  887                                 &iot[id].d.mu->baSourceId[iot[id].d.mu->bNrInPins];
  888                         return (r);
  889                 case UDESCSUB_AC_SELECTOR:
  890                         /* XXX This is not really right */
  891                         id = iot[id].d.su->baSourceId[0];
  892                         break;
  893                 case UDESCSUB_AC_FEATURE:
  894                         id = iot[id].d.fu->bSourceId;
  895                         break;
  896                 case UDESCSUB_AC_PROCESSING:
  897                         r = *(const struct usb_audio_cluster *)
  898                                 &iot[id].d.pu->baSourceId[iot[id].d.pu->bNrInPins];
  899                         return (r);
  900                 case UDESCSUB_AC_EXTENSION:
  901                         r = *(const struct usb_audio_cluster *)
  902                                 &iot[id].d.eu->baSourceId[iot[id].d.eu->bNrInPins];
  903                         return (r);
  904                 default:
  905                         goto bad;
  906                 }
  907         }
  908  bad:
  909         printf("uaudio_get_cluster: bad data\n");
  910         memset(&r, 0, sizeof r);
  911         return (r);
  912 
  913 }
  914 
  915 Static void
  916 uaudio_add_input(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
  917 {
  918 #ifdef USB_DEBUG
  919         const struct usb_audio_input_terminal *d = iot[id].d.it;
  920 
  921         DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x "
  922                     "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
  923                     "iChannelNames=%d iTerminal=%d\n",
  924                     d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
  925                     d->bNrChannels, UGETW(d->wChannelConfig),
  926                     d->iChannelNames, d->iTerminal));
  927 #endif
  928 }
  929 
  930 Static void
  931 uaudio_add_output(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
  932 {
  933 #ifdef USB_DEBUG
  934         const struct usb_audio_output_terminal *d = iot[id].d.ot;
  935 
  936         DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x "
  937                     "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
  938                     d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
  939                     d->bSourceId, d->iTerminal));
  940 #endif
  941 }
  942 
  943 Static void
  944 uaudio_add_mixer(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
  945 {
  946         const struct usb_audio_mixer_unit *d = iot[id].d.mu;
  947         const struct usb_audio_mixer_unit_1 *d1;
  948         int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k;
  949         const uByte *bm;
  950         struct mixerctl mix;
  951 
  952         DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n",
  953                     d->bUnitId, d->bNrInPins));
  954 
  955         /* Compute the number of input channels */
  956         ichs = 0;
  957         for (i = 0; i < d->bNrInPins; i++)
  958                 ichs += uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels;
  959 
  960         /* and the number of output channels */
  961         d1 = (const struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins];
  962         ochs = d1->bNrChannels;
  963         DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%d\n", ichs, ochs));
  964 
  965         bm = d1->bmControls;
  966         mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
  967         uaudio_determine_class(&iot[id], &mix);
  968         mix.type = MIX_SIGNED_16;
  969 #if !defined(__FreeBSD__)       /* XXXXX */
  970         mix.ctlunit = AudioNvolume;
  971 #endif
  972 
  973 #define BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1)
  974         for (p = i = 0; i < d->bNrInPins; i++) {
  975                 chs = uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels;
  976                 mc = 0;
  977                 for (c = 0; c < chs; c++) {
  978                         mo = 0;
  979                         for (o = 0; o < ochs; o++) {
  980                                 bno = (p + c) * ochs + o;
  981                                 if (BIT(bno))
  982                                         mo++;
  983                         }
  984                         if (mo == 1)
  985                                 mc++;
  986                 }
  987                 if (mc == chs && chs <= MIX_MAX_CHAN) {
  988                         k = 0;
  989                         for (c = 0; c < chs; c++)
  990                                 for (o = 0; o < ochs; o++) {
  991                                         bno = (p + c) * ochs + o;
  992                                         if (BIT(bno))
  993                                                 mix.wValue[k++] =
  994                                                         MAKE(p+c+1, o+1);
  995                                 }
  996 #if !defined(__FreeBSD__)
  997                         snprintf(mix.ctlname, sizeof(mix.ctlname), "mix%d-%s",
  998                             d->bUnitId, uaudio_id_name(sc, iot,
  999                             d->baSourceId[i]));
 1000 #endif
 1001                         mix.nchan = chs;
 1002                         uaudio_mixer_add_ctl(sc, &mix);
 1003                 } else {
 1004                         /* XXX */
 1005                 }
 1006 #undef BIT
 1007                 p += chs;
 1008         }
 1009 
 1010 }
 1011 
 1012 Static void
 1013 uaudio_add_selector(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
 1014 {
 1015         const struct usb_audio_selector_unit *d = iot[id].d.su;
 1016         struct mixerctl mix;
 1017 #if !defined(__FreeBSD__)
 1018         int i, wp;
 1019 #else
 1020         int i;
 1021         struct mixerctl dummy;
 1022 #endif
 1023 
 1024         DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n",
 1025                     d->bUnitId, d->bNrInPins));
 1026         mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
 1027         mix.wValue[0] = MAKE(0, 0);
 1028         uaudio_determine_class(&iot[id], &mix);
 1029         mix.nchan = 1;
 1030         mix.type = MIX_SELECTOR;
 1031 #if defined(__FreeBSD__)
 1032         mix.ctl = SOUND_MIXER_NRDEVICES;        /* XXXXX */
 1033         mix.minval = 1;
 1034         mix.maxval = d->bNrInPins;
 1035         mix.mul = mix.maxval - mix.minval;
 1036         for (i = 0; i < MAX_SELECTOR_INPUT_PIN; i++) {
 1037                 mix.slctrtype[i] = SOUND_MIXER_NRDEVICES;
 1038         }
 1039         for (i = mix.minval; i <= mix.maxval; i++) {
 1040                 mix.slctrtype[i - 1] = uaudio_feature_name(&iot[d->baSourceId[i - 1]], &dummy);
 1041         }
 1042 #else
 1043         mix.ctlunit = "";
 1044         mix.minval = 1;
 1045         mix.maxval = d->bNrInPins;
 1046         mix.mul = mix.maxval - mix.minval;
 1047         wp = snprintf(mix.ctlname, MAX_AUDIO_DEV_LEN, "sel%d-", d->bUnitId);
 1048         for (i = 1; i <= d->bNrInPins; i++) {
 1049                 wp += snprintf(mix.ctlname + wp, MAX_AUDIO_DEV_LEN - wp,
 1050                                "i%d", d->baSourceId[i - 1]);
 1051                 if (wp > MAX_AUDIO_DEV_LEN - 1)
 1052                         break;
 1053         }
 1054 #endif
 1055         uaudio_mixer_add_ctl(sc, &mix);
 1056 }
 1057 
 1058 #ifdef USB_DEBUG
 1059 Static const char *
 1060 uaudio_get_terminal_name(int terminal_type)
 1061 {
 1062         static char buf[100];
 1063 
 1064         switch (terminal_type) {
 1065         /* USB terminal types */
 1066         case UAT_UNDEFINED:     return "UAT_UNDEFINED";
 1067         case UAT_STREAM:        return "UAT_STREAM";
 1068         case UAT_VENDOR:        return "UAT_VENDOR";
 1069         /* input terminal types */
 1070         case UATI_UNDEFINED:    return "UATI_UNDEFINED";
 1071         case UATI_MICROPHONE:   return "UATI_MICROPHONE";
 1072         case UATI_DESKMICROPHONE:       return "UATI_DESKMICROPHONE";
 1073         case UATI_PERSONALMICROPHONE:   return "UATI_PERSONALMICROPHONE";
 1074         case UATI_OMNIMICROPHONE:       return "UATI_OMNIMICROPHONE";
 1075         case UATI_MICROPHONEARRAY:      return "UATI_MICROPHONEARRAY";
 1076         case UATI_PROCMICROPHONEARR:    return "UATI_PROCMICROPHONEARR";
 1077         /* output terminal types */
 1078         case UATO_UNDEFINED:    return "UATO_UNDEFINED";
 1079         case UATO_SPEAKER:      return "UATO_SPEAKER";
 1080         case UATO_HEADPHONES:   return "UATO_HEADPHONES";
 1081         case UATO_DISPLAYAUDIO: return "UATO_DISPLAYAUDIO";
 1082         case UATO_DESKTOPSPEAKER:       return "UATO_DESKTOPSPEAKER";
 1083         case UATO_ROOMSPEAKER:  return "UATO_ROOMSPEAKER";
 1084         case UATO_COMMSPEAKER:  return "UATO_COMMSPEAKER";
 1085         case UATO_SUBWOOFER:    return "UATO_SUBWOOFER";
 1086         /* bidir terminal types */
 1087         case UATB_UNDEFINED:    return "UATB_UNDEFINED";
 1088         case UATB_HANDSET:      return "UATB_HANDSET";
 1089         case UATB_HEADSET:      return "UATB_HEADSET";
 1090         case UATB_SPEAKERPHONE: return "UATB_SPEAKERPHONE";
 1091         case UATB_SPEAKERPHONEESUP:     return "UATB_SPEAKERPHONEESUP";
 1092         case UATB_SPEAKERPHONEECANC:    return "UATB_SPEAKERPHONEECANC";
 1093         /* telephony terminal types */
 1094         case UATT_UNDEFINED:    return "UATT_UNDEFINED";
 1095         case UATT_PHONELINE:    return "UATT_PHONELINE";
 1096         case UATT_TELEPHONE:    return "UATT_TELEPHONE";
 1097         case UATT_DOWNLINEPHONE:        return "UATT_DOWNLINEPHONE";
 1098         /* external terminal types */
 1099         case UATE_UNDEFINED:    return "UATE_UNDEFINED";
 1100         case UATE_ANALOGCONN:   return "UATE_ANALOGCONN";
 1101         case UATE_LINECONN:     return "UATE_LINECONN";
 1102         case UATE_LEGACYCONN:   return "UATE_LEGACYCONN";
 1103         case UATE_DIGITALAUIFC: return "UATE_DIGITALAUIFC";
 1104         case UATE_SPDIF:        return "UATE_SPDIF";
 1105         case UATE_1394DA:       return "UATE_1394DA";
 1106         case UATE_1394DV:       return "UATE_1394DV";
 1107         /* embedded function terminal types */
 1108         case UATF_UNDEFINED:    return "UATF_UNDEFINED";
 1109         case UATF_CALIBNOISE:   return "UATF_CALIBNOISE";
 1110         case UATF_EQUNOISE:     return "UATF_EQUNOISE";
 1111         case UATF_CDPLAYER:     return "UATF_CDPLAYER";
 1112         case UATF_DAT:  return "UATF_DAT";
 1113         case UATF_DCC:  return "UATF_DCC";
 1114         case UATF_MINIDISK:     return "UATF_MINIDISK";
 1115         case UATF_ANALOGTAPE:   return "UATF_ANALOGTAPE";
 1116         case UATF_PHONOGRAPH:   return "UATF_PHONOGRAPH";
 1117         case UATF_VCRAUDIO:     return "UATF_VCRAUDIO";
 1118         case UATF_VIDEODISCAUDIO:       return "UATF_VIDEODISCAUDIO";
 1119         case UATF_DVDAUDIO:     return "UATF_DVDAUDIO";
 1120         case UATF_TVTUNERAUDIO: return "UATF_TVTUNERAUDIO";
 1121         case UATF_SATELLITE:    return "UATF_SATELLITE";
 1122         case UATF_CABLETUNER:   return "UATF_CABLETUNER";
 1123         case UATF_DSS:  return "UATF_DSS";
 1124         case UATF_RADIORECV:    return "UATF_RADIORECV";
 1125         case UATF_RADIOXMIT:    return "UATF_RADIOXMIT";
 1126         case UATF_MULTITRACK:   return "UATF_MULTITRACK";
 1127         case UATF_SYNTHESIZER:  return "UATF_SYNTHESIZER";
 1128         default:
 1129                 snprintf(buf, sizeof(buf), "unknown type (0x%.4x)", terminal_type);
 1130                 return buf;
 1131         }
 1132 }
 1133 #endif
 1134 
 1135 Static int
 1136 uaudio_determine_class(const struct io_terminal *iot, struct mixerctl *mix)
 1137 {
 1138         int terminal_type;
 1139 
 1140         if (iot == NULL || iot->output == NULL) {
 1141                 mix->class = UAC_OUTPUT;
 1142                 return 0;
 1143         }
 1144         terminal_type = 0;
 1145         if (iot->output->size == 1)
 1146                 terminal_type = iot->output->terminals[0];
 1147         /*
 1148          * If the only output terminal is USB,
 1149          * the class is UAC_RECORD.
 1150          */
 1151         if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) {
 1152                 mix->class = UAC_RECORD;
 1153                 if (iot->inputs_size == 1
 1154                     && iot->inputs[0] != NULL
 1155                     && iot->inputs[0]->size == 1)
 1156                         return iot->inputs[0]->terminals[0];
 1157                 else
 1158                         return 0;
 1159         }
 1160         /*
 1161          * If the ultimate destination of the unit is just one output
 1162          * terminal and the unit is connected to the output terminal
 1163          * directly, the class is UAC_OUTPUT.
 1164          */
 1165         if (terminal_type != 0 && iot->direct) {
 1166                 mix->class = UAC_OUTPUT;
 1167                 return terminal_type;
 1168         }
 1169         /*
 1170          * If the unit is connected to just one input terminal,
 1171          * the class is UAC_INPUT.
 1172          */
 1173         if (iot->inputs_size == 1 && iot->inputs[0] != NULL
 1174             && iot->inputs[0]->size == 1) {
 1175                 mix->class = UAC_INPUT;
 1176                 return iot->inputs[0]->terminals[0];
 1177         }
 1178         /*
 1179          * Otherwise, the class is UAC_OUTPUT.
 1180          */
 1181         mix->class = UAC_OUTPUT;
 1182         return terminal_type;
 1183 }
 1184 
 1185 #if defined(__FreeBSD__)
 1186 const int 
 1187 uaudio_feature_name(const struct io_terminal *iot, struct mixerctl *mix)
 1188 {
 1189         int terminal_type;
 1190 
 1191         terminal_type = uaudio_determine_class(iot, mix);
 1192         if (mix->class == UAC_RECORD && terminal_type == 0)
 1193                 return SOUND_MIXER_IMIX;
 1194         DPRINTF(("%s: terminal_type=%s\n", __func__,
 1195                  uaudio_get_terminal_name(terminal_type)));
 1196         switch (terminal_type) {
 1197         case UAT_STREAM:
 1198                 return SOUND_MIXER_PCM;
 1199 
 1200         case UATI_MICROPHONE:
 1201         case UATI_DESKMICROPHONE:
 1202         case UATI_PERSONALMICROPHONE:
 1203         case UATI_OMNIMICROPHONE:
 1204         case UATI_MICROPHONEARRAY:
 1205         case UATI_PROCMICROPHONEARR:
 1206                 return SOUND_MIXER_MIC;
 1207 
 1208         case UATO_SPEAKER:
 1209         case UATO_DESKTOPSPEAKER:
 1210         case UATO_ROOMSPEAKER:
 1211         case UATO_COMMSPEAKER:
 1212                 return SOUND_MIXER_SPEAKER;
 1213 
 1214         case UATE_ANALOGCONN:
 1215         case UATE_LINECONN:
 1216         case UATE_LEGACYCONN:
 1217                 return SOUND_MIXER_LINE;
 1218 
 1219         case UATE_DIGITALAUIFC:
 1220         case UATE_SPDIF:
 1221         case UATE_1394DA:
 1222         case UATE_1394DV:
 1223                 return SOUND_MIXER_ALTPCM;
 1224 
 1225         case UATF_CDPLAYER:
 1226                 return SOUND_MIXER_CD;
 1227 
 1228         case UATF_SYNTHESIZER:
 1229                 return SOUND_MIXER_SYNTH;
 1230 
 1231         case UATF_VIDEODISCAUDIO:
 1232         case UATF_DVDAUDIO:
 1233         case UATF_TVTUNERAUDIO:
 1234                 return SOUND_MIXER_VIDEO;
 1235 
 1236 /* telephony terminal types */
 1237         case UATT_UNDEFINED:
 1238         case UATT_PHONELINE:
 1239         case UATT_TELEPHONE:
 1240         case UATT_DOWNLINEPHONE:
 1241                 return SOUND_MIXER_PHONEIN;
 1242 /*              return SOUND_MIXER_PHONEOUT;*/
 1243 
 1244         case UATF_RADIORECV:
 1245         case UATF_RADIOXMIT:
 1246                 return SOUND_MIXER_RADIO;
 1247 
 1248         case UAT_UNDEFINED:
 1249         case UAT_VENDOR:
 1250         case UATI_UNDEFINED:
 1251 /* output terminal types */
 1252         case UATO_UNDEFINED:
 1253         case UATO_DISPLAYAUDIO:
 1254         case UATO_SUBWOOFER:
 1255         case UATO_HEADPHONES:
 1256 /* bidir terminal types */
 1257         case UATB_UNDEFINED:
 1258         case UATB_HANDSET:
 1259         case UATB_HEADSET:
 1260         case UATB_SPEAKERPHONE:
 1261         case UATB_SPEAKERPHONEESUP:
 1262         case UATB_SPEAKERPHONEECANC:
 1263 /* external terminal types */
 1264         case UATE_UNDEFINED:
 1265 /* embedded function terminal types */
 1266         case UATF_UNDEFINED:
 1267         case UATF_CALIBNOISE:
 1268         case UATF_EQUNOISE:
 1269         case UATF_DAT:
 1270         case UATF_DCC:
 1271         case UATF_MINIDISK:
 1272         case UATF_ANALOGTAPE:
 1273         case UATF_PHONOGRAPH:
 1274         case UATF_VCRAUDIO:
 1275         case UATF_SATELLITE:
 1276         case UATF_CABLETUNER:
 1277         case UATF_DSS:
 1278         case UATF_MULTITRACK:
 1279         case 0xffff:
 1280         default:
 1281                 DPRINTF(("%s: 'master' for 0x%.4x\n", __func__, terminal_type));
 1282                 return SOUND_MIXER_VOLUME;
 1283         }
 1284         return SOUND_MIXER_VOLUME;
 1285 }
 1286 #else
 1287 Static const char *
 1288 uaudio_feature_name(const struct io_terminal *iot, struct mixerctl *mix)
 1289 {
 1290         int terminal_type;
 1291 
 1292         terminal_type = uaudio_determine_class(iot, mix);
 1293         if (mix->class == UAC_RECORD && terminal_type == 0)
 1294                 return AudioNmixerout;
 1295         DPRINTF(("%s: terminal_type=%s\n", __func__,
 1296                  uaudio_get_terminal_name(terminal_type)));
 1297         switch (terminal_type) {
 1298         case UAT_STREAM:
 1299                 return AudioNdac;
 1300 
 1301         case UATI_MICROPHONE:
 1302         case UATI_DESKMICROPHONE:
 1303         case UATI_PERSONALMICROPHONE:
 1304         case UATI_OMNIMICROPHONE:
 1305         case UATI_MICROPHONEARRAY:
 1306         case UATI_PROCMICROPHONEARR:
 1307                 return AudioNmicrophone;
 1308 
 1309         case UATO_SPEAKER:
 1310         case UATO_DESKTOPSPEAKER:
 1311         case UATO_ROOMSPEAKER:
 1312         case UATO_COMMSPEAKER:
 1313                 return AudioNspeaker;
 1314 
 1315         case UATO_HEADPHONES:
 1316                 return AudioNheadphone;
 1317 
 1318         case UATO_SUBWOOFER:
 1319                 return AudioNlfe;
 1320 
 1321         /* telephony terminal types */
 1322         case UATT_UNDEFINED:
 1323         case UATT_PHONELINE:
 1324         case UATT_TELEPHONE:
 1325         case UATT_DOWNLINEPHONE:
 1326                 return "phone";
 1327 
 1328         case UATE_ANALOGCONN:
 1329         case UATE_LINECONN:
 1330         case UATE_LEGACYCONN:
 1331                 return AudioNline;
 1332 
 1333         case UATE_DIGITALAUIFC:
 1334         case UATE_SPDIF:
 1335         case UATE_1394DA:
 1336         case UATE_1394DV:
 1337                 return AudioNaux;
 1338 
 1339         case UATF_CDPLAYER:
 1340                 return AudioNcd;
 1341 
 1342         case UATF_SYNTHESIZER:
 1343                 return AudioNfmsynth;
 1344 
 1345         case UATF_VIDEODISCAUDIO:
 1346         case UATF_DVDAUDIO:
 1347         case UATF_TVTUNERAUDIO:
 1348                 return AudioNvideo;
 1349 
 1350         case UAT_UNDEFINED:
 1351         case UAT_VENDOR:
 1352         case UATI_UNDEFINED:
 1353 /* output terminal types */
 1354         case UATO_UNDEFINED:
 1355         case UATO_DISPLAYAUDIO:
 1356 /* bidir terminal types */
 1357         case UATB_UNDEFINED:
 1358         case UATB_HANDSET:
 1359         case UATB_HEADSET:
 1360         case UATB_SPEAKERPHONE:
 1361         case UATB_SPEAKERPHONEESUP:
 1362         case UATB_SPEAKERPHONEECANC:
 1363 /* external terminal types */
 1364         case UATE_UNDEFINED:
 1365 /* embedded function terminal types */
 1366         case UATF_UNDEFINED:
 1367         case UATF_CALIBNOISE:
 1368         case UATF_EQUNOISE:
 1369         case UATF_DAT:
 1370         case UATF_DCC:
 1371         case UATF_MINIDISK:
 1372         case UATF_ANALOGTAPE:
 1373         case UATF_PHONOGRAPH:
 1374         case UATF_VCRAUDIO:
 1375         case UATF_SATELLITE:
 1376         case UATF_CABLETUNER:
 1377         case UATF_DSS:
 1378         case UATF_RADIORECV:
 1379         case UATF_RADIOXMIT:
 1380         case UATF_MULTITRACK:
 1381         case 0xffff:
 1382         default:
 1383                 DPRINTF(("%s: 'master' for 0x%.4x\n", __func__, terminal_type));
 1384                 return AudioNmaster;
 1385         }
 1386         return AudioNmaster;
 1387 }
 1388 #endif
 1389 
 1390 Static void
 1391 uaudio_add_feature(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
 1392 {
 1393         const struct usb_audio_feature_unit *d = iot[id].d.fu;
 1394         uByte *ctls = d->bmaControls;
 1395         int ctlsize = d->bControlSize;
 1396         int nchan = (d->bLength - 7) / ctlsize;
 1397         u_int fumask, mmask, cmask;
 1398         struct mixerctl mix;
 1399         int chan, ctl, i, unit;
 1400 #if defined(__FreeBSD__)
 1401         int mixernumber;
 1402 #else
 1403         const char *mixername;
 1404 #endif
 1405 
 1406 #define GET(i) (ctls[(i)*ctlsize] | \
 1407                 (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
 1408 
 1409         mmask = GET(0);
 1410         /* Figure out what we can control */
 1411         for (cmask = 0, chan = 1; chan < nchan; chan++) {
 1412                 DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%x\n",
 1413                             chan, GET(chan)));
 1414                 cmask |= GET(chan);
 1415         }
 1416 
 1417 #if !defined(__FreeBSD__)
 1418         DPRINTFN(1,("uaudio_add_feature: bUnitId=%d, "
 1419                     "%d channels, mmask=0x%04x, cmask=0x%04x\n",
 1420                     d->bUnitId, nchan, mmask, cmask));
 1421 #endif
 1422 
 1423         if (nchan > MIX_MAX_CHAN)
 1424                 nchan = MIX_MAX_CHAN;
 1425         unit = d->bUnitId;
 1426         mix.wIndex = MAKE(unit, sc->sc_ac_iface);
 1427         for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) {
 1428                 fumask = FU_MASK(ctl);
 1429                 DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04x\n",
 1430                             ctl, fumask));
 1431                 if (mmask & fumask) {
 1432                         mix.nchan = 1;
 1433                         mix.wValue[0] = MAKE(ctl, 0);
 1434                 } else if (cmask & fumask) {
 1435                         mix.nchan = nchan - 1;
 1436                         for (i = 1; i < nchan; i++) {
 1437                                 if (GET(i) & fumask)
 1438                                         mix.wValue[i-1] = MAKE(ctl, i);
 1439                                 else
 1440                                         mix.wValue[i-1] = -1;
 1441                         }
 1442                 } else {
 1443                         continue;
 1444                 }
 1445 #undef GET
 1446 
 1447 #if defined(__FreeBSD__)
 1448                 mixernumber = uaudio_feature_name(&iot[id], &mix);
 1449 #else
 1450                 mixername = uaudio_feature_name(&iot[id], &mix);
 1451 #endif
 1452                 switch (ctl) {
 1453                 case MUTE_CONTROL:
 1454                         mix.type = MIX_ON_OFF;
 1455 #if defined(__FreeBSD__)
 1456                         mix.ctl = SOUND_MIXER_NRDEVICES;
 1457 #else
 1458                         mix.ctlunit = "";
 1459                         snprintf(mix.ctlname, sizeof(mix.ctlname),
 1460                                  "%s.%s", mixername, AudioNmute);
 1461 #endif
 1462                         break;
 1463                 case VOLUME_CONTROL:
 1464                         mix.type = MIX_SIGNED_16;
 1465 #if defined(__FreeBSD__)
 1466                         mix.ctl = mixernumber;
 1467 #else
 1468                         mix.ctlunit = AudioNvolume;
 1469                         strlcpy(mix.ctlname, mixername, sizeof(mix.ctlname));
 1470 #endif
 1471                         break;
 1472                 case BASS_CONTROL:
 1473                         mix.type = MIX_SIGNED_8;
 1474 #if defined(__FreeBSD__)
 1475                         mix.ctl = SOUND_MIXER_BASS;
 1476 #else
 1477                         mix.ctlunit = AudioNbass;
 1478                         snprintf(mix.ctlname, sizeof(mix.ctlname),
 1479                                  "%s.%s", mixername, AudioNbass);
 1480 #endif
 1481                         break;
 1482                 case MID_CONTROL:
 1483                         mix.type = MIX_SIGNED_8;
 1484 #if defined(__FreeBSD__)
 1485                         mix.ctl = SOUND_MIXER_NRDEVICES;        /* XXXXX */
 1486 #else
 1487                         mix.ctlunit = AudioNmid;
 1488                         snprintf(mix.ctlname, sizeof(mix.ctlname),
 1489                                  "%s.%s", mixername, AudioNmid);
 1490 #endif
 1491                         break;
 1492                 case TREBLE_CONTROL:
 1493                         mix.type = MIX_SIGNED_8;
 1494 #if defined(__FreeBSD__)
 1495                         mix.ctl = SOUND_MIXER_TREBLE;
 1496 #else
 1497                         mix.ctlunit = AudioNtreble;
 1498                         snprintf(mix.ctlname, sizeof(mix.ctlname),
 1499                                  "%s.%s", mixername, AudioNtreble);
 1500 #endif
 1501                         break;
 1502                 case GRAPHIC_EQUALIZER_CONTROL:
 1503                         continue; /* XXX don't add anything */
 1504                         break;
 1505                 case AGC_CONTROL:
 1506                         mix.type = MIX_ON_OFF;
 1507 #if defined(__FreeBSD__)
 1508                         mix.ctl = SOUND_MIXER_NRDEVICES;        /* XXXXX */
 1509 #else
 1510                         mix.ctlunit = "";
 1511                         snprintf(mix.ctlname, sizeof(mix.ctlname), "%s.%s",
 1512                                  mixername, AudioNagc);
 1513 #endif
 1514                         break;
 1515                 case DELAY_CONTROL:
 1516                         mix.type = MIX_UNSIGNED_16;
 1517 #if defined(__FreeBSD__)
 1518                         mix.ctl = SOUND_MIXER_NRDEVICES;        /* XXXXX */
 1519 #else
 1520                         mix.ctlunit = "4 ms";
 1521                         snprintf(mix.ctlname, sizeof(mix.ctlname),
 1522                                  "%s.%s", mixername, AudioNdelay);
 1523 #endif
 1524                         break;
 1525                 case BASS_BOOST_CONTROL:
 1526                         mix.type = MIX_ON_OFF;
 1527 #if defined(__FreeBSD__)
 1528                         mix.ctl = SOUND_MIXER_NRDEVICES;        /* XXXXX */
 1529 #else
 1530                         mix.ctlunit = "";
 1531                         snprintf(mix.ctlname, sizeof(mix.ctlname),
 1532                                  "%s.%s", mixername, AudioNbassboost);
 1533 #endif
 1534                         break;
 1535                 case LOUDNESS_CONTROL:
 1536                         mix.type = MIX_ON_OFF;
 1537 #if defined(__FreeBSD__)
 1538                         mix.ctl = SOUND_MIXER_LOUD;     /* Is this correct ? */
 1539 #else
 1540                         mix.ctlunit = "";
 1541                         snprintf(mix.ctlname, sizeof(mix.ctlname),
 1542                                  "%s.%s", mixername, AudioNloudness);
 1543 #endif
 1544                         break;
 1545                 }
 1546                 uaudio_mixer_add_ctl(sc, &mix);
 1547         }
 1548 }
 1549 
 1550 Static void
 1551 uaudio_add_processing_updown(struct uaudio_softc *sc,
 1552                              const struct io_terminal *iot, int id)
 1553 {
 1554         const struct usb_audio_processing_unit *d = iot[id].d.pu;
 1555         const struct usb_audio_processing_unit_1 *d1 =
 1556             (const struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
 1557         const struct usb_audio_processing_unit_updown *ud =
 1558             (const struct usb_audio_processing_unit_updown *)
 1559                 &d1->bmControls[d1->bControlSize];
 1560         struct mixerctl mix;
 1561         int i;
 1562 
 1563         DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
 1564                     d->bUnitId, ud->bNrModes));
 1565 
 1566         if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
 1567                 DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
 1568                 return;
 1569         }
 1570 
 1571         mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
 1572         mix.nchan = 1;
 1573         mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
 1574         uaudio_determine_class(&iot[id], &mix);
 1575         mix.type = MIX_ON_OFF;  /* XXX */
 1576 #if !defined(__FreeBSD__)
 1577         mix.ctlunit = "";
 1578         snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d-mode", d->bUnitId);
 1579 #endif
 1580 
 1581         for (i = 0; i < ud->bNrModes; i++) {
 1582                 DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n",
 1583                             i, UGETW(ud->waModes[i])));
 1584                 /* XXX */
 1585         }
 1586         uaudio_mixer_add_ctl(sc, &mix);
 1587 }
 1588 
 1589 Static void
 1590 uaudio_add_processing(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
 1591 {
 1592         const struct usb_audio_processing_unit *d = iot[id].d.pu;
 1593         const struct usb_audio_processing_unit_1 *d1 =
 1594             (const struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
 1595         int ptype = UGETW(d->wProcessType);
 1596         struct mixerctl mix;
 1597 
 1598         DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
 1599                     "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins));
 1600 
 1601         if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
 1602                 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
 1603                 mix.nchan = 1;
 1604                 mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
 1605                 uaudio_determine_class(&iot[id], &mix);
 1606                 mix.type = MIX_ON_OFF;
 1607 #if !defined(__FreeBSD__)
 1608                 mix.ctlunit = "";
 1609                 snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d.%d-enable",
 1610                     d->bUnitId, ptype);
 1611 #endif
 1612                 uaudio_mixer_add_ctl(sc, &mix);
 1613         }
 1614 
 1615         switch(ptype) {
 1616         case UPDOWNMIX_PROCESS:
 1617                 uaudio_add_processing_updown(sc, iot, id);
 1618                 break;
 1619         case DOLBY_PROLOGIC_PROCESS:
 1620         case P3D_STEREO_EXTENDER_PROCESS:
 1621         case REVERBATION_PROCESS:
 1622         case CHORUS_PROCESS:
 1623         case DYN_RANGE_COMP_PROCESS:
 1624         default:
 1625 #ifdef USB_DEBUG
 1626                 printf("uaudio_add_processing: unit %d, type=%d not impl.\n",
 1627                        d->bUnitId, ptype);
 1628 #endif
 1629                 break;
 1630         }
 1631 }
 1632 
 1633 Static void
 1634 uaudio_add_extension(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
 1635 {
 1636         const struct usb_audio_extension_unit *d = iot[id].d.eu;
 1637         const struct usb_audio_extension_unit_1 *d1 =
 1638             (const struct usb_audio_extension_unit_1 *)&d->baSourceId[d->bNrInPins];
 1639         struct mixerctl mix;
 1640 
 1641         DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
 1642                     d->bUnitId, d->bNrInPins));
 1643 
 1644         if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU)
 1645                 return;
 1646 
 1647         if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
 1648                 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
 1649                 mix.nchan = 1;
 1650                 mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
 1651                 uaudio_determine_class(&iot[id], &mix);
 1652                 mix.type = MIX_ON_OFF;
 1653 #if !defined(__FreeBSD__)
 1654                 mix.ctlunit = "";
 1655                 snprintf(mix.ctlname, sizeof(mix.ctlname), "ext%d-enable",
 1656                     d->bUnitId);
 1657 #endif
 1658                 uaudio_mixer_add_ctl(sc, &mix);
 1659         }
 1660 }
 1661 
 1662 Static struct terminal_list*
 1663 uaudio_merge_terminal_list(const struct io_terminal *iot)
 1664 {
 1665         struct terminal_list *tml;
 1666         uint16_t *ptm;
 1667         int i, len;
 1668 
 1669         len = 0;
 1670         if (iot->inputs == NULL)
 1671                 return NULL;
 1672         for (i = 0; i < iot->inputs_size; i++) {
 1673                 if (iot->inputs[i] != NULL)
 1674                         len += iot->inputs[i]->size;
 1675         }
 1676         tml = malloc(TERMINAL_LIST_SIZE(len), M_TEMP, M_NOWAIT);
 1677         if (tml == NULL) {
 1678                 printf("uaudio_merge_terminal_list: no memory\n");
 1679                 return NULL;
 1680         }
 1681         tml->size = 0;
 1682         ptm = tml->terminals;
 1683         for (i = 0; i < iot->inputs_size; i++) {
 1684                 if (iot->inputs[i] == NULL)
 1685                         continue;
 1686                 if (iot->inputs[i]->size > len)
 1687                         break;
 1688                 memcpy(ptm, iot->inputs[i]->terminals,
 1689                        iot->inputs[i]->size * sizeof(uint16_t));
 1690                 tml->size += iot->inputs[i]->size;
 1691                 ptm += iot->inputs[i]->size;
 1692                 len -= iot->inputs[i]->size;
 1693         }
 1694         return tml;
 1695 }
 1696 
 1697 Static struct terminal_list *
 1698 uaudio_io_terminaltype(int outtype, struct io_terminal *iot, int id)
 1699 {
 1700         struct terminal_list *tml;
 1701         struct io_terminal *it;
 1702         int src_id, i;
 1703 
 1704         it = &iot[id];
 1705         if (it->output != NULL) {
 1706                 /* already has outtype? */
 1707                 for (i = 0; i < it->output->size; i++)
 1708                         if (it->output->terminals[i] == outtype)
 1709                                 return uaudio_merge_terminal_list(it);
 1710                 tml = malloc(TERMINAL_LIST_SIZE(it->output->size + 1),
 1711                              M_TEMP, M_NOWAIT);
 1712                 if (tml == NULL) {
 1713                         printf("uaudio_io_terminaltype: no memory\n");
 1714                         return uaudio_merge_terminal_list(it);
 1715                 }
 1716                 memcpy(tml, it->output, TERMINAL_LIST_SIZE(it->output->size));
 1717                 tml->terminals[it->output->size] = outtype;
 1718                 tml->size++;
 1719                 free(it->output, M_TEMP);
 1720                 it->output = tml;
 1721                 if (it->inputs != NULL) {
 1722                         for (i = 0; i < it->inputs_size; i++)
 1723                                 if (it->inputs[i] != NULL)
 1724                                         free(it->inputs[i], M_TEMP);
 1725                         free(it->inputs, M_TEMP);
 1726                 }
 1727                 it->inputs_size = 0;
 1728                 it->inputs = NULL;
 1729         } else {                /* end `iot[id] != NULL' */
 1730                 it->inputs_size = 0;
 1731                 it->inputs = NULL;
 1732                 it->output = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
 1733                 if (it->output == NULL) {
 1734                         printf("uaudio_io_terminaltype: no memory\n");
 1735                         return NULL;
 1736                 }
 1737                 it->output->terminals[0] = outtype;
 1738                 it->output->size = 1;
 1739                 it->direct = FALSE;
 1740         }
 1741 
 1742         switch (it->d.desc->bDescriptorSubtype) {
 1743         case UDESCSUB_AC_INPUT:
 1744                 it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
 1745                 if (it->inputs == NULL) {
 1746                         printf("uaudio_io_terminaltype: no memory\n");
 1747                         return NULL;
 1748                 }
 1749                 tml = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
 1750                 if (tml == NULL) {
 1751                         printf("uaudio_io_terminaltype: no memory\n");
 1752                         free(it->inputs, M_TEMP);
 1753                         it->inputs = NULL;
 1754                         return NULL;
 1755                 }
 1756                 it->inputs[0] = tml;
 1757                 tml->terminals[0] = UGETW(it->d.it->wTerminalType);
 1758                 tml->size = 1;
 1759                 it->inputs_size = 1;
 1760                 return uaudio_merge_terminal_list(it);
 1761         case UDESCSUB_AC_FEATURE:
 1762                 src_id = it->d.fu->bSourceId;
 1763                 it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
 1764                 if (it->inputs == NULL) {
 1765                         printf("uaudio_io_terminaltype: no memory\n");
 1766                         return uaudio_io_terminaltype(outtype, iot, src_id);
 1767                 }
 1768                 it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
 1769                 it->inputs_size = 1;
 1770                 return uaudio_merge_terminal_list(it);
 1771         case UDESCSUB_AC_OUTPUT:
 1772                 it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
 1773                 if (it->inputs == NULL) {
 1774                         printf("uaudio_io_terminaltype: no memory\n");
 1775                         return NULL;
 1776                 }
 1777                 src_id = it->d.ot->bSourceId;
 1778                 it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
 1779                 it->inputs_size = 1;
 1780                 iot[src_id].direct = TRUE;
 1781                 return NULL;
 1782         case UDESCSUB_AC_MIXER:
 1783                 it->inputs_size = 0;
 1784                 it->inputs = malloc(sizeof(struct terminal_list *)
 1785                                     * it->d.mu->bNrInPins, M_TEMP, M_NOWAIT);
 1786                 if (it->inputs == NULL) {
 1787                         printf("uaudio_io_terminaltype: no memory\n");
 1788                         return NULL;
 1789                 }
 1790                 for (i = 0; i < it->d.mu->bNrInPins; i++) {
 1791                         src_id = it->d.mu->baSourceId[i];
 1792                         it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
 1793                                                                src_id);
 1794                         it->inputs_size++;
 1795                 }
 1796                 return uaudio_merge_terminal_list(it);
 1797         case UDESCSUB_AC_SELECTOR:
 1798                 it->inputs_size = 0;
 1799                 it->inputs = malloc(sizeof(struct terminal_list *)
 1800                                     * it->d.su->bNrInPins, M_TEMP, M_NOWAIT);
 1801                 if (it->inputs == NULL) {
 1802                         printf("uaudio_io_terminaltype: no memory\n");
 1803                         return NULL;
 1804                 }
 1805                 for (i = 0; i < it->d.su->bNrInPins; i++) {
 1806                         src_id = it->d.su->baSourceId[i];
 1807                         it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
 1808                                                                src_id);
 1809                         it->inputs_size++;
 1810                 }
 1811                 return uaudio_merge_terminal_list(it);
 1812         case UDESCSUB_AC_PROCESSING:
 1813                 it->inputs_size = 0;
 1814                 it->inputs = malloc(sizeof(struct terminal_list *)
 1815                                     * it->d.pu->bNrInPins, M_TEMP, M_NOWAIT);
 1816                 if (it->inputs == NULL) {
 1817                         printf("uaudio_io_terminaltype: no memory\n");
 1818                         return NULL;
 1819                 }
 1820                 for (i = 0; i < it->d.pu->bNrInPins; i++) {
 1821                         src_id = it->d.pu->baSourceId[i];
 1822                         it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
 1823                                                                src_id);
 1824                         it->inputs_size++;
 1825                 }
 1826                 return uaudio_merge_terminal_list(it);
 1827         case UDESCSUB_AC_EXTENSION:
 1828                 it->inputs_size = 0;
 1829                 it->inputs = malloc(sizeof(struct terminal_list *)
 1830                                     * it->d.eu->bNrInPins, M_TEMP, M_NOWAIT);
 1831                 if (it->inputs == NULL) {
 1832                         printf("uaudio_io_terminaltype: no memory\n");
 1833                         return NULL;
 1834                 }
 1835                 for (i = 0; i < it->d.eu->bNrInPins; i++) {
 1836                         src_id = it->d.eu->baSourceId[i];
 1837                         it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
 1838                                                                src_id);
 1839                         it->inputs_size++;
 1840                 }
 1841                 return uaudio_merge_terminal_list(it);
 1842         case UDESCSUB_AC_HEADER:
 1843         default:
 1844                 return NULL;
 1845         }
 1846 }
 1847 
 1848 Static usbd_status
 1849 uaudio_identify(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
 1850 {
 1851         usbd_status err;
 1852 
 1853         err = uaudio_identify_ac(sc, cdesc);
 1854         if (err)
 1855                 return (err);
 1856         return (uaudio_identify_as(sc, cdesc));
 1857 }
 1858 
 1859 Static void
 1860 uaudio_add_alt(struct uaudio_softc *sc, const struct as_info *ai)
 1861 {
 1862         size_t len;
 1863         struct as_info *nai;
 1864 
 1865         len = sizeof(*ai) * (sc->sc_nalts + 1);
 1866         nai = malloc(len, M_USBDEV, M_NOWAIT);
 1867         if (nai == NULL) {
 1868                 printf("uaudio_add_alt: no memory\n");
 1869                 return;
 1870         }
 1871         /* Copy old data, if there was any */
 1872         if (sc->sc_nalts != 0) {
 1873                 memcpy(nai, sc->sc_alts, sizeof(*ai) * (sc->sc_nalts));
 1874                 free(sc->sc_alts, M_USBDEV);
 1875         }
 1876         sc->sc_alts = nai;
 1877         DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%d\n",
 1878                     ai->alt, ai->encoding));
 1879         sc->sc_alts[sc->sc_nalts++] = *ai;
 1880 }
 1881 
 1882 Static usbd_status
 1883 uaudio_process_as(struct uaudio_softc *sc, const char *buf, int *offsp,
 1884                   int size, const usb_interface_descriptor_t *id)
 1885 #define offs (*offsp)
 1886 {
 1887         const struct usb_audio_streaming_interface_descriptor *asid;
 1888         const struct usb_audio_streaming_type1_descriptor *asf1d;
 1889         const usb_endpoint_descriptor_audio_t *ed;
 1890         const usb_endpoint_descriptor_audio_t *epdesc1;
 1891         const struct usb_audio_streaming_endpoint_descriptor *sed;
 1892         int format, chan, prec, enc;
 1893         int dir, type, sync;
 1894         struct as_info ai;
 1895         const char *format_str;
 1896 
 1897         asid = (const void *)(buf + offs);
 1898         if (asid->bDescriptorType != UDESC_CS_INTERFACE ||
 1899             asid->bDescriptorSubtype != AS_GENERAL)
 1900                 return (USBD_INVAL);
 1901         DPRINTF(("uaudio_process_as: asid: bTerminakLink=%d wFormatTag=%d\n",
 1902                  asid->bTerminalLink, UGETW(asid->wFormatTag)));
 1903         offs += asid->bLength;
 1904         if (offs > size)
 1905                 return (USBD_INVAL);
 1906 
 1907         asf1d = (const void *)(buf + offs);
 1908         if (asf1d->bDescriptorType != UDESC_CS_INTERFACE ||
 1909             asf1d->bDescriptorSubtype != FORMAT_TYPE)
 1910                 return (USBD_INVAL);
 1911         offs += asf1d->bLength;
 1912         if (offs > size)
 1913                 return (USBD_INVAL);
 1914 
 1915         if (asf1d->bFormatType != FORMAT_TYPE_I) {
 1916                 printf("%s: ignored setting with type %d format\n",
 1917                        USBDEVNAME(sc->sc_dev), UGETW(asid->wFormatTag));
 1918                 return (USBD_NORMAL_COMPLETION);
 1919         }
 1920 
 1921         ed = (const void *)(buf + offs);
 1922         if (ed->bDescriptorType != UDESC_ENDPOINT)
 1923                 return (USBD_INVAL);
 1924         DPRINTF(("uaudio_process_as: endpoint[0] bLength=%d bDescriptorType=%d "
 1925                  "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d "
 1926                  "bInterval=%d bRefresh=%d bSynchAddress=%d\n",
 1927                  ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
 1928                  ed->bmAttributes, UGETW(ed->wMaxPacketSize),
 1929                  ed->bInterval, ed->bRefresh, ed->bSynchAddress));
 1930         offs += ed->bLength;
 1931         if (offs > size)
 1932                 return (USBD_INVAL);
 1933         if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
 1934                 return (USBD_INVAL);
 1935 
 1936         dir = UE_GET_DIR(ed->bEndpointAddress);
 1937         type = UE_GET_ISO_TYPE(ed->bmAttributes);
 1938         if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) &&
 1939             dir == UE_DIR_IN && type == UE_ISO_ADAPT)
 1940                 type = UE_ISO_ASYNC;
 1941 
 1942         /* We can't handle endpoints that need a sync pipe yet. */
 1943         sync = FALSE;
 1944         if (dir == UE_DIR_IN && type == UE_ISO_ADAPT) {
 1945                 sync = TRUE;
 1946 #ifndef UAUDIO_MULTIPLE_ENDPOINTS
 1947                 printf("%s: ignored input endpoint of type adaptive\n",
 1948                        USBDEVNAME(sc->sc_dev));
 1949                 return (USBD_NORMAL_COMPLETION);
 1950 #endif
 1951         }
 1952         if (dir != UE_DIR_IN && type == UE_ISO_ASYNC) {
 1953                 sync = TRUE;
 1954 #ifndef UAUDIO_MULTIPLE_ENDPOINTS
 1955                 printf("%s: ignored output endpoint of type async\n",
 1956                        USBDEVNAME(sc->sc_dev));
 1957                 return (USBD_NORMAL_COMPLETION);
 1958 #endif
 1959         }
 1960 
 1961         sed = (const void *)(buf + offs);
 1962         if (sed->bDescriptorType != UDESC_CS_ENDPOINT ||
 1963             sed->bDescriptorSubtype != AS_GENERAL)
 1964                 return (USBD_INVAL);
 1965         DPRINTF((" streadming_endpoint: offset=%d bLength=%d\n", offs, sed->bLength));
 1966         offs += sed->bLength;
 1967         if (offs > size)
 1968                 return (USBD_INVAL);
 1969 
 1970         if (sync && id->bNumEndpoints <= 1) {
 1971                 printf("%s: a sync-pipe endpoint but no other endpoint\n",
 1972                        USBDEVNAME(sc->sc_dev));
 1973                 return USBD_INVAL;
 1974         }
 1975         if (!sync && id->bNumEndpoints > 1) {
 1976                 printf("%s: non sync-pipe endpoint but multiple endpoints\n",
 1977                        USBDEVNAME(sc->sc_dev));
 1978                 return USBD_INVAL;
 1979         }
 1980         epdesc1 = NULL;
 1981         if (id->bNumEndpoints > 1) {
 1982                 epdesc1 = (const void*)(buf + offs);
 1983                 if (epdesc1->bDescriptorType != UDESC_ENDPOINT)
 1984                         return USBD_INVAL;
 1985                 DPRINTF(("uaudio_process_as: endpoint[1] bLength=%d "
 1986                          "bDescriptorType=%d bEndpointAddress=%d "
 1987                          "bmAttributes=0x%x wMaxPacketSize=%d bInterval=%d "
 1988                          "bRefresh=%d bSynchAddress=%d\n",
 1989                          epdesc1->bLength, epdesc1->bDescriptorType,
 1990                          epdesc1->bEndpointAddress, epdesc1->bmAttributes,
 1991                          UGETW(epdesc1->wMaxPacketSize), epdesc1->bInterval,
 1992                          epdesc1->bRefresh, epdesc1->bSynchAddress));
 1993                 offs += epdesc1->bLength;
 1994                 if (offs > size)
 1995                         return USBD_INVAL;
 1996                 if (epdesc1->bSynchAddress != 0) {
 1997                         printf("%s: invalid endpoint: bSynchAddress=0\n",
 1998                                USBDEVNAME(sc->sc_dev));
 1999                         return USBD_INVAL;
 2000                 }
 2001                 if (UE_GET_XFERTYPE(epdesc1->bmAttributes) != UE_ISOCHRONOUS) {
 2002                         printf("%s: invalid endpoint: bmAttributes=0x%x\n",
 2003                                USBDEVNAME(sc->sc_dev), epdesc1->bmAttributes);
 2004                         return USBD_INVAL;
 2005                 }
 2006                 if (epdesc1->bEndpointAddress != ed->bSynchAddress) {
 2007                         printf("%s: invalid endpoint addresses: "
 2008                                "ep[0]->bSynchAddress=0x%x "
 2009                                "ep[1]->bEndpointAddress=0x%x\n",
 2010                                USBDEVNAME(sc->sc_dev), ed->bSynchAddress,
 2011                                epdesc1->bEndpointAddress);
 2012                         return USBD_INVAL;
 2013                 }
 2014                 /* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */
 2015         }
 2016 
 2017         format = UGETW(asid->wFormatTag);
 2018         chan = asf1d->bNrChannels;
 2019         prec = asf1d->bBitResolution;
 2020         if (prec != 8 && prec != 16 && prec != 24) {
 2021                 printf("%s: ignored setting with precision %d\n",
 2022                        USBDEVNAME(sc->sc_dev), prec);
 2023                 return (USBD_NORMAL_COMPLETION);
 2024         }
 2025         switch (format) {
 2026         case UA_FMT_PCM:
 2027                 if (prec == 8) {
 2028                         sc->sc_altflags |= HAS_8;
 2029                 } else if (prec == 16) {
 2030                         sc->sc_altflags |= HAS_16;
 2031                 } else if (prec == 24) {
 2032                         sc->sc_altflags |= HAS_24;
 2033                 }
 2034                 enc = AUDIO_ENCODING_SLINEAR_LE;
 2035                 format_str = "pcm";
 2036                 break;
 2037         case UA_FMT_PCM8:
 2038                 enc = AUDIO_ENCODING_ULINEAR_LE;
 2039                 sc->sc_altflags |= HAS_8U;
 2040                 format_str = "pcm8";
 2041                 break;
 2042         case UA_FMT_ALAW:
 2043                 enc = AUDIO_ENCODING_ALAW;
 2044                 sc->sc_altflags |= HAS_ALAW;
 2045                 format_str = "alaw";
 2046                 break;
 2047         case UA_FMT_MULAW:
 2048                 enc = AUDIO_ENCODING_ULAW;
 2049                 sc->sc_altflags |= HAS_MULAW;
 2050                 format_str = "mulaw";
 2051                 break;
 2052         case UA_FMT_IEEE_FLOAT:
 2053         default:
 2054                 printf("%s: ignored setting with format %d\n",
 2055                        USBDEVNAME(sc->sc_dev), format);
 2056                 return (USBD_NORMAL_COMPLETION);
 2057         }
 2058 #ifdef USB_DEBUG
 2059         printf("%s: %s: %dch, %d/%dbit, %s,", USBDEVNAME(sc->sc_dev),
 2060                dir == UE_DIR_IN ? "recording" : "playback",
 2061                chan, prec, asf1d->bSubFrameSize * 8, format_str);
 2062         if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
 2063                 printf(" %d-%dHz\n", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
 2064         } else {
 2065                 int r;
 2066                 printf(" %d", UA_GETSAMP(asf1d, 0));
 2067                 for (r = 1; r < asf1d->bSamFreqType; r++)
 2068                         printf(",%d", UA_GETSAMP(asf1d, r));
 2069                 printf("Hz\n");
 2070         }
 2071 #endif
 2072         ai.alt = id->bAlternateSetting;
 2073         ai.encoding = enc;
 2074         ai.attributes = sed->bmAttributes;
 2075         ai.idesc = id;
 2076         ai.edesc = ed;
 2077         ai.edesc1 = epdesc1;
 2078         ai.asf1desc = asf1d;
 2079         ai.sc_busy = 0;
 2080         uaudio_add_alt(sc, &ai);
 2081 #ifdef USB_DEBUG
 2082         if (ai.attributes & UA_SED_FREQ_CONTROL)
 2083                 DPRINTFN(1, ("uaudio_process_as:  FREQ_CONTROL\n"));
 2084         if (ai.attributes & UA_SED_PITCH_CONTROL)
 2085                 DPRINTFN(1, ("uaudio_process_as:  PITCH_CONTROL\n"));
 2086 #endif
 2087         sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD;
 2088 
 2089         return (USBD_NORMAL_COMPLETION);
 2090 }
 2091 #undef offs
 2092 
 2093 Static usbd_status
 2094 uaudio_identify_as(struct uaudio_softc *sc,
 2095                    const usb_config_descriptor_t *cdesc)
 2096 {
 2097         const usb_interface_descriptor_t *id;
 2098         const char *buf;
 2099         int size, offs;
 2100 
 2101         size = UGETW(cdesc->wTotalLength);
 2102         buf = (const char *)cdesc;
 2103 
 2104         /* Locate the AudioStreaming interface descriptor. */
 2105         offs = 0;
 2106         id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM);
 2107         if (id == NULL)
 2108                 return (USBD_INVAL);
 2109 
 2110         /* Loop through all the alternate settings. */
 2111         while (offs <= size) {
 2112                 DPRINTFN(2, ("uaudio_identify: interface=%d offset=%d\n",
 2113                     id->bInterfaceNumber, offs));
 2114                 switch (id->bNumEndpoints) {
 2115                 case 0:
 2116                         DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n",
 2117                                      id->bAlternateSetting));
 2118                         sc->sc_nullalt = id->bAlternateSetting;
 2119                         break;
 2120                 case 1:
 2121 #ifdef UAUDIO_MULTIPLE_ENDPOINTS
 2122                 case 2:
 2123 #endif
 2124                         uaudio_process_as(sc, buf, &offs, size, id);
 2125                         break;
 2126                 default:
 2127                         printf("%s: ignored audio interface with %d "
 2128                                "endpoints\n",
 2129                                USBDEVNAME(sc->sc_dev), id->bNumEndpoints);
 2130                         break;
 2131                 }
 2132                 id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM);
 2133                 if (id == NULL)
 2134                         break;
 2135         }
 2136         if (offs > size)
 2137                 return (USBD_INVAL);
 2138         DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts));
 2139 
 2140         if (sc->sc_mode == 0) {
 2141                 printf("%s: no usable endpoint found\n",
 2142                        USBDEVNAME(sc->sc_dev));
 2143                 return (USBD_INVAL);
 2144         }
 2145 
 2146         return (USBD_NORMAL_COMPLETION);
 2147 }
 2148 
 2149 Static usbd_status
 2150 uaudio_identify_ac(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
 2151 {
 2152         struct io_terminal* iot;
 2153         const usb_interface_descriptor_t *id;
 2154         const struct usb_audio_control_descriptor *acdp;
 2155         const usb_descriptor_t *dp;
 2156         const struct usb_audio_output_terminal *pot;
 2157         struct terminal_list *tml;
 2158         const char *buf, *ibuf, *ibufend;
 2159         int size, offs, aclen, ndps, i, j;
 2160 
 2161         size = UGETW(cdesc->wTotalLength);
 2162         buf = (const char *)cdesc;
 2163 
 2164         /* Locate the AudioControl interface descriptor. */
 2165         offs = 0;
 2166         id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL);
 2167         if (id == NULL)
 2168                 return (USBD_INVAL);
 2169         if (offs + sizeof *acdp > size)
 2170                 return (USBD_INVAL);
 2171         sc->sc_ac_iface = id->bInterfaceNumber;
 2172         DPRINTFN(2,("uaudio_identify_ac: AC interface is %d\n", sc->sc_ac_iface));
 2173 
 2174         /* A class-specific AC interface header should follow. */
 2175         ibuf = buf + offs;
 2176         acdp = (const struct usb_audio_control_descriptor *)ibuf;
 2177         if (acdp->bDescriptorType != UDESC_CS_INTERFACE ||
 2178             acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)
 2179                 return (USBD_INVAL);
 2180         aclen = UGETW(acdp->wTotalLength);
 2181         if (offs + aclen > size)
 2182                 return (USBD_INVAL);
 2183 
 2184         if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) &&
 2185              UGETW(acdp->bcdADC) != UAUDIO_VERSION)
 2186                 return (USBD_INVAL);
 2187 
 2188         sc->sc_audio_rev = UGETW(acdp->bcdADC);
 2189         DPRINTFN(2,("uaudio_identify_ac: found AC header, vers=%03x, len=%d\n",
 2190                  sc->sc_audio_rev, aclen));
 2191 
 2192         sc->sc_nullalt = -1;
 2193 
 2194         /* Scan through all the AC specific descriptors */
 2195         ibufend = ibuf + aclen;
 2196         dp = (const usb_descriptor_t *)ibuf;
 2197         ndps = 0;
 2198         iot = malloc(sizeof(struct io_terminal) * 256, M_TEMP, M_NOWAIT | M_ZERO);
 2199         if (iot == NULL) {
 2200                 printf("%s: no memory\n", __func__);
 2201                 return USBD_NOMEM;
 2202         }
 2203         for (;;) {
 2204                 ibuf += dp->bLength;
 2205                 if (ibuf >= ibufend)
 2206                         break;
 2207                 dp = (const usb_descriptor_t *)ibuf;
 2208                 if (ibuf + dp->bLength > ibufend)
 2209                         return (USBD_INVAL);
 2210                 if (dp->bDescriptorType != UDESC_CS_INTERFACE) {
 2211                         printf("uaudio_identify_ac: skip desc type=0x%02x\n",
 2212                                dp->bDescriptorType);
 2213                         continue;
 2214                 }
 2215                 i = ((const struct usb_audio_input_terminal *)dp)->bTerminalId;
 2216                 iot[i].d.desc = dp;
 2217                 if (i > ndps)
 2218                         ndps = i;
 2219         }
 2220         ndps++;
 2221 
 2222         /* construct io_terminal */
 2223         for (i = 0; i < ndps; i++) {
 2224                 dp = iot[i].d.desc;
 2225                 if (dp == NULL)
 2226                         continue;
 2227                 if (dp->bDescriptorSubtype != UDESCSUB_AC_OUTPUT)
 2228                         continue;
 2229                 pot = iot[i].d.ot;
 2230                 tml = uaudio_io_terminaltype(UGETW(pot->wTerminalType), iot, i);
 2231                 if (tml != NULL)
 2232                         free(tml, M_TEMP);
 2233         }
 2234 
 2235 #ifdef USB_DEBUG
 2236         for (i = 0; i < 256; i++) {
 2237                 struct usb_audio_cluster cluster;
 2238 
 2239                 if (iot[i].d.desc == NULL)
 2240                         continue;
 2241                 logprintf("id %d:\t", i);
 2242                 switch (iot[i].d.desc->bDescriptorSubtype) {
 2243                 case UDESCSUB_AC_INPUT:
 2244                         logprintf("AC_INPUT type=%s\n", uaudio_get_terminal_name
 2245                                   (UGETW(iot[i].d.it->wTerminalType)));
 2246                         logprintf("\t");
 2247                         cluster = uaudio_get_cluster(i, iot);
 2248                         uaudio_dump_cluster(&cluster);
 2249                         logprintf("\n");
 2250                         break;
 2251                 case UDESCSUB_AC_OUTPUT:
 2252                         logprintf("AC_OUTPUT type=%s ", uaudio_get_terminal_name
 2253                                   (UGETW(iot[i].d.ot->wTerminalType)));
 2254                         logprintf("src=%d\n", iot[i].d.ot->bSourceId);
 2255                         break;
 2256                 case UDESCSUB_AC_MIXER:
 2257                         logprintf("AC_MIXER src=");
 2258                         for (j = 0; j < iot[i].d.mu->bNrInPins; j++)
 2259                                 logprintf("%d ", iot[i].d.mu->baSourceId[j]);
 2260                         logprintf("\n\t");
 2261                         cluster = uaudio_get_cluster(i, iot);
 2262                         uaudio_dump_cluster(&cluster);
 2263                         logprintf("\n");
 2264                         break;
 2265                 case UDESCSUB_AC_SELECTOR:
 2266                         logprintf("AC_SELECTOR src=");
 2267                         for (j = 0; j < iot[i].d.su->bNrInPins; j++)
 2268                                 logprintf("%d ", iot[i].d.su->baSourceId[j]);
 2269                         logprintf("\n");
 2270                         break;
 2271                 case UDESCSUB_AC_FEATURE:
 2272                         logprintf("AC_FEATURE src=%d\n", iot[i].d.fu->bSourceId);
 2273                         break;
 2274                 case UDESCSUB_AC_PROCESSING:
 2275                         logprintf("AC_PROCESSING src=");
 2276                         for (j = 0; j < iot[i].d.pu->bNrInPins; j++)
 2277                                 logprintf("%d ", iot[i].d.pu->baSourceId[j]);
 2278                         logprintf("\n\t");
 2279                         cluster = uaudio_get_cluster(i, iot);
 2280                         uaudio_dump_cluster(&cluster);
 2281                         logprintf("\n");
 2282                         break;
 2283                 case UDESCSUB_AC_EXTENSION:
 2284                         logprintf("AC_EXTENSION src=");
 2285                         for (j = 0; j < iot[i].d.eu->bNrInPins; j++)
 2286                                 logprintf("%d ", iot[i].d.eu->baSourceId[j]);
 2287                         logprintf("\n\t");
 2288                         cluster = uaudio_get_cluster(i, iot);
 2289                         uaudio_dump_cluster(&cluster);
 2290                         logprintf("\n");
 2291                         break;
 2292                 default:
 2293                         logprintf("unknown audio control (subtype=%d)\n",
 2294                                   iot[i].d.desc->bDescriptorSubtype);
 2295                 }
 2296                 for (j = 0; j < iot[i].inputs_size; j++) {
 2297                         int k;
 2298                         logprintf("\tinput%d: ", j);
 2299                         tml = iot[i].inputs[j];
 2300                         if (tml == NULL) {
 2301                                 logprintf("NULL\n");
 2302                                 continue;
 2303                         }
 2304                         for (k = 0; k < tml->size; k++)
 2305                                 logprintf("%s ", uaudio_get_terminal_name
 2306                                           (tml->terminals[k]));
 2307                         logprintf("\n");
 2308                 }
 2309                 logprintf("\toutput: ");
 2310                 tml = iot[i].output;
 2311                 for (j = 0; j < tml->size; j++)
 2312                         logprintf("%s ", uaudio_get_terminal_name(tml->terminals[j]));
 2313                 logprintf("\n");
 2314         }
 2315 #endif
 2316 
 2317         for (i = 0; i < ndps; i++) {
 2318                 dp = iot[i].d.desc;
 2319                 if (dp == NULL)
 2320                         continue;
 2321                 DPRINTF(("uaudio_identify_ac: id=%d subtype=%d\n",
 2322                          i, dp->bDescriptorSubtype));
 2323                 switch (dp->bDescriptorSubtype) {
 2324                 case UDESCSUB_AC_HEADER:
 2325                         printf("uaudio_identify_ac: unexpected AC header\n");
 2326                         break;
 2327                 case UDESCSUB_AC_INPUT:
 2328                         uaudio_add_input(sc, iot, i);
 2329                         break;
 2330                 case UDESCSUB_AC_OUTPUT:
 2331                         uaudio_add_output(sc, iot, i);
 2332                         break;
 2333                 case UDESCSUB_AC_MIXER:
 2334                         uaudio_add_mixer(sc, iot, i);
 2335                         break;
 2336                 case UDESCSUB_AC_SELECTOR:
 2337                         uaudio_add_selector(sc, iot, i);
 2338                         break;
 2339                 case UDESCSUB_AC_FEATURE:
 2340                         uaudio_add_feature(sc, iot, i);
 2341                         break;
 2342                 case UDESCSUB_AC_PROCESSING:
 2343                         uaudio_add_processing(sc, iot, i);
 2344                         break;
 2345                 case UDESCSUB_AC_EXTENSION:
 2346                         uaudio_add_extension(sc, iot, i);
 2347                         break;
 2348                 default:
 2349                         printf("uaudio_identify_ac: bad AC desc subtype=0x%02x\n",
 2350                                dp->bDescriptorSubtype);
 2351                         break;
 2352                 }
 2353         }
 2354 
 2355         /* delete io_terminal */
 2356         for (i = 0; i < 256; i++) {
 2357                 if (iot[i].d.desc == NULL)
 2358                         continue;
 2359                 if (iot[i].inputs != NULL) {
 2360                         for (j = 0; j < iot[i].inputs_size; j++) {
 2361                                 if (iot[i].inputs[j] != NULL)
 2362                                         free(iot[i].inputs[j], M_TEMP);
 2363                         }
 2364                         free(iot[i].inputs, M_TEMP);
 2365                 }
 2366                 if (iot[i].output != NULL)
 2367                         free(iot[i].output, M_TEMP);
 2368                 iot[i].d.desc = NULL;
 2369         }
 2370         free(iot, M_TEMP);
 2371 
 2372         return (USBD_NORMAL_COMPLETION);
 2373 }
 2374 
 2375 #if defined(__NetBSD__) || defined(__OpenBSD__)
 2376 Static int
 2377 uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi)
 2378 {
 2379         struct uaudio_softc *sc = addr;
 2380         struct mixerctl *mc;
 2381         int n, nctls, i;
 2382 
 2383         DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi->index));
 2384         if (sc->sc_dying)
 2385                 return (EIO);
 2386 
 2387         n = mi->index;
 2388         nctls = sc->sc_nctls;
 2389 
 2390         switch (n) {
 2391         case UAC_OUTPUT:
 2392                 mi->type = AUDIO_MIXER_CLASS;
 2393                 mi->mixer_class = UAC_OUTPUT;
 2394                 mi->next = mi->prev = AUDIO_MIXER_LAST;
 2395                 strlcpy(mi->label.name, AudioCoutputs, sizeof(mi->label.name));
 2396                 return (0);
 2397         case UAC_INPUT:
 2398                 mi->type = AUDIO_MIXER_CLASS;
 2399                 mi->mixer_class = UAC_INPUT;
 2400                 mi->next = mi->prev = AUDIO_MIXER_LAST;
 2401                 strlcpy(mi->label.name, AudioCinputs, sizeof(mi->label.name));
 2402                 return (0);
 2403         case UAC_EQUAL:
 2404                 mi->type = AUDIO_MIXER_CLASS;
 2405                 mi->mixer_class = UAC_EQUAL;
 2406                 mi->next = mi->prev = AUDIO_MIXER_LAST;
 2407                 strlcpy(mi->label.name, AudioCequalization,
 2408                     sizeof(mi->label.name));
 2409                 return (0);
 2410         case UAC_RECORD:
 2411                 mi->type = AUDIO_MIXER_CLASS;
 2412                 mi->mixer_class = UAC_RECORD;
 2413                 mi->next = mi->prev = AUDIO_MIXER_LAST;
 2414                 strlcpy(mi->label.name, AudioCrecord, sizeof(mi->label.name));
 2415                 return 0;
 2416         default:
 2417                 break;
 2418         }
 2419 
 2420         n -= UAC_NCLASSES;
 2421         if (n < 0 || n >= nctls)
 2422                 return (ENXIO);
 2423 
 2424         mc = &sc->sc_ctls[n];
 2425         strlcpy(mi->label.name, mc->ctlname, sizeof(mi->label.name));
 2426         mi->mixer_class = mc->class;
 2427         mi->next = mi->prev = AUDIO_MIXER_LAST; /* XXX */
 2428         switch (mc->type) {
 2429         case MIX_ON_OFF:
 2430                 mi->type = AUDIO_MIXER_ENUM;
 2431                 mi->un.e.num_mem = 2;
 2432                 strlcpy(mi->un.e.member[0].label.name, AudioNoff,
 2433                     sizeof(mi->un.e.member[0].label.name));
 2434                 mi->un.e.member[0].ord = 0;
 2435                 strlcpy(mi->un.e.member[1].label.name, AudioNon,
 2436                     sizeof(mi->un.e.member[1].label.name));
 2437                 mi->un.e.member[1].ord = 1;
 2438                 break;
 2439         case MIX_SELECTOR:
 2440                 mi->type = AUDIO_MIXER_ENUM;
 2441                 mi->un.e.num_mem = mc->maxval - mc->minval + 1;
 2442                 for (i = 0; i <= mc->maxval - mc->minval; i++) {
 2443                         snprintf(mi->un.e.member[i].label.name,
 2444                                  sizeof(mi->un.e.member[i].label.name),
 2445                                  "%d", i + mc->minval);
 2446                         mi->un.e.member[i].ord = i + mc->minval;
 2447                 }
 2448                 break;
 2449         default:
 2450                 mi->type = AUDIO_MIXER_VALUE;
 2451                 strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN);
 2452                 mi->un.v.num_channels = mc->nchan;
 2453                 mi->un.v.delta = mc->delta;
 2454                 break;
 2455         }
 2456         return (0);
 2457 }
 2458 
 2459 Static int
 2460 uaudio_open(void *addr, int flags)
 2461 {
 2462         struct uaudio_softc *sc = addr;
 2463 
 2464         DPRINTF(("uaudio_open: sc=%p\n", sc));
 2465         if (sc->sc_dying)
 2466                 return (EIO);
 2467 
 2468         if ((flags & FWRITE) && !(sc->sc_mode & AUMODE_PLAY))
 2469                 return (EACCES);
 2470         if ((flags & FREAD) && !(sc->sc_mode & AUMODE_RECORD))
 2471                 return (EACCES);
 2472 
 2473         return (0);
 2474 }
 2475 
 2476 /*
 2477  * Close function is called at splaudio().
 2478  */
 2479 Static void
 2480 uaudio_close(void *addr)
 2481 {
 2482 }
 2483 
 2484 Static int
 2485 uaudio_drain(void *addr)
 2486 {
 2487         struct uaudio_softc *sc = addr;
 2488 
 2489         usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
 2490 
 2491         return (0);
 2492 }
 2493 
 2494 Static int
 2495 uaudio_halt_out_dma(void *addr)
 2496 {
 2497         struct uaudio_softc *sc = addr;
 2498 
 2499         if (sc->sc_dying)
 2500                 return (EIO);
 2501 
 2502         DPRINTF(("uaudio_halt_out_dma: enter\n"));
 2503         if (sc->sc_playchan.pipe != NULL) {
 2504                 uaudio_chan_close(sc, &sc->sc_playchan);
 2505                 sc->sc_playchan.pipe = NULL;
 2506                 uaudio_chan_free_buffers(sc, &sc->sc_playchan);
 2507                 sc->sc_playchan.intr = NULL;
 2508         }
 2509         return (0);
 2510 }
 2511 
 2512 Static int
 2513 uaudio_halt_in_dma(void *addr)
 2514 {
 2515         struct uaudio_softc *sc = addr;
 2516 
 2517         DPRINTF(("uaudio_halt_in_dma: enter\n"));
 2518         if (sc->sc_recchan.pipe != NULL) {
 2519                 uaudio_chan_close(sc, &sc->sc_recchan);
 2520                 sc->sc_recchan.pipe = NULL;
 2521                 uaudio_chan_free_buffers(sc, &sc->sc_recchan);
 2522                 sc->sc_recchan.intr = NULL;
 2523         }
 2524         return (0);
 2525 }
 2526 
 2527 Static int
 2528 uaudio_getdev(void *addr, struct audio_device *retp)
 2529 {
 2530         struct uaudio_softc *sc = addr;
 2531 
 2532         DPRINTF(("uaudio_mixer_getdev:\n"));
 2533         if (sc->sc_dying)
 2534                 return (EIO);
 2535 
 2536         *retp = uaudio_device;
 2537         return (0);
 2538 }
 2539 
 2540 /*
 2541  * Make sure the block size is large enough to hold all outstanding transfers.
 2542  */
 2543 Static int
 2544 uaudio_round_blocksize(void *addr, int blk)
 2545 {
 2546         struct uaudio_softc *sc = addr;
 2547         int bpf;
 2548 
 2549         DPRINTF(("uaudio_round_blocksize: p.bpf=%d r.bpf=%d\n",
 2550                  sc->sc_playchan.bytes_per_frame,
 2551                  sc->sc_recchan.bytes_per_frame));
 2552         if (sc->sc_playchan.bytes_per_frame > sc->sc_recchan.bytes_per_frame) {
 2553                 bpf = sc->sc_playchan.bytes_per_frame
 2554                     + sc->sc_playchan.sample_size;
 2555         } else {
 2556                 bpf = sc->sc_recchan.bytes_per_frame
 2557                     + sc->sc_recchan.sample_size;
 2558         }
 2559         /* XXX */
 2560         bpf *= UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
 2561 
 2562         bpf = (bpf + 15) &~ 15;
 2563 
 2564         if (blk < bpf)
 2565                 blk = bpf;
 2566 
 2567 #ifdef DIAGNOSTIC
 2568         if (blk <= 0) {
 2569                 printf("uaudio_round_blocksize: blk=%d\n", blk);
 2570                 blk = 512;
 2571         }
 2572 #endif
 2573 
 2574         DPRINTFN(1,("uaudio_round_blocksize: blk=%d\n", blk));
 2575         return (blk);
 2576 }
 2577 
 2578 Static int
 2579 uaudio_get_props(void *addr)
 2580 {
 2581         return (AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT);
 2582 
 2583 }
 2584 #endif  /* NetBSD or OpenBSD */
 2585 
 2586 Static int
 2587 uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue,
 2588            int wIndex, int len)
 2589 {
 2590         usb_device_request_t req;
 2591         u_int8_t data[4];
 2592         usbd_status err;
 2593         int val;
 2594 
 2595 #if defined(__FreeBSD__)
 2596         if (sc->sc_dying)
 2597                 return (EIO);
 2598 #endif
 2599 
 2600         if (wValue == -1)
 2601                 return (0);
 2602 
 2603         req.bmRequestType = type;
 2604         req.bRequest = which;
 2605         USETW(req.wValue, wValue);
 2606         USETW(req.wIndex, wIndex);
 2607         USETW(req.wLength, len);
 2608         DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
 2609                     "wIndex=0x%04x len=%d\n",
 2610                     type, which, wValue, wIndex, len));
 2611         err = usbd_do_request(sc->sc_udev, &req, data);
 2612         if (err) {
 2613                 DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
 2614                 return (-1);
 2615         }
 2616         switch (len) {
 2617         case 1:
 2618                 val = data[0];
 2619                 break;
 2620         case 2:
 2621                 val = data[0] | (data[1] << 8);
 2622                 break;
 2623         default:
 2624                 DPRINTF(("uaudio_get: bad length=%d\n", len));
 2625                 return (-1);
 2626         }
 2627         DPRINTFN(2,("uaudio_get: val=%d\n", val));
 2628         return (val);
 2629 }
 2630 
 2631 Static void
 2632 uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue,
 2633            int wIndex, int len, int val)
 2634 {
 2635         usb_device_request_t req;
 2636         u_int8_t data[4];
 2637         usbd_status err;
 2638 
 2639 #if defined(__FreeBSD__)
 2640         if (sc->sc_dying)
 2641                 return;
 2642 #endif
 2643 
 2644         if (wValue == -1)
 2645                 return;
 2646 
 2647         req.bmRequestType = type;
 2648         req.bRequest = which;
 2649         USETW(req.wValue, wValue);
 2650         USETW(req.wIndex, wIndex);
 2651         USETW(req.wLength, len);
 2652         switch (len) {
 2653         case 1:
 2654                 data[0] = val;
 2655                 break;
 2656         case 2:
 2657                 data[0] = val;
 2658                 data[1] = val >> 8;
 2659                 break;
 2660         default:
 2661                 return;
 2662         }
 2663         DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
 2664                     "wIndex=0x%04x len=%d, val=%d\n",
 2665                     type, which, wValue, wIndex, len, val & 0xffff));
 2666         err = usbd_do_request(sc->sc_udev, &req, data);
 2667 #ifdef USB_DEBUG
 2668         if (err)
 2669                 DPRINTF(("uaudio_set: err=%d\n", err));
 2670 #endif
 2671 }
 2672 
 2673 Static int
 2674 uaudio_signext(int type, int val)
 2675 {
 2676         if (!MIX_UNSIGNED(type)) {
 2677                 if (MIX_SIZE(type) == 2)
 2678                         val = (int16_t)val;
 2679                 else
 2680                         val = (int8_t)val;
 2681         }
 2682         return (val);
 2683 }
 2684 
 2685 #if defined(__NetBSD__) || defined(__OpenBSD__)
 2686 Static int
 2687 uaudio_value2bsd(struct mixerctl *mc, int val)
 2688 {
 2689         DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ",
 2690                      mc->type, val, mc->minval, mc->maxval));
 2691         if (mc->type == MIX_ON_OFF) {
 2692                 val = (val != 0);
 2693         } else if (mc->type == MIX_SELECTOR) {
 2694                 if (val < mc->minval || val > mc->maxval)
 2695                         val = mc->minval;
 2696         } else
 2697                 val = ((uaudio_signext(mc->type, val) - mc->minval) * 255
 2698                         + mc->mul/2) / mc->mul;
 2699         DPRINTFN(5, ("val'=%d\n", val));
 2700         return (val);
 2701 }
 2702 #endif
 2703 
 2704 int
 2705 uaudio_bsd2value(struct mixerctl *mc, int val)
 2706 {
 2707         DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ",
 2708                     mc->type, val, mc->minval, mc->maxval));
 2709         if (mc->type == MIX_ON_OFF) {
 2710                 val = (val != 0);
 2711         } else if (mc->type == MIX_SELECTOR) {
 2712                 if (val < mc->minval || val > mc->maxval)
 2713                         val = mc->minval;
 2714         } else
 2715                 val = (val + mc->delta/2) * mc->mul / 255 + mc->minval;
 2716         DPRINTFN(5, ("val'=%d\n", val));
 2717         return (val);
 2718 }
 2719 
 2720 #if defined(__NetBSD__) || defined(__OpenBSD__)
 2721 Static int
 2722 uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc,
 2723                int chan)
 2724 {
 2725         int val;
 2726 
 2727         DPRINTFN(5,("uaudio_ctl_get: which=%d chan=%d\n", which, chan));
 2728         val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan],
 2729                          mc->wIndex, MIX_SIZE(mc->type));
 2730         return (uaudio_value2bsd(mc, val));
 2731 }
 2732 #endif
 2733 
 2734 Static void
 2735 uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc,
 2736                int chan, int val)
 2737 {
 2738         val = uaudio_bsd2value(mc, val);
 2739         uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan],
 2740                    mc->wIndex, MIX_SIZE(mc->type), val);
 2741 }
 2742 
 2743 #if defined(__NetBSD__) || defined(__OpenBSD__)
 2744 Static int
 2745 uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp)
 2746 {
 2747         struct uaudio_softc *sc = addr;
 2748         struct mixerctl *mc;
 2749         int i, n, vals[MIX_MAX_CHAN], val;
 2750 
 2751         DPRINTFN(2,("uaudio_mixer_get_port: index=%d\n", cp->dev));
 2752 
 2753         if (sc->sc_dying)
 2754                 return (EIO);
 2755 
 2756         n = cp->dev - UAC_NCLASSES;
 2757         if (n < 0 || n >= sc->sc_nctls)
 2758                 return (ENXIO);
 2759         mc = &sc->sc_ctls[n];
 2760 
 2761         if (mc->type == MIX_ON_OFF) {
 2762                 if (cp->type != AUDIO_MIXER_ENUM)
 2763                         return (EINVAL);
 2764                 cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
 2765         } else if (mc->type == MIX_SELECTOR) {
 2766                 if (cp->type != AUDIO_MIXER_ENUM)
 2767                         return (EINVAL);
 2768                 cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
 2769         } else {
 2770                 if (cp->type != AUDIO_MIXER_VALUE)
 2771                         return (EINVAL);
 2772                 if (cp->un.value.num_channels != 1 &&
 2773                     cp->un.value.num_channels != mc->nchan)
 2774                         return (EINVAL);
 2775                 for (i = 0; i < mc->nchan; i++)
 2776                         vals[i] = uaudio_ctl_get(sc, GET_CUR, mc, i);
 2777                 if (cp->un.value.num_channels == 1 && mc->nchan != 1) {
 2778                         for (val = 0, i = 0; i < mc->nchan; i++)
 2779                                 val += vals[i];
 2780                         vals[0] = val / mc->nchan;
 2781                 }
 2782                 for (i = 0; i < cp->un.value.num_channels; i++)
 2783                         cp->un.value.level[i] = vals[i];
 2784         }
 2785 
 2786         return (0);
 2787 }
 2788 
 2789 Static int
 2790 uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp)
 2791 {
 2792         struct uaudio_softc *sc = addr;
 2793         struct mixerctl *mc;
 2794         int i, n, vals[MIX_MAX_CHAN];
 2795 
 2796         DPRINTFN(2,("uaudio_mixer_set_port: index = %d\n", cp->dev));
 2797         if (sc->sc_dying)
 2798                 return (EIO);
 2799 
 2800         n = cp->dev - UAC_NCLASSES;
 2801         if (n < 0 || n >= sc->sc_nctls)
 2802                 return (ENXIO);
 2803         mc = &sc->sc_ctls[n];
 2804 
 2805         if (mc->type == MIX_ON_OFF) {
 2806                 if (cp->type != AUDIO_MIXER_ENUM)
 2807                         return (EINVAL);
 2808                 uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
 2809         } else if (mc->type == MIX_SELECTOR) {
 2810                 if (cp->type != AUDIO_MIXER_ENUM)
 2811                         return (EINVAL);
 2812                 uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
 2813         } else {
 2814                 if (cp->type != AUDIO_MIXER_VALUE)
 2815                         return (EINVAL);
 2816                 if (cp->un.value.num_channels == 1)
 2817                         for (i = 0; i < mc->nchan; i++)
 2818                                 vals[i] = cp->un.value.level[0];
 2819                 else if (cp->un.value.num_channels == mc->nchan)
 2820                         for (i = 0; i < mc->nchan; i++)
 2821                                 vals[i] = cp->un.value.level[i];
 2822                 else
 2823                         return (EINVAL);
 2824                 for (i = 0; i < mc->nchan; i++)
 2825                         uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]);
 2826         }
 2827         return (0);
 2828 }
 2829 
 2830 Static int
 2831 uaudio_trigger_input(void *addr, void *start, void *end, int blksize,
 2832                      void (*intr)(void *), void *arg,
 2833                      struct audio_params *param)
 2834 {
 2835         struct uaudio_softc *sc = addr;
 2836         struct chan *ch = &sc->sc_recchan;
 2837         usbd_status err;
 2838         int i, s;
 2839 
 2840         if (sc->sc_dying)
 2841                 return (EIO);
 2842 
 2843         DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p "
 2844                     "blksize=%d\n", sc, start, end, blksize));
 2845 
 2846         uaudio_chan_set_param(ch, start, end, blksize);
 2847         DPRINTFN(3,("uaudio_trigger_input: sample_size=%d bytes/frame=%d "
 2848                     "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
 2849                     ch->fraction));
 2850 
 2851         err = uaudio_chan_alloc_buffers(sc, ch);
 2852         if (err)
 2853                 return (EIO);
 2854 
 2855         err = uaudio_chan_open(sc, ch);
 2856         if (err) {
 2857                 uaudio_chan_free_buffers(sc, ch);
 2858                 return (EIO);
 2859         }
 2860 
 2861         ch->intr = intr;
 2862         ch->arg = arg;
 2863 
 2864         s = splusb();
 2865         for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
 2866                 uaudio_chan_rtransfer(ch);
 2867         splx(s);
 2868 
 2869         return (0);
 2870 }
 2871 
 2872 Static int
 2873 uaudio_trigger_output(void *addr, void *start, void *end, int blksize,
 2874                       void (*intr)(void *), void *arg,
 2875                       struct audio_params *param)
 2876 {
 2877         struct uaudio_softc *sc = addr;
 2878         struct chan *ch = &sc->sc_playchan;
 2879         usbd_status err;
 2880         int i, s;
 2881 
 2882         if (sc->sc_dying)
 2883                 return (EIO);
 2884 
 2885         DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p "
 2886                     "blksize=%d\n", sc, start, end, blksize));
 2887 
 2888         uaudio_chan_set_param(ch, start, end, blksize);
 2889         DPRINTFN(3,("uaudio_trigger_output: sample_size=%d bytes/frame=%d "
 2890                     "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
 2891                     ch->fraction));
 2892 
 2893         err = uaudio_chan_alloc_buffers(sc, ch);
 2894         if (err)
 2895                 return (EIO);
 2896 
 2897         err = uaudio_chan_open(sc, ch);
 2898         if (err) {
 2899                 uaudio_chan_free_buffers(sc, ch);
 2900                 return (EIO);
 2901         }
 2902 
 2903         ch->intr = intr;
 2904         ch->arg = arg;
 2905 
 2906         s = splusb();
 2907         for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
 2908                 uaudio_chan_ptransfer(ch);
 2909         splx(s);
 2910 
 2911         return (0);
 2912 }
 2913 #endif  /* NetBSD or OpenBSD */
 2914 
 2915 /* Set up a pipe for a channel. */
 2916 Static usbd_status
 2917 uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
 2918 {
 2919         struct as_info *as = &sc->sc_alts[ch->altidx];
 2920         int endpt = as->edesc->bEndpointAddress;
 2921         usbd_status err;
 2922 
 2923 #if defined(__FreeBSD__)
 2924         if (sc->sc_dying)
 2925                 return (EIO);
 2926 #endif
 2927 
 2928         DPRINTF(("uaudio_chan_open: endpt=0x%02x, speed=%d, alt=%d\n",
 2929                  endpt, ch->sample_rate, as->alt));
 2930 
 2931         /* Set alternate interface corresponding to the mode. */
 2932         err = usbd_set_interface(as->ifaceh, as->alt);
 2933         if (err)
 2934                 return (err);
 2935 
 2936         /*
 2937          * If just one sampling rate is supported,
 2938          * no need to call uaudio_set_speed().
 2939          * Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request.
 2940          */
 2941         if (as->asf1desc->bSamFreqType != 1) {
 2942                 err = uaudio_set_speed(sc, endpt, ch->sample_rate);
 2943                 if (err)
 2944                         DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n",
 2945                                  usbd_errstr(err)));
 2946         }
 2947 
 2948         ch->pipe = 0;
 2949         ch->sync_pipe = 0;
 2950         DPRINTF(("uaudio_chan_open: create pipe to 0x%02x\n", endpt));
 2951         err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
 2952         if (err)
 2953                 return err;
 2954         if (as->edesc1 != NULL) {
 2955                 endpt = as->edesc1->bEndpointAddress;
 2956                 DPRINTF(("uaudio_chan_open: create sync-pipe to 0x%02x\n", endpt));
 2957                 err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->sync_pipe);
 2958         }
 2959         return err;
 2960 }
 2961 
 2962 Static void
 2963 uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
 2964 {
 2965         struct as_info *as = &sc->sc_alts[ch->altidx];
 2966 
 2967 #if defined(__FreeBSD__)
 2968         if (sc->sc_dying)
 2969                 return ;
 2970 #endif
 2971 
 2972         as->sc_busy = 0;
 2973         if (sc->sc_nullalt >= 0) {
 2974                 DPRINTF(("uaudio_chan_close: set null alt=%d\n",
 2975                          sc->sc_nullalt));
 2976                 usbd_set_interface(as->ifaceh, sc->sc_nullalt);
 2977         }
 2978         if (ch->pipe) {
 2979                 usbd_abort_pipe(ch->pipe);
 2980                 usbd_close_pipe(ch->pipe);
 2981         }
 2982         if (ch->sync_pipe) {
 2983                 usbd_abort_pipe(ch->sync_pipe);
 2984                 usbd_close_pipe(ch->sync_pipe);
 2985         }
 2986 }
 2987 
 2988 Static usbd_status
 2989 uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch)
 2990 {
 2991         usbd_xfer_handle xfer;
 2992         void *buf;
 2993         int i, size;
 2994 
 2995         size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES;
 2996         for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
 2997                 xfer = usbd_alloc_xfer(sc->sc_udev);
 2998                 if (xfer == 0)
 2999                         goto bad;
 3000                 ch->chanbufs[i].xfer = xfer;
 3001                 buf = usbd_alloc_buffer(xfer, size);
 3002                 if (buf == 0) {
 3003                         i++;
 3004                         goto bad;
 3005                 }
 3006                 ch->chanbufs[i].buffer = buf;
 3007                 ch->chanbufs[i].chan = ch;
 3008         }
 3009 
 3010         return (USBD_NORMAL_COMPLETION);
 3011 
 3012 bad:
 3013         while (--i >= 0)
 3014                 /* implicit buffer free */
 3015                 usbd_free_xfer(ch->chanbufs[i].xfer);
 3016         return (USBD_NOMEM);
 3017 }
 3018 
 3019 Static void
 3020 uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch)
 3021 {
 3022         int i;
 3023 
 3024         for (i = 0; i < UAUDIO_NCHANBUFS; i++)
 3025                 usbd_free_xfer(ch->chanbufs[i].xfer);
 3026 }
 3027 
 3028 /* Called at splusb() */
 3029 Static void
 3030 uaudio_chan_ptransfer(struct chan *ch)
 3031 {
 3032         struct chanbuf *cb;
 3033         int i, n, size, residue, total;
 3034 
 3035         if (ch->sc->sc_dying)
 3036                 return;
 3037 
 3038         /* Pick the next channel buffer. */
 3039         cb = &ch->chanbufs[ch->curchanbuf];
 3040         if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
 3041                 ch->curchanbuf = 0;
 3042 
 3043         /* Compute the size of each frame in the next transfer. */
 3044         residue = ch->residue;
 3045         total = 0;
 3046         for (i = 0; i < UAUDIO_NFRAMES; i++) {
 3047                 size = ch->bytes_per_frame;
 3048                 residue += ch->fraction;
 3049                 if (residue >= USB_FRAMES_PER_SECOND) {
 3050                         if ((ch->sc->sc_altflags & UA_NOFRAC) == 0)
 3051                                 size += ch->sample_size;
 3052                         residue -= USB_FRAMES_PER_SECOND;
 3053                 }
 3054                 cb->sizes[i] = size;
 3055                 total += size;
 3056         }
 3057         ch->residue = residue;
 3058         cb->size = total;
 3059 
 3060         /*
 3061          * Transfer data from upper layer buffer to channel buffer, taking
 3062          * care of wrapping the upper layer buffer.
 3063          */
 3064         n = min(total, ch->end - ch->cur);
 3065         memcpy(cb->buffer, ch->cur, n);
 3066         ch->cur += n;
 3067         if (ch->cur >= ch->end)
 3068                 ch->cur = ch->start;
 3069         if (total > n) {
 3070                 total -= n;
 3071                 memcpy(cb->buffer + n, ch->cur, total);
 3072                 ch->cur += total;
 3073         }
 3074 
 3075 #ifdef USB_DEBUG
 3076         if (uaudiodebug > 8) {
 3077                 DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03d\n",
 3078                          cb->buffer, ch->residue));
 3079                 for (i = 0; i < UAUDIO_NFRAMES; i++) {
 3080                         DPRINTF(("   [%d] length %d\n", i, cb->sizes[i]));
 3081                 }
 3082         }
 3083 #endif
 3084 
 3085         DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer));
 3086         /* Fill the request */
 3087         usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
 3088                              UAUDIO_NFRAMES, USBD_NO_COPY,
 3089                              uaudio_chan_pintr);
 3090 
 3091         (void)usbd_transfer(cb->xfer);
 3092 }
 3093 
 3094 Static void
 3095 uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv,
 3096                   usbd_status status)
 3097 {
 3098         struct chanbuf *cb = priv;
 3099         struct chan *ch = cb->chan;
 3100         u_int32_t count;
 3101         int s;
 3102 
 3103         /* Return if we are aborting. */
 3104         if (status == USBD_CANCELLED)
 3105                 return;
 3106 
 3107         usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
 3108         DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n",
 3109                     count, ch->transferred));
 3110 #ifdef DIAGNOSTIC
 3111         if (count != cb->size) {
 3112                 printf("uaudio_chan_pintr: count(%d) != size(%d)\n",
 3113                        count, cb->size);
 3114         }
 3115 #endif
 3116 
 3117         ch->transferred += cb->size;
 3118 #if defined(__FreeBSD__)
 3119         /* s = spltty(); */
 3120         s = splhigh();
 3121         chn_intr(ch->pcm_ch);
 3122         splx(s);
 3123 #else
 3124         s = splaudio();
 3125         /* Call back to upper layer */
 3126         while (ch->transferred >= ch->blksize) {
 3127                 ch->transferred -= ch->blksize;
 3128                 DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)\n",
 3129                             ch->intr, ch->arg));
 3130                 ch->intr(ch->arg);
 3131         }
 3132         splx(s);
 3133 #endif
 3134 
 3135         /* start next transfer */
 3136         uaudio_chan_ptransfer(ch);
 3137 }
 3138 
 3139 /* Called at splusb() */
 3140 Static void
 3141 uaudio_chan_rtransfer(struct chan *ch)
 3142 {
 3143         struct chanbuf *cb;
 3144         int i, size, residue, total;
 3145 
 3146         if (ch->sc->sc_dying)
 3147                 return;
 3148 
 3149         /* Pick the next channel buffer. */
 3150         cb = &ch->chanbufs[ch->curchanbuf];
 3151         if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
 3152                 ch->curchanbuf = 0;
 3153 
 3154         /* Compute the size of each frame in the next transfer. */
 3155         residue = ch->residue;
 3156         total = 0;
 3157         for (i = 0; i < UAUDIO_NFRAMES; i++) {
 3158                 size = ch->bytes_per_frame;
 3159                 cb->sizes[i] = size;
 3160                 cb->offsets[i] = total;
 3161                 total += size;
 3162         }
 3163         ch->residue = residue;
 3164         cb->size = total;
 3165 
 3166 #ifdef USB_DEBUG
 3167         if (uaudiodebug > 8) {
 3168                 DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03d\n",
 3169                          cb->buffer, ch->residue));
 3170                 for (i = 0; i < UAUDIO_NFRAMES; i++) {
 3171                         DPRINTF(("   [%d] length %d\n", i, cb->sizes[i]));
 3172                 }
 3173         }
 3174 #endif
 3175 
 3176         DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer));
 3177         /* Fill the request */
 3178         usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
 3179                              UAUDIO_NFRAMES, USBD_NO_COPY,
 3180                              uaudio_chan_rintr);
 3181 
 3182         (void)usbd_transfer(cb->xfer);
 3183 }
 3184 
 3185 Static void
 3186 uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv,
 3187                   usbd_status status)
 3188 {
 3189         struct chanbuf *cb = priv;
 3190         struct chan *ch = cb->chan;
 3191         u_int32_t count;
 3192         int s, i, n, frsize;
 3193 
 3194         /* Return if we are aborting. */
 3195         if (status == USBD_CANCELLED)
 3196                 return;
 3197 
 3198         usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
 3199         DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n",
 3200                     count, ch->transferred));
 3201 
 3202         /* count < cb->size is normal for asynchronous source */
 3203 #ifdef DIAGNOSTIC
 3204         if (count > cb->size) {
 3205                 printf("uaudio_chan_rintr: count(%d) > size(%d)\n",
 3206                        count, cb->size);
 3207         }
 3208 #endif
 3209 
 3210         /*
 3211          * Transfer data from channel buffer to upper layer buffer, taking
 3212          * care of wrapping the upper layer buffer.
 3213          */
 3214         for(i = 0; i < UAUDIO_NFRAMES; i++) {
 3215                 frsize = cb->sizes[i];
 3216                 n = min(frsize, ch->end - ch->cur);
 3217                 memcpy(ch->cur, cb->buffer + cb->offsets[i], n);
 3218                 ch->cur += n;
 3219                 if (ch->cur >= ch->end)
 3220                         ch->cur = ch->start;
 3221                 if (frsize > n) {
 3222                         memcpy(ch->cur, cb->buffer + cb->offsets[i] + n,
 3223                             frsize - n);
 3224                         ch->cur += frsize - n;
 3225                 }
 3226         }
 3227 
 3228         /* Call back to upper layer */
 3229         ch->transferred += count;
 3230 #if defined(__FreeBSD__)
 3231         s = spltty();
 3232         chn_intr(ch->pcm_ch);
 3233         splx(s);
 3234 #else
 3235         s = splaudio();
 3236         while (ch->transferred >= ch->blksize) {
 3237                 ch->transferred -= ch->blksize;
 3238                 DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)\n",
 3239                             ch->intr, ch->arg));
 3240                 ch->intr(ch->arg);
 3241         }
 3242         splx(s);
 3243 #endif
 3244 
 3245         /* start next transfer */
 3246         uaudio_chan_rtransfer(ch);
 3247 }
 3248 
 3249 #if defined(__NetBSD__) || defined(__OpenBSD__)
 3250 Static void
 3251 uaudio_chan_init(struct chan *ch, int altidx, const struct audio_params *param,
 3252     int maxpktsize)
 3253 {
 3254         int samples_per_frame, sample_size;
 3255 
 3256         ch->altidx = altidx;
 3257         sample_size = param->precision * param->factor * param->hw_channels / 8;
 3258         samples_per_frame = param->hw_sample_rate / USB_FRAMES_PER_SECOND;
 3259         ch->sample_size = sample_size;
 3260         ch->sample_rate = param->hw_sample_rate;
 3261         if (maxpktsize == 0) {
 3262                 ch->fraction = param->hw_sample_rate % USB_FRAMES_PER_SECOND;
 3263                 ch->bytes_per_frame = samples_per_frame * sample_size;
 3264         } else {
 3265                 ch->fraction = 0;
 3266                 ch->bytes_per_frame = maxpktsize;
 3267         }
 3268         ch->residue = 0;
 3269 }
 3270 
 3271 Static void
 3272 uaudio_chan_set_param(struct chan *ch, u_char *start, u_char *end, int blksize)
 3273 {
 3274         ch->start = start;
 3275         ch->end = end;
 3276         ch->cur = start;
 3277         ch->blksize = blksize;
 3278         ch->transferred = 0;
 3279 
 3280         ch->curchanbuf = 0;
 3281 }
 3282 
 3283 Static void
 3284 uaudio_get_minmax_rates(int nalts, const struct as_info *alts,
 3285                         const struct audio_params *p, int mode,
 3286                         u_long *min, u_long *max)
 3287 {
 3288         const struct usb_audio_streaming_type1_descriptor *a1d;
 3289         int i, j;
 3290 
 3291         *min = ULONG_MAX;
 3292         *max = 0;
 3293         for (i = 0; i < nalts; i++) {
 3294                 a1d = alts[i].asf1desc;
 3295                 if (alts[i].sc_busy)
 3296                         continue;
 3297                 if (p->hw_channels != a1d->bNrChannels)
 3298                         continue;
 3299                 if (p->hw_precision != a1d->bBitResolution)
 3300                         continue;
 3301                 if (p->hw_encoding != alts[i].encoding)
 3302                         continue;
 3303                 if (mode != UE_GET_DIR(alts[i].edesc->bEndpointAddress))
 3304                         continue;
 3305                 if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
 3306                         DPRINTFN(2,("uaudio_get_minmax_rates: cont %d-%d\n",
 3307                                     UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
 3308                         if (UA_SAMP_LO(a1d) < *min)
 3309                                 *min = UA_SAMP_LO(a1d);
 3310                         if (UA_SAMP_HI(a1d) > *max)
 3311                                 *max = UA_SAMP_HI(a1d);
 3312                 } else {
 3313                         for (j = 0; j < a1d->bSamFreqType; j++) {
 3314                                 DPRINTFN(2,("uaudio_get_minmax_rates: disc #%d: %d\n",
 3315                                             j, UA_GETSAMP(a1d, j)));
 3316                                 if (UA_GETSAMP(a1d, j) < *min)
 3317                                         *min = UA_GETSAMP(a1d, j);
 3318                                 if (UA_GETSAMP(a1d, j) > *max)
 3319                                         *max = UA_GETSAMP(a1d, j);
 3320                         }
 3321                 }
 3322         }
 3323 }
 3324 
 3325 Static int
 3326 uaudio_match_alt_sub(int nalts, const struct as_info *alts,
 3327                      const struct audio_params *p, int mode, u_long rate)
 3328 {
 3329         const struct usb_audio_streaming_type1_descriptor *a1d;
 3330         int i, j;
 3331 
 3332         DPRINTF(("uaudio_match_alt_sub: search for %luHz %dch\n",
 3333                  rate, p->hw_channels));
 3334         for (i = 0; i < nalts; i++) {
 3335                 a1d = alts[i].asf1desc;
 3336                 if (alts[i].sc_busy)
 3337                         continue;
 3338                 if (p->hw_channels != a1d->bNrChannels)
 3339                         continue;
 3340                 if (p->hw_precision != a1d->bBitResolution)
 3341                         continue;
 3342                 if (p->hw_encoding != alts[i].encoding)
 3343                         continue;
 3344                 if (mode != UE_GET_DIR(alts[i].edesc->bEndpointAddress))
 3345                         continue;
 3346                 if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
 3347                         DPRINTFN(3,("uaudio_match_alt_sub: cont %d-%d\n",
 3348                                     UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
 3349                         if (UA_SAMP_LO(a1d) <= rate && rate <= UA_SAMP_HI(a1d))
 3350                                 return i;
 3351                 } else {
 3352                         for (j = 0; j < a1d->bSamFreqType; j++) {
 3353                                 DPRINTFN(3,("uaudio_match_alt_sub: disc #%d: %d\n",
 3354                                             j, UA_GETSAMP(a1d, j)));
 3355                                 /* XXX allow for some slack */
 3356                                 if (UA_GETSAMP(a1d, j) == rate)
 3357                                         return i;
 3358                         }
 3359                 }
 3360         }
 3361         return -1;
 3362 }
 3363 
 3364 Static int
 3365 uaudio_match_alt_chan(int nalts, const struct as_info *alts,
 3366                       struct audio_params *p, int mode)
 3367 {
 3368         int i, n;
 3369         u_long min, max;
 3370         u_long rate;
 3371 
 3372         /* Exact match */
 3373         DPRINTF(("uaudio_match_alt_chan: examine %ldHz %dch %dbit.\n",
 3374                  p->sample_rate, p->hw_channels, p->hw_precision));
 3375         i = uaudio_match_alt_sub(nalts, alts, p, mode, p->sample_rate);
 3376         if (i >= 0)
 3377                 return i;
 3378 
 3379         uaudio_get_minmax_rates(nalts, alts, p, mode, &min, &max);
 3380         DPRINTF(("uaudio_match_alt_chan: min=%lu max=%lu\n", min, max));
 3381         if (max <= 0)
 3382                 return -1;
 3383         /* Search for biggers */
 3384         n = 2;
 3385         while ((rate = p->sample_rate * n++) <= max) {
 3386                 i = uaudio_match_alt_sub(nalts, alts, p, mode, rate);
 3387                 if (i >= 0) {
 3388                         p->hw_sample_rate = rate;
 3389                         return i;
 3390                 }
 3391         }
 3392         if (p->sample_rate >= min) {
 3393                 i = uaudio_match_alt_sub(nalts, alts, p, mode, max);
 3394                 if (i >= 0) {
 3395                         p->hw_sample_rate = max;
 3396                         return i;
 3397                 }
 3398         } else {
 3399                 i = uaudio_match_alt_sub(nalts, alts, p, mode, min);
 3400                 if (i >= 0) {
 3401                         p->hw_sample_rate = min;
 3402                         return i;
 3403                 }
 3404         }
 3405         return -1;
 3406 }
 3407 
 3408 Static int
 3409 uaudio_match_alt(int nalts, const struct as_info *alts,
 3410                  struct audio_params *p, int mode)
 3411 {
 3412         int i, n;
 3413 
 3414         mode = mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN;
 3415         i = uaudio_match_alt_chan(nalts, alts, p, mode);
 3416         if (i >= 0)
 3417                 return i;
 3418 
 3419         for (n = p->channels + 1; n <= AUDIO_MAX_CHANNELS; n++) {
 3420                 p->hw_channels = n;
 3421                 i = uaudio_match_alt_chan(nalts, alts, p, mode);
 3422                 if (i >= 0)
 3423                         return i;
 3424         }
 3425 
 3426         if (p->channels != 2)
 3427                 return -1;
 3428         p->hw_channels = 1;
 3429         return uaudio_match_alt_chan(nalts, alts, p, mode);
 3430 }
 3431 
 3432 Static int
 3433 uaudio_set_params(void *addr, int setmode, int usemode,
 3434                   struct audio_params *play, struct audio_params *rec)
 3435 {
 3436         struct uaudio_softc *sc = addr;
 3437         int flags = sc->sc_altflags;
 3438         int factor;
 3439         int enc, i;
 3440         int paltidx=-1, raltidx=-1;
 3441         void (*swcode)(void *, u_char *buf, int cnt);
 3442         struct audio_params *p;
 3443         int mode;
 3444 
 3445         if (sc->sc_dying)
 3446                 return (EIO);
 3447 
 3448         if (((usemode & AUMODE_PLAY) && sc->sc_playchan.pipe != NULL) ||
 3449             ((usemode & AUMODE_RECORD) && sc->sc_recchan.pipe != NULL))
 3450                 return (EBUSY);
 3451 
 3452         if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1)
 3453                 sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 0;
 3454         if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1)
 3455                 sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 0;
 3456 
 3457         /* Some uaudio devices are unidirectional.  Don't try to find a
 3458            matching mode for the unsupported direction. */
 3459         setmode &= sc->sc_mode;
 3460 
 3461         for (mode = AUMODE_RECORD; mode != -1;
 3462              mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
 3463                 if ((setmode & mode) == 0)
 3464                         continue;
 3465 
 3466                 p = (mode == AUMODE_PLAY) ? play : rec;
 3467 
 3468                 factor = 1;
 3469                 swcode = 0;
 3470                 enc = p->encoding;
 3471                 switch (enc) {
 3472                 case AUDIO_ENCODING_SLINEAR_BE:
 3473                         /* FALLTHROUGH */
 3474                 case AUDIO_ENCODING_SLINEAR_LE:
 3475                         if (enc == AUDIO_ENCODING_SLINEAR_BE
 3476                             && p->precision == 16 && (flags & HAS_16)) {
 3477                                 swcode = swap_bytes;
 3478                                 enc = AUDIO_ENCODING_SLINEAR_LE;
 3479                         } else if (p->precision == 8) {
 3480                                 if (flags & HAS_8) {
 3481                                         /* No conversion */
 3482                                 } else if (flags & HAS_8U) {
 3483                                         swcode = change_sign8;
 3484                                         enc = AUDIO_ENCODING_ULINEAR_LE;
 3485                                 } else if (flags & HAS_16) {
 3486                                         factor = 2;
 3487                                         p->hw_precision = 16;
 3488                                         if (mode == AUMODE_PLAY)
 3489                                                 swcode = linear8_to_linear16_le;
 3490                                         else
 3491                                                 swcode = linear16_to_linear8_le;
 3492                                 }
 3493                         }
 3494                         break;
 3495                 case AUDIO_ENCODING_ULINEAR_BE:
 3496                         /* FALLTHROUGH */
 3497                 case AUDIO_ENCODING_ULINEAR_LE:
 3498                         if (p->precision == 16) {
 3499                                 if (enc == AUDIO_ENCODING_ULINEAR_LE)
 3500                                         swcode = change_sign16_le;
 3501                                 else if (mode == AUMODE_PLAY)
 3502                                         swcode = swap_bytes_change_sign16_le;
 3503                                 else
 3504                                         swcode = change_sign16_swap_bytes_le;
 3505                                 enc = AUDIO_ENCODING_SLINEAR_LE;
 3506                         } else if (p->precision == 8) {
 3507                                 if (flags & HAS_8U) {
 3508                                         /* No conversion */
 3509                                 } else if (flags & HAS_8) {
 3510                                         swcode = change_sign8;
 3511                                         enc = AUDIO_ENCODING_SLINEAR_LE;
 3512                                 } else if (flags & HAS_16) {
 3513                                         factor = 2;
 3514                                         p->hw_precision = 16;
 3515                                         enc = AUDIO_ENCODING_SLINEAR_LE;
 3516                                         if (mode == AUMODE_PLAY)
 3517                                                 swcode = ulinear8_to_slinear16_le;
 3518                                         else
 3519                                                 swcode = slinear16_to_ulinear8_le;
 3520                                 }
 3521                         }
 3522                         break;
 3523                 case AUDIO_ENCODING_ULAW:
 3524                         if (flags & HAS_MULAW)
 3525                                 break;
 3526                         if (flags & HAS_16) {
 3527                                 if (mode == AUMODE_PLAY)
 3528                                         swcode = mulaw_to_slinear16_le;
 3529                                 else
 3530                                         swcode = slinear16_to_mulaw_le;
 3531                                 factor = 2;
 3532                                 enc = AUDIO_ENCODING_SLINEAR_LE;
 3533                                 p->hw_precision = 16;
 3534                         } else if (flags & HAS_8U) {
 3535                                 if (mode == AUMODE_PLAY)
 3536                                         swcode = mulaw_to_ulinear8;
 3537                                 else
 3538                                         swcode = ulinear8_to_mulaw;
 3539                                 enc = AUDIO_ENCODING_ULINEAR_LE;
 3540                         } else if (flags & HAS_8) {
 3541                                 if (mode == AUMODE_PLAY)
 3542                                         swcode = mulaw_to_slinear8;
 3543                                 else
 3544                                         swcode = slinear8_to_mulaw;
 3545                                 enc = AUDIO_ENCODING_SLINEAR_LE;
 3546                         } else
 3547                                 return (EINVAL);
 3548                         break;
 3549                 case AUDIO_ENCODING_ALAW:
 3550                         if (flags & HAS_ALAW)
 3551                                 break;
 3552                         if (mode == AUMODE_PLAY && (flags & HAS_16)) {
 3553                                 swcode = alaw_to_slinear16_le;
 3554                                 factor = 2;
 3555                                 enc = AUDIO_ENCODING_SLINEAR_LE;
 3556                                 p->hw_precision = 16;
 3557                         } else if (flags & HAS_8U) {
 3558                                 if (mode == AUMODE_PLAY)
 3559                                         swcode = alaw_to_ulinear8;
 3560                                 else
 3561                                         swcode = ulinear8_to_alaw;
 3562                                 enc = AUDIO_ENCODING_ULINEAR_LE;
 3563                         } else if (flags & HAS_8) {
 3564                                 if (mode == AUMODE_PLAY)
 3565                                         swcode = alaw_to_slinear8;
 3566                                 else
 3567                                         swcode = slinear8_to_alaw;
 3568                                 enc = AUDIO_ENCODING_SLINEAR_LE;
 3569                         } else
 3570                                 return (EINVAL);
 3571                         break;
 3572                 default:
 3573                         return (EINVAL);
 3574                 }
 3575                 /* XXX do some other conversions... */
 3576 
 3577                 DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n",
 3578                          p->channels, p->hw_precision, enc, p->sample_rate));
 3579 
 3580                 p->hw_encoding = enc;
 3581                 i = uaudio_match_alt(sc->sc_nalts, sc->sc_alts, p, mode);
 3582                 if (i < 0)
 3583                         return (EINVAL);
 3584 
 3585                 p->sw_code = swcode;
 3586                 p->factor  = factor;
 3587 
 3588                 if (mode == AUMODE_PLAY)
 3589                         paltidx = i;
 3590                 else
 3591                         raltidx = i;
 3592         }
 3593 
 3594         if ((setmode & AUMODE_PLAY)) {
 3595                 /* XXX abort transfer if currently happening? */
 3596                 uaudio_chan_init(&sc->sc_playchan, paltidx, play, 0);
 3597         }
 3598         if ((setmode & AUMODE_RECORD)) {
 3599                 /* XXX abort transfer if currently happening? */
 3600                 uaudio_chan_init(&sc->sc_recchan, raltidx, rec,
 3601                     UGETW(sc->sc_alts[raltidx].edesc->wMaxPacketSize));
 3602         }
 3603 
 3604         if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1)
 3605                 sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 1;
 3606         if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1)
 3607                 sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 1;
 3608 
 3609         DPRINTF(("uaudio_set_params: use altidx=p%d/r%d, altno=p%d/r%d\n",
 3610                  sc->sc_playchan.altidx, sc->sc_recchan.altidx,
 3611                  (sc->sc_playchan.altidx >= 0)
 3612                    ?sc->sc_alts[sc->sc_playchan.altidx].idesc->bAlternateSetting
 3613                    : -1,
 3614                  (sc->sc_recchan.altidx >= 0)
 3615                    ? sc->sc_alts[sc->sc_recchan.altidx].idesc->bAlternateSetting
 3616                    : -1));
 3617 
 3618         return (0);
 3619 }
 3620 #endif /* NetBSD or OpenBSD */
 3621 
 3622 Static usbd_status
 3623 uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed)
 3624 {
 3625         usb_device_request_t req;
 3626         u_int8_t data[3];
 3627 
 3628         DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%u\n", endpt, speed));
 3629         req.bmRequestType = UT_WRITE_CLASS_ENDPOINT;
 3630         req.bRequest = SET_CUR;
 3631         USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
 3632         USETW(req.wIndex, endpt);
 3633         USETW(req.wLength, 3);
 3634         data[0] = speed;
 3635         data[1] = speed >> 8;
 3636         data[2] = speed >> 16;
 3637 
 3638         return (usbd_do_request(sc->sc_udev, &req, data));
 3639 }
 3640 
 3641 
 3642 #if defined(__FreeBSD__)
 3643 /************************************************************/
 3644 int
 3645 uaudio_init_params(struct uaudio_softc *sc, struct chan *ch, int mode)
 3646 {
 3647         int i, j, enc;
 3648         int samples_per_frame, sample_size;
 3649 
 3650         if ((sc->sc_playchan.pipe != NULL) || (sc->sc_recchan.pipe != NULL))
 3651                 return (-1);
 3652 
 3653         switch(ch->format & 0x0000FFFF) {
 3654         case AFMT_U8:
 3655                 enc = AUDIO_ENCODING_ULINEAR_LE;
 3656                 ch->precision = 8;
 3657                 break;
 3658         case AFMT_S8:
 3659                 enc = AUDIO_ENCODING_SLINEAR_LE;
 3660                 ch->precision = 8;
 3661                 break;
 3662         case AFMT_A_LAW:        /* ? */
 3663                 enc = AUDIO_ENCODING_ALAW;
 3664                 ch->precision = 8;
 3665                 break;
 3666         case AFMT_MU_LAW:       /* ? */
 3667                 enc = AUDIO_ENCODING_ULAW;
 3668                 ch->precision = 8;
 3669                 break;
 3670         case AFMT_S16_LE:
 3671                 enc = AUDIO_ENCODING_SLINEAR_LE;
 3672                 ch->precision = 16;
 3673                 break;
 3674         case AFMT_S16_BE:
 3675                 enc = AUDIO_ENCODING_SLINEAR_BE;
 3676                 ch->precision = 16;
 3677                 break;
 3678         case AFMT_U16_LE:
 3679                 enc = AUDIO_ENCODING_ULINEAR_LE;
 3680                 ch->precision = 16;
 3681                 break;
 3682         case AFMT_U16_BE:
 3683                 enc = AUDIO_ENCODING_ULINEAR_BE;
 3684                 ch->precision = 16;
 3685                 break;
 3686         default:
 3687                 enc = 0;
 3688                 ch->precision = 16;
 3689                 printf("Unknown format %x\n", ch->format);
 3690         }
 3691 
 3692         if (ch->format & AFMT_STEREO) {
 3693                 ch->channels = 2;
 3694         } else {
 3695                 ch->channels = 1;
 3696         }
 3697 
 3698 /*      for (mode =  ......      */
 3699                 for (i = 0; i < sc->sc_nalts; i++) {
 3700                         const struct usb_audio_streaming_type1_descriptor *a1d =
 3701                                 sc->sc_alts[i].asf1desc;
 3702                         if (ch->channels == a1d->bNrChannels &&
 3703                             ch->precision == a1d->bBitResolution &&
 3704 #if 0
 3705                             enc == sc->sc_alts[i].encoding) {
 3706 #else
 3707                             enc == sc->sc_alts[i].encoding &&
 3708                             (mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) ==
 3709                             UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) {
 3710 #endif
 3711                                 if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
 3712                                         DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
 3713                                             UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
 3714                                         if (UA_SAMP_LO(a1d) < ch->sample_rate &&
 3715                                             ch->sample_rate < UA_SAMP_HI(a1d)) {
 3716                                                 if (mode == AUMODE_PLAY)
 3717                                                         sc->sc_playchan.altidx = i;
 3718                                                 else
 3719                                                         sc->sc_recchan.altidx = i;
 3720                                                 goto found;
 3721                                         }
 3722                                 } else {
 3723                                         for (j = 0; j < a1d->bSamFreqType; j++) {
 3724                                                 DPRINTFN(2,("uaudio_set_params: disc #"
 3725                                                     "%d: %d\n", j, UA_GETSAMP(a1d, j)));
 3726                                                 /* XXX allow for some slack */
 3727                                                 if (UA_GETSAMP(a1d, j) ==
 3728                                                     ch->sample_rate) {
 3729                                                         if (mode == AUMODE_PLAY)
 3730                                                                 sc->sc_playchan.altidx = i;
 3731                                                         else
 3732                                                                 sc->sc_recchan.altidx = i;
 3733                                                         goto found;
 3734                                                 }
 3735                                         }
 3736                                 }
 3737                         }
 3738                 }
 3739                 /* return (EINVAL); */
 3740                 if (mode == AUMODE_PLAY) 
 3741                         printf("uaudio: This device can't play in rate=%d.\n", ch->sample_rate);
 3742                 else
 3743                         printf("uaudio: This device can't record in rate=%d.\n", ch->sample_rate);
 3744                 return (-1);
 3745 
 3746         found:
 3747 #if 0 /* XXX */
 3748                 p->sw_code = swcode;
 3749                 p->factor  = factor;
 3750                 if (usemode == mode)
 3751                         sc->sc_curaltidx = i;
 3752 #endif
 3753 /*      } */
 3754 
 3755         sample_size = ch->precision * ch->channels / 8;
 3756         samples_per_frame = ch->sample_rate / USB_FRAMES_PER_SECOND;
 3757         ch->fraction = ch->sample_rate % USB_FRAMES_PER_SECOND;
 3758         ch->sample_size = sample_size;
 3759         ch->bytes_per_frame = samples_per_frame * sample_size;
 3760         ch->residue = 0;
 3761 
 3762         ch->cur = ch->start;
 3763         ch->transferred = 0;
 3764         ch->curchanbuf = 0;
 3765         return (0);
 3766 }
 3767 
 3768 void
 3769 uaudio_query_formats(device_t dev, u_int32_t *pfmt, u_int32_t *rfmt)
 3770 {
 3771         int i, pn=0, rn=0;
 3772         int prec, dir;
 3773         u_int32_t fmt;
 3774         struct uaudio_softc *sc;
 3775 
 3776         const struct usb_audio_streaming_type1_descriptor *a1d;
 3777 
 3778         sc = device_get_softc(dev);
 3779 
 3780         for (i = 0; i < sc->sc_nalts; i++) {
 3781                 fmt = 0;
 3782                 a1d = sc->sc_alts[i].asf1desc;
 3783                 prec = a1d->bBitResolution;     /* precision */
 3784 
 3785                 switch (sc->sc_alts[i].encoding) {
 3786                 case AUDIO_ENCODING_ULINEAR_LE:
 3787                         if (prec == 8) {
 3788                                 fmt = AFMT_U8;
 3789                         } else if (prec == 16) {
 3790                                 fmt = AFMT_U16_LE;
 3791                         }
 3792                         break;
 3793                 case AUDIO_ENCODING_SLINEAR_LE:
 3794                         if (prec == 8) {
 3795                                 fmt = AFMT_S8;
 3796                         } else if (prec == 16) {
 3797                                 fmt = AFMT_S16_LE;
 3798                         }
 3799                         break;
 3800                 case AUDIO_ENCODING_ULINEAR_BE:
 3801                         if (prec == 16) {
 3802                                 fmt = AFMT_U16_BE;
 3803                         }
 3804                         break;
 3805                 case AUDIO_ENCODING_SLINEAR_BE:
 3806                         if (prec == 16) {
 3807                                 fmt = AFMT_S16_BE;
 3808                         }
 3809                         break;
 3810                 case AUDIO_ENCODING_ALAW:
 3811                         if (prec == 8) {
 3812                                 fmt = AFMT_A_LAW;
 3813                         }
 3814                         break;
 3815                 case AUDIO_ENCODING_ULAW:
 3816                         if (prec == 8) {
 3817                                 fmt = AFMT_MU_LAW;
 3818                         }
 3819                         break;
 3820                 }
 3821 
 3822                 if (fmt != 0) {
 3823                         if (a1d->bNrChannels == 2) {    /* stereo/mono */
 3824                                 fmt |= AFMT_STEREO;
 3825                         } else if (a1d->bNrChannels != 1) {
 3826                                 fmt = 0;
 3827                         }
 3828                 }
 3829 
 3830                 if (fmt != 0) {
 3831                         dir= UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
 3832                         if (dir == UE_DIR_OUT) {
 3833                                 pfmt[pn++] = fmt;
 3834                         } else if (dir == UE_DIR_IN) {
 3835                                 rfmt[rn++] = fmt;
 3836                         }
 3837                 }
 3838 
 3839                 if ((pn > 8*2) || (rn > 8*2))
 3840                         break;
 3841         }
 3842         pfmt[pn] = 0;
 3843         rfmt[rn] = 0;
 3844         return;
 3845 }
 3846 
 3847 void
 3848 uaudio_chan_set_param_pcm_dma_buff(device_t dev, u_char *start, u_char *end,
 3849                 struct pcm_channel *pc, int dir)
 3850 {
 3851         struct uaudio_softc *sc;
 3852         struct chan *ch;
 3853 
 3854         sc = device_get_softc(dev);
 3855 #ifndef NO_RECORDING
 3856         if (dir == PCMDIR_PLAY)
 3857                 ch = &sc->sc_playchan;
 3858         else
 3859                 ch = &sc->sc_recchan;
 3860 #else
 3861         ch = &sc->sc_playchan;
 3862 #endif
 3863 
 3864         ch->start = start;
 3865         ch->end = end;
 3866 
 3867         ch->pcm_ch = pc;
 3868 
 3869         return;
 3870 }
 3871 
 3872 void
 3873 uaudio_chan_set_param_blocksize(device_t dev, u_int32_t blocksize, int dir)
 3874 {
 3875         struct uaudio_softc *sc;
 3876         struct chan *ch;
 3877 
 3878         sc = device_get_softc(dev);
 3879 #ifndef NO_RECORDING
 3880         if (dir == PCMDIR_PLAY)
 3881                 ch = &sc->sc_playchan;
 3882         else
 3883                 ch = &sc->sc_recchan;
 3884 #else
 3885         ch = &sc->sc_playchan;
 3886 #endif
 3887 
 3888         ch->blksize = blocksize;
 3889 
 3890         return;
 3891 }
 3892 
 3893 void
 3894 uaudio_chan_set_param_speed(device_t dev, u_int32_t speed, int dir)
 3895 {
 3896         struct uaudio_softc *sc;
 3897         struct chan *ch;
 3898 
 3899         sc = device_get_softc(dev);
 3900 #ifndef NO_RECORDING
 3901         if (dir == PCMDIR_PLAY)
 3902                 ch = &sc->sc_playchan;
 3903         else
 3904                 ch = &sc->sc_recchan;
 3905 #else
 3906         ch = &sc->sc_playchan;
 3907 #endif
 3908 
 3909         ch->sample_rate = speed;
 3910 
 3911         return;
 3912 }
 3913 
 3914 int
 3915 uaudio_chan_getptr(device_t dev, int dir)
 3916 {
 3917         struct uaudio_softc *sc;
 3918         struct chan *ch;
 3919         int ptr;
 3920 
 3921         sc = device_get_softc(dev);
 3922 #ifndef NO_RECORDING
 3923         if (dir == PCMDIR_PLAY)
 3924                 ch = &sc->sc_playchan;
 3925         else
 3926                 ch = &sc->sc_recchan;
 3927 #else
 3928         ch = &sc->sc_playchan;
 3929 #endif
 3930 
 3931         ptr = ch->cur - ch->start;
 3932 
 3933         return ptr;
 3934 }
 3935 
 3936 void
 3937 uaudio_chan_set_param_format(device_t dev, u_int32_t format, int dir)
 3938 {
 3939         struct uaudio_softc *sc;
 3940         struct chan *ch;
 3941 
 3942         sc = device_get_softc(dev);
 3943 #ifndef NO_RECORDING
 3944         if (dir == PCMDIR_PLAY)
 3945                 ch = &sc->sc_playchan;
 3946         else
 3947                 ch = &sc->sc_recchan;
 3948 #else
 3949         ch = &sc->sc_playchan;
 3950 #endif
 3951 
 3952         ch->format = format;
 3953 
 3954         return;
 3955 }
 3956 
 3957 int
 3958 uaudio_halt_out_dma(device_t dev)
 3959 {
 3960         struct uaudio_softc *sc;
 3961 
 3962         sc = device_get_softc(dev);
 3963 
 3964         DPRINTF(("uaudio_halt_out_dma: enter\n"));
 3965         if (sc->sc_playchan.pipe != NULL) {
 3966                 uaudio_chan_close(sc, &sc->sc_playchan);
 3967                 sc->sc_playchan.pipe = 0;
 3968                 uaudio_chan_free_buffers(sc, &sc->sc_playchan);
 3969         }
 3970         return (0);
 3971 }
 3972 
 3973 int
 3974 uaudio_halt_in_dma(device_t dev)
 3975 {
 3976         struct uaudio_softc *sc;
 3977 
 3978         sc = device_get_softc(dev);
 3979 
 3980         if (sc->sc_dying)
 3981                 return (EIO);
 3982 
 3983         DPRINTF(("uaudio_halt_in_dma: enter\n"));
 3984         if (sc->sc_recchan.pipe != NULL) {
 3985                 uaudio_chan_close(sc, &sc->sc_recchan);
 3986                 sc->sc_recchan.pipe = NULL;
 3987                 uaudio_chan_free_buffers(sc, &sc->sc_recchan);
 3988 /*              sc->sc_recchan.intr = NULL; */
 3989         }
 3990         return (0);
 3991 }
 3992 
 3993 int
 3994 uaudio_trigger_input(device_t dev)
 3995 {
 3996         struct uaudio_softc *sc;
 3997         struct chan *ch;
 3998         usbd_status err;
 3999         int i, s;
 4000 
 4001         sc = device_get_softc(dev);
 4002         ch = &sc->sc_recchan;
 4003 
 4004         if (sc->sc_dying)
 4005                 return (EIO);
 4006 
 4007 /*      uaudio_chan_set_param(ch, start, end, blksize) */
 4008         if (uaudio_init_params(sc, ch, AUMODE_RECORD))
 4009                 return (EIO);
 4010 
 4011         err = uaudio_chan_alloc_buffers(sc, ch);
 4012         if (err)
 4013                 return (EIO);
 4014 
 4015         err = uaudio_chan_open(sc, ch);
 4016         if (err) {
 4017                 uaudio_chan_free_buffers(sc, ch);
 4018                 return (EIO);
 4019         }
 4020 
 4021 /*      ch->intr = intr;
 4022         ch->arg = arg; */
 4023 
 4024         s = splusb();
 4025         for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
 4026                 uaudio_chan_rtransfer(ch);
 4027         splx(s);
 4028 
 4029         return (0);
 4030 }
 4031 
 4032 int
 4033 uaudio_trigger_output(device_t dev)
 4034 {
 4035         struct uaudio_softc *sc;
 4036         struct chan *ch;
 4037         usbd_status err;
 4038         int i, s;
 4039 
 4040         sc = device_get_softc(dev);
 4041         ch = &sc->sc_playchan;
 4042 
 4043         if (sc->sc_dying)
 4044                 return (EIO);
 4045 
 4046         if (uaudio_init_params(sc, ch, AUMODE_PLAY))
 4047                 return (EIO);
 4048 
 4049         err = uaudio_chan_alloc_buffers(sc, ch);
 4050         if (err)
 4051                 return (EIO);
 4052 
 4053         err = uaudio_chan_open(sc, ch);
 4054         if (err) {
 4055                 uaudio_chan_free_buffers(sc, ch);
 4056                 return (EIO);
 4057         }
 4058 
 4059         s = splusb();
 4060         for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
 4061                 uaudio_chan_ptransfer(ch);
 4062         splx(s);
 4063 
 4064         return (0);
 4065 }
 4066 
 4067 u_int32_t
 4068 uaudio_query_mix_info(device_t dev)
 4069 {
 4070         int i;
 4071         u_int32_t mask = 0;
 4072         struct uaudio_softc *sc;
 4073         struct mixerctl *mc;
 4074 
 4075         sc = device_get_softc(dev);
 4076         for (i=0; i < sc->sc_nctls; i++) {
 4077                 mc = &sc->sc_ctls[i];
 4078                 if (mc->ctl != SOUND_MIXER_NRDEVICES) {
 4079                         /* Set device mask bits. 
 4080                            See /usr/include/machine/soundcard.h */
 4081                         mask |= (1 << mc->ctl);
 4082                 }
 4083         }
 4084         return mask;
 4085 }
 4086 
 4087 u_int32_t
 4088 uaudio_query_recsrc_info(device_t dev)
 4089 {
 4090         int i, rec_selector_id;
 4091         u_int32_t mask = 0;
 4092         struct uaudio_softc *sc;
 4093         struct mixerctl *mc;
 4094 
 4095         sc = device_get_softc(dev);
 4096         rec_selector_id = -1;
 4097         for (i=0; i < sc->sc_nctls; i++) {
 4098                 mc = &sc->sc_ctls[i];
 4099                 if (mc->ctl == SOUND_MIXER_NRDEVICES && 
 4100                     mc->type == MIX_SELECTOR && mc->class == UAC_RECORD) {
 4101                         if (rec_selector_id == -1) {
 4102                                 rec_selector_id = i;
 4103                         } else {
 4104                                 printf("There are many selectors.  Can't recognize which selector is a record source selector.\n");
 4105                                 return mask;
 4106                         }
 4107                 }
 4108         }
 4109         if (rec_selector_id == -1)
 4110                 return mask;
 4111         mc = &sc->sc_ctls[rec_selector_id];
 4112         for (i = mc->minval; i <= mc->maxval; i++) {
 4113                 if (mc->slctrtype[i - 1] == SOUND_MIXER_NRDEVICES)
 4114                         continue;
 4115                 mask |= 1 << mc->slctrtype[i - 1];
 4116         }
 4117         return mask;
 4118 }
 4119 
 4120 void
 4121 uaudio_mixer_set(device_t dev, unsigned type, unsigned left, unsigned right)
 4122 {
 4123         int i;
 4124         struct uaudio_softc *sc;
 4125         struct mixerctl *mc;
 4126 
 4127         sc = device_get_softc(dev);
 4128         for (i=0; i < sc->sc_nctls; i++) {
 4129                 mc = &sc->sc_ctls[i];
 4130                 if (mc->ctl == type) {
 4131                         if (mc->nchan == 2) {
 4132                                 /* set Right */
 4133                                 uaudio_ctl_set(sc, SET_CUR, mc, 1, (int)(right*256)/100);
 4134                         }
 4135                         /* set Left or Mono */
 4136                         uaudio_ctl_set(sc, SET_CUR, mc, 0, (int)(left*256)/100);
 4137                 }
 4138         }
 4139         return;
 4140 }
 4141 
 4142 u_int32_t
 4143 uaudio_mixer_setrecsrc(device_t dev, u_int32_t src)
 4144 {
 4145         int i, rec_selector_id;
 4146         struct uaudio_softc *sc;
 4147         struct mixerctl *mc;
 4148 
 4149         sc = device_get_softc(dev);
 4150         rec_selector_id = -1;
 4151         for (i=0; i < sc->sc_nctls; i++) {
 4152                 mc = &sc->sc_ctls[i];
 4153                 if (mc->ctl == SOUND_MIXER_NRDEVICES && 
 4154                     mc->type == MIX_SELECTOR && mc->class == UAC_RECORD) {
 4155                         if (rec_selector_id == -1) {
 4156                                 rec_selector_id = i;
 4157                         } else {
 4158                                 return src; /* Can't recognize which selector is record source selector */
 4159                         }
 4160                 }
 4161         }
 4162         if (rec_selector_id == -1)
 4163                 return src;
 4164         mc = &sc->sc_ctls[rec_selector_id];
 4165         for (i = mc->minval; i <= mc->maxval; i++) {
 4166                 if (src != (1 << mc->slctrtype[i - 1]))
 4167                         continue;
 4168                 uaudio_ctl_set(sc, SET_CUR, mc, 0, i);
 4169                 return (1 << mc->slctrtype[i - 1]);
 4170         }
 4171         uaudio_ctl_set(sc, SET_CUR, mc, 0, mc->minval);
 4172         return (1 << mc->slctrtype[mc->minval - 1]);
 4173 }
 4174 
 4175 Static int
 4176 audio_attach_mi(device_t dev)
 4177 {
 4178         device_t child;
 4179         struct sndcard_func *func;
 4180 
 4181         /* Attach the children. */
 4182         /* PCM Audio */
 4183         func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
 4184         if (func == NULL)
 4185                 return (ENOMEM);
 4186         bzero(func, sizeof(*func));
 4187         func->func = SCF_PCM;
 4188         child = device_add_child(dev, "pcm", -1);
 4189         device_set_ivars(child, func);
 4190 
 4191         bus_generic_attach(dev);
 4192 
 4193         return 0; /* XXXXX */
 4194 }
 4195 
 4196 DRIVER_MODULE(uaudio, uhub, uaudio_driver, uaudio_devclass, usbd_driver_load, 0);
 4197 MODULE_VERSION(uaudio, 1);
 4198 
 4199 #endif

Cache object: da17e133a4641e52d8d705f517e32701


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.