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