LCOV - code coverage report
Current view: top level - dev/usb - uaudio.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1508 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 59 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: uaudio.c,v 1.133 2018/08/31 07:18:18 miko Exp $ */
       2             : /*      $NetBSD: uaudio.c,v 1.90 2004/10/29 17:12:53 kent Exp $ */
       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             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      22             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      23             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      24             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      25             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      26             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      27             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      28             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      29             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      30             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      31             :  * POSSIBILITY OF SUCH DAMAGE.
      32             :  */
      33             : 
      34             : /*
      35             :  * USB audio specs: http://www.usb.org/developers/devclass_docs/audio10.pdf
      36             :  *                  http://www.usb.org/developers/devclass_docs/frmts10.pdf
      37             :  *                  http://www.usb.org/developers/devclass_docs/termt10.pdf
      38             :  */
      39             : 
      40             : #include <sys/param.h>
      41             : #include <sys/systm.h>
      42             : #include <sys/kernel.h>
      43             : #include <sys/malloc.h>
      44             : #include <sys/device.h>
      45             : #include <sys/ioctl.h>
      46             : #include <sys/tty.h>
      47             : #include <sys/fcntl.h>
      48             : #include <sys/selinfo.h>
      49             : #include <sys/poll.h>
      50             : 
      51             : #include <machine/bus.h>
      52             : 
      53             : #include <sys/audioio.h>
      54             : #include <dev/audio_if.h>
      55             : 
      56             : #include <dev/usb/usb.h>
      57             : #include <dev/usb/usbdevs.h>
      58             : #include <dev/usb/usbdi.h>
      59             : #include <dev/usb/usbdi_util.h>
      60             : #include <dev/usb/usbdivar.h>
      61             : 
      62             : #include <dev/usb/uaudioreg.h>
      63             : 
      64             : /* #define UAUDIO_DEBUG */
      65             : #ifdef UAUDIO_DEBUG
      66             : #define DPRINTF(x)      do { if (uaudiodebug) printf x; } while (0)
      67             : #define DPRINTFN(n,x)   do { if (uaudiodebug>(n)) printf x; } while (0)
      68             : int     uaudiodebug = 0;
      69             : #else
      70             : #define DPRINTF(x)
      71             : #define DPRINTFN(n,x)
      72             : #endif
      73             : 
      74             : #define UAUDIO_NCHANBUFS 3      /* number of outstanding request */
      75             : #define UAUDIO_MIN_FRAMES 2     /* ms of sound in each request */
      76             : #define UAUDIO_MAX_FRAMES 16
      77             : #define UAUDIO_NSYNCBUFS 3      /* number of outstanding sync requests */
      78             : 
      79             : #define UAUDIO_MAX_ALTS  32     /* max alt settings allowed by driver */
      80             : 
      81             : #define MIX_MAX_CHAN 8
      82             : struct mixerctl {
      83             :         u_int16_t       wValue[MIX_MAX_CHAN]; /* using nchan */
      84             :         u_int16_t       wIndex;
      85             :         u_int8_t        nchan;
      86             :         u_int8_t        type;
      87             : #define MIX_ON_OFF      1
      88             : #define MIX_SIGNED_16   2
      89             : #define MIX_UNSIGNED_16 3
      90             : #define MIX_SIGNED_8    4
      91             : #define MIX_SELECTOR    5
      92             : #define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1)
      93             : #define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16)
      94             :         int             minval, maxval;
      95             :         u_int           delta;
      96             :         u_int8_t        class;
      97             :         char            ctlname[MAX_AUDIO_DEV_LEN];
      98             :         char            *ctlunit;
      99             : };
     100             : #define MAKE(h,l) (((h) << 8) | (l))
     101             : 
     102             : struct as_info {
     103             :         u_int8_t        alt;
     104             :         u_int8_t        encoding;
     105             :         u_int8_t        attributes; /* Copy of bmAttributes of
     106             :                                      * usb_audio_streaming_endpoint_descriptor
     107             :                                      */
     108             :         struct usbd_interface *ifaceh;
     109             :         const usb_interface_descriptor_t *idesc;
     110             :         const struct usb_endpoint_descriptor_audio *edesc;
     111             :         const struct usb_endpoint_descriptor_audio *edesc1;
     112             :         const struct usb_audio_streaming_type1_descriptor *asf1desc;
     113             :         int             sc_busy;        /* currently used */
     114             : };
     115             : 
     116             : struct chan {
     117             :         void    (*intr)(void *);        /* DMA completion intr handler */
     118             :         void    *arg;           /* arg for intr() */
     119             :         struct usbd_pipe *pipe;
     120             :         struct usbd_pipe *sync_pipe;
     121             : 
     122             :         u_int   sample_size;
     123             :         u_int   sample_rate;
     124             :         u_int   bytes_per_frame;
     125             :         u_int   max_bytes_per_frame;
     126             :         u_int   fraction;       /* fraction/frac_denom is the extra samples/frame */
     127             :         u_int   frac_denom;     /* denominator for fractional samples */
     128             :         u_int   residue;        /* accumulates the fractional samples */
     129             :         u_int   nframes;        /* # of frames per transfer */
     130             :         u_int   nsync_frames;   /* # of frames per sync transfer */
     131             :         u_int   usb_fps;
     132             :         u_int   maxpktsize;
     133             :         u_int   reqms;          /* usb request data duration, in ms */
     134             :         u_int   hi_speed;
     135             : 
     136             :         u_char  *start;         /* upper layer buffer start */
     137             :         u_char  *end;           /* upper layer buffer end */
     138             :         u_char  *cur;           /* current position in upper layer buffer */
     139             :         int     blksize;        /* chunk size to report up */
     140             :         int     transferred;    /* transferred bytes not reported up */
     141             : 
     142             :         int     altidx;         /* currently used altidx */
     143             : 
     144             :         int     curchanbuf;
     145             :         int     cursyncbuf;
     146             : 
     147             :         struct chanbuf {
     148             :                 struct chan     *chan;
     149             :                 struct usbd_xfer *xfer;
     150             :                 u_char          *buffer;
     151             :                 u_int16_t       sizes[UAUDIO_MAX_FRAMES];
     152             :                 u_int16_t       offsets[UAUDIO_MAX_FRAMES];
     153             :                 u_int16_t       size;
     154             :         } chanbufs[UAUDIO_NCHANBUFS];
     155             : 
     156             :         struct syncbuf {
     157             :                 struct chan     *chan;
     158             :                 struct usbd_xfer *xfer;
     159             :                 u_char          *buffer;
     160             :                 u_int16_t       sizes[UAUDIO_MAX_FRAMES];
     161             :                 u_int16_t       offsets[UAUDIO_MAX_FRAMES];
     162             :                 u_int16_t       size;
     163             :         } syncbufs[UAUDIO_NSYNCBUFS];
     164             : 
     165             :         struct uaudio_softc *sc; /* our softc */
     166             : };
     167             : 
     168             : #define UAUDIO_FLAG_BAD_AUDIO    0x0001 /* claims audio class, but isn't */
     169             : #define UAUDIO_FLAG_NO_FRAC      0x0002 /* don't use fractional samples */
     170             : #define UAUDIO_FLAG_NO_XU        0x0004 /* has broken extension unit */
     171             : #define UAUDIO_FLAG_BAD_ADC      0x0008 /* bad audio spec version number */
     172             : #define UAUDIO_FLAG_VENDOR_CLASS 0x0010 /* claims vendor class but works */
     173             : #define UAUDIO_FLAG_DEPENDENT    0x0020 /* play and record params must equal */
     174             : #define UAUDIO_FLAG_EMU0202      0x0040
     175             : #define UAUDIO_FLAG_BAD_ADC_LEN  0x0080 /* bad audio control descriptor size */
     176             : 
     177             : struct uaudio_devs {
     178             :         struct usb_devno         uv_dev;
     179             :         int                      flags;
     180             : } uaudio_devs[] = {
     181             :         { { USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_UR22 },
     182             :                 UAUDIO_FLAG_VENDOR_CLASS },
     183             :         { { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70 },
     184             :                 UAUDIO_FLAG_BAD_ADC } ,
     185             :         { { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495 },
     186             :                 UAUDIO_FLAG_BAD_AUDIO },
     187             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE },
     188             :                 UAUDIO_FLAG_BAD_AUDIO },
     189             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G },
     190             :                 UAUDIO_FLAG_BAD_AUDIO },
     191             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3GS },
     192             :                 UAUDIO_FLAG_BAD_AUDIO },
     193             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4_GSM },
     194             :                 UAUDIO_FLAG_BAD_AUDIO },
     195             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4_CDMA },
     196             :                 UAUDIO_FLAG_BAD_AUDIO },
     197             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4S },
     198             :                 UAUDIO_FLAG_BAD_AUDIO },
     199             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_6 },
     200             :                 UAUDIO_FLAG_BAD_AUDIO },
     201             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH },
     202             :                 UAUDIO_FLAG_BAD_AUDIO },
     203             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH_2G },
     204             :                 UAUDIO_FLAG_BAD_AUDIO },
     205             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH_3G },
     206             :                 UAUDIO_FLAG_BAD_AUDIO },
     207             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH_4G },
     208             :                 UAUDIO_FLAG_BAD_AUDIO },
     209             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPAD },
     210             :                 UAUDIO_FLAG_BAD_AUDIO },
     211             :         { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPAD2 },
     212             :                 UAUDIO_FLAG_BAD_AUDIO },
     213             :         { { USB_VENDOR_CREATIVE, USB_PRODUCT_CREATIVE_EMU0202 },
     214             :                 UAUDIO_FLAG_VENDOR_CLASS | UAUDIO_FLAG_EMU0202 |
     215             :                 UAUDIO_FLAG_DEPENDENT },
     216             :         { { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502 },
     217             :                 UAUDIO_FLAG_NO_XU | UAUDIO_FLAG_BAD_ADC },
     218             :         { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMNBDLX },
     219             :                 UAUDIO_FLAG_BAD_AUDIO },
     220             :         { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRONB },
     221             :                 UAUDIO_FLAG_BAD_AUDIO },
     222             :         { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRO4K },
     223             :                 UAUDIO_FLAG_BAD_AUDIO },
     224             :         { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMZOOM },
     225             :                 UAUDIO_FLAG_BAD_AUDIO },
     226             :         { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WEBCAMC200 },
     227             :                 UAUDIO_FLAG_BAD_ADC_LEN },
     228             :         { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WEBCAMC210 },
     229             :                 UAUDIO_FLAG_BAD_ADC_LEN },
     230             :         { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WEBCAMC250 },
     231             :                 UAUDIO_FLAG_BAD_ADC_LEN },
     232             :         { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WEBCAMC270 },
     233             :                 UAUDIO_FLAG_BAD_ADC_LEN },
     234             :         { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WEBCAMC310 },
     235             :                 UAUDIO_FLAG_BAD_ADC_LEN },
     236             :         { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WEBCAMC500 },
     237             :                 UAUDIO_FLAG_BAD_ADC_LEN },
     238             :         { { USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1 },
     239             :                 UAUDIO_FLAG_NO_FRAC }
     240             : };
     241             : #define uaudio_lookup(v, p) \
     242             :         ((struct uaudio_devs *)usb_lookup(uaudio_devs, v, p))
     243             : 
     244             : struct uaudio_softc {
     245             :         struct device    sc_dev;        /* base device */
     246             :         struct usbd_device *sc_udev;    /* USB device */
     247             :         int              sc_ac_iface;   /* Audio Control interface */
     248             :         struct chan      sc_playchan;   /* play channel */
     249             :         struct chan      sc_recchan;    /* record channel */
     250             :         int              sc_nullalt;
     251             :         int              sc_audio_rev;
     252             :         struct as_info  *sc_alts;       /* alternate settings */
     253             :         int              sc_nalts;      /* # of alternate settings */
     254             :         int              sc_altflags;
     255             : #define HAS_8            0x01
     256             : #define HAS_16           0x02
     257             : #define HAS_8U           0x04
     258             : #define HAS_ALAW         0x08
     259             : #define HAS_MULAW        0x10
     260             : #define UA_NOFRAC        0x20           /* don't do sample rate adjustment */
     261             : #define HAS_24           0x40
     262             :         int              sc_mode;       /* play/record capability */
     263             :         struct mixerctl *sc_ctls;       /* mixer controls */
     264             :         int              sc_nctls;      /* # of mixer controls */
     265             :         int              sc_quirks;
     266             : };
     267             : 
     268             : struct terminal_list {
     269             :         int size;
     270             :         uint16_t terminals[1];
     271             : };
     272             : #define TERMINAL_LIST_SIZE(N)   (offsetof(struct terminal_list, terminals) \
     273             :                                 + sizeof(uint16_t) * (N))
     274             : 
     275             : struct io_terminal {
     276             :         union {
     277             :                 const usb_descriptor_t *desc;
     278             :                 const struct usb_audio_input_terminal *it;
     279             :                 const struct usb_audio_output_terminal *ot;
     280             :                 const struct usb_audio_mixer_unit *mu;
     281             :                 const struct usb_audio_selector_unit *su;
     282             :                 const struct usb_audio_feature_unit *fu;
     283             :                 const struct usb_audio_processing_unit *pu;
     284             :                 const struct usb_audio_extension_unit *eu;
     285             :         } d;
     286             :         int inputs_size;
     287             :         struct terminal_list **inputs; /* list of source input terminals */
     288             :         struct terminal_list *output; /* list of destination output terminals */
     289             :         int direct;             /* directly connected to an output terminal */
     290             : };
     291             : 
     292             : #define UAC_OUTPUT      0
     293             : #define UAC_INPUT       1
     294             : #define UAC_EQUAL       2
     295             : #define UAC_RECORD      3
     296             : #define UAC_NCLASSES    4
     297             : #ifdef UAUDIO_DEBUG
     298             : const char *uac_names[] = {
     299             :         AudioCoutputs, AudioCinputs, AudioCequalization, AudioCrecord,
     300             : };
     301             : #endif
     302             : 
     303             : usbd_status uaudio_identify_ac
     304             :         (struct uaudio_softc *, const usb_config_descriptor_t *);
     305             : usbd_status uaudio_identify_as
     306             :         (struct uaudio_softc *, const usb_config_descriptor_t *);
     307             : usbd_status uaudio_process_as
     308             :         (struct uaudio_softc *, const char *, int *, int,
     309             :          const usb_interface_descriptor_t *);
     310             : 
     311             : void    uaudio_add_alt(struct uaudio_softc *, const struct as_info *);
     312             : 
     313             : const usb_interface_descriptor_t *uaudio_find_iface
     314             :         (const char *, int, int *, int, int);
     315             : 
     316             : void    uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *);
     317             : uByte   uaudio_get_cluster_nchan
     318             :         (int, const struct io_terminal *);
     319             : void    uaudio_add_input
     320             :         (struct uaudio_softc *, const struct io_terminal *, int);
     321             : void    uaudio_add_output
     322             :         (struct uaudio_softc *, const struct io_terminal *, int);
     323             : void    uaudio_add_mixer
     324             :         (struct uaudio_softc *, const struct io_terminal *, int);
     325             : void    uaudio_add_selector
     326             :         (struct uaudio_softc *, const struct io_terminal *, int);
     327             : #ifdef UAUDIO_DEBUG
     328             : const char *uaudio_get_terminal_name(int);
     329             : #endif
     330             : int     uaudio_determine_class
     331             :         (const struct io_terminal *, struct mixerctl *);
     332             : const char *uaudio_feature_name
     333             :         (const struct io_terminal *, struct mixerctl *);
     334             : void    uaudio_add_feature
     335             :         (struct uaudio_softc *, const struct io_terminal *, int);
     336             : void    uaudio_add_processing_updown
     337             :         (struct uaudio_softc *, const struct io_terminal *, int);
     338             : void    uaudio_add_processing
     339             :         (struct uaudio_softc *, const struct io_terminal *, int);
     340             : void    uaudio_add_extension
     341             :         (struct uaudio_softc *, const struct io_terminal *, int);
     342             : struct terminal_list *uaudio_merge_terminal_list
     343             :         (const struct io_terminal *);
     344             : struct terminal_list *uaudio_io_terminaltype
     345             :         (int, struct io_terminal *, int);
     346             : usbd_status uaudio_identify
     347             :         (struct uaudio_softc *, const usb_config_descriptor_t *);
     348             : 
     349             : int     uaudio_signext(int, int);
     350             : int     uaudio_unsignext(int, int);
     351             : int     uaudio_value2bsd(struct mixerctl *, int);
     352             : int     uaudio_bsd2value(struct mixerctl *, int);
     353             : int     uaudio_get(struct uaudio_softc *, int, int, int, int, int);
     354             : int     uaudio_ctl_get
     355             :         (struct uaudio_softc *, int, struct mixerctl *, int);
     356             : void    uaudio_set
     357             :         (struct uaudio_softc *, int, int, int, int, int, int);
     358             : void    uaudio_ctl_set
     359             :         (struct uaudio_softc *, int, struct mixerctl *, int, int);
     360             : 
     361             : usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int);
     362             : void    uaudio_set_speed_emu0202(struct chan *ch);
     363             : 
     364             : usbd_status uaudio_chan_open(struct uaudio_softc *, struct chan *);
     365             : void    uaudio_chan_close(struct uaudio_softc *, struct chan *);
     366             : usbd_status uaudio_chan_alloc_buffers
     367             :         (struct uaudio_softc *, struct chan *);
     368             : void    uaudio_chan_free_buffers(struct uaudio_softc *, struct chan *);
     369             : void    uaudio_chan_init
     370             :         (struct chan *, int, int, const struct audio_params *);
     371             : void    uaudio_chan_set_param(struct chan *, u_char *, u_char *, int);
     372             : void    uaudio_chan_ptransfer(struct chan *);
     373             : void    uaudio_chan_pintr
     374             :         (struct usbd_xfer *, void *, usbd_status);
     375             : void    uaudio_chan_psync_transfer(struct chan *);
     376             : void    uaudio_chan_psync_intr
     377             :         (struct usbd_xfer *, void *, usbd_status);
     378             : 
     379             : void    uaudio_chan_rtransfer(struct chan *);
     380             : void    uaudio_chan_rintr
     381             :         (struct usbd_xfer *, void *, usbd_status);
     382             : 
     383             : int     uaudio_open(void *, int);
     384             : void    uaudio_close(void *);
     385             : void    uaudio_get_minmax_rates
     386             :         (int, const struct as_info *, const struct audio_params *,
     387             :          int, int, int, u_long *, u_long *);
     388             : int     uaudio_match_alt_rate(void *, int, int);
     389             : int     uaudio_match_alt(void *, struct audio_params *, int);
     390             : int     uaudio_set_params
     391             :         (void *, int, int, struct audio_params *, struct audio_params *);
     392             : int     uaudio_round_blocksize(void *, int);
     393             : int     uaudio_trigger_output
     394             :         (void *, void *, void *, int, void (*)(void *), void *,
     395             :          struct audio_params *);
     396             : int     uaudio_trigger_input
     397             :         (void *, void *, void *, int, void (*)(void *), void *,
     398             :          struct audio_params *);
     399             : int     uaudio_halt_in_dma(void *);
     400             : int     uaudio_halt_out_dma(void *);
     401             : int     uaudio_mixer_set_port(void *, mixer_ctrl_t *);
     402             : int     uaudio_mixer_get_port(void *, mixer_ctrl_t *);
     403             : int     uaudio_query_devinfo(void *, mixer_devinfo_t *);
     404             : int     uaudio_get_props(void *);
     405             : 
     406             : struct audio_hw_if uaudio_hw_if = {
     407             :         uaudio_open,
     408             :         uaudio_close,
     409             :         uaudio_set_params,
     410             :         uaudio_round_blocksize,
     411             :         NULL,
     412             :         NULL,
     413             :         NULL,
     414             :         NULL,
     415             :         NULL,
     416             :         uaudio_halt_out_dma,
     417             :         uaudio_halt_in_dma,
     418             :         NULL,
     419             :         NULL,
     420             :         uaudio_mixer_set_port,
     421             :         uaudio_mixer_get_port,
     422             :         uaudio_query_devinfo,
     423             :         NULL,
     424             :         NULL,
     425             :         NULL,
     426             :         uaudio_get_props,
     427             :         uaudio_trigger_output,
     428             :         uaudio_trigger_input
     429             : };
     430             : 
     431             : int uaudio_match(struct device *, void *, void *); 
     432             : void uaudio_attach(struct device *, struct device *, void *); 
     433             : int uaudio_detach(struct device *, int); 
     434             : 
     435             : struct cfdriver uaudio_cd = { 
     436             :         NULL, "uaudio", DV_DULL 
     437             : }; 
     438             : 
     439             : const struct cfattach uaudio_ca = {
     440             :         sizeof(struct uaudio_softc), uaudio_match, uaudio_attach, uaudio_detach
     441             : };
     442             : 
     443             : int
     444           0 : uaudio_match(struct device *parent, void *match, void *aux)
     445             : {
     446           0 :         struct usb_attach_arg *uaa = aux;
     447             :         usb_interface_descriptor_t *id;
     448             :         const usb_interface_descriptor_t *cd_id;
     449             :         usb_config_descriptor_t *cdesc;
     450             :         struct uaudio_devs *quirk;
     451             :         const char *buf;
     452           0 :         int flags = 0, size, offs;
     453             : 
     454           0 :         if (uaa->iface == NULL || uaa->device == NULL)
     455           0 :                 return (UMATCH_NONE);
     456             : 
     457           0 :         quirk = uaudio_lookup(uaa->vendor, uaa->product);
     458           0 :         if (quirk)
     459           0 :                 flags = quirk->flags;
     460             : 
     461           0 :         if (flags & UAUDIO_FLAG_BAD_AUDIO)
     462           0 :                 return (UMATCH_NONE);
     463             : 
     464           0 :         id = usbd_get_interface_descriptor(uaa->iface);
     465           0 :         if (id == NULL)
     466           0 :                 return (UMATCH_NONE);
     467             : 
     468           0 :         if (!(id->bInterfaceClass == UICLASS_AUDIO ||
     469           0 :             ((flags & UAUDIO_FLAG_VENDOR_CLASS) &&
     470           0 :             id->bInterfaceClass == UICLASS_VENDOR)))
     471           0 :                 return (UMATCH_NONE);
     472             : 
     473           0 :         if (id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL)
     474           0 :                 return (UMATCH_NONE);
     475             : 
     476           0 :         cdesc = usbd_get_config_descriptor(uaa->device);
     477           0 :         if (cdesc == NULL)
     478           0 :                 return (UMATCH_NONE);
     479             : 
     480           0 :         size = UGETW(cdesc->wTotalLength);
     481           0 :         buf = (const char *)cdesc;
     482             : 
     483           0 :         offs = 0;
     484           0 :         cd_id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM,
     485             :             flags);
     486           0 :         if (cd_id == NULL)
     487           0 :                 return (UMATCH_NONE);
     488             : 
     489           0 :         offs = 0;
     490           0 :         cd_id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL,
     491             :             flags);
     492           0 :         if (cd_id == NULL)
     493           0 :                 return (UMATCH_NONE);
     494             : 
     495           0 :         return (UMATCH_VENDOR_PRODUCT_CONF_IFACE);
     496           0 : }
     497             : 
     498             : void
     499           0 : uaudio_attach(struct device *parent, struct device *self, void *aux)
     500             : {
     501           0 :         struct uaudio_softc *sc = (struct uaudio_softc *)self;
     502           0 :         struct usb_attach_arg *uaa = aux;
     503             :         struct uaudio_devs *quirk;
     504             :         usb_interface_descriptor_t *id;
     505             :         usb_config_descriptor_t *cdesc;
     506             :         usbd_status err;
     507             :         int i, j, found;
     508             : 
     509           0 :         sc->sc_udev = uaa->device;
     510             : 
     511           0 :         quirk = uaudio_lookup(uaa->vendor, uaa->product);
     512           0 :         if (quirk)
     513           0 :                 sc->sc_quirks = quirk->flags;
     514             : 
     515           0 :         cdesc = usbd_get_config_descriptor(sc->sc_udev);
     516           0 :         if (cdesc == NULL) {
     517           0 :                 printf("%s: failed to get configuration descriptor\n",
     518           0 :                        sc->sc_dev.dv_xname);
     519           0 :                 return;
     520             :         }
     521             : 
     522           0 :         err = uaudio_identify(sc, cdesc);
     523           0 :         if (err) {
     524           0 :                 printf("%s: audio descriptors make no sense, error=%d\n",
     525           0 :                        sc->sc_dev.dv_xname, err);
     526           0 :                 return;
     527             :         }
     528             : 
     529             :         /* Pick up the AS interface. */
     530           0 :         for (i = 0; i < uaa->nifaces; i++) {
     531           0 :                 if (usbd_iface_claimed(sc->sc_udev, i))
     532             :                         continue;
     533           0 :                 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
     534           0 :                 if (id == NULL)
     535             :                         continue;
     536             :                 found = 0;
     537           0 :                 for (j = 0; j < sc->sc_nalts; j++) {
     538           0 :                         if (id->bInterfaceNumber ==
     539           0 :                             sc->sc_alts[j].idesc->bInterfaceNumber) {
     540           0 :                                 sc->sc_alts[j].ifaceh = uaa->ifaces[i];
     541             :                                 found = 1;
     542           0 :                         }
     543             :                 }
     544           0 :                 if (found)
     545           0 :                         usbd_claim_iface(sc->sc_udev, i);
     546             :         }
     547             : 
     548           0 :         for (j = 0; j < sc->sc_nalts; j++) {
     549           0 :                 if (sc->sc_alts[j].ifaceh == NULL) {
     550           0 :                         printf("%s: alt %d missing AS interface(s)\n",
     551           0 :                             sc->sc_dev.dv_xname, j);
     552           0 :                         return;
     553             :                 }
     554             :         }
     555             : 
     556           0 :         printf("%s: audio rev %d.%02x", sc->sc_dev.dv_xname,
     557           0 :                sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
     558             : 
     559           0 :         sc->sc_playchan.sc = sc->sc_recchan.sc = sc;
     560           0 :         sc->sc_playchan.altidx = -1;
     561           0 :         sc->sc_recchan.altidx = -1;
     562             : 
     563           0 :         if (sc->sc_quirks & UAUDIO_FLAG_NO_FRAC)
     564           0 :                 sc->sc_altflags |= UA_NOFRAC;
     565             : 
     566           0 :         printf(", %d mixer controls\n", sc->sc_nctls);
     567             : 
     568             :         DPRINTF(("%s: doing audio_attach_mi\n", __func__));
     569           0 :         audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
     570           0 : }
     571             : 
     572             : int
     573           0 : uaudio_detach(struct device *self, int flags)
     574             : {
     575           0 :         struct uaudio_softc *sc = (struct uaudio_softc *)self;
     576             : 
     577             :         /*
     578             :          * sc_alts may be NULL if uaudio_identify_as() failed, in
     579             :          * which case uaudio_attach() didn't finish and there's
     580             :          * nothing to detach.
     581             :          */
     582           0 :         if (sc->sc_alts == NULL)
     583           0 :                 return (0);
     584           0 :         return (config_detach_children(self, flags));
     585           0 : }
     586             : 
     587             : const usb_interface_descriptor_t *
     588           0 : uaudio_find_iface(const char *buf, int size, int *offsp, int subtype, int flags)
     589             : {
     590             :         const usb_interface_descriptor_t *d;
     591             : 
     592           0 :         while (*offsp < size) {
     593           0 :                 d = (const void *)(buf + *offsp);
     594           0 :                 *offsp += d->bLength;
     595           0 :                 if (d->bDescriptorType == UDESC_INTERFACE &&
     596           0 :                     d->bInterfaceSubClass == subtype &&
     597           0 :                     (d->bInterfaceClass == UICLASS_AUDIO ||
     598           0 :                     (d->bInterfaceClass == UICLASS_VENDOR &&
     599           0 :                     (flags & UAUDIO_FLAG_VENDOR_CLASS))))
     600           0 :                         return (d);
     601             :         }
     602           0 :         return (NULL);
     603           0 : }
     604             : 
     605             : void
     606           0 : uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc)
     607             : {
     608             :         int res, range;
     609             :         size_t len;
     610             :         struct mixerctl *nmc;
     611             : 
     612             :         if (mc->class < UAC_NCLASSES) {
     613             :                 DPRINTF(("%s: adding %s.%s\n",
     614             :                          __func__, uac_names[mc->class], mc->ctlname));
     615             :         } else {
     616             :                 DPRINTF(("%s: adding %s\n", __func__, mc->ctlname));
     617             :         }
     618             : 
     619           0 :         nmc = mallocarray(sc->sc_nctls + 1, sizeof(*mc), M_USBDEV, M_NOWAIT);
     620           0 :         if (nmc == NULL) {
     621           0 :                 printf("%s: no memory\n", __func__);
     622           0 :                 return;
     623             :         }
     624           0 :         len = sizeof(*mc) * (sc->sc_nctls + 1);
     625             : 
     626             :         /* Copy old data, if there was any */
     627           0 :         if (sc->sc_nctls != 0) {
     628           0 :                 memcpy(nmc, sc->sc_ctls, sizeof(*mc) * (sc->sc_nctls));
     629           0 :                 free(sc->sc_ctls, M_USBDEV, sc->sc_nctls * sizeof(*mc));
     630           0 :         }
     631           0 :         sc->sc_ctls = nmc;
     632             : 
     633           0 :         mc->delta = 0;
     634           0 :         if (mc->type == MIX_ON_OFF) {
     635           0 :                 mc->minval = 0;
     636           0 :                 mc->maxval = 1;
     637           0 :         } else if (mc->type == MIX_SELECTOR) {
     638             :                 ;
     639             :         } else {
     640             :                 /* Determine min and max values. */
     641           0 :                 mc->minval = uaudio_signext(mc->type,
     642           0 :                         uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
     643           0 :                                    mc->wValue[0], mc->wIndex,
     644           0 :                                    MIX_SIZE(mc->type)));
     645           0 :                 mc->maxval = uaudio_signext(mc->type,
     646           0 :                         uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE,
     647           0 :                                    mc->wValue[0], mc->wIndex,
     648           0 :                                    MIX_SIZE(mc->type)));
     649           0 :                 range = mc->maxval - mc->minval;
     650           0 :                 res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
     651           0 :                                  mc->wValue[0], mc->wIndex,
     652           0 :                                  MIX_SIZE(mc->type));
     653           0 :                 if (res > 0 && range > 0)
     654           0 :                         mc->delta = (res * 255 + res - 1) / range;
     655             :         }
     656             : 
     657           0 :         sc->sc_ctls[sc->sc_nctls++] = *mc;
     658             : 
     659             : #ifdef UAUDIO_DEBUG
     660             :         if (uaudiodebug > 2) {
     661             :                 int i;
     662             :                 DPRINTF(("%s: wValue=%04x", __func__, mc->wValue[0]));
     663             :                 for (i = 1; i < mc->nchan; i++)
     664             :                         DPRINTF((",%04x", mc->wValue[i]));
     665             :                 DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' "
     666             :                          "min=%d max=%d\n",
     667             :                          mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
     668             :                          mc->minval, mc->maxval));
     669             :         }
     670             : #endif
     671           0 : }
     672             : 
     673             : uByte
     674           0 : uaudio_get_cluster_nchan(int id, const struct io_terminal *iot)
     675             : {
     676           0 :         struct usb_audio_cluster r;
     677             :         const usb_descriptor_t *dp;
     678             :         int i;
     679             : 
     680           0 :         for (i = 0; i < 25; i++) { /* avoid infinite loops */
     681           0 :                 dp = iot[id].d.desc;
     682           0 :                 if (dp == 0)
     683             :                         goto bad;
     684           0 :                 switch (dp->bDescriptorSubtype) {
     685             :                 case UDESCSUB_AC_INPUT:
     686           0 :                         return (iot[id].d.it->bNrChannels);
     687             :                 case UDESCSUB_AC_OUTPUT:
     688           0 :                         id = iot[id].d.ot->bSourceId;
     689           0 :                         break;
     690             :                 case UDESCSUB_AC_MIXER:
     691           0 :                         r = *(struct usb_audio_cluster *)
     692           0 :                                 &iot[id].d.mu->baSourceId[iot[id].d.mu->bNrInPins];
     693           0 :                         return (r.bNrChannels);
     694             :                 case UDESCSUB_AC_SELECTOR:
     695             :                         /* XXX This is not really right */
     696           0 :                         id = iot[id].d.su->baSourceId[0];
     697           0 :                         break;
     698             :                 case UDESCSUB_AC_FEATURE:
     699           0 :                         id = iot[id].d.fu->bSourceId;
     700           0 :                         break;
     701             :                 case UDESCSUB_AC_PROCESSING:
     702           0 :                         r = *(struct usb_audio_cluster *)
     703           0 :                                 &iot[id].d.pu->baSourceId[iot[id].d.pu->bNrInPins];
     704           0 :                         return (r.bNrChannels);
     705             :                 case UDESCSUB_AC_EXTENSION:
     706           0 :                         r = *(struct usb_audio_cluster *)
     707           0 :                                 &iot[id].d.eu->baSourceId[iot[id].d.eu->bNrInPins];
     708           0 :                         return (r.bNrChannels);
     709             :                 default:
     710             :                         goto bad;
     711             :                 }
     712             :         }
     713             : bad:
     714           0 :         printf("%s: bad data\n", __func__);
     715           0 :         return (0);
     716           0 : }
     717             : 
     718             : void
     719           0 : uaudio_add_input(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
     720             : {
     721             : #ifdef UAUDIO_DEBUG
     722             :         const struct usb_audio_input_terminal *d = iot[id].d.it;
     723             : 
     724             :         DPRINTFN(2,("%s: bTerminalId=%d wTerminalType=0x%04x "
     725             :                     "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
     726             :                     "iChannelNames=%d iTerminal=%d\n",
     727             :                     __func__,
     728             :                     d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
     729             :                     d->bNrChannels, UGETW(d->wChannelConfig),
     730             :                     d->iChannelNames, d->iTerminal));
     731             : #endif
     732           0 : }
     733             : 
     734             : void
     735           0 : uaudio_add_output(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
     736             : {
     737             : #ifdef UAUDIO_DEBUG
     738             :         const struct usb_audio_output_terminal *d = iot[id].d.ot;
     739             : 
     740             :         DPRINTFN(2,("%s: bTerminalId=%d wTerminalType=0x%04x "
     741             :                     "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
     742             :                     __func__,
     743             :                     d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
     744             :                     d->bSourceId, d->iTerminal));
     745             : #endif
     746           0 : }
     747             : 
     748             : void
     749           0 : uaudio_add_mixer(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
     750             : {
     751           0 :         const struct usb_audio_mixer_unit *d = iot[id].d.mu;
     752             :         struct usb_audio_mixer_unit_1 *d1;
     753             :         int c, chs, ochs, i, o, bno, p, mo, mc, k;
     754             : #ifdef UAUDIO_DEBUG
     755             :         int ichs = 0;
     756             : #endif
     757             :         uByte *bm;
     758           0 :         struct mixerctl mix;
     759             : 
     760             :         DPRINTFN(2,("%s: bUnitId=%d bNrInPins=%d\n", __func__,
     761             :                     d->bUnitId, d->bNrInPins));
     762             : 
     763             : #ifdef UAUDIO_DEBUG
     764             :         /* Compute the number of input channels */
     765             :         for (i = 0; i < d->bNrInPins; i++)
     766             :                 ichs += uaudio_get_cluster_nchan(d->baSourceId[i], iot);
     767             : #endif
     768             : 
     769             :         /* and the number of output channels */
     770           0 :         d1 = (struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins];
     771           0 :         ochs = d1->bNrChannels;
     772             :         DPRINTFN(2,("%s: ichs=%d ochs=%d\n", __func__, ichs, ochs));
     773             : 
     774           0 :         bm = d1->bmControls;
     775           0 :         mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
     776           0 :         uaudio_determine_class(&iot[id], &mix);
     777           0 :         mix.type = MIX_SIGNED_16;
     778           0 :         mix.ctlunit = AudioNvolume;
     779             : #define BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1)
     780           0 :         for (p = i = 0; i < d->bNrInPins; i++) {
     781           0 :                 chs = uaudio_get_cluster_nchan(d->baSourceId[i], iot);
     782             :                 mc = 0;
     783           0 :                 for (c = 0; c < chs; c++) {
     784             :                         mo = 0;
     785           0 :                         for (o = 0; o < ochs; o++) {
     786           0 :                                 bno = (p + c) * ochs + o;
     787           0 :                                 if (BIT(bno))
     788           0 :                                         mo++;
     789             :                         }
     790           0 :                         if (mo == 1)
     791           0 :                                 mc++;
     792             :                 }
     793           0 :                 if (mc == chs && chs <= MIX_MAX_CHAN) {
     794             :                         k = 0;
     795           0 :                         for (c = 0; c < chs; c++)
     796           0 :                                 for (o = 0; o < ochs; o++) {
     797           0 :                                         bno = (p + c) * ochs + o;
     798           0 :                                         if (BIT(bno))
     799           0 :                                                 mix.wValue[k++] =
     800           0 :                                                         MAKE(p+c+1, o+1);
     801             :                                 }
     802           0 :                         snprintf(mix.ctlname, sizeof(mix.ctlname), "mix%d-i%d",
     803           0 :                             d->bUnitId, d->baSourceId[i]);
     804           0 :                         mix.nchan = chs;
     805           0 :                         uaudio_mixer_add_ctl(sc, &mix);
     806           0 :                 } else {
     807             :                         /* XXX */
     808             :                 }
     809             : #undef BIT
     810           0 :                 p += chs;
     811             :         }
     812             : 
     813           0 : }
     814             : 
     815             : void
     816           0 : uaudio_add_selector(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
     817             : {
     818           0 :         const struct usb_audio_selector_unit *d = iot[id].d.su;
     819           0 :         struct mixerctl mix;
     820             :         int i, wp;
     821             : 
     822             :         DPRINTFN(2,("%s: bUnitId=%d bNrInPins=%d\n", __func__,
     823             :                     d->bUnitId, d->bNrInPins));
     824           0 :         mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
     825           0 :         mix.wValue[0] = MAKE(0, 0);
     826           0 :         uaudio_determine_class(&iot[id], &mix);
     827           0 :         mix.nchan = 1;
     828           0 :         mix.type = MIX_SELECTOR;
     829           0 :         mix.ctlunit = "";
     830           0 :         mix.minval = 1;
     831           0 :         mix.maxval = d->bNrInPins;
     832           0 :         wp = snprintf(mix.ctlname, MAX_AUDIO_DEV_LEN, "sel%d-", d->bUnitId);
     833           0 :         for (i = 1; i <= d->bNrInPins; i++) {
     834           0 :                 wp += snprintf(mix.ctlname + wp, MAX_AUDIO_DEV_LEN - wp,
     835           0 :                                "i%d", d->baSourceId[i - 1]);
     836           0 :                 if (wp > MAX_AUDIO_DEV_LEN - 1)
     837             :                         break;
     838             :         }
     839           0 :         uaudio_mixer_add_ctl(sc, &mix);
     840           0 : }
     841             : 
     842             : #ifdef UAUDIO_DEBUG
     843             : const char *
     844             : uaudio_get_terminal_name(int terminal_type)
     845             : {
     846             :         static char buf[100];
     847             : 
     848             :         switch (terminal_type) {
     849             :         /* USB terminal types */
     850             :         case UAT_UNDEFINED:     return "UAT_UNDEFINED";
     851             :         case UAT_STREAM:        return "UAT_STREAM";
     852             :         case UAT_VENDOR:        return "UAT_VENDOR";
     853             :         /* input terminal types */
     854             :         case UATI_UNDEFINED:    return "UATI_UNDEFINED";
     855             :         case UATI_MICROPHONE:   return "UATI_MICROPHONE";
     856             :         case UATI_DESKMICROPHONE:       return "UATI_DESKMICROPHONE";
     857             :         case UATI_PERSONALMICROPHONE:   return "UATI_PERSONALMICROPHONE";
     858             :         case UATI_OMNIMICROPHONE:       return "UATI_OMNIMICROPHONE";
     859             :         case UATI_MICROPHONEARRAY:      return "UATI_MICROPHONEARRAY";
     860             :         case UATI_PROCMICROPHONEARR:    return "UATI_PROCMICROPHONEARR";
     861             :         /* output terminal types */
     862             :         case UATO_UNDEFINED:    return "UATO_UNDEFINED";
     863             :         case UATO_SPEAKER:      return "UATO_SPEAKER";
     864             :         case UATO_HEADPHONES:   return "UATO_HEADPHONES";
     865             :         case UATO_DISPLAYAUDIO: return "UATO_DISPLAYAUDIO";
     866             :         case UATO_DESKTOPSPEAKER:       return "UATO_DESKTOPSPEAKER";
     867             :         case UATO_ROOMSPEAKER:  return "UATO_ROOMSPEAKER";
     868             :         case UATO_COMMSPEAKER:  return "UATO_COMMSPEAKER";
     869             :         case UATO_SUBWOOFER:    return "UATO_SUBWOOFER";
     870             :         /* bidir terminal types */
     871             :         case UATB_UNDEFINED:    return "UATB_UNDEFINED";
     872             :         case UATB_HANDSET:      return "UATB_HANDSET";
     873             :         case UATB_HEADSET:      return "UATB_HEADSET";
     874             :         case UATB_SPEAKERPHONE: return "UATB_SPEAKERPHONE";
     875             :         case UATB_SPEAKERPHONEESUP:     return "UATB_SPEAKERPHONEESUP";
     876             :         case UATB_SPEAKERPHONEECANC:    return "UATB_SPEAKERPHONEECANC";
     877             :         /* telephony terminal types */
     878             :         case UATT_UNDEFINED:    return "UATT_UNDEFINED";
     879             :         case UATT_PHONELINE:    return "UATT_PHONELINE";
     880             :         case UATT_TELEPHONE:    return "UATT_TELEPHONE";
     881             :         case UATT_DOWNLINEPHONE:        return "UATT_DOWNLINEPHONE";
     882             :         /* external terminal types */
     883             :         case UATE_UNDEFINED:    return "UATE_UNDEFINED";
     884             :         case UATE_ANALOGCONN:   return "UATE_ANALOGCONN";
     885             :         case UATE_LINECONN:     return "UATE_LINECONN";
     886             :         case UATE_LEGACYCONN:   return "UATE_LEGACYCONN";
     887             :         case UATE_DIGITALAUIFC: return "UATE_DIGITALAUIFC";
     888             :         case UATE_SPDIF:        return "UATE_SPDIF";
     889             :         case UATE_1394DA:       return "UATE_1394DA";
     890             :         case UATE_1394DV:       return "UATE_1394DV";
     891             :         /* embedded function terminal types */
     892             :         case UATF_UNDEFINED:    return "UATF_UNDEFINED";
     893             :         case UATF_CALIBNOISE:   return "UATF_CALIBNOISE";
     894             :         case UATF_EQUNOISE:     return "UATF_EQUNOISE";
     895             :         case UATF_CDPLAYER:     return "UATF_CDPLAYER";
     896             :         case UATF_DAT:  return "UATF_DAT";
     897             :         case UATF_DCC:  return "UATF_DCC";
     898             :         case UATF_MINIDISK:     return "UATF_MINIDISK";
     899             :         case UATF_ANALOGTAPE:   return "UATF_ANALOGTAPE";
     900             :         case UATF_PHONOGRAPH:   return "UATF_PHONOGRAPH";
     901             :         case UATF_VCRAUDIO:     return "UATF_VCRAUDIO";
     902             :         case UATF_VIDEODISCAUDIO:       return "UATF_VIDEODISCAUDIO";
     903             :         case UATF_DVDAUDIO:     return "UATF_DVDAUDIO";
     904             :         case UATF_TVTUNERAUDIO: return "UATF_TVTUNERAUDIO";
     905             :         case UATF_SATELLITE:    return "UATF_SATELLITE";
     906             :         case UATF_CABLETUNER:   return "UATF_CABLETUNER";
     907             :         case UATF_DSS:  return "UATF_DSS";
     908             :         case UATF_RADIORECV:    return "UATF_RADIORECV";
     909             :         case UATF_RADIOXMIT:    return "UATF_RADIOXMIT";
     910             :         case UATF_MULTITRACK:   return "UATF_MULTITRACK";
     911             :         case UATF_SYNTHESIZER:  return "UATF_SYNTHESIZER";
     912             :         default:
     913             :                 snprintf(buf, sizeof(buf), "unknown type (0x%.4x)", terminal_type);
     914             :                 return buf;
     915             :         }
     916             : }
     917             : #endif
     918             : 
     919             : int
     920           0 : uaudio_determine_class(const struct io_terminal *iot, struct mixerctl *mix)
     921             : {
     922             :         int terminal_type;
     923             : 
     924           0 :         if (iot == NULL || iot->output == NULL) {
     925           0 :                 mix->class = UAC_OUTPUT;
     926           0 :                 return 0;
     927             :         }
     928             :         terminal_type = 0;
     929           0 :         if (iot->output->size == 1)
     930           0 :                 terminal_type = iot->output->terminals[0];
     931             :         /*
     932             :          * If the only output terminal is USB,
     933             :          * the class is UAC_RECORD.
     934             :          */
     935           0 :         if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) {
     936           0 :                 mix->class = UAC_RECORD;
     937           0 :                 if (iot->inputs_size == 1
     938           0 :                     && iot->inputs[0] != NULL
     939           0 :                     && iot->inputs[0]->size == 1)
     940           0 :                         return iot->inputs[0]->terminals[0];
     941             :                 else
     942           0 :                         return 0;
     943             :         }
     944             :         /*
     945             :          * If the ultimate destination of the unit is just one output
     946             :          * terminal and the unit is connected to the output terminal
     947             :          * directly, the class is UAC_OUTPUT.
     948             :          */
     949           0 :         if (terminal_type != 0 && iot->direct) {
     950           0 :                 mix->class = UAC_OUTPUT;
     951           0 :                 return terminal_type;
     952             :         }
     953             :         /*
     954             :          * If the unit is connected to just one input terminal,
     955             :          * the class is UAC_INPUT.
     956             :          */
     957           0 :         if (iot->inputs_size == 1 && iot->inputs[0] != NULL
     958           0 :             && iot->inputs[0]->size == 1) {
     959           0 :                 mix->class = UAC_INPUT;
     960           0 :                 return iot->inputs[0]->terminals[0];
     961             :         }
     962             :         /*
     963             :          * Otherwise, the class is UAC_OUTPUT.
     964             :          */
     965           0 :         mix->class = UAC_OUTPUT;
     966           0 :         return terminal_type;
     967           0 : }
     968             : 
     969             : const char *
     970           0 : uaudio_feature_name(const struct io_terminal *iot, struct mixerctl *mix)
     971             : {
     972             :         int terminal_type;
     973             : 
     974           0 :         terminal_type = uaudio_determine_class(iot, mix);
     975           0 :         if (mix->class == UAC_RECORD && terminal_type == 0)
     976           0 :                 return AudioNmixerout;
     977             :         DPRINTF(("%s: terminal_type=%s\n", __func__,
     978             :                  uaudio_get_terminal_name(terminal_type)));
     979           0 :         switch (terminal_type) {
     980             :         case UAT_STREAM:
     981           0 :                 return AudioNdac;
     982             : 
     983             :         case UATI_MICROPHONE:
     984             :         case UATI_DESKMICROPHONE:
     985             :         case UATI_PERSONALMICROPHONE:
     986             :         case UATI_OMNIMICROPHONE:
     987             :         case UATI_MICROPHONEARRAY:
     988             :         case UATI_PROCMICROPHONEARR:
     989           0 :                 return AudioNmicrophone;
     990             : 
     991             :         case UATO_SPEAKER:
     992             :         case UATO_DESKTOPSPEAKER:
     993             :         case UATO_ROOMSPEAKER:
     994             :         case UATO_COMMSPEAKER:
     995           0 :                 return AudioNspeaker;
     996             : 
     997             :         case UATO_HEADPHONES:
     998           0 :                 return AudioNheadphone;
     999             : 
    1000             :         case UATO_SUBWOOFER:
    1001           0 :                 return AudioNlfe;
    1002             : 
    1003             :         /* telephony terminal types */
    1004             :         case UATT_UNDEFINED:
    1005             :         case UATT_PHONELINE:
    1006             :         case UATT_TELEPHONE:
    1007             :         case UATT_DOWNLINEPHONE:
    1008           0 :                 return "phone";
    1009             : 
    1010             :         case UATE_ANALOGCONN:
    1011             :         case UATE_LINECONN:
    1012             :         case UATE_LEGACYCONN:
    1013           0 :                 return AudioNline;
    1014             : 
    1015             :         case UATE_DIGITALAUIFC:
    1016             :         case UATE_SPDIF:
    1017             :         case UATE_1394DA:
    1018             :         case UATE_1394DV:
    1019           0 :                 return AudioNaux;
    1020             : 
    1021             :         case UATF_CDPLAYER:
    1022           0 :                 return AudioNcd;
    1023             : 
    1024             :         case UATF_SYNTHESIZER:
    1025           0 :                 return AudioNfmsynth;
    1026             : 
    1027             :         case UATF_VIDEODISCAUDIO:
    1028             :         case UATF_DVDAUDIO:
    1029             :         case UATF_TVTUNERAUDIO:
    1030           0 :                 return AudioNvideo;
    1031             : 
    1032             :         case UAT_UNDEFINED:
    1033             :         case UAT_VENDOR:
    1034             :         case UATI_UNDEFINED:
    1035             : /* output terminal types */
    1036             :         case UATO_UNDEFINED:
    1037             :         case UATO_DISPLAYAUDIO:
    1038             : /* bidir terminal types */
    1039             :         case UATB_UNDEFINED:
    1040             :         case UATB_HANDSET:
    1041             :         case UATB_HEADSET:
    1042             :         case UATB_SPEAKERPHONE:
    1043             :         case UATB_SPEAKERPHONEESUP:
    1044             :         case UATB_SPEAKERPHONEECANC:
    1045             : /* external terminal types */
    1046             :         case UATE_UNDEFINED:
    1047             : /* embedded function terminal types */
    1048             :         case UATF_UNDEFINED:
    1049             :         case UATF_CALIBNOISE:
    1050             :         case UATF_EQUNOISE:
    1051             :         case UATF_DAT:
    1052             :         case UATF_DCC:
    1053             :         case UATF_MINIDISK:
    1054             :         case UATF_ANALOGTAPE:
    1055             :         case UATF_PHONOGRAPH:
    1056             :         case UATF_VCRAUDIO:
    1057             :         case UATF_SATELLITE:
    1058             :         case UATF_CABLETUNER:
    1059             :         case UATF_DSS:
    1060             :         case UATF_RADIORECV:
    1061             :         case UATF_RADIOXMIT:
    1062             :         case UATF_MULTITRACK:
    1063             :         case 0xffff:
    1064             :         default:
    1065             :                 DPRINTF(("%s: 'master' for 0x%.4x\n", __func__, terminal_type));
    1066           0 :                 return AudioNmaster;
    1067             :         }
    1068           0 : }
    1069             : 
    1070             : void
    1071           0 : uaudio_add_feature(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
    1072             : {
    1073           0 :         const struct usb_audio_feature_unit *d = iot[id].d.fu;
    1074           0 :         uByte *ctls = (uByte *)d->bmaControls;
    1075           0 :         int ctlsize = d->bControlSize;
    1076             :         u_int fumask, mmask, cmask;
    1077           0 :         struct mixerctl mix;
    1078             :         int chan, ctl, i, nchan, unit;
    1079             :         const char *mixername;
    1080             : 
    1081             : #define GET(i) (ctls[(i)*ctlsize] | \
    1082             :                 (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
    1083             : 
    1084           0 :         if (ctlsize == 0) {
    1085             :                 DPRINTF(("ignoring feature %d: bControlSize == 0\n", id));
    1086           0 :                 return;
    1087             :         }
    1088           0 :         nchan = (d->bLength - 7) / ctlsize;
    1089           0 :         mmask = GET(0);
    1090             :         /* Figure out what we can control */
    1091           0 :         for (cmask = 0, chan = 1; chan < nchan; chan++) {
    1092             :                 DPRINTFN(9,("%s: chan=%d mask=%x\n",
    1093             :                             __func__, chan, GET(chan)));
    1094           0 :                 cmask |= GET(chan);
    1095             :         }
    1096             : 
    1097             :         DPRINTFN(1,("%s: bUnitId=%d, "
    1098             :                     "%d channels, mmask=0x%04x, cmask=0x%04x\n",
    1099             :                     __func__, d->bUnitId, nchan, mmask, cmask));
    1100             : 
    1101           0 :         if (nchan > MIX_MAX_CHAN)
    1102           0 :                 nchan = MIX_MAX_CHAN;
    1103           0 :         unit = d->bUnitId;
    1104           0 :         mix.wIndex = MAKE(unit, sc->sc_ac_iface);
    1105           0 :         for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) {
    1106           0 :                 fumask = FU_MASK(ctl);
    1107             :                 DPRINTFN(4,("%s: ctl=%d fumask=0x%04x\n",
    1108             :                             __func__, ctl, fumask));
    1109           0 :                 if (mmask & fumask) {
    1110           0 :                         mix.nchan = 1;
    1111           0 :                         mix.wValue[0] = MAKE(ctl, 0);
    1112           0 :                 } else if (cmask & fumask) {
    1113           0 :                         mix.nchan = nchan - 1;
    1114           0 :                         for (i = 1; i < nchan; i++) {
    1115           0 :                                 if (GET(i) & fumask)
    1116           0 :                                         mix.wValue[i-1] = MAKE(ctl, i);
    1117             :                                 else
    1118           0 :                                         mix.wValue[i-1] = -1;
    1119             :                         }
    1120             :                 } else {
    1121             :                         continue;
    1122             :                 }
    1123             : #undef GET
    1124           0 :                 mixername = uaudio_feature_name(&iot[id], &mix);
    1125           0 :                 switch (ctl) {
    1126             :                 case MUTE_CONTROL:
    1127           0 :                         mix.type = MIX_ON_OFF;
    1128           0 :                         mix.ctlunit = "";
    1129           0 :                         snprintf(mix.ctlname, sizeof(mix.ctlname),
    1130             :                                  "%s.%s", mixername, AudioNmute);
    1131           0 :                         break;
    1132             :                 case VOLUME_CONTROL:
    1133           0 :                         mix.type = MIX_SIGNED_16;
    1134           0 :                         mix.ctlunit = AudioNvolume;
    1135           0 :                         strlcpy(mix.ctlname, mixername, sizeof(mix.ctlname));
    1136           0 :                         break;
    1137             :                 case BASS_CONTROL:
    1138           0 :                         mix.type = MIX_SIGNED_8;
    1139           0 :                         mix.ctlunit = AudioNbass;
    1140           0 :                         snprintf(mix.ctlname, sizeof(mix.ctlname),
    1141             :                                  "%s.%s", mixername, AudioNbass);
    1142           0 :                         break;
    1143             :                 case MID_CONTROL:
    1144           0 :                         mix.type = MIX_SIGNED_8;
    1145           0 :                         mix.ctlunit = AudioNmid;
    1146           0 :                         snprintf(mix.ctlname, sizeof(mix.ctlname),
    1147             :                                  "%s.%s", mixername, AudioNmid);
    1148           0 :                         break;
    1149             :                 case TREBLE_CONTROL:
    1150           0 :                         mix.type = MIX_SIGNED_8;
    1151           0 :                         mix.ctlunit = AudioNtreble;
    1152           0 :                         snprintf(mix.ctlname, sizeof(mix.ctlname),
    1153             :                                  "%s.%s", mixername, AudioNtreble);
    1154           0 :                         break;
    1155             :                 case GRAPHIC_EQUALIZER_CONTROL:
    1156             :                         continue; /* XXX don't add anything */
    1157             :                         break;
    1158             :                 case AGC_CONTROL:
    1159           0 :                         mix.type = MIX_ON_OFF;
    1160           0 :                         mix.ctlunit = "";
    1161           0 :                         snprintf(mix.ctlname, sizeof(mix.ctlname), "%s.%s",
    1162             :                                  mixername, AudioNagc);
    1163           0 :                         break;
    1164             :                 case DELAY_CONTROL:
    1165           0 :                         mix.type = MIX_UNSIGNED_16;
    1166           0 :                         mix.ctlunit = "4 ms";
    1167           0 :                         snprintf(mix.ctlname, sizeof(mix.ctlname),
    1168             :                                  "%s.%s", mixername, AudioNdelay);
    1169           0 :                         break;
    1170             :                 case BASS_BOOST_CONTROL:
    1171           0 :                         mix.type = MIX_ON_OFF;
    1172           0 :                         mix.ctlunit = "";
    1173           0 :                         snprintf(mix.ctlname, sizeof(mix.ctlname),
    1174             :                                  "%s.%s", mixername, AudioNbassboost);
    1175           0 :                         break;
    1176             :                 case LOUDNESS_CONTROL:
    1177           0 :                         mix.type = MIX_ON_OFF;
    1178           0 :                         mix.ctlunit = "";
    1179           0 :                         snprintf(mix.ctlname, sizeof(mix.ctlname),
    1180             :                                  "%s.%s", mixername, AudioNloudness);
    1181           0 :                         break;
    1182             :                 }
    1183           0 :                 uaudio_mixer_add_ctl(sc, &mix);
    1184           0 :         }
    1185           0 : }
    1186             : 
    1187             : void
    1188           0 : uaudio_add_processing_updown(struct uaudio_softc *sc,
    1189             :                              const struct io_terminal *iot, int id)
    1190             : {
    1191           0 :         const struct usb_audio_processing_unit *d = iot[id].d.pu;
    1192             :         const struct usb_audio_processing_unit_1 *d1 =
    1193           0 :             (const struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
    1194             :         const struct usb_audio_processing_unit_updown *ud =
    1195           0 :             (const struct usb_audio_processing_unit_updown *)
    1196           0 :                 &d1->bmControls[d1->bControlSize];
    1197           0 :         struct mixerctl mix;
    1198             :         int i;
    1199             : 
    1200             :         DPRINTFN(2,("%s: bUnitId=%d bNrModes=%d\n",
    1201             :                     __func__, d->bUnitId, ud->bNrModes));
    1202             : 
    1203           0 :         if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
    1204             :                 DPRINTF(("%s: no mode select\n", __func__));
    1205           0 :                 return;
    1206             :         }
    1207             : 
    1208           0 :         mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
    1209           0 :         mix.nchan = 1;
    1210           0 :         mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
    1211           0 :         uaudio_determine_class(&iot[id], &mix);
    1212           0 :         mix.type = MIX_ON_OFF;  /* XXX */
    1213           0 :         mix.ctlunit = "";
    1214           0 :         snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d-mode", d->bUnitId);
    1215             : 
    1216           0 :         for (i = 0; i < ud->bNrModes; i++) {
    1217             :                 DPRINTFN(2,("%s: i=%d bm=0x%x\n",
    1218             :                             __func__, i, UGETW(ud->waModes[i])));
    1219             :                 /* XXX */
    1220             :         }
    1221           0 :         uaudio_mixer_add_ctl(sc, &mix);
    1222           0 : }
    1223             : 
    1224             : void
    1225           0 : uaudio_add_processing(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
    1226             : {
    1227           0 :         const struct usb_audio_processing_unit *d = iot[id].d.pu;
    1228             :         const struct usb_audio_processing_unit_1 *d1 =
    1229           0 :             (const struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
    1230           0 :         int ptype = UGETW(d->wProcessType);
    1231           0 :         struct mixerctl mix;
    1232             : 
    1233             :         DPRINTFN(2,("%s: wProcessType=%d bUnitId=%d "
    1234             :                     "bNrInPins=%d\n", __func__, ptype, d->bUnitId,
    1235             :                     d->bNrInPins));
    1236             : 
    1237           0 :         if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
    1238           0 :                 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
    1239           0 :                 mix.nchan = 1;
    1240           0 :                 mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
    1241           0 :                 uaudio_determine_class(&iot[id], &mix);
    1242           0 :                 mix.type = MIX_ON_OFF;
    1243           0 :                 mix.ctlunit = "";
    1244           0 :                 snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d.%d-enable",
    1245           0 :                     d->bUnitId, ptype);
    1246           0 :                 uaudio_mixer_add_ctl(sc, &mix);
    1247           0 :         }
    1248             : 
    1249           0 :         switch(ptype) {
    1250             :         case UPDOWNMIX_PROCESS:
    1251           0 :                 uaudio_add_processing_updown(sc, iot, id);
    1252           0 :                 break;
    1253             :         case DOLBY_PROLOGIC_PROCESS:
    1254             :         case P3D_STEREO_EXTENDER_PROCESS:
    1255             :         case REVERBATION_PROCESS:
    1256             :         case CHORUS_PROCESS:
    1257             :         case DYN_RANGE_COMP_PROCESS:
    1258             :         default:
    1259             :                 DPRINTF(("%s: unit %d, type=%d not impl.\n",
    1260             :                        __func__, d->bUnitId, ptype));
    1261             :                 break;
    1262             :         }
    1263           0 : }
    1264             : 
    1265             : void
    1266           0 : uaudio_add_extension(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
    1267             : {
    1268           0 :         const struct usb_audio_extension_unit *d = iot[id].d.eu;
    1269             :         const struct usb_audio_extension_unit_1 *d1 =
    1270           0 :             (const struct usb_audio_extension_unit_1 *)&d->baSourceId[d->bNrInPins];
    1271           0 :         struct mixerctl mix;
    1272             : 
    1273             :         DPRINTFN(2,("%s: bUnitId=%d bNrInPins=%d\n",
    1274             :                     __func__, d->bUnitId, d->bNrInPins));
    1275             : 
    1276           0 :         if (sc->sc_quirks & UAUDIO_FLAG_NO_XU)
    1277           0 :                 return;
    1278             : 
    1279           0 :         if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
    1280           0 :                 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
    1281           0 :                 mix.nchan = 1;
    1282           0 :                 mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
    1283           0 :                 uaudio_determine_class(&iot[id], &mix);
    1284           0 :                 mix.type = MIX_ON_OFF;
    1285           0 :                 mix.ctlunit = "";
    1286           0 :                 snprintf(mix.ctlname, sizeof(mix.ctlname), "ext%d-enable",
    1287           0 :                     d->bUnitId);
    1288           0 :                 uaudio_mixer_add_ctl(sc, &mix);
    1289           0 :         }
    1290           0 : }
    1291             : 
    1292             : struct terminal_list*
    1293           0 : uaudio_merge_terminal_list(const struct io_terminal *iot)
    1294             : {
    1295             :         struct terminal_list *tml;
    1296             :         uint16_t *ptm;
    1297             :         int i, len;
    1298             : 
    1299             :         len = 0;
    1300           0 :         if (iot->inputs == NULL)
    1301           0 :                 return NULL;
    1302           0 :         for (i = 0; i < iot->inputs_size; i++) {
    1303           0 :                 if (iot->inputs[i] != NULL)
    1304           0 :                         len += iot->inputs[i]->size;
    1305             :         }
    1306           0 :         tml = malloc(TERMINAL_LIST_SIZE(len), M_TEMP, M_NOWAIT);
    1307           0 :         if (tml == NULL) {
    1308           0 :                 printf("%s: no memory\n", __func__);
    1309           0 :                 return NULL;
    1310             :         }
    1311           0 :         tml->size = 0;
    1312           0 :         ptm = tml->terminals;
    1313           0 :         for (i = 0; i < iot->inputs_size; i++) {
    1314           0 :                 if (iot->inputs[i] == NULL)
    1315             :                         continue;
    1316           0 :                 if (iot->inputs[i]->size > len)
    1317             :                         break;
    1318           0 :                 memcpy(ptm, iot->inputs[i]->terminals,
    1319             :                        iot->inputs[i]->size * sizeof(uint16_t));
    1320           0 :                 tml->size += iot->inputs[i]->size;
    1321           0 :                 ptm += iot->inputs[i]->size;
    1322           0 :                 len -= iot->inputs[i]->size;
    1323           0 :         }
    1324           0 :         return tml;
    1325           0 : }
    1326             : 
    1327             : struct terminal_list *
    1328           0 : uaudio_io_terminaltype(int outtype, struct io_terminal *iot, int id)
    1329             : {
    1330             :         struct terminal_list *tml;
    1331             :         struct io_terminal *it;
    1332             :         int src_id, i;
    1333             : 
    1334           0 :         it = &iot[id];
    1335           0 :         if (it->output != NULL) {
    1336             :                 /* already has outtype? */
    1337           0 :                 for (i = 0; i < it->output->size; i++)
    1338           0 :                         if (it->output->terminals[i] == outtype)
    1339           0 :                                 return uaudio_merge_terminal_list(it);
    1340           0 :                 tml = malloc(TERMINAL_LIST_SIZE(it->output->size + 1),
    1341             :                     M_TEMP, M_NOWAIT);
    1342           0 :                 if (tml == NULL) {
    1343           0 :                         printf("%s: no memory\n", __func__);
    1344           0 :                         return uaudio_merge_terminal_list(it);
    1345             :                 }
    1346           0 :                 memcpy(tml, it->output, TERMINAL_LIST_SIZE(it->output->size));
    1347           0 :                 tml->terminals[it->output->size] = outtype;
    1348           0 :                 tml->size++;
    1349           0 :                 free(it->output, M_TEMP, 0);
    1350           0 :                 it->output = tml;
    1351           0 :                 if (it->inputs != NULL) {
    1352           0 :                         for (i = 0; i < it->inputs_size; i++)
    1353           0 :                                 free(it->inputs[i], M_TEMP, 0);
    1354           0 :                         free(it->inputs, M_TEMP, 0);
    1355           0 :                 }
    1356           0 :                 it->inputs_size = 0;
    1357           0 :                 it->inputs = NULL;
    1358           0 :         } else {                /* end `iot[id] != NULL' */
    1359           0 :                 it->inputs_size = 0;
    1360           0 :                 it->inputs = NULL;
    1361           0 :                 it->output = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
    1362           0 :                 if (it->output == NULL) {
    1363           0 :                         printf("%s: no memory\n", __func__);
    1364           0 :                         return NULL;
    1365             :                 }
    1366           0 :                 it->output->terminals[0] = outtype;
    1367           0 :                 it->output->size = 1;
    1368           0 :                 it->direct = 0;
    1369             :         }
    1370             : 
    1371           0 :         switch (it->d.desc->bDescriptorSubtype) {
    1372             :         case UDESCSUB_AC_INPUT:
    1373           0 :                 it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
    1374           0 :                 if (it->inputs == NULL) {
    1375           0 :                         printf("%s: no memory\n", __func__);
    1376           0 :                         return NULL;
    1377             :                 }
    1378           0 :                 tml = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
    1379           0 :                 if (tml == NULL) {
    1380           0 :                         printf("%s: no memory\n", __func__);
    1381           0 :                         free(it->inputs, M_TEMP, 0);
    1382           0 :                         it->inputs = NULL;
    1383           0 :                         return NULL;
    1384             :                 }
    1385           0 :                 it->inputs[0] = tml;
    1386           0 :                 tml->terminals[0] = UGETW(it->d.it->wTerminalType);
    1387           0 :                 tml->size = 1;
    1388           0 :                 it->inputs_size = 1;
    1389           0 :                 return uaudio_merge_terminal_list(it);
    1390             :         case UDESCSUB_AC_FEATURE:
    1391           0 :                 src_id = it->d.fu->bSourceId;
    1392           0 :                 it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
    1393           0 :                 if (it->inputs == NULL) {
    1394           0 :                         printf("%s: no memory\n", __func__);
    1395           0 :                         return uaudio_io_terminaltype(outtype, iot, src_id);
    1396             :                 }
    1397           0 :                 it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
    1398           0 :                 it->inputs_size = 1;
    1399           0 :                 return uaudio_merge_terminal_list(it);
    1400             :         case UDESCSUB_AC_OUTPUT:
    1401           0 :                 it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
    1402           0 :                 if (it->inputs == NULL) {
    1403           0 :                         printf("%s: no memory\n", __func__);
    1404           0 :                         return NULL;
    1405             :                 }
    1406           0 :                 src_id = it->d.ot->bSourceId;
    1407           0 :                 it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
    1408           0 :                 it->inputs_size = 1;
    1409           0 :                 iot[src_id].direct = 1;
    1410           0 :                 return NULL;
    1411             :         case UDESCSUB_AC_MIXER:
    1412           0 :                 it->inputs_size = 0;
    1413           0 :                 it->inputs = mallocarray(it->d.mu->bNrInPins,
    1414             :                     sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
    1415           0 :                 if (it->inputs == NULL) {
    1416           0 :                         printf("%s: no memory\n", __func__);
    1417           0 :                         return NULL;
    1418             :                 }
    1419           0 :                 for (i = 0; i < it->d.mu->bNrInPins; i++) {
    1420           0 :                         src_id = it->d.mu->baSourceId[i];
    1421           0 :                         it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
    1422             :                                                                src_id);
    1423           0 :                         it->inputs_size++;
    1424             :                 }
    1425           0 :                 return uaudio_merge_terminal_list(it);
    1426             :         case UDESCSUB_AC_SELECTOR:
    1427           0 :                 it->inputs_size = 0;
    1428           0 :                 it->inputs = mallocarray(it->d.su->bNrInPins,
    1429             :                     sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
    1430           0 :                 if (it->inputs == NULL) {
    1431           0 :                         printf("%s: no memory\n", __func__);
    1432           0 :                         return NULL;
    1433             :                 }
    1434           0 :                 for (i = 0; i < it->d.su->bNrInPins; i++) {
    1435           0 :                         src_id = it->d.su->baSourceId[i];
    1436           0 :                         it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
    1437             :                                                                src_id);
    1438           0 :                         it->inputs_size++;
    1439             :                 }
    1440           0 :                 return uaudio_merge_terminal_list(it);
    1441             :         case UDESCSUB_AC_PROCESSING:
    1442           0 :                 it->inputs_size = 0;
    1443           0 :                 it->inputs = mallocarray(it->d.pu->bNrInPins,
    1444             :                     sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
    1445           0 :                 if (it->inputs == NULL) {
    1446           0 :                         printf("%s: no memory\n", __func__);
    1447           0 :                         return NULL;
    1448             :                 }
    1449           0 :                 for (i = 0; i < it->d.pu->bNrInPins; i++) {
    1450           0 :                         src_id = it->d.pu->baSourceId[i];
    1451           0 :                         it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
    1452             :                                                                src_id);
    1453           0 :                         it->inputs_size++;
    1454             :                 }
    1455           0 :                 return uaudio_merge_terminal_list(it);
    1456             :         case UDESCSUB_AC_EXTENSION:
    1457           0 :                 it->inputs_size = 0;
    1458           0 :                 it->inputs = mallocarray(it->d.eu->bNrInPins,
    1459             :                     sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
    1460           0 :                 if (it->inputs == NULL) {
    1461           0 :                         printf("%s: no memory\n", __func__);
    1462           0 :                         return NULL;
    1463             :                 }
    1464           0 :                 for (i = 0; i < it->d.eu->bNrInPins; i++) {
    1465           0 :                         src_id = it->d.eu->baSourceId[i];
    1466           0 :                         it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
    1467             :                                                                src_id);
    1468           0 :                         it->inputs_size++;
    1469             :                 }
    1470           0 :                 return uaudio_merge_terminal_list(it);
    1471             :         case UDESCSUB_AC_HEADER:
    1472             :         default:
    1473           0 :                 return NULL;
    1474             :         }
    1475           0 : }
    1476             : 
    1477             : usbd_status
    1478           0 : uaudio_identify(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
    1479             : {
    1480             :         usbd_status err;
    1481             : 
    1482           0 :         err = uaudio_identify_ac(sc, cdesc);
    1483           0 :         if (err)
    1484           0 :                 return (err);
    1485           0 :         return (uaudio_identify_as(sc, cdesc));
    1486           0 : }
    1487             : 
    1488             : void
    1489           0 : uaudio_add_alt(struct uaudio_softc *sc, const struct as_info *ai)
    1490             : {
    1491             :         struct as_info *nai;
    1492             : 
    1493           0 :         nai = mallocarray(sc->sc_nalts + 1, sizeof(*ai), M_USBDEV, M_NOWAIT);
    1494           0 :         if (nai == NULL) {
    1495           0 :                 printf("%s: no memory\n", __func__);
    1496           0 :                 return;
    1497             :         }
    1498             : 
    1499             :         /* Copy old data, if there was any */
    1500           0 :         if (sc->sc_nalts != 0) {
    1501           0 :                 memcpy(nai, sc->sc_alts, sizeof(*ai) * (sc->sc_nalts));
    1502           0 :                 free(sc->sc_alts, M_USBDEV, sc->sc_nalts * sizeof(*ai));
    1503           0 :         }
    1504           0 :         sc->sc_alts = nai;
    1505             :         DPRINTFN(2,("%s: adding alt=%d, enc=%d\n",
    1506             :                     __func__, ai->alt, ai->encoding));
    1507           0 :         sc->sc_alts[sc->sc_nalts++] = *ai;
    1508           0 : }
    1509             : 
    1510             : usbd_status
    1511           0 : uaudio_process_as(struct uaudio_softc *sc, const char *buf, int *offsp,
    1512             :                   int size, const usb_interface_descriptor_t *id)
    1513             : #define offs (*offsp)
    1514             : {
    1515             :         const struct usb_audio_streaming_interface_descriptor *asid;
    1516             :         const struct usb_audio_streaming_type1_descriptor *asf1d;
    1517             :         const struct usb_endpoint_descriptor_audio *ed;
    1518             :         const struct usb_endpoint_descriptor_audio *sync_ed;
    1519             :         const struct usb_audio_streaming_endpoint_descriptor *sed;
    1520             :         int format, chan, prec, enc, bps;
    1521             :         int dir, type, sync, sync_addr;
    1522           0 :         struct as_info ai;
    1523             :         const char *format_str;
    1524             : 
    1525           0 :         asid = (const void *)(buf + offs);
    1526           0 :         if (asid->bDescriptorType != UDESC_CS_INTERFACE ||
    1527           0 :             asid->bDescriptorSubtype != AS_GENERAL)
    1528           0 :                 return (USBD_INVAL);
    1529             :         DPRINTF(("%s: asid: bTerminalLink=%d wFormatTag=%d\n", __func__,
    1530             :                  asid->bTerminalLink, UGETW(asid->wFormatTag)));
    1531           0 :         offs += asid->bLength;
    1532           0 :         if (offs > size)
    1533           0 :                 return (USBD_INVAL);
    1534             : 
    1535           0 :         asf1d = (const void *)(buf + offs);
    1536           0 :         if (asf1d->bDescriptorType != UDESC_CS_INTERFACE ||
    1537           0 :             asf1d->bDescriptorSubtype != FORMAT_TYPE)
    1538           0 :                 return (USBD_INVAL);
    1539           0 :         offs += asf1d->bLength;
    1540           0 :         if (offs > size)
    1541           0 :                 return (USBD_INVAL);
    1542             : 
    1543           0 :         if (asf1d->bFormatType != FORMAT_TYPE_I) {
    1544           0 :                 printf("%s: ignored setting with type %d format\n",
    1545           0 :                        sc->sc_dev.dv_xname, UGETW(asid->wFormatTag));
    1546           0 :                 return (USBD_NORMAL_COMPLETION);
    1547             :         }
    1548             : 
    1549           0 :         ed = (const void *)(buf + offs);
    1550           0 :         if (ed->bDescriptorType != UDESC_ENDPOINT)
    1551           0 :                 return (USBD_INVAL);
    1552             :         DPRINTF(("%s: endpoint[0] bLength=%d bDescriptorType=%d "
    1553             :                  "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d "
    1554             :                  "bInterval=%d bRefresh=%d bSynchAddress=%d\n",
    1555             :                  __func__,
    1556             :                  ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
    1557             :                  ed->bmAttributes, UGETW(ed->wMaxPacketSize),
    1558             :                  ed->bInterval, ed->bRefresh, ed->bSynchAddress));
    1559           0 :         offs += ed->bLength;
    1560           0 :         if (offs > size)
    1561           0 :                 return (USBD_INVAL);
    1562           0 :         if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
    1563           0 :                 return (USBD_INVAL);
    1564             : 
    1565           0 :         dir = UE_GET_DIR(ed->bEndpointAddress);
    1566           0 :         type = UE_GET_ISO_TYPE(ed->bmAttributes);
    1567             : 
    1568             :         /* Check for sync endpoint. */
    1569             :         sync = 0;
    1570             :         sync_addr = 0;
    1571           0 :         if (id->bNumEndpoints > 1 &&
    1572           0 :             ((dir == UE_DIR_IN && type == UE_ISO_ADAPT) ||
    1573           0 :             (dir != UE_DIR_IN && type == UE_ISO_ASYNC)))
    1574           0 :                 sync = 1;
    1575             : 
    1576             :         /* Check whether sync endpoint address is given. */
    1577           0 :         if (ed->bLength >= USB_ENDPOINT_DESCRIPTOR_AUDIO_SIZE) {
    1578             :                 /* bSynchAdress set to 0 indicates sync is not used. */
    1579           0 :                 if (ed->bSynchAddress == 0)
    1580           0 :                         sync = 0;
    1581             :                 else
    1582             :                         sync_addr = ed->bSynchAddress;
    1583             :         }
    1584             : 
    1585           0 :         sed = (const void *)(buf + offs);
    1586           0 :         if (sed->bDescriptorType != UDESC_CS_ENDPOINT ||
    1587           0 :             sed->bDescriptorSubtype != AS_GENERAL)
    1588           0 :                 return (USBD_INVAL);
    1589             :         DPRINTF((" streaming_endpoint: offset=%d bLength=%d\n", offs, sed->bLength));
    1590           0 :         offs += sed->bLength;
    1591           0 :         if (offs > size)
    1592           0 :                 return (USBD_INVAL);
    1593             : 
    1594             :         sync_ed = NULL;
    1595           0 :         if (sync == 1) {
    1596           0 :                 sync_ed = (const void*)(buf + offs);
    1597           0 :                 if (sync_ed->bDescriptorType != UDESC_ENDPOINT) {
    1598           0 :                         printf("%s: sync ep descriptor wrong type\n",
    1599           0 :                             sc->sc_dev.dv_xname);
    1600           0 :                         return (USBD_NORMAL_COMPLETION);
    1601             :                 }
    1602             :                 DPRINTF(("%s: endpoint[1] bLength=%d "
    1603             :                          "bDescriptorType=%d bEndpointAddress=%d "
    1604             :                          "bmAttributes=0x%x wMaxPacketSize=%d bInterval=%d "
    1605             :                          "bRefresh=%d bSynchAddress=%d\n",
    1606             :                          __func__,
    1607             :                          sync_ed->bLength, sync_ed->bDescriptorType,
    1608             :                          sync_ed->bEndpointAddress, sync_ed->bmAttributes,
    1609             :                          UGETW(sync_ed->wMaxPacketSize), sync_ed->bInterval,
    1610             :                          sync_ed->bRefresh, sync_ed->bSynchAddress));
    1611           0 :                 offs += sync_ed->bLength;
    1612           0 :                 if (offs > size) {
    1613           0 :                         printf("%s: sync ep descriptor too large\n",
    1614           0 :                             sc->sc_dev.dv_xname);
    1615           0 :                         return (USBD_NORMAL_COMPLETION);
    1616             :                 }
    1617           0 :                 if (dir == UE_GET_DIR(sync_ed->bEndpointAddress)) {
    1618           0 :                         printf("%s: sync ep wrong direction\n",
    1619           0 :                                sc->sc_dev.dv_xname);
    1620           0 :                         return (USBD_NORMAL_COMPLETION);
    1621             :                 }
    1622           0 :                 if (UE_GET_XFERTYPE(sync_ed->bmAttributes) != UE_ISOCHRONOUS) {
    1623           0 :                         printf("%s: sync ep wrong xfer type\n",
    1624           0 :                                sc->sc_dev.dv_xname);
    1625           0 :                         return (USBD_NORMAL_COMPLETION);
    1626             :                 }
    1627           0 :                 if (sync_ed->bLength >=
    1628           0 :                     USB_ENDPOINT_DESCRIPTOR_AUDIO_SIZE &&
    1629           0 :                     sync_ed->bSynchAddress != 0) {
    1630           0 :                         printf("%s: sync ep bSynchAddress != 0\n",
    1631           0 :                                sc->sc_dev.dv_xname);
    1632           0 :                         return (USBD_NORMAL_COMPLETION);
    1633             :                 }
    1634           0 :                 if (sync_addr &&
    1635           0 :                     UE_GET_ADDR(sync_ed->bEndpointAddress) !=
    1636           0 :                     UE_GET_ADDR(sync_addr)) {
    1637           0 :                         printf("%s: sync ep address mismatch\n",
    1638           0 :                                sc->sc_dev.dv_xname);
    1639           0 :                         return (USBD_NORMAL_COMPLETION);
    1640             :                 }
    1641             :         }
    1642           0 :         if (sync_ed != NULL && dir == UE_DIR_IN) {
    1643           0 :                 printf("%s: sync pipe for recording not yet implemented\n",
    1644           0 :                     sc->sc_dev.dv_xname);
    1645           0 :                 return (USBD_NORMAL_COMPLETION);
    1646             :         }
    1647             : 
    1648           0 :         format = UGETW(asid->wFormatTag);
    1649           0 :         chan = asf1d->bNrChannels;
    1650           0 :         prec = asf1d->bBitResolution;
    1651           0 :         bps = asf1d->bSubFrameSize;
    1652           0 :         if ((prec != 8 && prec != 16 && prec != 24) || (bps < 1 || bps > 4)) {
    1653           0 :                 printf("%s: ignored setting with precision %d bps %d\n",
    1654           0 :                        sc->sc_dev.dv_xname, prec, bps);
    1655           0 :                 return (USBD_NORMAL_COMPLETION);
    1656             :         }
    1657           0 :         switch (format) {
    1658             :         case UA_FMT_PCM:
    1659           0 :                 if (prec == 8) {
    1660           0 :                         sc->sc_altflags |= HAS_8;
    1661           0 :                 } else if (prec == 16) {
    1662           0 :                         sc->sc_altflags |= HAS_16;
    1663           0 :                 } else if (prec == 24) {
    1664           0 :                         sc->sc_altflags |= HAS_24;
    1665           0 :                 }
    1666             :                 enc = AUDIO_ENCODING_SLINEAR_LE;
    1667             :                 format_str = "pcm";
    1668           0 :                 break;
    1669             :         case UA_FMT_PCM8:
    1670             :                 enc = AUDIO_ENCODING_ULINEAR_LE;
    1671           0 :                 sc->sc_altflags |= HAS_8U;
    1672             :                 format_str = "pcm8";
    1673           0 :                 break;
    1674             :         case UA_FMT_ALAW:
    1675             :                 enc = AUDIO_ENCODING_ALAW;
    1676           0 :                 sc->sc_altflags |= HAS_ALAW;
    1677             :                 format_str = "alaw";
    1678           0 :                 break;
    1679             :         case UA_FMT_MULAW:
    1680             :                 enc = AUDIO_ENCODING_ULAW;
    1681           0 :                 sc->sc_altflags |= HAS_MULAW;
    1682             :                 format_str = "mulaw";
    1683           0 :                 break;
    1684             :         case UA_FMT_IEEE_FLOAT:
    1685             :         default:
    1686           0 :                 printf("%s: ignored setting with format %d\n",
    1687           0 :                        sc->sc_dev.dv_xname, format);
    1688           0 :                 return (USBD_NORMAL_COMPLETION);
    1689             :         }
    1690             : #ifdef UAUDIO_DEBUG
    1691             :         printf("%s: %s: %d-ch %d-bit %d-byte %s,", sc->sc_dev.dv_xname,
    1692             :                dir == UE_DIR_IN ? "recording" : "playback",
    1693             :                chan, prec, bps, format_str);
    1694             :         if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
    1695             :                 printf(" %d-%dHz\n", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
    1696             :         } else {
    1697             :                 int r;
    1698             :                 printf(" %d", UA_GETSAMP(asf1d, 0));
    1699             :                 for (r = 1; r < asf1d->bSamFreqType; r++)
    1700             :                         printf(",%d", UA_GETSAMP(asf1d, r));
    1701             :                 printf("Hz\n");
    1702             :         }
    1703             : #endif
    1704           0 :         ai.alt = id->bAlternateSetting;
    1705           0 :         ai.encoding = enc;
    1706           0 :         ai.attributes = sed->bmAttributes;
    1707           0 :         ai.idesc = id;
    1708           0 :         ai.edesc = ed;
    1709           0 :         ai.edesc1 = sync_ed;
    1710           0 :         ai.asf1desc = asf1d;
    1711           0 :         ai.sc_busy = 0;
    1712           0 :         if (sc->sc_nalts < UAUDIO_MAX_ALTS)
    1713           0 :                 uaudio_add_alt(sc, &ai);
    1714             : #ifdef UAUDIO_DEBUG
    1715             :         if (ai.attributes & UA_SED_FREQ_CONTROL)
    1716             :                 DPRINTFN(1, ("%s:  FREQ_CONTROL\n", __func__));
    1717             :         if (ai.attributes & UA_SED_PITCH_CONTROL)
    1718             :                 DPRINTFN(1, ("%s:  PITCH_CONTROL\n", __func__));
    1719             : #endif
    1720           0 :         sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD;
    1721             : 
    1722           0 :         return (USBD_NORMAL_COMPLETION);
    1723           0 : }
    1724             : #undef offs
    1725             : 
    1726             : usbd_status
    1727           0 : uaudio_identify_as(struct uaudio_softc *sc,
    1728             :                    const usb_config_descriptor_t *cdesc)
    1729             : {
    1730             :         const usb_interface_descriptor_t *id;
    1731             :         const char *buf;
    1732           0 :         int size, offs;
    1733             : 
    1734           0 :         size = UGETW(cdesc->wTotalLength);
    1735           0 :         buf = (const char *)cdesc;
    1736             : 
    1737             :         /* Locate the AudioStreaming interface descriptor. */
    1738           0 :         offs = 0;
    1739           0 :         id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM,
    1740           0 :             sc->sc_quirks);
    1741           0 :         if (id == NULL)
    1742           0 :                 return (USBD_INVAL);
    1743             : 
    1744             :         /* Loop through all the alternate settings. */
    1745           0 :         while (offs <= size) {
    1746             :                 DPRINTFN(2, ("%s: interface=%d offset=%d\n",
    1747             :                     __func__, id->bInterfaceNumber, offs));
    1748           0 :                 switch (id->bNumEndpoints) {
    1749             :                 case 0:
    1750             :                         DPRINTFN(2, ("%s: AS null alt=%d\n",
    1751             :                                      __func__, id->bAlternateSetting));
    1752           0 :                         sc->sc_nullalt = id->bAlternateSetting;
    1753           0 :                         break;
    1754             :                 case 1:
    1755             :                 case 2:
    1756           0 :                         uaudio_process_as(sc, buf, &offs, size, id);
    1757           0 :                         break;
    1758             :                 default:
    1759           0 :                         printf("%s: ignored audio interface with %d "
    1760             :                                "endpoints\n",
    1761           0 :                                sc->sc_dev.dv_xname, id->bNumEndpoints);
    1762           0 :                         break;
    1763             :                 }
    1764           0 :                 id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM,
    1765           0 :                     sc->sc_quirks);
    1766           0 :                 if (id == NULL)
    1767             :                         break;
    1768             :         }
    1769           0 :         if (offs > size)
    1770           0 :                 return (USBD_INVAL);
    1771             :         DPRINTF(("%s: %d alts available\n", __func__, sc->sc_nalts));
    1772             : 
    1773           0 :         if (sc->sc_mode == 0) {
    1774           0 :                 printf("%s: no usable endpoint found\n",
    1775           0 :                        sc->sc_dev.dv_xname);
    1776           0 :                 return (USBD_INVAL);
    1777             :         }
    1778             : 
    1779           0 :         return (USBD_NORMAL_COMPLETION);
    1780           0 : }
    1781             : 
    1782             : usbd_status
    1783           0 : uaudio_identify_ac(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
    1784             : {
    1785             :         struct io_terminal* iot;
    1786             :         const usb_interface_descriptor_t *id;
    1787             :         const struct usb_audio_control_descriptor *acdp;
    1788             :         const usb_descriptor_t *dp;
    1789             :         const struct usb_audio_output_terminal *pot;
    1790             :         struct terminal_list *tml;
    1791             :         const char *buf, *ibuf, *ibufend;
    1792           0 :         int size, offs, aclen, ndps, i, j;
    1793             : 
    1794           0 :         size = UGETW(cdesc->wTotalLength);
    1795           0 :         buf = (char *)cdesc;
    1796             : 
    1797             :         /* Locate the AudioControl interface descriptor. */
    1798           0 :         offs = 0;
    1799           0 :         id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL,
    1800           0 :             sc->sc_quirks);
    1801           0 :         if (id == NULL)
    1802           0 :                 return (USBD_INVAL);
    1803           0 :         if (offs + sizeof *acdp > size)
    1804           0 :                 return (USBD_INVAL);
    1805           0 :         sc->sc_ac_iface = id->bInterfaceNumber;
    1806             :         DPRINTFN(2,("%s: AC interface is %d\n", 
    1807             :             __func__, sc->sc_ac_iface));
    1808             : 
    1809             :         /* A class-specific AC interface header should follow. */
    1810           0 :         ibuf = buf + offs;
    1811           0 :         acdp = (const struct usb_audio_control_descriptor *)ibuf;
    1812           0 :         if (acdp->bDescriptorType != UDESC_CS_INTERFACE ||
    1813           0 :             acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)
    1814           0 :                 return (USBD_INVAL);
    1815           0 :         aclen = UGETW(acdp->wTotalLength);
    1816           0 :         if (offs + aclen > size)
    1817           0 :                 return (USBD_INVAL);
    1818             : 
    1819           0 :         if (!(sc->sc_quirks & UAUDIO_FLAG_BAD_ADC) &&
    1820           0 :              UGETW(acdp->bcdADC) != UAUDIO_VERSION)
    1821           0 :                 return (USBD_INVAL);
    1822             : 
    1823           0 :         sc->sc_audio_rev = UGETW(acdp->bcdADC);
    1824             :         DPRINTFN(2,("%s: found AC header, vers=%03x, len=%d\n",
    1825             :                  __func__, sc->sc_audio_rev, aclen));
    1826             : 
    1827             :         /* Some webcams descriptors advertise an off-by-one wTotalLength */
    1828           0 :         if (sc->sc_quirks & UAUDIO_FLAG_BAD_ADC_LEN)
    1829           0 :                 aclen++;
    1830             : 
    1831           0 :         sc->sc_nullalt = -1;
    1832             : 
    1833             :         /* Scan through all the AC specific descriptors */
    1834           0 :         ibufend = ibuf + aclen;
    1835           0 :         dp = (const usb_descriptor_t *)ibuf;
    1836             :         ndps = 0;
    1837           0 :         iot = mallocarray(256, sizeof(struct io_terminal),
    1838             :             M_TEMP, M_NOWAIT | M_ZERO);
    1839           0 :         if (iot == NULL) {
    1840           0 :                 printf("%s: no memory\n", __func__);
    1841           0 :                 return USBD_NOMEM;
    1842             :         }
    1843           0 :         for (;;) {
    1844           0 :                 ibuf += dp->bLength;
    1845           0 :                 if (ibuf >= ibufend)
    1846             :                         break;
    1847           0 :                 dp = (const usb_descriptor_t *)ibuf;
    1848           0 :                 if (ibuf + dp->bLength > ibufend) {
    1849           0 :                         free(iot, M_TEMP, 0);
    1850           0 :                         return (USBD_INVAL);
    1851             :                 }
    1852           0 :                 if (dp->bDescriptorType != UDESC_CS_INTERFACE) {
    1853           0 :                         printf("%s: skip desc type=0x%02x\n",
    1854             :                                __func__, dp->bDescriptorType);
    1855           0 :                         continue;
    1856             :                 }
    1857           0 :                 i = ((const struct usb_audio_input_terminal *)dp)->bTerminalId;
    1858           0 :                 iot[i].d.desc = dp;
    1859           0 :                 if (i > ndps)
    1860           0 :                         ndps = i;
    1861             :         }
    1862           0 :         ndps++;
    1863             : 
    1864             :         /* construct io_terminal */
    1865           0 :         for (i = 0; i < ndps; i++) {
    1866           0 :                 dp = iot[i].d.desc;
    1867           0 :                 if (dp == NULL)
    1868             :                         continue;
    1869           0 :                 if (dp->bDescriptorSubtype != UDESCSUB_AC_OUTPUT)
    1870             :                         continue;
    1871           0 :                 pot = iot[i].d.ot;
    1872           0 :                 tml = uaudio_io_terminaltype(UGETW(pot->wTerminalType), iot, i);
    1873           0 :                 free(tml, M_TEMP, 0);
    1874           0 :         }
    1875             : 
    1876             : #ifdef UAUDIO_DEBUG
    1877             :         for (i = 0; i < 256; i++) {
    1878             :                 if (iot[i].d.desc == NULL)
    1879             :                         continue;
    1880             :                 printf("id %d:\t", i);
    1881             :                 switch (iot[i].d.desc->bDescriptorSubtype) {
    1882             :                 case UDESCSUB_AC_INPUT:
    1883             :                         printf("AC_INPUT type=%s\n", uaudio_get_terminal_name
    1884             :                                (UGETW(iot[i].d.it->wTerminalType)));
    1885             :                         break;
    1886             :                 case UDESCSUB_AC_OUTPUT:
    1887             :                         printf("AC_OUTPUT type=%s ", uaudio_get_terminal_name
    1888             :                                (UGETW(iot[i].d.ot->wTerminalType)));
    1889             :                         printf("src=%d\n", iot[i].d.ot->bSourceId);
    1890             :                         break;
    1891             :                 case UDESCSUB_AC_MIXER:
    1892             :                         printf("AC_MIXER src=");
    1893             :                         for (j = 0; j < iot[i].d.mu->bNrInPins; j++)
    1894             :                                 printf("%d ", iot[i].d.mu->baSourceId[j]);
    1895             :                         printf("\n");
    1896             :                         break;
    1897             :                 case UDESCSUB_AC_SELECTOR:
    1898             :                         printf("AC_SELECTOR src=");
    1899             :                         for (j = 0; j < iot[i].d.su->bNrInPins; j++)
    1900             :                                 printf("%d ", iot[i].d.su->baSourceId[j]);
    1901             :                         printf("\n");
    1902             :                         break;
    1903             :                 case UDESCSUB_AC_FEATURE:
    1904             :                         printf("AC_FEATURE src=%d\n", iot[i].d.fu->bSourceId);
    1905             :                         break;
    1906             :                 case UDESCSUB_AC_PROCESSING:
    1907             :                         printf("AC_PROCESSING src=");
    1908             :                         for (j = 0; j < iot[i].d.pu->bNrInPins; j++)
    1909             :                                 printf("%d ", iot[i].d.pu->baSourceId[j]);
    1910             :                         printf("\n");
    1911             :                         break;
    1912             :                 case UDESCSUB_AC_EXTENSION:
    1913             :                         printf("AC_EXTENSION src=");
    1914             :                         for (j = 0; j < iot[i].d.eu->bNrInPins; j++)
    1915             :                                 printf("%d ", iot[i].d.eu->baSourceId[j]);
    1916             :                         printf("\n");
    1917             :                         break;
    1918             :                 default:
    1919             :                         printf("unknown audio control (subtype=%d)\n",
    1920             :                                iot[i].d.desc->bDescriptorSubtype);
    1921             :                 }
    1922             :                 for (j = 0; j < iot[i].inputs_size; j++) {
    1923             :                         int k;
    1924             :                         printf("\tinput%d: ", j);
    1925             :                         tml = iot[i].inputs[j];
    1926             :                         if (tml == NULL) {
    1927             :                                 printf("NULL\n");
    1928             :                                 continue;
    1929             :                         }
    1930             :                         for (k = 0; k < tml->size; k++)
    1931             :                                 printf("%s ", uaudio_get_terminal_name
    1932             :                                        (tml->terminals[k]));
    1933             :                         printf("\n");
    1934             :                 }
    1935             :                 printf("\toutput: ");
    1936             :                 tml = iot[i].output;
    1937             :                 for (j = 0; j < tml->size; j++)
    1938             :                         printf("%s ", uaudio_get_terminal_name(tml->terminals[j]));
    1939             :                 printf("\n");
    1940             :         }
    1941             : #endif
    1942             : 
    1943           0 :         for (i = 0; i < ndps; i++) {
    1944           0 :                 dp = iot[i].d.desc;
    1945           0 :                 if (dp == NULL)
    1946             :                         continue;
    1947             :                 DPRINTF(("%s: id=%d subtype=%d\n",
    1948             :                          __func__, i, dp->bDescriptorSubtype));
    1949           0 :                 switch (dp->bDescriptorSubtype) {
    1950             :                 case UDESCSUB_AC_HEADER:
    1951           0 :                         printf("%s: unexpected AC header\n", __func__);
    1952           0 :                         break;
    1953             :                 case UDESCSUB_AC_INPUT:
    1954           0 :                         uaudio_add_input(sc, iot, i);
    1955           0 :                         break;
    1956             :                 case UDESCSUB_AC_OUTPUT:
    1957           0 :                         uaudio_add_output(sc, iot, i);
    1958           0 :                         break;
    1959             :                 case UDESCSUB_AC_MIXER:
    1960           0 :                         uaudio_add_mixer(sc, iot, i);
    1961           0 :                         break;
    1962             :                 case UDESCSUB_AC_SELECTOR:
    1963           0 :                         uaudio_add_selector(sc, iot, i);
    1964           0 :                         break;
    1965             :                 case UDESCSUB_AC_FEATURE:
    1966           0 :                         uaudio_add_feature(sc, iot, i);
    1967           0 :                         break;
    1968             :                 case UDESCSUB_AC_PROCESSING:
    1969           0 :                         uaudio_add_processing(sc, iot, i);
    1970           0 :                         break;
    1971             :                 case UDESCSUB_AC_EXTENSION:
    1972           0 :                         uaudio_add_extension(sc, iot, i);
    1973           0 :                         break;
    1974             :                 default:
    1975           0 :                         printf("%s: bad AC desc subtype=0x%02x\n",
    1976             :                                __func__, dp->bDescriptorSubtype);
    1977           0 :                         break;
    1978             :                 }
    1979             :         }
    1980             : 
    1981             :         /* delete io_terminal */
    1982           0 :         for (i = 0; i < 256; i++) {
    1983           0 :                 if (iot[i].d.desc == NULL)
    1984             :                         continue;
    1985           0 :                 if (iot[i].inputs != NULL) {
    1986           0 :                         for (j = 0; j < iot[i].inputs_size; j++)
    1987           0 :                                 free(iot[i].inputs[j], M_TEMP, 0);
    1988           0 :                         free(iot[i].inputs, M_TEMP, 0);
    1989           0 :                 }
    1990           0 :                 free(iot[i].output, M_TEMP, 0);
    1991           0 :                 iot[i].d.desc = NULL;
    1992           0 :         }
    1993           0 :         free(iot, M_TEMP, 256 * sizeof(struct io_terminal));
    1994             : 
    1995           0 :         return (USBD_NORMAL_COMPLETION);
    1996           0 : }
    1997             : 
    1998             : int
    1999           0 : uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi)
    2000             : {
    2001           0 :         struct uaudio_softc *sc = addr;
    2002             :         struct mixerctl *mc;
    2003             :         int n, nctls, i;
    2004             : 
    2005             :         DPRINTFN(2,("%s: index=%d\n", __func__, mi->index));
    2006           0 :         if (usbd_is_dying(sc->sc_udev))
    2007           0 :                 return (EIO);
    2008             : 
    2009           0 :         n = mi->index;
    2010           0 :         nctls = sc->sc_nctls;
    2011             : 
    2012           0 :         switch (n) {
    2013             :         case UAC_OUTPUT:
    2014           0 :                 mi->type = AUDIO_MIXER_CLASS;
    2015           0 :                 mi->mixer_class = UAC_OUTPUT;
    2016           0 :                 mi->next = mi->prev = AUDIO_MIXER_LAST;
    2017           0 :                 strlcpy(mi->label.name, AudioCoutputs, sizeof(mi->label.name));
    2018           0 :                 return (0);
    2019             :         case UAC_INPUT:
    2020           0 :                 mi->type = AUDIO_MIXER_CLASS;
    2021           0 :                 mi->mixer_class = UAC_INPUT;
    2022           0 :                 mi->next = mi->prev = AUDIO_MIXER_LAST;
    2023           0 :                 strlcpy(mi->label.name, AudioCinputs, sizeof(mi->label.name));
    2024           0 :                 return (0);
    2025             :         case UAC_EQUAL:
    2026           0 :                 mi->type = AUDIO_MIXER_CLASS;
    2027           0 :                 mi->mixer_class = UAC_EQUAL;
    2028           0 :                 mi->next = mi->prev = AUDIO_MIXER_LAST;
    2029           0 :                 strlcpy(mi->label.name, AudioCequalization,
    2030             :                     sizeof(mi->label.name));
    2031           0 :                 return (0);
    2032             :         case UAC_RECORD:
    2033           0 :                 mi->type = AUDIO_MIXER_CLASS;
    2034           0 :                 mi->mixer_class = UAC_RECORD;
    2035           0 :                 mi->next = mi->prev = AUDIO_MIXER_LAST;
    2036           0 :                 strlcpy(mi->label.name, AudioCrecord, sizeof(mi->label.name));
    2037           0 :                 return 0;
    2038             :         default:
    2039             :                 break;
    2040             :         }
    2041             : 
    2042           0 :         n -= UAC_NCLASSES;
    2043           0 :         if (n < 0 || n >= nctls)
    2044           0 :                 return (ENXIO);
    2045             : 
    2046           0 :         mc = &sc->sc_ctls[n];
    2047           0 :         strlcpy(mi->label.name, mc->ctlname, sizeof(mi->label.name));
    2048           0 :         mi->mixer_class = mc->class;
    2049           0 :         mi->next = mi->prev = AUDIO_MIXER_LAST;   /* XXX */
    2050           0 :         switch (mc->type) {
    2051             :         case MIX_ON_OFF:
    2052           0 :                 mi->type = AUDIO_MIXER_ENUM;
    2053           0 :                 mi->un.e.num_mem = 2;
    2054           0 :                 strlcpy(mi->un.e.member[0].label.name, AudioNoff,
    2055             :                     sizeof(mi->un.e.member[0].label.name));
    2056           0 :                 mi->un.e.member[0].ord = 0;
    2057           0 :                 strlcpy(mi->un.e.member[1].label.name, AudioNon,
    2058             :                     sizeof(mi->un.e.member[1].label.name));
    2059           0 :                 mi->un.e.member[1].ord = 1;
    2060           0 :                 break;
    2061             :         case MIX_SELECTOR:
    2062           0 :                 mi->type = AUDIO_MIXER_ENUM;
    2063           0 :                 mi->un.e.num_mem = mc->maxval - mc->minval + 1;
    2064           0 :                 for (i = 0; i <= mc->maxval - mc->minval; i++) {
    2065           0 :                         snprintf(mi->un.e.member[i].label.name,
    2066             :                                  sizeof(mi->un.e.member[i].label.name),
    2067           0 :                                  "%d", i + mc->minval);
    2068           0 :                         mi->un.e.member[i].ord = i + mc->minval;
    2069             :                 }
    2070             :                 break;
    2071             :         default:
    2072           0 :                 mi->type = AUDIO_MIXER_VALUE;
    2073           0 :                 strlcpy(mi->un.v.units.name, mc->ctlunit,
    2074             :                     sizeof(mi->un.v.units.name));
    2075           0 :                 mi->un.v.num_channels = mc->nchan;
    2076           0 :                 mi->un.v.delta = mc->delta;
    2077           0 :                 break;
    2078             :         }
    2079           0 :         return (0);
    2080           0 : }
    2081             : 
    2082             : int
    2083           0 : uaudio_open(void *addr, int flags)
    2084             : {
    2085           0 :         struct uaudio_softc *sc = addr;
    2086             : 
    2087             :         DPRINTF(("%s: sc=%p\n", __func__, sc));
    2088           0 :         if (usbd_is_dying(sc->sc_udev))
    2089           0 :                 return (EIO);
    2090             : 
    2091           0 :         if ((flags & FWRITE) && !(sc->sc_mode & AUMODE_PLAY))
    2092           0 :                 return (ENXIO);
    2093           0 :         if ((flags & FREAD) && !(sc->sc_mode & AUMODE_RECORD))
    2094           0 :                 return (ENXIO);
    2095             : 
    2096           0 :         return (0);
    2097           0 : }
    2098             : 
    2099             : /*
    2100             :  * Close function is called at splaudio().
    2101             :  */
    2102             : void
    2103           0 : uaudio_close(void *addr)
    2104             : {
    2105           0 :         struct uaudio_softc *sc = addr;
    2106             : 
    2107           0 :         if (sc->sc_playchan.altidx != -1)
    2108           0 :                 uaudio_chan_close(sc, &sc->sc_playchan);
    2109           0 :         if (sc->sc_recchan.altidx != -1)
    2110           0 :                 uaudio_chan_close(sc, &sc->sc_recchan);
    2111           0 : }
    2112             : 
    2113             : int
    2114           0 : uaudio_halt_out_dma(void *addr)
    2115             : {
    2116           0 :         struct uaudio_softc *sc = addr;
    2117             : 
    2118             :         DPRINTF(("%s: enter\n", __func__));
    2119           0 :         if (sc->sc_playchan.pipe != NULL) {
    2120           0 :                 uaudio_chan_close(sc, &sc->sc_playchan);
    2121           0 :                 sc->sc_playchan.pipe = NULL;
    2122           0 :                 if (sc->sc_playchan.sync_pipe != NULL)
    2123           0 :                         sc->sc_playchan.sync_pipe = NULL;
    2124           0 :                 uaudio_chan_free_buffers(sc, &sc->sc_playchan);
    2125           0 :                 sc->sc_playchan.intr = NULL;
    2126           0 :         }
    2127           0 :         return (0);
    2128             : }
    2129             : 
    2130             : int
    2131           0 : uaudio_halt_in_dma(void *addr)
    2132             : {
    2133           0 :         struct uaudio_softc *sc = addr;
    2134             : 
    2135             :         DPRINTF(("%s: enter\n", __func__));
    2136           0 :         if (sc->sc_recchan.pipe != NULL) {
    2137           0 :                 uaudio_chan_close(sc, &sc->sc_recchan);
    2138           0 :                 sc->sc_recchan.pipe = NULL;
    2139           0 :                 if (sc->sc_recchan.sync_pipe != NULL)
    2140           0 :                         sc->sc_recchan.sync_pipe = NULL;
    2141           0 :                 uaudio_chan_free_buffers(sc, &sc->sc_recchan);
    2142           0 :                 sc->sc_recchan.intr = NULL;
    2143           0 :         }
    2144           0 :         return (0);
    2145             : }
    2146             : 
    2147             : /*
    2148             :  * Make sure the block size is large enough to hold at least 1 transfer.
    2149             :  * Ideally, the block size should be a multiple of the transfer size.
    2150             :  * Currently, the transfer size for play and record can differ, and there's
    2151             :  * no way to round playback and record blocksizes separately.
    2152             :  */
    2153             : int
    2154           0 : uaudio_round_blocksize(void *addr, int blk)
    2155             : {
    2156           0 :         struct uaudio_softc *sc = addr;
    2157             :         int bpf, pbpf, rbpf;
    2158             : 
    2159             :         DPRINTF(("%s: p.mbpf=%d r.mbpf=%d\n", __func__,
    2160             :                  sc->sc_playchan.max_bytes_per_frame,
    2161             :                  sc->sc_recchan.max_bytes_per_frame));
    2162             : 
    2163             :         pbpf = rbpf = 0;
    2164           0 :         if (sc->sc_mode & AUMODE_PLAY) {
    2165           0 :                 pbpf = (sc->sc_playchan.max_bytes_per_frame) *
    2166           0 :                     sc->sc_playchan.nframes;
    2167           0 :         }
    2168           0 :         if (sc->sc_mode & AUMODE_RECORD) {
    2169           0 :                 rbpf = (sc->sc_recchan.max_bytes_per_frame) *
    2170           0 :                     sc->sc_recchan.nframes;
    2171           0 :         }
    2172           0 :         bpf = max(pbpf, rbpf);
    2173             : 
    2174           0 :         if (blk < bpf)
    2175           0 :                 blk = bpf;
    2176             : 
    2177             : #ifdef DIAGNOSTIC
    2178           0 :         if (blk <= 0) {
    2179           0 :                 printf("%s: blk=%d\n", __func__, blk);
    2180             :                 blk = 512;
    2181           0 :         }
    2182             : #endif
    2183             : 
    2184             :         DPRINTFN(1,("%s: blk=%d\n", __func__, blk));
    2185           0 :         return (blk);
    2186             : }
    2187             : 
    2188             : int
    2189           0 : uaudio_get_props(void *addr)
    2190             : {
    2191           0 :         struct uaudio_softc *sc = addr;
    2192             :         int props = 0;
    2193             : 
    2194           0 :         if (!(sc->sc_quirks & UAUDIO_FLAG_DEPENDENT))
    2195           0 :                 props |= AUDIO_PROP_INDEPENDENT;
    2196             : 
    2197           0 :         if ((sc->sc_mode & (AUMODE_PLAY | AUMODE_RECORD)) ==
    2198             :             (AUMODE_PLAY | AUMODE_RECORD))
    2199           0 :                 props |= AUDIO_PROP_FULLDUPLEX;
    2200             : 
    2201           0 :         return props;
    2202             : }
    2203             : 
    2204             : int
    2205           0 : uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue,
    2206             :            int wIndex, int len)
    2207             : {
    2208           0 :         usb_device_request_t req;
    2209           0 :         u_int8_t data[4];
    2210             :         usbd_status err;
    2211             :         int val;
    2212             : 
    2213           0 :         if (wValue == -1)
    2214           0 :                 return (0);
    2215             : 
    2216           0 :         req.bmRequestType = type;
    2217           0 :         req.bRequest = which;
    2218           0 :         USETW(req.wValue, wValue);
    2219           0 :         USETW(req.wIndex, wIndex);
    2220           0 :         USETW(req.wLength, len);
    2221             :         DPRINTFN(2,("%s: type=0x%02x req=0x%02x wValue=0x%04x "
    2222             :                     "wIndex=0x%04x len=%d\n",
    2223             :                     __func__, type, which, wValue, wIndex, len));
    2224           0 :         err = usbd_do_request(sc->sc_udev, &req, data);
    2225           0 :         if (err) {
    2226             :                 DPRINTF(("%s: err=%s\n", __func__, usbd_errstr(err)));
    2227           0 :                 return (-1);
    2228             :         }
    2229           0 :         switch (len) {
    2230             :         case 1:
    2231           0 :                 val = data[0];
    2232           0 :                 break;
    2233             :         case 2:
    2234           0 :                 val = data[0] | (data[1] << 8);
    2235           0 :                 break;
    2236             :         default:
    2237             :                 DPRINTF(("%s: bad length=%d\n", __func__, len));
    2238           0 :                 return (-1);
    2239             :         }
    2240             :         DPRINTFN(2,("%s: val=%d\n", __func__, val));
    2241           0 :         return (val);
    2242           0 : }
    2243             : 
    2244             : void
    2245           0 : uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue,
    2246             :            int wIndex, int len, int val)
    2247             : {
    2248           0 :         usb_device_request_t req;
    2249           0 :         u_int8_t data[4];
    2250             :         usbd_status err;
    2251             : 
    2252           0 :         if (wValue == -1)
    2253           0 :                 return;
    2254             : 
    2255           0 :         req.bmRequestType = type;
    2256           0 :         req.bRequest = which;
    2257           0 :         USETW(req.wValue, wValue);
    2258           0 :         USETW(req.wIndex, wIndex);
    2259           0 :         USETW(req.wLength, len);
    2260           0 :         switch (len) {
    2261             :         case 1:
    2262           0 :                 data[0] = val;
    2263           0 :                 break;
    2264             :         case 2:
    2265           0 :                 data[0] = val;
    2266           0 :                 data[1] = val >> 8;
    2267           0 :                 break;
    2268             :         default:
    2269           0 :                 return;
    2270             :         }
    2271             :         DPRINTFN(2,("%s: type=0x%02x req=0x%02x wValue=0x%04x "
    2272             :                     "wIndex=0x%04x len=%d, val=%d\n", __func__,
    2273             :                     type, which, wValue, wIndex, len, val & 0xffff));
    2274           0 :         err = usbd_do_request(sc->sc_udev, &req, data);
    2275             : #ifdef UAUDIO_DEBUG
    2276             :         if (err)
    2277             :                 DPRINTF(("%s: err=%d\n", __func__, err));
    2278             : #endif
    2279           0 : }
    2280             : 
    2281             : int
    2282           0 : uaudio_signext(int type, int val)
    2283             : {
    2284           0 :         if (!MIX_UNSIGNED(type)) {
    2285           0 :                 if (MIX_SIZE(type) == 2)
    2286           0 :                         val = (int16_t)val;
    2287             :                 else
    2288           0 :                         val = (int8_t)val;
    2289             :         }
    2290           0 :         return (val);
    2291             : }
    2292             : 
    2293             : int
    2294           0 : uaudio_unsignext(int type, int val)
    2295             : {
    2296           0 :         if (!MIX_UNSIGNED(type)) {
    2297           0 :                 if (MIX_SIZE(type) == 2)
    2298           0 :                         val = (u_int16_t)val;
    2299             :                 else
    2300           0 :                         val = (u_int8_t)val;
    2301             :         }
    2302           0 :         return (val);
    2303             : }
    2304             : 
    2305             : int
    2306           0 : uaudio_value2bsd(struct mixerctl *mc, int val)
    2307             : {
    2308             :         int range;
    2309             :         DPRINTFN(5, ("%s: type=%03x val=%d min=%d max=%d ",
    2310             :                      __func__, mc->type, val, mc->minval, mc->maxval));
    2311           0 :         if (mc->type == MIX_ON_OFF) {
    2312           0 :                 val = (val != 0);
    2313           0 :         } else if (mc->type == MIX_SELECTOR) {
    2314           0 :                 if (val < mc->minval || val > mc->maxval)
    2315           0 :                         val = mc->minval;
    2316             :         } else {
    2317           0 :                 range = mc->maxval - mc->minval;
    2318           0 :                 if (range == 0) 
    2319           0 :                         val = 0;
    2320             :                 else
    2321           0 :                         val = 255 * (uaudio_signext(mc->type, val) - 
    2322           0 :                             mc->minval) / range;
    2323             :         }
    2324             :         DPRINTFN(5, ("val'=%d\n", val));
    2325           0 :         return (val);
    2326             : }
    2327             : 
    2328             : int
    2329           0 : uaudio_bsd2value(struct mixerctl *mc, int val)
    2330             : {
    2331             :         DPRINTFN(5,("%s: type=%03x val=%d min=%d max=%d ",
    2332             :                     __func__, mc->type, val, mc->minval, mc->maxval));
    2333           0 :         if (mc->type == MIX_ON_OFF) {
    2334           0 :                 val = (val != 0);
    2335           0 :         } else if (mc->type == MIX_SELECTOR) {
    2336           0 :                 if (val < mc->minval || val > mc->maxval)
    2337           0 :                         val = mc->minval;
    2338             :         } else
    2339           0 :                 val = uaudio_unsignext(mc->type, 
    2340           0 :                     val * (mc->maxval - mc->minval) / 255 + mc->minval);
    2341             :         DPRINTFN(5, ("val'=%d\n", val));
    2342           0 :         return (val);
    2343             : }
    2344             : 
    2345             : int
    2346           0 : uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc,
    2347             :                int chan)
    2348             : {
    2349             :         int val;
    2350             : 
    2351             :         DPRINTFN(5,("%s: which=%d chan=%d\n", __func__, which, chan));
    2352           0 :         val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan],
    2353           0 :                          mc->wIndex, MIX_SIZE(mc->type));
    2354           0 :         return (uaudio_value2bsd(mc, val));
    2355             : }
    2356             : 
    2357             : void
    2358           0 : uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc,
    2359             :                int chan, int val)
    2360             : {
    2361           0 :         val = uaudio_bsd2value(mc, val);
    2362           0 :         uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan],
    2363           0 :                    mc->wIndex, MIX_SIZE(mc->type), val);
    2364           0 : }
    2365             : 
    2366             : int
    2367           0 : uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp)
    2368             : {
    2369           0 :         struct uaudio_softc *sc = addr;
    2370             :         struct mixerctl *mc;
    2371           0 :         int i, n, vals[MIX_MAX_CHAN], val;
    2372             : 
    2373             :         DPRINTFN(2,("%s: index=%d\n", __func__, cp->dev));
    2374             : 
    2375           0 :         if (usbd_is_dying(sc->sc_udev))
    2376           0 :                 return (EIO);
    2377             : 
    2378           0 :         n = cp->dev - UAC_NCLASSES;
    2379           0 :         if (n < 0 || n >= sc->sc_nctls)
    2380           0 :                 return (ENXIO);
    2381           0 :         mc = &sc->sc_ctls[n];
    2382             : 
    2383           0 :         if (mc->type == MIX_ON_OFF) {
    2384           0 :                 if (cp->type != AUDIO_MIXER_ENUM)
    2385           0 :                         return (EINVAL);
    2386           0 :                 cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
    2387           0 :         } else if (mc->type == MIX_SELECTOR) {
    2388           0 :                 if (cp->type != AUDIO_MIXER_ENUM)
    2389           0 :                         return (EINVAL);
    2390           0 :                 cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
    2391           0 :         } else {
    2392           0 :                 if (cp->type != AUDIO_MIXER_VALUE)
    2393           0 :                         return (EINVAL);
    2394           0 :                 if (cp->un.value.num_channels != 1 &&
    2395           0 :                     cp->un.value.num_channels != mc->nchan)
    2396           0 :                         return (EINVAL);
    2397           0 :                 for (i = 0; i < mc->nchan; i++)
    2398           0 :                         vals[i] = uaudio_ctl_get(sc, GET_CUR, mc, i);
    2399           0 :                 if (cp->un.value.num_channels == 1 && mc->nchan != 1) {
    2400           0 :                         for (val = 0, i = 0; i < mc->nchan; i++)
    2401           0 :                                 val += vals[i];
    2402           0 :                         vals[0] = val / mc->nchan;
    2403           0 :                 }
    2404           0 :                 for (i = 0; i < cp->un.value.num_channels; i++)
    2405           0 :                         cp->un.value.level[i] = vals[i];
    2406             :         }
    2407             : 
    2408           0 :         return (0);
    2409           0 : }
    2410             : 
    2411             : int
    2412           0 : uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp)
    2413             : {
    2414           0 :         struct uaudio_softc *sc = addr;
    2415             :         struct mixerctl *mc;
    2416           0 :         int i, n, vals[MIX_MAX_CHAN];
    2417             : 
    2418             :         DPRINTFN(2,("%s: index = %d\n", __func__, cp->dev));
    2419           0 :         if (usbd_is_dying(sc->sc_udev))
    2420           0 :                 return (EIO);
    2421             : 
    2422           0 :         n = cp->dev - UAC_NCLASSES;
    2423           0 :         if (n < 0 || n >= sc->sc_nctls)
    2424           0 :                 return (ENXIO);
    2425           0 :         mc = &sc->sc_ctls[n];
    2426             : 
    2427           0 :         if (mc->type == MIX_ON_OFF) {
    2428           0 :                 if (cp->type != AUDIO_MIXER_ENUM)
    2429           0 :                         return (EINVAL);
    2430           0 :                 uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
    2431           0 :         } else if (mc->type == MIX_SELECTOR) {
    2432           0 :                 if (cp->type != AUDIO_MIXER_ENUM)
    2433           0 :                         return (EINVAL);
    2434           0 :                 uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
    2435           0 :         } else {
    2436           0 :                 if (cp->type != AUDIO_MIXER_VALUE)
    2437           0 :                         return (EINVAL);
    2438           0 :                 if (cp->un.value.num_channels == 1)
    2439           0 :                         for (i = 0; i < mc->nchan; i++)
    2440           0 :                                 vals[i] = cp->un.value.level[0];
    2441           0 :                 else if (cp->un.value.num_channels == mc->nchan)
    2442           0 :                         for (i = 0; i < mc->nchan; i++)
    2443           0 :                                 vals[i] = cp->un.value.level[i];
    2444             :                 else
    2445           0 :                         return (EINVAL);
    2446           0 :                 for (i = 0; i < mc->nchan; i++)
    2447           0 :                         uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]);
    2448             :         }
    2449           0 :         return (0);
    2450           0 : }
    2451             : 
    2452             : int
    2453           0 : uaudio_trigger_input(void *addr, void *start, void *end, int blksize,
    2454             :                      void (*intr)(void *), void *arg,
    2455             :                      struct audio_params *param)
    2456             : {
    2457           0 :         struct uaudio_softc *sc = addr;
    2458           0 :         struct chan *ch = &sc->sc_recchan;
    2459             :         usbd_status err;
    2460             :         int i, s;
    2461             : 
    2462           0 :         if (usbd_is_dying(sc->sc_udev))
    2463           0 :                 return (EIO);
    2464             : 
    2465             :         DPRINTFN(3,("%s: sc=%p start=%p end=%p "
    2466             :                     "blksize=%d\n", __func__, sc, start, end, blksize));
    2467             : 
    2468           0 :         uaudio_chan_set_param(ch, start, end, blksize);
    2469             :         DPRINTFN(3,("%s: sample_size=%d bytes/frame=%d "
    2470             :                     "fraction=0.%03d\n",
    2471             :                     __func__, ch->sample_size, ch->bytes_per_frame,
    2472             :                     ch->fraction));
    2473             : 
    2474           0 :         err = uaudio_chan_alloc_buffers(sc, ch);
    2475           0 :         if (err)
    2476           0 :                 return (EIO);
    2477             : 
    2478           0 :         err = uaudio_chan_open(sc, ch);
    2479           0 :         if (err) {
    2480           0 :                 uaudio_chan_free_buffers(sc, ch);
    2481           0 :                 return (EIO);
    2482             :         }
    2483             : 
    2484           0 :         ch->intr = intr;
    2485           0 :         ch->arg = arg;
    2486             : 
    2487           0 :         s = splusb();
    2488           0 :         for (i = 0; i < UAUDIO_NCHANBUFS; i++)
    2489           0 :                 uaudio_chan_rtransfer(ch);
    2490           0 :         splx(s);
    2491             : 
    2492           0 :         return (0);
    2493           0 : }
    2494             : 
    2495             : int
    2496           0 : uaudio_trigger_output(void *addr, void *start, void *end, int blksize,
    2497             :                       void (*intr)(void *), void *arg,
    2498             :                       struct audio_params *param)
    2499             : {
    2500           0 :         struct uaudio_softc *sc = addr;
    2501           0 :         struct chan *ch = &sc->sc_playchan;
    2502             :         usbd_status err;
    2503             :         int i, s;
    2504             : 
    2505           0 :         if (usbd_is_dying(sc->sc_udev))
    2506           0 :                 return (EIO);
    2507             : 
    2508             :         DPRINTFN(3,("%s: sc=%p start=%p end=%p "
    2509             :                     "blksize=%d\n", __func__, sc, start, end, blksize));
    2510             : 
    2511           0 :         uaudio_chan_set_param(ch, start, end, blksize);
    2512             :         DPRINTFN(3,("%s: sample_size=%d bytes/frame=%d "
    2513             :                     "fraction=0.%03d\n", __func__, ch->sample_size,
    2514             :                     ch->bytes_per_frame, ch->fraction));
    2515             : 
    2516           0 :         err = uaudio_chan_alloc_buffers(sc, ch);
    2517           0 :         if (err)
    2518           0 :                 return (EIO);
    2519             : 
    2520           0 :         err = uaudio_chan_open(sc, ch);
    2521           0 :         if (err) {
    2522           0 :                 uaudio_chan_free_buffers(sc, ch);
    2523           0 :                 return (EIO);
    2524             :         }
    2525             : 
    2526           0 :         ch->intr = intr;
    2527           0 :         ch->arg = arg;
    2528             : 
    2529           0 :         s = splusb();
    2530           0 :         for (i = 0; i < UAUDIO_NCHANBUFS; i++)
    2531           0 :                 uaudio_chan_ptransfer(ch);
    2532           0 :         if (ch->sync_pipe) {
    2533           0 :                 for (i = 0; i < UAUDIO_NSYNCBUFS; i++)
    2534           0 :                         uaudio_chan_psync_transfer(ch);
    2535             :         }
    2536           0 :         splx(s);
    2537             : 
    2538           0 :         return (0);
    2539           0 : }
    2540             : 
    2541             : /* Set up a pipe for a channel. */
    2542             : usbd_status
    2543           0 : uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
    2544             : {
    2545           0 :         struct as_info *as = &sc->sc_alts[ch->altidx];
    2546           0 :         int endpt = as->edesc->bEndpointAddress;
    2547             :         usbd_status err;
    2548             : 
    2549             :         DPRINTF(("%s: endpt=0x%02x, speed=%d, alt=%d\n",
    2550             :                  __func__, endpt, ch->sample_rate, as->alt));
    2551             : 
    2552             :         /* Set alternate interface corresponding to the mode. */
    2553           0 :         err = usbd_set_interface(as->ifaceh, as->alt);
    2554           0 :         if (err) {
    2555             :                 DPRINTF(("%s: usbd_set_interface failed\n", __func__));
    2556           0 :                 return (err);
    2557             :         }
    2558             : 
    2559             :         /*
    2560             :          * If just one sampling rate is supported,
    2561             :          * no need to call uaudio_set_speed().
    2562             :          * Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request.
    2563             :          */
    2564           0 :         if (as->asf1desc->bSamFreqType != 1) {
    2565           0 :                 err = uaudio_set_speed(sc, endpt, ch->sample_rate);
    2566             :                 if (err)
    2567             :                         DPRINTF(("%s: set_speed failed err=%s\n",
    2568             :                                  __func__, usbd_errstr(err)));
    2569           0 :         }
    2570             : 
    2571           0 :         if (sc->sc_quirks & UAUDIO_FLAG_EMU0202)
    2572           0 :                 uaudio_set_speed_emu0202(ch);
    2573             : 
    2574           0 :         ch->pipe = 0;
    2575           0 :         ch->sync_pipe = 0;
    2576             :         DPRINTF(("%s: create pipe to 0x%02x\n", __func__, endpt));
    2577           0 :         err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
    2578           0 :         if (err) {
    2579           0 :                 printf("%s: error creating pipe: err=%s endpt=0x%02x\n",
    2580           0 :                     __func__, usbd_errstr(err), endpt);
    2581           0 :                 return err;
    2582             :         }
    2583           0 :         if (as->edesc1 != NULL) {
    2584           0 :                 endpt = as->edesc1->bEndpointAddress;
    2585             :                 DPRINTF(("%s: create sync-pipe to 0x%02x\n", __func__, endpt));
    2586           0 :                 err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->sync_pipe);
    2587           0 :                 if (err) {
    2588           0 :                         printf("%s: error creating sync-pipe: err=%s endpt=0x%02x\n",
    2589           0 :                             __func__, usbd_errstr(err), endpt);
    2590           0 :                 }
    2591             :         }
    2592           0 :         return err;
    2593           0 : }
    2594             : 
    2595             : void
    2596           0 : uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
    2597             : {
    2598           0 :         struct as_info *as = &sc->sc_alts[ch->altidx];
    2599             : 
    2600           0 :         as->sc_busy = 0;
    2601           0 :         if (sc->sc_nullalt >= 0) {
    2602             :                 DPRINTF(("%s: set null alt=%d\n",
    2603             :                          __func__, sc->sc_nullalt));
    2604           0 :                 usbd_set_interface(as->ifaceh, sc->sc_nullalt);
    2605           0 :         }
    2606           0 :         if (ch->pipe) {
    2607           0 :                 usbd_abort_pipe(ch->pipe);
    2608           0 :                 usbd_close_pipe(ch->pipe);
    2609           0 :         }
    2610           0 :         if (ch->sync_pipe) {
    2611           0 :                 usbd_abort_pipe(ch->sync_pipe);
    2612           0 :                 usbd_close_pipe(ch->sync_pipe);
    2613           0 :         }
    2614           0 : }
    2615             : 
    2616             : usbd_status
    2617           0 : uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch)
    2618             : {
    2619           0 :         struct as_info *as = &sc->sc_alts[ch->altidx];
    2620             :         struct usbd_xfer *xfer;
    2621             :         void *buf;
    2622             :         int i, size;
    2623             : 
    2624             :         DPRINTF(("%s: max_bytes_per_frame=%d nframes=%d\n", __func__,
    2625             :             ch->max_bytes_per_frame, ch->nframes));
    2626             : 
    2627           0 :         size = ch->max_bytes_per_frame * ch->nframes;
    2628           0 :         for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
    2629           0 :                 xfer = usbd_alloc_xfer(sc->sc_udev);
    2630           0 :                 if (xfer == 0)
    2631             :                         goto bad;
    2632           0 :                 ch->chanbufs[i].xfer = xfer;
    2633           0 :                 buf = usbd_alloc_buffer(xfer, size);
    2634           0 :                 if (buf == 0) {
    2635           0 :                         i++;
    2636           0 :                         goto bad;
    2637             :                 }
    2638           0 :                 ch->chanbufs[i].buffer = buf;
    2639           0 :                 ch->chanbufs[i].chan = ch;
    2640             :         }
    2641           0 :         if (as->edesc1 != NULL) {
    2642           0 :                 size = (ch->hi_speed ? 4 : 3) * ch->nsync_frames;
    2643           0 :                 for (i = 0; i < UAUDIO_NSYNCBUFS; i++) {
    2644           0 :                         xfer = usbd_alloc_xfer(sc->sc_udev);
    2645           0 :                         if (xfer == 0)
    2646             :                                 goto bad_sync;
    2647           0 :                         ch->syncbufs[i].xfer = xfer;
    2648           0 :                         buf = usbd_alloc_buffer(xfer, size);
    2649           0 :                         if (buf == 0) {
    2650           0 :                                 i++;
    2651           0 :                                 goto bad_sync;
    2652             :                         }
    2653           0 :                         ch->syncbufs[i].buffer = buf;
    2654           0 :                         ch->syncbufs[i].chan = ch;
    2655             :                 }
    2656             :         }
    2657             : 
    2658           0 :         return (USBD_NORMAL_COMPLETION);
    2659             : 
    2660             : bad:
    2661           0 :         while (--i >= 0)
    2662             :                 /* implicit buffer free */
    2663           0 :                 usbd_free_xfer(ch->chanbufs[i].xfer);
    2664           0 :         return (USBD_NOMEM);
    2665             : 
    2666             : bad_sync:
    2667           0 :         while (--i >= 0)
    2668             :                 /* implicit buffer free */
    2669           0 :                 usbd_free_xfer(ch->syncbufs[i].xfer);
    2670           0 :         return (USBD_NOMEM);
    2671             : 
    2672           0 : }
    2673             : 
    2674             : void
    2675           0 : uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch)
    2676             : {
    2677           0 :         struct as_info *as = &sc->sc_alts[ch->altidx];
    2678             :         int i;
    2679             : 
    2680           0 :         for (i = 0; i < UAUDIO_NCHANBUFS; i++)
    2681           0 :                 usbd_free_xfer(ch->chanbufs[i].xfer);
    2682           0 :         if (as->edesc1 != NULL) {
    2683           0 :                 for (i = 0; i < UAUDIO_NSYNCBUFS; i++)
    2684           0 :                         usbd_free_xfer(ch->syncbufs[i].xfer);
    2685             :         }
    2686           0 : }
    2687             : 
    2688             : /* Called at splusb() */
    2689             : void
    2690           0 : uaudio_chan_ptransfer(struct chan *ch)
    2691             : {
    2692             :         struct chanbuf *cb;
    2693             :         u_char *pos;
    2694             :         int i, n, size, residue, total;
    2695             : 
    2696           0 :         if (usbd_is_dying(ch->sc->sc_udev))
    2697           0 :                 return;
    2698             : 
    2699             :         /* Pick the next channel buffer. */
    2700           0 :         cb = &ch->chanbufs[ch->curchanbuf];
    2701           0 :         if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
    2702           0 :                 ch->curchanbuf = 0;
    2703             : 
    2704             :         /* Compute the size of each frame in the next transfer. */
    2705           0 :         residue = ch->residue;
    2706             :         total = 0;
    2707           0 :         for (i = 0; i < ch->nframes; i++) {
    2708           0 :                 size = ch->bytes_per_frame;
    2709           0 :                 residue += ch->fraction;
    2710           0 :                 if (residue >= ch->frac_denom) {
    2711           0 :                         if ((ch->sc->sc_altflags & UA_NOFRAC) == 0)
    2712           0 :                                 size += ch->sample_size;
    2713           0 :                         residue -= ch->frac_denom;
    2714           0 :                 }
    2715           0 :                 cb->sizes[i] = size;
    2716           0 :                 total += size;
    2717             :         }
    2718           0 :         ch->residue = residue;
    2719           0 :         cb->size = total;
    2720             : 
    2721             :         /*
    2722             :          * Transfer data from upper layer buffer to channel buffer.  Be sure
    2723             :          * to let the upper layer know each time a block is moved, so it can
    2724             :          * add more.
    2725             :          */
    2726           0 :         pos = cb->buffer;
    2727           0 :         while (total > 0) {
    2728           0 :                 n = min(total, ch->end - ch->cur);
    2729           0 :                 n = min(n, ch->blksize - ch->transferred);
    2730           0 :                 memcpy(pos, ch->cur, n);
    2731           0 :                 total -= n;
    2732           0 :                 pos += n;
    2733           0 :                 ch->cur += n;
    2734           0 :                 if (ch->cur >= ch->end)
    2735           0 :                         ch->cur = ch->start;
    2736             : 
    2737           0 :                 ch->transferred += n;
    2738             :                 /* Call back to upper layer */
    2739           0 :                 if (ch->transferred >= ch->blksize) {
    2740             :                         DPRINTFN(5,("%s: call %p(%p)\n",
    2741             :                                     __func__, ch->intr, ch->arg));
    2742           0 :                         mtx_enter(&audio_lock);
    2743           0 :                         ch->intr(ch->arg);
    2744           0 :                         mtx_leave(&audio_lock);
    2745           0 :                         ch->transferred -= ch->blksize;
    2746           0 :                 }
    2747             :         }
    2748             : 
    2749             : #ifdef UAUDIO_DEBUG
    2750             :         if (uaudiodebug > 8) {
    2751             :                 DPRINTF(("%s: buffer=%p, residue=0.%03d\n",
    2752             :                          __func__, cb->buffer, ch->residue));
    2753             :                 for (i = 0; i < ch->nframes; i++) {
    2754             :                         DPRINTF(("   [%d] length %d\n", i, cb->sizes[i]));
    2755             :                 }
    2756             :         }
    2757             : #endif
    2758             : 
    2759             :         DPRINTFN(5,("%s: transfer xfer=%p\n", __func__, cb->xfer));
    2760           0 :         usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, ch->nframes,
    2761             :             USBD_NO_COPY | USBD_SHORT_XFER_OK, uaudio_chan_pintr);
    2762             : 
    2763           0 :         (void)usbd_transfer(cb->xfer);
    2764           0 : }
    2765             : 
    2766             : void
    2767           0 : uaudio_chan_pintr(struct usbd_xfer *xfer, void *priv,
    2768             :                   usbd_status status)
    2769             : {
    2770           0 :         struct chanbuf *cb = priv;
    2771           0 :         struct chan *ch = cb->chan;
    2772           0 :         u_int32_t count;
    2773             : 
    2774             :         /* Return if we are aborting. */
    2775           0 :         if (status == USBD_CANCELLED)
    2776           0 :                 return;
    2777             : 
    2778           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
    2779             :         DPRINTFN(5,("%s: count=%d, transferred=%d\n",
    2780             :                     __func__, count, ch->transferred));
    2781             : #ifdef UAUDIO_DEBUG
    2782             :         if (count != cb->size) {
    2783             :                 printf("%s: count(%d) != size(%d)\n",
    2784             :                        __func__, count, cb->size);
    2785             :         }
    2786             : #endif
    2787             : 
    2788             :         /* start next transfer */
    2789           0 :         uaudio_chan_ptransfer(ch);
    2790           0 : }
    2791             : 
    2792             : /* Called at splusb() */
    2793             : void
    2794           0 : uaudio_chan_psync_transfer(struct chan *ch)
    2795             : {
    2796             :         struct syncbuf *sb;
    2797             :         int i, size, total = 0;
    2798             : 
    2799           0 :         if (usbd_is_dying(ch->sc->sc_udev))
    2800           0 :                 return;
    2801             : 
    2802             :         /* Pick the next sync buffer. */
    2803           0 :         sb = &ch->syncbufs[ch->cursyncbuf];
    2804           0 :         if (++ch->cursyncbuf >= UAUDIO_NSYNCBUFS)
    2805           0 :                 ch->cursyncbuf = 0;
    2806             : 
    2807           0 :         size = ch->hi_speed ? 4 : 3;
    2808           0 :         for (i = 0; i < ch->nsync_frames; i++) {
    2809           0 :                 sb->sizes[i] = size;
    2810           0 :                 sb->offsets[i] = total;
    2811           0 :                 total += size;
    2812             :         }
    2813           0 :         sb->size = total;
    2814             : 
    2815             :         DPRINTFN(5,("%s: transfer xfer=%p\n", __func__, sb->xfer));
    2816           0 :         usbd_setup_isoc_xfer(sb->xfer, ch->sync_pipe, sb, sb->sizes,
    2817           0 :             ch->nsync_frames, USBD_NO_COPY | USBD_SHORT_XFER_OK,
    2818             :             uaudio_chan_psync_intr);
    2819             : 
    2820           0 :         (void)usbd_transfer(sb->xfer);
    2821           0 : }
    2822             : 
    2823             : void
    2824           0 : uaudio_chan_psync_intr(struct usbd_xfer *xfer, void *priv,
    2825             :     usbd_status status)
    2826             : {
    2827           0 :         struct syncbuf *sb = priv;
    2828           0 :         struct chan *ch = sb->chan;
    2829           0 :         u_int32_t count, tmp;
    2830             :         u_int32_t freq, freq_w, freq_f;
    2831             :         int i, pos, size;
    2832             : 
    2833             :         /* Return if we are aborting. */
    2834           0 :         if (status == USBD_CANCELLED)
    2835           0 :                 return;
    2836             : 
    2837           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
    2838             :         DPRINTFN(5,("%s: count=%d\n", __func__, count));
    2839             : 
    2840           0 :         size = ch->hi_speed ? 4 : 3;
    2841           0 :         for (i = 0; count > 0 && i < ch->nsync_frames; i++) {
    2842           0 :                 if (sb->sizes[i] != size)
    2843             :                         continue;
    2844           0 :                 count -= size;
    2845           0 :                 pos = sb->offsets[i];
    2846           0 :                 if (ch->hi_speed) {
    2847             :                         /* 16.16 (12.13) -> 16.16 (12.16) */
    2848           0 :                         freq = sb->buffer[pos+3] << 24 |
    2849           0 :                             sb->buffer[pos+2] << 16 |
    2850           0 :                             sb->buffer[pos+1] << 8 |
    2851           0 :                             sb->buffer[pos];
    2852           0 :                 } else {
    2853             :                         /* 10.14 (10.10) -> 16.16 (10.16) */
    2854           0 :                         freq = sb->buffer[pos+2] << 18 |
    2855           0 :                             sb->buffer[pos+1] << 10 |
    2856           0 :                             sb->buffer[pos] << 2;
    2857             :                 }
    2858           0 :                 freq_w = (freq >> 16) & (ch->hi_speed ? 0x0fff : 0x03ff);
    2859           0 :                 freq_f = freq & 0xffff;
    2860             :                 DPRINTFN(5,("%s: freq = %d %d/%d\n", __func__, freq_w, freq_f,
    2861             :                     ch->frac_denom));
    2862           0 :                 tmp = freq_w * ch->sample_size;
    2863           0 :                 if (tmp + (freq_f ? ch->sample_size : 0) >
    2864           0 :                     ch->max_bytes_per_frame) {
    2865             :                         DPRINTF(("%s: packet size request too large: %d/%d/%d\n",
    2866             :                             __func__, tmp, ch->max_bytes_per_frame, ch->maxpktsize));
    2867             :                 } else {
    2868           0 :                         ch->bytes_per_frame = tmp;
    2869           0 :                         ch->fraction = freq_f;
    2870             :                 }
    2871             :         }
    2872             : 
    2873             :         /* start next transfer */
    2874           0 :         uaudio_chan_psync_transfer(ch);
    2875           0 : }
    2876             : 
    2877             : /* Called at splusb() */
    2878             : void
    2879           0 : uaudio_chan_rtransfer(struct chan *ch)
    2880             : {
    2881             :         struct chanbuf *cb;
    2882             :         int i, size, total;
    2883             : 
    2884           0 :         if (usbd_is_dying(ch->sc->sc_udev))
    2885           0 :                 return;
    2886             : 
    2887             :         /* Pick the next channel buffer. */
    2888           0 :         cb = &ch->chanbufs[ch->curchanbuf];
    2889           0 :         if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
    2890           0 :                 ch->curchanbuf = 0;
    2891             : 
    2892             :         /* Compute the size of each frame in the next transfer. */
    2893             :         total = 0;
    2894           0 :         for (i = 0; i < ch->nframes; i++) {
    2895           0 :                 size = ch->bytes_per_frame;
    2896           0 :                 cb->sizes[i] = size;
    2897           0 :                 cb->offsets[i] = total;
    2898           0 :                 total += size;
    2899             :         }
    2900           0 :         cb->size = total;
    2901             : 
    2902             : #ifdef UAUDIO_DEBUG
    2903             :         if (uaudiodebug > 8) {
    2904             :                 DPRINTF(("%s: buffer=%p, residue=0.%03d\n",
    2905             :                          __func__, cb->buffer, ch->residue));
    2906             :                 for (i = 0; i < ch->nframes; i++) {
    2907             :                         DPRINTF(("   [%d] length %d\n", i, cb->sizes[i]));
    2908             :                 }
    2909             :         }
    2910             : #endif
    2911             : 
    2912             :         DPRINTFN(5,("%s: transfer xfer=%p\n", __func__, cb->xfer));
    2913           0 :         usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, ch->nframes,
    2914             :             USBD_NO_COPY | USBD_SHORT_XFER_OK, uaudio_chan_rintr);
    2915             : 
    2916           0 :         (void)usbd_transfer(cb->xfer);
    2917           0 : }
    2918             : 
    2919             : void
    2920           0 : uaudio_chan_rintr(struct usbd_xfer *xfer, void *priv,
    2921             :                   usbd_status status)
    2922             : {
    2923           0 :         struct chanbuf *cb = priv;
    2924           0 :         struct chan *ch = cb->chan;
    2925             :         u_int16_t pos;
    2926           0 :         u_int32_t count;
    2927             :         int i, n, frsize;
    2928             : 
    2929             :         /* Return if we are aborting. */
    2930           0 :         if (status == USBD_CANCELLED)
    2931           0 :                 return;
    2932             : 
    2933           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
    2934             :         DPRINTFN(5,("%s: count=%d, transferred=%d\n",
    2935             :                     __func__, count, ch->transferred));
    2936             : 
    2937             :         /* count < cb->size is normal for asynchronous source */
    2938             : #ifdef DIAGNOSTIC
    2939           0 :         if (count > cb->size) {
    2940           0 :                 printf("%s: count(%d) > size(%d)\n",
    2941             :                        __func__, count, cb->size);
    2942           0 :         }
    2943             : #endif
    2944             : 
    2945             :         /*
    2946             :          * Transfer data from channel buffer to upper layer buffer, taking
    2947             :          * care of wrapping the upper layer buffer.
    2948             :          */
    2949           0 :         for (i = 0; i < ch->nframes; i++) {
    2950           0 :                 frsize = cb->sizes[i];
    2951           0 :                 pos = cb->offsets[i];
    2952           0 :                 while (frsize > 0) {
    2953           0 :                         n = min(frsize, ch->end - ch->cur);
    2954           0 :                         n = min(n, ch->blksize - ch->transferred);
    2955           0 :                         memcpy(ch->cur, cb->buffer + pos, n);
    2956           0 :                         frsize -= n;
    2957           0 :                         pos += n;
    2958           0 :                         ch->cur += n;
    2959           0 :                         if (ch->cur >= ch->end)
    2960           0 :                                 ch->cur = ch->start;
    2961             : 
    2962           0 :                         ch->transferred += n;
    2963             :                         /* Call back to upper layer */
    2964           0 :                         if (ch->transferred >= ch->blksize) {
    2965             :                                 DPRINTFN(5,("%s: call %p(%p)\n",
    2966             :                                             __func__, ch->intr, ch->arg));
    2967           0 :                                 mtx_enter(&audio_lock);
    2968           0 :                                 ch->intr(ch->arg);
    2969           0 :                                 mtx_leave(&audio_lock);
    2970           0 :                                 ch->transferred -= ch->blksize;
    2971           0 :                         }
    2972           0 :                         if (count < n)
    2973           0 :                                 printf("%s: count < n\n", __func__);
    2974             :                         else
    2975           0 :                                 count -= n;
    2976             :                 }
    2977             :         }
    2978           0 :         if (count != 0) {
    2979           0 :                 printf("%s: transfer count - frame total = %d\n",
    2980             :                     __func__, count);
    2981           0 :         }
    2982             : 
    2983             :         /* start next transfer */
    2984           0 :         uaudio_chan_rtransfer(ch);
    2985           0 : }
    2986             : 
    2987             : void
    2988           0 : uaudio_chan_init(struct chan *ch, int mode, int altidx,
    2989             :     const struct audio_params *param)
    2990             : {
    2991           0 :         struct as_info *ai = &ch->sc->sc_alts[altidx];
    2992             :         int samples_per_frame, ival, use_maxpkt = 0;
    2993             : 
    2994           0 :         if (ai->attributes & UA_SED_MAXPACKETSONLY) {
    2995             :                 DPRINTF(("%s: alt %d needs maxpktsize packets\n",
    2996             :                     __func__, altidx));
    2997             :                 use_maxpkt = 1;
    2998           0 :         }
    2999           0 :         else if (mode == AUMODE_RECORD) {
    3000             :                 DPRINTF(("%s: using maxpktsize packets for record channel\n",
    3001             :                     __func__));
    3002             :                 use_maxpkt = 1;
    3003           0 :         }
    3004             : 
    3005           0 :         ch->altidx = altidx;
    3006           0 :         ch->maxpktsize = UGETW(ai->edesc->wMaxPacketSize);
    3007           0 :         ch->sample_rate = param->sample_rate;
    3008           0 :         ch->sample_size = param->channels * param->bps;
    3009           0 :         ch->usb_fps = USB_FRAMES_PER_SECOND;
    3010           0 :         ch->hi_speed = ch->sc->sc_udev->speed == USB_SPEED_HIGH;
    3011           0 :         if (ch->hi_speed) {
    3012           0 :                 ch->usb_fps *= 8;
    3013             :                 /*
    3014             :                  * Polling interval is considered a frame, as opposed to
    3015             :                  * micro-frame being a frame.
    3016             :                  */
    3017           0 :                 ival = ch->sc->sc_alts[altidx].edesc->bInterval;
    3018           0 :                 if (ival > 0 && ival <= 4)
    3019           0 :                         ch->usb_fps >>= (ival - 1);
    3020             :                 DPRINTF(("%s: detected USB high-speed with ival %d\n",
    3021             :                     __func__, ival));
    3022             :         }
    3023             : 
    3024             :         /*
    3025             :          * Use UAUDIO_MIN_FRAMES here, so uaudio_round_blocksize() can
    3026             :          * make sure the blocksize duration will be > 1 USB frame.
    3027             :          */
    3028           0 :         samples_per_frame = ch->sample_rate / ch->usb_fps;
    3029           0 :         if (!use_maxpkt) {
    3030           0 :                 ch->fraction = ch->sample_rate % ch->usb_fps;
    3031           0 :                 if (samples_per_frame * ch->sample_size > ch->maxpktsize) {
    3032             :                         DPRINTF(("%s: packet size %d too big, max %d\n",
    3033             :                             __func__, ch->bytes_per_frame, ch->maxpktsize));
    3034           0 :                         samples_per_frame = ch->maxpktsize / ch->sample_size;
    3035           0 :                 }
    3036           0 :                 ch->bytes_per_frame = samples_per_frame * ch->sample_size;
    3037           0 :                 ch->nframes = UAUDIO_MIN_FRAMES;
    3038           0 :         } else {
    3039           0 :                 ch->fraction = 0;
    3040           0 :                 ch->bytes_per_frame = ch->maxpktsize;
    3041           0 :                 ch->nframes = UAUDIO_MIN_FRAMES * samples_per_frame *
    3042           0 :                     ch->sample_size / ch->maxpktsize;
    3043             :         }
    3044           0 :         if (ch->nframes > UAUDIO_MAX_FRAMES)
    3045           0 :                 ch->nframes = UAUDIO_MAX_FRAMES;
    3046           0 :         else if (ch->nframes < 1)
    3047           0 :                 ch->nframes = 1;
    3048             : 
    3049           0 :         ch->max_bytes_per_frame = ch->bytes_per_frame;
    3050           0 :         if (!use_maxpkt)
    3051           0 :                 ch->max_bytes_per_frame += ch->sample_size;
    3052           0 :         if (ch->max_bytes_per_frame > ch->maxpktsize)
    3053           0 :                 ch->max_bytes_per_frame = ch->maxpktsize;
    3054             : 
    3055           0 :         ch->residue = 0;
    3056           0 :         ch->frac_denom = ch->usb_fps;
    3057           0 :         if (ai->edesc1 != NULL) {
    3058             :                 /*
    3059             :                  * The lower 16-bits of the sync request represent
    3060             :                  * fractional samples.  Scale up the fraction here once
    3061             :                  * so all fractions are using the same denominator.
    3062             :                  */
    3063           0 :                 ch->frac_denom = 1 << 16;
    3064           0 :                 ch->fraction = (ch->fraction * ch->frac_denom) / ch->usb_fps;
    3065             : 
    3066             :                 /*
    3067             :                  * Have to set nsync_frames somewhere.  We can request
    3068             :                  * a lot of sync data; the device will reply when it's
    3069             :                  * ready, with empty frames meaning to keep using the
    3070             :                  * current rate.
    3071             :                  */
    3072           0 :                 ch->nsync_frames = UAUDIO_MAX_FRAMES;
    3073           0 :         }
    3074             :         DPRINTF(("%s: residual sample fraction: %d/%d\n", __func__,
    3075             :             ch->fraction, ch->frac_denom));
    3076           0 : }
    3077             : 
    3078             : void
    3079           0 : uaudio_chan_set_param(struct chan *ch, u_char *start, u_char *end, int blksize)
    3080             : {
    3081           0 :         ch->start = start;
    3082           0 :         ch->end = end;
    3083           0 :         ch->cur = start;
    3084           0 :         ch->transferred = 0;
    3085           0 :         ch->curchanbuf = 0;
    3086           0 :         ch->blksize = blksize;
    3087             : 
    3088             :         /*
    3089             :          * Recompute nframes based on blksize, but make sure nframes
    3090             :          * is not longer in time duration than blksize.
    3091             :          */
    3092           0 :         ch->nframes = ch->blksize * ch->usb_fps /
    3093           0 :             (ch->bytes_per_frame * ch->usb_fps +
    3094           0 :             ch->sample_size * ch->fraction);
    3095           0 :         if (ch->nframes > UAUDIO_MAX_FRAMES)
    3096           0 :                 ch->nframes = UAUDIO_MAX_FRAMES;
    3097           0 :         else if (ch->nframes < 1)
    3098           0 :                 ch->nframes = 1;
    3099             : 
    3100           0 :         ch->reqms = ch->bytes_per_frame / ch->sample_size *
    3101           0 :             ch->nframes * 1000 / ch->sample_rate;
    3102             : 
    3103             :         DPRINTF(("%s: alt=%d blk=%d maxpkt=%u bpf=%u rate=%u nframes=%u reqms=%u\n",
    3104             :             __func__, ch->altidx, ch->blksize, ch->maxpktsize,
    3105             :             ch->bytes_per_frame, ch->sample_rate, ch->nframes, ch->reqms));
    3106           0 : }
    3107             : 
    3108             : int
    3109           0 : uaudio_match_alt_rate(void *addr, int alt, int rate)
    3110             : {
    3111           0 :         struct uaudio_softc *sc = addr;
    3112             :         const struct usb_audio_streaming_type1_descriptor *a1d;
    3113             :         int i, j, r;
    3114             : 
    3115           0 :         a1d = sc->sc_alts[alt].asf1desc;
    3116           0 :         if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
    3117           0 :                 if ((UA_SAMP_LO(a1d) <= rate) &&
    3118           0 :                     (UA_SAMP_HI(a1d) >= rate)) {
    3119           0 :                         return rate;
    3120             :                 } else {
    3121           0 :                         if (UA_SAMP_LO(a1d) > rate)
    3122           0 :                                 return UA_SAMP_LO(a1d);
    3123             :                         else
    3124           0 :                                 return UA_SAMP_HI(a1d);
    3125             :                 }
    3126             :         } else {
    3127           0 :                 for (i = 0; i < 100; i++) {
    3128           0 :                         for (j = 0; j < a1d->bSamFreqType; j++) {
    3129           0 :                                 r = UA_GETSAMP(a1d, j);
    3130           0 :                                 if ((r - (500 * i) <= rate) &&
    3131           0 :                                     (r + (500 * i) >= rate))
    3132           0 :                                         return r;
    3133             :                         }
    3134             :                 }
    3135             :                 /* assumes rates are listed in order from lowest to highest */
    3136           0 :                 if (rate < UA_GETSAMP(a1d, 0))
    3137           0 :                         j = 0;
    3138             :                 else
    3139           0 :                         j = a1d->bSamFreqType - 1;
    3140           0 :                 return UA_GETSAMP(a1d, j);
    3141             :         }
    3142             :         DPRINTF(("%s: could not match rate\n", __func__));
    3143             :         return rate;
    3144           0 : }
    3145             : 
    3146             : int
    3147           0 : uaudio_match_alt(void *addr, struct audio_params *p, int mode)
    3148             : {
    3149           0 :         struct uaudio_softc *sc = addr;
    3150             :         const struct usb_audio_streaming_type1_descriptor *a1d;
    3151             :         int i, j, dir, rate;
    3152             :         int alts_eh, alts_ch, ualt;
    3153             : 
    3154             :         DPRINTF(("%s: mode=%s rate=%ld ch=%d pre=%d bps=%d enc=%d\n",
    3155             :             __func__, mode == AUMODE_RECORD ? "rec" : "play", p->sample_rate,
    3156             :             p->channels, p->precision, p->bps, p->encoding));
    3157             : 
    3158             :         alts_eh = 0;
    3159           0 :         for (i = 0; i < sc->sc_nalts; i++) {
    3160           0 :                 dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
    3161           0 :                 if ((mode == AUMODE_RECORD && dir != UE_DIR_IN) ||
    3162           0 :                     (mode == AUMODE_PLAY && dir == UE_DIR_IN))
    3163             :                         continue;
    3164             :                 DPRINTFN(6,("%s: matched %s alt %d for direction\n", __func__,
    3165             :                     mode == AUMODE_RECORD ? "rec" : "play", i));
    3166           0 :                 if (sc->sc_alts[i].encoding != p->encoding)
    3167             :                         continue;
    3168           0 :                 a1d = sc->sc_alts[i].asf1desc;
    3169           0 :                 if (a1d->bBitResolution != p->precision)
    3170             :                         continue;
    3171           0 :                 alts_eh |= 1 << i;
    3172             :                 DPRINTFN(6,("%s: matched %s alt %d for enc/pre\n", __func__,
    3173             :                     mode == AUMODE_RECORD ? "rec" : "play", i));
    3174           0 :         }
    3175           0 :         if (alts_eh == 0) {
    3176             :                 DPRINTF(("%s: could not match dir/enc/prec\n", __func__));
    3177           0 :                 return -1;
    3178             :         }
    3179             : 
    3180             :         alts_ch = 0;
    3181           0 :         for (i = 0; i < 3; i++) {
    3182           0 :                 for (j = 0; j < sc->sc_nalts; j++) {
    3183           0 :                         if (!(alts_eh & (1 << j)))
    3184             :                                 continue;
    3185           0 :                         a1d = sc->sc_alts[j].asf1desc;
    3186           0 :                         if (a1d->bNrChannels == p->channels) {
    3187           0 :                                 alts_ch |= 1 << j;
    3188             :                                 DPRINTFN(6,("%s: matched alt %d for channels\n",
    3189             :                                     __func__, j));
    3190           0 :                         }
    3191             :                 }
    3192           0 :                 if (alts_ch)
    3193             :                         break;
    3194           0 :                 if (p->channels == 2)
    3195           0 :                         p->channels = 1;
    3196             :                 else
    3197           0 :                         p->channels = 2;
    3198             :         }
    3199           0 :         if (!alts_ch) {
    3200             :                 /* just use the first alt that matched the encoding */
    3201           0 :                 for (i = 0; i < sc->sc_nalts; i++)
    3202           0 :                         if (alts_eh & (1 << i))
    3203             :                                 break;
    3204           0 :                 alts_ch = 1 << i;
    3205           0 :                 a1d = sc->sc_alts[i].asf1desc;
    3206           0 :                 p->channels = a1d->bNrChannels;
    3207           0 :         }
    3208             : 
    3209             :         ualt = -1;
    3210           0 :         for (i = 0; i < sc->sc_nalts; i++) {
    3211           0 :                 if (alts_ch & (1 << i)) {
    3212           0 :                         rate = uaudio_match_alt_rate(sc, i, p->sample_rate);
    3213           0 :                         if (rate - 50 <= p->sample_rate &&
    3214           0 :                             rate + 50 >= p->sample_rate) {
    3215             :                                 DPRINTFN(6,("%s: alt %d matched rate %ld with %d\n",
    3216             :                                     __func__, i, p->sample_rate, rate));
    3217           0 :                                 p->sample_rate = rate;
    3218           0 :                                 break;
    3219             :                         }
    3220             :                 }
    3221             :         }
    3222           0 :         if (i < sc->sc_nalts) {
    3223             :                 ualt = i;
    3224           0 :         } else {
    3225           0 :                 for (i = 0; i < sc->sc_nalts; i++) {
    3226           0 :                         if (alts_ch & (1 << i)) {
    3227             :                                 ualt = i;
    3228           0 :                                 p->sample_rate = uaudio_match_alt_rate(sc,
    3229           0 :                                     i, p->sample_rate);
    3230           0 :                                 break;
    3231             :                         }
    3232             :                 }
    3233             :         }
    3234             : 
    3235           0 :         return ualt;
    3236           0 : }
    3237             : 
    3238             : int
    3239           0 : uaudio_set_params(void *addr, int setmode, int usemode,
    3240             :     struct audio_params *play, struct audio_params *rec)
    3241             : {
    3242           0 :         struct uaudio_softc *sc = addr;
    3243           0 :         int flags = sc->sc_altflags;
    3244             :         int i;
    3245             :         int paltidx = -1, raltidx = -1;
    3246             :         struct audio_params *p;
    3247             :         int mode;
    3248             : 
    3249           0 :         if (usbd_is_dying(sc->sc_udev))
    3250           0 :                 return (EIO);
    3251             : 
    3252           0 :         if (((usemode & AUMODE_PLAY) && sc->sc_playchan.pipe != NULL) ||
    3253           0 :             ((usemode & AUMODE_RECORD) && sc->sc_recchan.pipe != NULL))
    3254           0 :                 return (EBUSY);
    3255             : 
    3256           0 :         if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1)
    3257           0 :                 sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 0;
    3258           0 :         if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1)
    3259           0 :                 sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 0;
    3260             : 
    3261             :         /* Some uaudio devices are unidirectional.  Don't try to find a
    3262             :            matching mode for the unsupported direction. */
    3263           0 :         setmode &= sc->sc_mode;
    3264             : 
    3265           0 :         for (mode = AUMODE_RECORD; mode != -1;
    3266           0 :              mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
    3267           0 :                 if ((setmode & mode) == 0)
    3268             :                         continue;
    3269             : 
    3270           0 :                 p = (mode == AUMODE_PLAY) ? play : rec;
    3271             : 
    3272           0 :                 switch (p->precision) {
    3273             :                 case 24:
    3274           0 :                         if (!(flags & HAS_24)) {
    3275           0 :                                 if (flags & HAS_16)
    3276           0 :                                         p->precision = 16;
    3277             :                                 else
    3278           0 :                                         p->precision = 8;
    3279             :                         }
    3280             :                         break;
    3281             :                 case 16:
    3282           0 :                         if (!(flags & HAS_16)) {
    3283           0 :                                 if (flags & HAS_24)
    3284           0 :                                         p->precision = 24;
    3285             :                                 else
    3286           0 :                                         p->precision = 8;
    3287             :                         }
    3288             :                         break;
    3289             :                 case 8:
    3290           0 :                         if (!(flags & HAS_8) && !(flags & HAS_8U)) {
    3291           0 :                                 if (flags & HAS_16)
    3292           0 :                                         p->precision = 16;
    3293             :                                 else
    3294           0 :                                         p->precision = 24;
    3295             :                         }
    3296             :                         break;
    3297             :                 }
    3298             : 
    3299           0 :                 i = uaudio_match_alt(sc, p, mode);
    3300           0 :                 if (i < 0) {
    3301             :                         DPRINTF(("%s: uaudio_match_alt failed for %s\n",
    3302             :                             __func__, mode == AUMODE_RECORD ? "rec" : "play"));
    3303             :                         continue;
    3304             :                 }
    3305             : 
    3306           0 :                 p->bps = sc->sc_alts[i].asf1desc->bSubFrameSize;
    3307           0 :                 p->msb = 1;
    3308             : 
    3309           0 :                 if (mode == AUMODE_PLAY)
    3310           0 :                         paltidx = i;
    3311             :                 else
    3312             :                         raltidx = i;
    3313             :         }
    3314             : 
    3315           0 :         if (setmode & AUMODE_PLAY) {
    3316           0 :                 if (paltidx == -1) {
    3317             :                         DPRINTF(("%s: did not find alt for playback\n",
    3318             :                             __func__));
    3319           0 :                         return (EINVAL);
    3320             :                 }
    3321             :                 /* XXX abort transfer if currently happening? */
    3322           0 :                 uaudio_chan_init(&sc->sc_playchan, AUMODE_PLAY, paltidx, play);
    3323           0 :         }
    3324           0 :         if (setmode & AUMODE_RECORD) {
    3325           0 :                 if (raltidx == -1) {
    3326             :                         DPRINTF(("%s: did not find alt for recording\n",
    3327             :                             __func__));
    3328           0 :                         return (EINVAL);
    3329             :                 }
    3330             :                 /* XXX abort transfer if currently happening? */
    3331           0 :                 uaudio_chan_init(&sc->sc_recchan, AUMODE_RECORD, raltidx, rec);
    3332           0 :         }
    3333             : 
    3334           0 :         if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1)
    3335           0 :                 sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 1;
    3336           0 :         if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1)
    3337           0 :                 sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 1;
    3338             : 
    3339             :         DPRINTF(("%s: use altidx=p%d/r%d, altno=p%d/r%d\n", __func__,
    3340             :                  sc->sc_playchan.altidx, sc->sc_recchan.altidx,
    3341             :                  (sc->sc_playchan.altidx >= 0)
    3342             :                    ?sc->sc_alts[sc->sc_playchan.altidx].idesc->bAlternateSetting
    3343             :                    : -1,
    3344             :                  (sc->sc_recchan.altidx >= 0)
    3345             :                    ? sc->sc_alts[sc->sc_recchan.altidx].idesc->bAlternateSetting
    3346             :                    : -1));
    3347             : 
    3348           0 :         return (0);
    3349           0 : }
    3350             : 
    3351             : usbd_status
    3352           0 : uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed)
    3353             : {
    3354           0 :         usb_device_request_t req;
    3355           0 :         u_int8_t data[3];
    3356             : 
    3357             :         DPRINTFN(5,("%s: endpt=%d speed=%u\n", __func__, endpt, speed));
    3358           0 :         req.bmRequestType = UT_WRITE_CLASS_ENDPOINT;
    3359           0 :         req.bRequest = SET_CUR;
    3360           0 :         USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
    3361           0 :         USETW(req.wIndex, endpt);
    3362           0 :         USETW(req.wLength, 3);
    3363           0 :         data[0] = speed;
    3364           0 :         data[1] = speed >> 8;
    3365           0 :         data[2] = speed >> 16;
    3366             : 
    3367           0 :         return (usbd_do_request(sc->sc_udev, &req, data));
    3368           0 : }
    3369             : 
    3370             : void
    3371           0 : uaudio_set_speed_emu0202(struct chan *ch)
    3372             : {
    3373           0 :         usb_device_request_t req;
    3374           0 :         int rates[6] = { 44100, 48000, 88200, 96000, 176400, 192000 };
    3375             :         int i;
    3376           0 :         u_int8_t data[1];
    3377             : 
    3378           0 :         for (i = 0; i < 6; i++)
    3379           0 :                 if (rates[i] >= ch->sample_rate)
    3380             :                         break;
    3381           0 :         if (i >= 6) {
    3382             :                 DPRINTF(("%s: unhandled rate %d\n", __func__, ch->sample_rate));
    3383             :                 i = 0;
    3384           0 :         }
    3385             : 
    3386           0 :         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
    3387           0 :         req.bRequest = SET_CUR;
    3388           0 :         USETW2(req.wValue, 0x03, 0);
    3389           0 :         USETW2(req.wIndex, 12, ch->sc->sc_ac_iface);
    3390           0 :         USETW(req.wLength, 1);
    3391           0 :         data[0] = i;
    3392             : 
    3393           0 :         usbd_do_request(ch->sc->sc_udev, &req, data);
    3394           0 : }

Generated by: LCOV version 1.13