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