xref: /freebsd/sys/dev/sound/usb/uaudio.c (revision 71fe318b852b8dfb3e799cb12ef184750f7f8eac)
1 /*	$NetBSD: uaudio.c,v 1.41 2001/01/23 14:04:13 augustss Exp $	*/
2 /*	$FreeBSD$: */
3 
4 /*
5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Lennart Augustsson (lennart@augustsson.net) at
10  * Carlstedt Research & Technology.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *        This product includes software developed by the NetBSD
23  *        Foundation, Inc. and its contributors.
24  * 4. Neither the name of The NetBSD Foundation nor the names of its
25  *    contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 /*
42  * USB audio specs: http://www.usb.org/developers/data/devclass/audio10.pdf
43  *                  http://www.usb.org/developers/data/devclass/frmts10.pdf
44  *                  http://www.usb.org/developers/data/devclass/termt10.pdf
45  */
46 
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/malloc.h>
51 #if defined(__NetBSD__) || defined(__OpenBSD__)
52 #include <sys/device.h>
53 #include <sys/ioctl.h>
54 #endif
55 #include <sys/tty.h>
56 #include <sys/file.h>
57 #include <sys/reboot.h>		/* for bootverbose */
58 #include <sys/select.h>
59 #include <sys/proc.h>
60 #include <sys/vnode.h>
61 #if defined(__NetBSD__) || defined(__OpenBSD__)
62 #include <sys/device.h>
63 #elif defined(__FreeBSD__)
64 #include <sys/module.h>
65 #include <sys/bus.h>
66 #include <sys/conf.h>
67 #endif
68 #include <sys/poll.h>
69 #include <sys/sysctl.h>
70 
71 #if defined(__NetBSD__) || defined(__OpenBSD__)
72 #include <sys/audioio.h>
73 #include <dev/audio_if.h>
74 #include <dev/mulaw.h>
75 #include <dev/auconv.h>
76 #elif defined(__FreeBSD__)
77 #include <dev/sound/pcm/sound.h>	/* XXXXX */
78 #include <dev/sound/chip.h>
79 #endif
80 
81 #include <dev/usb/usb.h>
82 #include <dev/usb/usbdi.h>
83 #include <dev/usb/usbdi_util.h>
84 #include <dev/usb/usb_quirks.h>
85 
86 #include <dev/sound/usb/uaudioreg.h>
87 #include <dev/sound/usb/uaudio.h>
88 
89 #ifdef USB_DEBUG
90 #define DPRINTF(x)	if (uaudiodebug) logprintf x
91 #define DPRINTFN(n,x)	if (uaudiodebug>(n)) logprintf x
92 int	uaudiodebug = 0;
93 SYSCTL_NODE(_hw_usb, OID_AUTO, uaudio, CTLFLAG_RW, 0, "USB uaudio");
94 SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, debug, CTLFLAG_RW,
95 	   &uaudiodebug, 0, "uaudio debug level");
96 #else
97 #define DPRINTF(x)
98 #define DPRINTFN(n,x)
99 #endif
100 
101 #define UAUDIO_NCHANBUFS 6	/* number of outstanding request */
102 #define UAUDIO_NFRAMES   20	/* ms of sound in each request */
103 
104 
105 #define MIX_MAX_CHAN 8
106 struct mixerctl {
107 	u_int16_t	wValue[MIX_MAX_CHAN]; /* using nchan */
108 	u_int16_t	wIndex;
109 	u_int8_t	nchan;
110 	u_int8_t	type;
111 #define MIX_ON_OFF	1
112 #define MIX_SIGNED_16	2
113 #define MIX_UNSIGNED_16	3
114 #define MIX_SIGNED_8	4
115 #define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1)
116 #define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16)
117 	int		minval, maxval;
118 	u_int		delta;
119 	u_int		mul;
120 #if defined(__FreeBSD__) /* XXXXX */
121 	unsigned	ctl;
122 #else
123 	u_int8_t	class;
124 	char		ctlname[MAX_AUDIO_DEV_LEN];
125 	char		*ctlunit;
126 #endif
127 };
128 #define MAKE(h,l) (((h) << 8) | (l))
129 
130 struct as_info {
131 	u_int8_t	alt;
132 	u_int8_t	encoding;
133 	usbd_interface_handle	ifaceh;
134 	usb_interface_descriptor_t *idesc;
135 	usb_endpoint_descriptor_audio_t *edesc;
136 	struct usb_audio_streaming_type1_descriptor *asf1desc;
137 };
138 
139 struct chan {
140 	int	terminal;	/* terminal id */
141 #if defined(__NetBSD__) || defined(__OpenBSD__)
142 	void	(*intr)(void *);	/* dma completion intr handler */
143 	void	*arg;		/* arg for intr() */
144 #else
145 	struct pcm_channel *pcm_ch;
146 #endif
147 	usbd_pipe_handle pipe;
148 	int	dir;		/* direction */
149 
150 	u_int	sample_size;
151 	u_int	sample_rate;
152 	u_int	bytes_per_frame;
153 	u_int	fraction;	/* fraction/1000 is the extra samples/frame */
154 	u_int	residue;	/* accumulates the fractional samples */
155 
156 	u_char	*start;		/* upper layer buffer start */
157 	u_char	*end;		/* upper layer buffer end */
158 	u_char	*cur;		/* current position in upper layer buffer */
159 	int	blksize;	/* chunk size to report up */
160 	int	transferred;	/* transferred bytes not reported up */
161 
162 	char	nofrac;		/* don't do sample rate adjustment */
163 
164 	int	curchanbuf;
165 	struct chanbuf {
166 		struct chan         *chan;
167 		usbd_xfer_handle xfer;
168 		u_char              *buffer;
169 		u_int16_t           sizes[UAUDIO_NFRAMES];
170 		u_int16_t	    size;
171 	} chanbufs[UAUDIO_NCHANBUFS];
172 
173 	struct uaudio_softc *sc; /* our softc */
174 #if defined(__FreeBSD__)
175 	u_int32_t format;
176 	int	precision;
177 	int	channels;
178 #endif
179 };
180 
181 struct uaudio_softc {
182 	USBBASEDEVICE sc_dev;		/* base device */
183 	usbd_device_handle sc_udev;	/* USB device */
184 
185 	char	sc_dead;	/* The device is dead -- kill it */
186 
187 	int	sc_ac_iface;	/* Audio Control interface */
188 	usbd_interface_handle	sc_ac_ifaceh;
189 
190 	struct chan sc_chan;
191 
192 	int	sc_curaltidx;
193 
194 	int	sc_nullalt;
195 
196 	int	sc_audio_rev;
197 
198 	struct as_info *sc_alts;
199 	int	sc_nalts;
200 	int	sc_props;
201 
202 	int	sc_altflags;
203 #define HAS_8     0x01
204 #define HAS_16    0x02
205 #define HAS_8U    0x04
206 #define HAS_ALAW  0x08
207 #define HAS_MULAW 0x10
208 
209 	struct mixerctl *sc_ctls;
210 	int	sc_nctls;
211 
212 	device_ptr_t sc_audiodev;
213 	char	sc_dying;
214 };
215 
216 #define UAC_OUTPUT 0
217 #define UAC_INPUT  1
218 #define UAC_EQUAL  2
219 
220 Static usbd_status	uaudio_identify_ac(struct uaudio_softc *sc,
221 					   usb_config_descriptor_t *cdesc);
222 Static usbd_status	uaudio_identify_as(struct uaudio_softc *sc,
223 					   usb_config_descriptor_t *cdesc);
224 Static usbd_status	uaudio_process_as(struct uaudio_softc *sc,
225 			    char *buf, int *offsp, int size,
226 			    usb_interface_descriptor_t *id);
227 
228 Static void 		uaudio_add_alt(struct uaudio_softc *sc,
229 				       struct as_info *ai);
230 
231 Static usb_interface_descriptor_t *uaudio_find_iface(char *buf,
232 			    int size, int *offsp, int subtype);
233 
234 Static void		uaudio_mixer_add_ctl(struct uaudio_softc *sc,
235 					     struct mixerctl *mp);
236 
237 #if defined(__NetBSD__) || defined(__OpenBSD__)
238 Static char 		*uaudio_id_name(struct uaudio_softc *sc,
239 					usb_descriptor_t **dps, int id);
240 #endif
241 
242 Static struct usb_audio_cluster uaudio_get_cluster(int id,
243 						   usb_descriptor_t **dps);
244 Static void		uaudio_add_input(struct uaudio_softc *sc,
245 			    usb_descriptor_t *v, usb_descriptor_t **dps);
246 Static void 		uaudio_add_output(struct uaudio_softc *sc,
247 			    usb_descriptor_t *v, usb_descriptor_t **dps);
248 Static void		uaudio_add_mixer(struct uaudio_softc *sc,
249 			    usb_descriptor_t *v, usb_descriptor_t **dps);
250 Static void		uaudio_add_selector(struct uaudio_softc *sc,
251 			    usb_descriptor_t *v, usb_descriptor_t **dps);
252 Static void		uaudio_add_feature(struct uaudio_softc *sc,
253 			    usb_descriptor_t *v, usb_descriptor_t **dps);
254 Static void		uaudio_add_processing_updown(struct uaudio_softc *sc,
255 			         usb_descriptor_t *v, usb_descriptor_t **dps);
256 Static void		uaudio_add_processing(struct uaudio_softc *sc,
257 			    usb_descriptor_t *v, usb_descriptor_t **dps);
258 Static void		uaudio_add_extension(struct uaudio_softc *sc,
259 			    usb_descriptor_t *v, usb_descriptor_t **dps);
260 Static usbd_status	uaudio_identify(struct uaudio_softc *sc,
261 			    usb_config_descriptor_t *cdesc);
262 
263 Static int 		uaudio_signext(int type, int val);
264 #if defined(__NetBSD__) || defined(__OpenBSD__)
265 Static int 		uaudio_value2bsd(struct mixerctl *mc, int val);
266 #endif
267 Static int 		uaudio_bsd2value(struct mixerctl *mc, int val);
268 Static int 		uaudio_get(struct uaudio_softc *sc, int type,
269 			    int which, int wValue, int wIndex, int len);
270 #if defined(__NetBSD__) || defined(__OpenBSD__)
271 Static int		uaudio_ctl_get(struct uaudio_softc *sc, int which,
272 			    struct mixerctl *mc, int chan);
273 #endif
274 Static void		uaudio_set(struct uaudio_softc *sc, int type,
275 			    int which, int wValue, int wIndex, int l, int v);
276 Static void 		uaudio_ctl_set(struct uaudio_softc *sc, int which,
277 			    struct mixerctl *mc, int chan, int val);
278 
279 Static usbd_status	uaudio_set_speed(struct uaudio_softc *, int, u_int);
280 
281 Static usbd_status	uaudio_chan_open(struct uaudio_softc *sc,
282 					 struct chan *ch);
283 Static void		uaudio_chan_close(struct uaudio_softc *sc,
284 					  struct chan *ch);
285 Static usbd_status	uaudio_chan_alloc_buffers(struct uaudio_softc *,
286 						  struct chan *);
287 Static void		uaudio_chan_free_buffers(struct uaudio_softc *,
288 						 struct chan *);
289 
290 #if defined(__NetBSD__) || defined(__OpenBSD__)
291 Static void		uaudio_chan_set_param(struct chan *ch,
292 			    struct audio_params *param, u_char *start,
293 			    u_char *end, int blksize);
294 #endif
295 
296 Static void		uaudio_chan_ptransfer(struct chan *ch);
297 Static void		uaudio_chan_pintr(usbd_xfer_handle xfer,
298 			    usbd_private_handle priv, usbd_status status);
299 
300 Static void		uaudio_chan_rtransfer(struct chan *ch);
301 Static void		uaudio_chan_rintr(usbd_xfer_handle xfer,
302 			    usbd_private_handle priv, usbd_status status);
303 
304 #if defined(__NetBSD__) || defined(__OpenBSD__)
305 Static int		uaudio_open(void *, int);
306 Static void		uaudio_close(void *);
307 Static int		uaudio_drain(void *);
308 Static int		uaudio_query_encoding(void *, struct audio_encoding *);
309 Static int		uaudio_set_params(void *, int, int,
310 			    struct audio_params *, struct audio_params *);
311 Static int		uaudio_round_blocksize(void *, int);
312 Static int		uaudio_trigger_output(void *, void *, void *,
313 					      int, void (*)(void *), void *,
314 					      struct audio_params *);
315 Static int		uaudio_trigger_input (void *, void *, void *,
316 					      int, void (*)(void *), void *,
317 					      struct audio_params *);
318 Static int		uaudio_halt_in_dma(void *);
319 Static int		uaudio_halt_out_dma(void *);
320 Static int		uaudio_getdev(void *, struct audio_device *);
321 Static int		uaudio_mixer_set_port(void *, mixer_ctrl_t *);
322 Static int		uaudio_mixer_get_port(void *, mixer_ctrl_t *);
323 Static int		uaudio_query_devinfo(void *, mixer_devinfo_t *);
324 Static int		uaudio_get_props(void *);
325 
326 Static struct audio_hw_if uaudio_hw_if = {
327 	uaudio_open,
328 	uaudio_close,
329 	uaudio_drain,
330 	uaudio_query_encoding,
331 	uaudio_set_params,
332 	uaudio_round_blocksize,
333 	NULL,
334 	NULL,
335 	NULL,
336 	NULL,
337 	NULL,
338 	uaudio_halt_out_dma,
339 	uaudio_halt_in_dma,
340 	NULL,
341 	uaudio_getdev,
342 	NULL,
343 	uaudio_mixer_set_port,
344 	uaudio_mixer_get_port,
345 	uaudio_query_devinfo,
346 	NULL,
347 	NULL,
348 	NULL,
349 	NULL,
350 	uaudio_get_props,
351 	uaudio_trigger_output,
352 	uaudio_trigger_input,
353 };
354 
355 Static struct audio_device uaudio_device = {
356 	"USB audio",
357 	"",
358 	"uaudio"
359 };
360 
361 #elif defined(__FreeBSD__)
362 Static int	audio_attach_mi(device_t);
363 Static void	uaudio_init_params(struct uaudio_softc * sc, struct chan *ch);
364 
365 /* for NetBSD compatibirity */
366 #define	AUMODE_PLAY	0x01
367 #define	AUMODE_RECORD	0x02
368 
369 #define	AUDIO_PROP_FULLDUPLEX	0x01
370 
371 #define	AUDIO_ENCODING_ULAW		1
372 #define	AUDIO_ENCODING_ALAW		2
373 #define	AUDIO_ENCODING_SLINEAR_LE	6
374 #define	AUDIO_ENCODING_SLINEAR_BE	7
375 #define	AUDIO_ENCODING_ULINEAR_LE	8
376 #define	AUDIO_ENCODING_ULINEAR_BE	9
377 
378 #endif	/* FreeBSD */
379 
380 
381 #if defined(__NetBSD__) || defined(__OpenBSD__)
382 
383 USB_DECLARE_DRIVER(uaudio);
384 
385 #elif defined(__FreeBSD__)
386 
387 USB_DECLARE_DRIVER_INIT(uaudio,
388 		DEVMETHOD(device_suspend, bus_generic_suspend),
389 		DEVMETHOD(device_resume, bus_generic_resume),
390 		DEVMETHOD(device_shutdown, bus_generic_shutdown),
391 		DEVMETHOD(bus_print_child, bus_generic_print_child)
392 		);
393 #endif
394 
395 
396 USB_MATCH(uaudio)
397 {
398 	USB_MATCH_START(uaudio, uaa);
399 	usb_interface_descriptor_t *id;
400 
401 	if (uaa->iface == NULL)
402 		return (UMATCH_NONE);
403 
404 	id = usbd_get_interface_descriptor(uaa->iface);
405 	/* Trigger on the control interface. */
406 	if (id == NULL ||
407 	    id->bInterfaceClass != UICLASS_AUDIO ||
408 	    id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL ||
409 	    (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
410 		return (UMATCH_NONE);
411 
412 	return (UMATCH_IFACECLASS_IFACESUBCLASS);
413 }
414 
415 USB_ATTACH(uaudio)
416 {
417 	USB_ATTACH_START(uaudio, sc, uaa);
418 	usb_interface_descriptor_t *id;
419 	usb_config_descriptor_t *cdesc;
420 	char devinfo[1024];
421 	usbd_status err;
422 	int i, j, found;
423 
424 	usbd_devinfo(uaa->device, 0, devinfo);
425 	USB_ATTACH_SETUP;
426 
427 #if !defined(__FreeBSD__)
428 	printf(": %s\n", devinfo);
429 #endif
430 
431 	sc->sc_udev = uaa->device;
432 
433 	cdesc = usbd_get_config_descriptor(sc->sc_udev);
434 	if (cdesc == NULL) {
435 		printf("%s: failed to get configuration descriptor\n",
436 		       USBDEVNAME(sc->sc_dev));
437 		USB_ATTACH_ERROR_RETURN;
438 	}
439 
440 	err = uaudio_identify(sc, cdesc);
441 	if (err) {
442 		printf("%s: audio descriptors make no sense, error=%d\n",
443 		       USBDEVNAME(sc->sc_dev), err);
444 		USB_ATTACH_ERROR_RETURN;
445 	}
446 
447 	sc->sc_ac_ifaceh = uaa->iface;
448 	/* Pick up the AS interface. */
449 	for (i = 0; i < uaa->nifaces; i++) {
450 		if (uaa->ifaces[i] == NULL)
451 			continue;
452 		id = usbd_get_interface_descriptor(uaa->ifaces[i]);
453 		if (id == NULL)
454 			continue;
455 		found = 0;
456 		for (j = 0; j < sc->sc_nalts; j++) {
457 			if (id->bInterfaceNumber ==
458 			    sc->sc_alts[j].idesc->bInterfaceNumber) {
459 				sc->sc_alts[j].ifaceh = uaa->ifaces[i];
460 				found = 1;
461 			}
462 		}
463 		if (found)
464 			uaa->ifaces[i] = NULL;
465 	}
466 
467 	for (j = 0; j < sc->sc_nalts; j++) {
468 		if (sc->sc_alts[j].ifaceh == NULL) {
469 			printf("%s: alt %d missing AS interface(s)\n",
470 			    USBDEVNAME(sc->sc_dev), j);
471 			USB_ATTACH_ERROR_RETURN;
472 		}
473 	}
474 
475 	printf("%s: audio rev %d.%02x\n", USBDEVNAME(sc->sc_dev),
476 	       sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
477 
478 	sc->sc_chan.sc = sc;
479 
480 	if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
481 		sc->sc_chan.nofrac = 1;
482 
483 #ifndef USB_DEBUG
484 	if (bootverbose)
485 #endif
486 		printf("%s: %d mixer controls\n", USBDEVNAME(sc->sc_dev),
487 		    sc->sc_nctls);
488 
489 #if !defined(__FreeBSD__)
490 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
491 			   USBDEV(sc->sc_dev));
492 #endif
493 
494 	DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
495 #if defined(__OpenBSD__)
496 	audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
497 #elif defined(__NetBSD__)
498 	sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
499 #elif defined(__FreeBSD__)
500 	sc->sc_dying = 0;
501 	if (audio_attach_mi(sc->sc_dev)) {
502 		printf("audio_attach_mi failed\n");
503 		USB_ATTACH_ERROR_RETURN;
504 	}
505 #endif
506 
507 	USB_ATTACH_SUCCESS_RETURN;
508 }
509 
510 #if defined(__NetBSD__) || defined(__OpenBSD__)
511 int
512 uaudio_activate(device_ptr_t self, enum devact act)
513 {
514 	struct uaudio_softc *sc = (struct uaudio_softc *)self;
515 	int rv = 0;
516 
517 	switch (act) {
518 	case DVACT_ACTIVATE:
519 		return (EOPNOTSUPP);
520 		break;
521 
522 	case DVACT_DEACTIVATE:
523 		if (sc->sc_audiodev != NULL)
524 			rv = config_deactivate(sc->sc_audiodev);
525 		sc->sc_dying = 1;
526 		break;
527 	}
528 	return (rv);
529 }
530 #endif
531 
532 #if defined(__NetBSD__) || defined(__OpenBSD__)
533 int
534 uaudio_detach(device_ptr_t self, int flags)
535 {
536 	struct uaudio_softc *sc = (struct uaudio_softc *)self;
537 	int rv = 0;
538 
539 	/* Wait for outstanding requests to complete. */
540 	usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
541 
542 	if (sc->sc_audiodev != NULL)
543 		rv = config_detach(sc->sc_audiodev, flags);
544 
545 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
546 			   USBDEV(sc->sc_dev));
547 
548 	return (rv);
549 }
550 #elif defined(__FreeBSD__)
551 
552 USB_DETACH(uaudio)
553 {
554 	USB_DETACH_START(uaudio, sc);
555 
556 	sc->sc_dying = 1;
557 
558 #if 0 /* XXX */
559 	/* Wait for outstanding requests to complete. */
560 	usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
561 #endif
562 
563 	/* do nothing ? */
564 	return bus_generic_detach(sc->sc_dev);
565 }
566 #endif
567 
568 #if defined(__NetBSD__) || defined(__OpenBSD__)
569 int
570 uaudio_query_encoding(void *addr, struct audio_encoding *fp)
571 {
572 	struct uaudio_softc *sc = addr;
573 	int flags = sc->sc_altflags;
574 	int idx;
575 
576 	if (sc->sc_dying)
577 		return (EIO);
578 
579 	if (sc->sc_nalts == 0 || flags == 0)
580 		return (ENXIO);
581 
582 	idx = fp->index;
583 	switch (idx) {
584 	case 0:
585 		strcpy(fp->name, AudioEulinear);
586 		fp->encoding = AUDIO_ENCODING_ULINEAR;
587 		fp->precision = 8;
588 		fp->flags = flags&HAS_8U ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
589 		return (0);
590 	case 1:
591 		strcpy(fp->name, AudioEmulaw);
592 		fp->encoding = AUDIO_ENCODING_ULAW;
593 		fp->precision = 8;
594 		fp->flags = flags&HAS_MULAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
595 		return (0);
596 	case 2:
597 		strcpy(fp->name, AudioEalaw);
598 		fp->encoding = AUDIO_ENCODING_ALAW;
599 		fp->precision = 8;
600 		fp->flags = flags&HAS_ALAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
601 		return (0);
602 	case 3:
603 		strcpy(fp->name, AudioEslinear);
604 		fp->encoding = AUDIO_ENCODING_SLINEAR;
605 		fp->precision = 8;
606 		fp->flags = flags&HAS_8 ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
607 		return (0);
608         case 4:
609 		strcpy(fp->name, AudioEslinear_le);
610 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
611 		fp->precision = 16;
612 		fp->flags = 0;
613 		return (0);
614 	case 5:
615 		strcpy(fp->name, AudioEulinear_le);
616 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
617 		fp->precision = 16;
618 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
619 		return (0);
620 	case 6:
621 		strcpy(fp->name, AudioEslinear_be);
622 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
623 		fp->precision = 16;
624 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
625 		return (0);
626 	case 7:
627 		strcpy(fp->name, AudioEulinear_be);
628 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
629 		fp->precision = 16;
630 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
631 		return (0);
632 	default:
633 		return (EINVAL);
634 	}
635 }
636 #endif
637 
638 usb_interface_descriptor_t *
639 uaudio_find_iface(char *buf, int size, int *offsp, int subtype)
640 {
641 	usb_interface_descriptor_t *d;
642 
643 	while (*offsp < size) {
644 		d = (void *)(buf + *offsp);
645 		*offsp += d->bLength;
646 		if (d->bDescriptorType == UDESC_INTERFACE &&
647 		    d->bInterfaceClass == UICLASS_AUDIO &&
648 		    d->bInterfaceSubClass == subtype)
649 			return (d);
650 	}
651 	return (NULL);
652 }
653 
654 void
655 uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc)
656 {
657 	int res;
658 	size_t len = sizeof(*mc) * (sc->sc_nctls + 1);
659 	struct mixerctl *nmc = sc->sc_nctls == 0 ?
660 	  malloc(len, M_USBDEV, M_NOWAIT) :
661 	  realloc(sc->sc_ctls, len, M_USBDEV, M_NOWAIT);
662 
663 	if(nmc == NULL){
664 		printf("uaudio_mixer_add_ctl: no memory\n");
665 		return;
666 	}
667 	sc->sc_ctls = nmc;
668 
669 	mc->delta = 0;
670 	if (mc->type != MIX_ON_OFF) {
671 		/* Determine min and max values. */
672 		mc->minval = uaudio_signext(mc->type,
673 			uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
674 				   mc->wValue[0], mc->wIndex,
675 				   MIX_SIZE(mc->type)));
676 		mc->maxval = 1 + uaudio_signext(mc->type,
677 			uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE,
678 				   mc->wValue[0], mc->wIndex,
679 				   MIX_SIZE(mc->type)));
680 		mc->mul = mc->maxval - mc->minval;
681 		if (mc->mul == 0)
682 			mc->mul = 1;
683 		res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
684 				 mc->wValue[0], mc->wIndex,
685 				 MIX_SIZE(mc->type));
686 		if (res > 0)
687 			mc->delta = (res * 256 + mc->mul/2) / mc->mul;
688 	} else {
689 		mc->minval = 0;
690 		mc->maxval = 1;
691 	}
692 
693 	sc->sc_ctls[sc->sc_nctls++] = *mc;
694 
695 #ifdef USB_DEBUG
696 	if (uaudiodebug > 2) {
697 		int i;
698 		DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc->wValue[0]));
699 		for (i = 1; i < mc->nchan; i++)
700 			DPRINTF((",%04x", mc->wValue[i]));
701 #if defined(__FreeBSD__)
702 		DPRINTF((" wIndex=%04x type=%d ctl='%d' "
703 			 "min=%d max=%d\n",
704 			 mc->wIndex, mc->type, mc->ctl,
705 			 mc->minval, mc->maxval));
706 #else
707 		DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' "
708 			 "min=%d max=%d\n",
709 			 mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
710 			 mc->minval, mc->maxval));
711 #endif
712 	}
713 #endif
714 }
715 
716 #if defined(__NetBSD__) || defined(__OpenBSD__)
717 char *
718 uaudio_id_name(struct uaudio_softc *sc, usb_descriptor_t **dps, int id)
719 {
720 	static char buf[32];
721 	sprintf(buf, "i%d", id);
722 	return (buf);
723 }
724 #endif
725 
726 struct usb_audio_cluster
727 uaudio_get_cluster(int id, usb_descriptor_t **dps)
728 {
729 	struct usb_audio_cluster r;
730 	usb_descriptor_t *dp;
731 	int i;
732 
733 	for (i = 0; i < 25; i++) { /* avoid infinite loops */
734 		dp = dps[id];
735 		if (dp == 0)
736 			goto bad;
737 		switch (dp->bDescriptorSubtype) {
738 		case UDESCSUB_AC_INPUT:
739 #define p ((struct usb_audio_input_terminal *)dp)
740 			r.bNrChannels = p->bNrChannels;
741 			USETW(r.wChannelConfig, UGETW(p->wChannelConfig));
742 			r.iChannelNames = p->iChannelNames;
743 #undef p
744 			return (r);
745 		case UDESCSUB_AC_OUTPUT:
746 #define p ((struct usb_audio_output_terminal *)dp)
747 			id = p->bSourceId;
748 #undef p
749 			break;
750 		case UDESCSUB_AC_MIXER:
751 #define p ((struct usb_audio_mixer_unit *)dp)
752 			r = *(struct usb_audio_cluster *)
753 				&p->baSourceId[p->bNrInPins];
754 #undef p
755 			return (r);
756 		case UDESCSUB_AC_SELECTOR:
757 			/* XXX This is not really right */
758 #define p ((struct usb_audio_selector_unit *)dp)
759 			id = p->baSourceId[0];
760 #undef p
761 			break;
762 		case UDESCSUB_AC_FEATURE:
763 #define p ((struct usb_audio_feature_unit *)dp)
764 			id = p->bSourceId;
765 #undef p
766 			break;
767 		case UDESCSUB_AC_PROCESSING:
768 #define p ((struct usb_audio_processing_unit *)dp)
769 			r = *(struct usb_audio_cluster *)
770 				&p->baSourceId[p->bNrInPins];
771 #undef p
772 			return (r);
773 		case UDESCSUB_AC_EXTENSION:
774 #define p ((struct usb_audio_extension_unit *)dp)
775 			r = *(struct usb_audio_cluster *)
776 				&p->baSourceId[p->bNrInPins];
777 #undef p
778 			return (r);
779 		default:
780 			goto bad;
781 		}
782 	}
783  bad:
784 	printf("uaudio_get_cluster: bad data\n");
785 	memset(&r, 0, sizeof r);
786 	return (r);
787 
788 }
789 
790 void
791 uaudio_add_input(struct uaudio_softc *sc, usb_descriptor_t *v,
792 		 usb_descriptor_t **dps)
793 {
794 #ifdef USB_DEBUG
795 	struct usb_audio_input_terminal *d =
796 		(struct usb_audio_input_terminal *)v;
797 
798 	DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x "
799 		    "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
800 		    "iChannelNames=%d iTerminal=%d\n",
801 		    d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
802 		    d->bNrChannels, UGETW(d->wChannelConfig),
803 		    d->iChannelNames, d->iTerminal));
804 #endif
805 }
806 
807 void
808 uaudio_add_output(struct uaudio_softc *sc, usb_descriptor_t *v,
809 		  usb_descriptor_t **dps)
810 {
811 #ifdef USB_DEBUG
812 	struct usb_audio_output_terminal *d =
813 		(struct usb_audio_output_terminal *)v;
814 
815 	DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x "
816 		    "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
817 		    d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
818 		    d->bSourceId, d->iTerminal));
819 #endif
820 }
821 
822 void
823 uaudio_add_mixer(struct uaudio_softc *sc, usb_descriptor_t *v,
824 		 usb_descriptor_t **dps)
825 {
826 	struct usb_audio_mixer_unit *d = (struct usb_audio_mixer_unit *)v;
827 	struct usb_audio_mixer_unit_1 *d1;
828 	int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k;
829 	uByte *bm;
830 	struct mixerctl mix;
831 
832 	DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n",
833 		    d->bUnitId, d->bNrInPins));
834 
835 	/* Compute the number of input channels */
836 	ichs = 0;
837 	for (i = 0; i < d->bNrInPins; i++)
838 		ichs += uaudio_get_cluster(d->baSourceId[i], dps).bNrChannels;
839 
840 	/* and the number of output channels */
841 	d1 = (struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins];
842 	ochs = d1->bNrChannels;
843 	DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%d\n", ichs, ochs));
844 
845 	bm = d1->bmControls;
846 	mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
847 #if !defined(__FreeBSD__)
848 	mix.class = -1;
849 #endif
850 	mix.type = MIX_SIGNED_16;
851 #if !defined(__FreeBSD__)	/* XXXXX */
852 	mix.ctlunit = AudioNvolume;
853 #endif
854 
855 #define BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1)
856 	for (p = i = 0; i < d->bNrInPins; i++) {
857 		chs = uaudio_get_cluster(d->baSourceId[i], dps).bNrChannels;
858 		mc = 0;
859 		for (c = 0; c < chs; c++) {
860 			mo = 0;
861 			for (o = 0; o < ochs; o++) {
862 				bno = (p + c) * ochs + o;
863 				if (BIT(bno))
864 					mo++;
865 			}
866 			if (mo == 1)
867 				mc++;
868 		}
869 		if (mc == chs && chs <= MIX_MAX_CHAN) {
870 			k = 0;
871 			for (c = 0; c < chs; c++)
872 				for (o = 0; o < ochs; o++) {
873 					bno = (p + c) * ochs + o;
874 					if (BIT(bno))
875 						mix.wValue[k++] =
876 							MAKE(p+c+1, o+1);
877 				}
878 #if !defined(__FreeBSD__)
879 			sprintf(mix.ctlname, "mix%d-%s", d->bUnitId,
880 				uaudio_id_name(sc, dps, d->baSourceId[i]));
881 #endif
882 			mix.nchan = chs;
883 			uaudio_mixer_add_ctl(sc, &mix);
884 		} else {
885 			/* XXX */
886 		}
887 #undef BIT
888 		p += chs;
889 	}
890 
891 }
892 
893 void
894 uaudio_add_selector(struct uaudio_softc *sc, usb_descriptor_t *v,
895 		    usb_descriptor_t **dps)
896 {
897 #ifdef USB_DEBUG
898 	struct usb_audio_selector_unit *d =
899 		(struct usb_audio_selector_unit *)v;
900 
901 	DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n",
902 		    d->bUnitId, d->bNrInPins));
903 #endif
904 	printf("uaudio_add_selector: NOT IMPLEMENTED\n");
905 }
906 
907 void
908 uaudio_add_feature(struct uaudio_softc *sc, usb_descriptor_t *v,
909 		   usb_descriptor_t **dps)
910 {
911 	struct usb_audio_feature_unit *d = (struct usb_audio_feature_unit *)v;
912 	uByte *ctls = d->bmaControls;
913 	int ctlsize = d->bControlSize;
914 	int nchan = (d->bLength - 7) / ctlsize;
915 #if !defined(__FreeBSD__)
916 	int srcId = d->bSourceId;
917 #endif
918 	u_int fumask, mmask, cmask;
919 	struct mixerctl mix;
920 	int chan, ctl, i, unit;
921 
922 #define GET(i) (ctls[(i)*ctlsize] | \
923 		(ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
924 
925 	mmask = GET(0);
926 	/* Figure out what we can control */
927 	for (cmask = 0, chan = 1; chan < nchan; chan++) {
928 		DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%x\n",
929 			    chan, GET(chan)));
930 		cmask |= GET(chan);
931 	}
932 
933 #if !defined(__FreeBSD__)
934 	DPRINTFN(1,("uaudio_add_feature: bUnitId=%d bSourceId=%d, "
935 		    "%d channels, mmask=0x%04x, cmask=0x%04x\n",
936 		    d->bUnitId, srcId, nchan, mmask, cmask));
937 #endif
938 
939 	if (nchan > MIX_MAX_CHAN)
940 		nchan = MIX_MAX_CHAN;
941 	unit = d->bUnitId;
942 	mix.wIndex = MAKE(unit, sc->sc_ac_iface);
943 	for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) {
944 		fumask = FU_MASK(ctl);
945 		DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04x\n",
946 			    ctl, fumask));
947 		if (mmask & fumask) {
948 			mix.nchan = 1;
949 			mix.wValue[0] = MAKE(ctl, 0);
950 		} else if (cmask & fumask) {
951 			mix.nchan = nchan - 1;
952 			for (i = 1; i < nchan; i++) {
953 				if (GET(i) & fumask)
954 					mix.wValue[i-1] = MAKE(ctl, i);
955 				else
956 					mix.wValue[i-1] = -1;
957 			}
958 		} else {
959 			continue;
960 		}
961 #undef GET
962 
963 #if !defined(__FreeBSD__)
964 		mix.class = -1;	/* XXX */
965 #endif
966 		switch (ctl) {
967 		case MUTE_CONTROL:
968 			mix.type = MIX_ON_OFF;
969 #if defined(__FreeBSD__)
970 			mix.ctl = SOUND_MIXER_NRDEVICES;
971 #else
972 			sprintf(mix.ctlname, "fea%d-%s-%s", unit,
973 				uaudio_id_name(sc, dps, srcId),
974 				AudioNmute);
975 			mix.ctlunit = "";
976 #endif
977 			break;
978 		case VOLUME_CONTROL:
979 			mix.type = MIX_SIGNED_16;
980 #if defined(__FreeBSD__)
981 			/* mix.ctl = SOUND_MIXER_VOLUME; */
982 			mix.ctl = SOUND_MIXER_PCM;
983 #else
984 			sprintf(mix.ctlname, "fea%d-%s-%s", unit,
985 				uaudio_id_name(sc, dps, srcId),
986 				AudioNmaster);
987 			mix.ctlunit = AudioNvolume;
988 #endif
989 			break;
990 		case BASS_CONTROL:
991 			mix.type = MIX_SIGNED_8;
992 #if defined(__FreeBSD__)
993 			mix.ctl = SOUND_MIXER_BASS;
994 #else
995 			sprintf(mix.ctlname, "fea%d-%s-%s", unit,
996 				uaudio_id_name(sc, dps, srcId),
997 				AudioNbass);
998 			mix.ctlunit = AudioNbass;
999 #endif
1000 			break;
1001 		case MID_CONTROL:
1002 			mix.type = MIX_SIGNED_8;
1003 #if defined(__FreeBSD__)
1004 			mix.ctl = SOUND_MIXER_NRDEVICES;	/* XXXXX */
1005 #else
1006 			sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1007 				uaudio_id_name(sc, dps, srcId),
1008 				AudioNmid);
1009 			mix.ctlunit = AudioNmid;
1010 #endif
1011 			break;
1012 		case TREBLE_CONTROL:
1013 			mix.type = MIX_SIGNED_8;
1014 #if defined(__FreeBSD__)
1015 			mix.ctl = SOUND_MIXER_TREBLE;
1016 #else
1017 			sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1018 				uaudio_id_name(sc, dps, srcId),
1019 				AudioNtreble);
1020 			mix.ctlunit = AudioNtreble;
1021 #endif
1022 			break;
1023 		case GRAPHIC_EQUALIZER_CONTROL:
1024 			continue; /* XXX don't add anything */
1025 			break;
1026 		case AGC_CONTROL:
1027 			mix.type = MIX_ON_OFF;
1028 #if defined(__FreeBSD__)
1029 			mix.ctl = SOUND_MIXER_NRDEVICES;	/* XXXXX */
1030 #else
1031 			sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1032 				uaudio_id_name(sc, dps, srcId),
1033 				AudioNagc);
1034 			mix.ctlunit = "";
1035 #endif
1036 			break;
1037 		case DELAY_CONTROL:
1038 			mix.type = MIX_UNSIGNED_16;
1039 #if defined(__FreeBSD__)
1040 			mix.ctl = SOUND_MIXER_NRDEVICES;	/* XXXXX */
1041 #else
1042 			sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1043 				uaudio_id_name(sc, dps, srcId),
1044 				AudioNdelay);
1045 			mix.ctlunit = "4 ms";
1046 #endif
1047 			break;
1048 		case BASS_BOOST_CONTROL:
1049 			mix.type = MIX_ON_OFF;
1050 #if defined(__FreeBSD__)
1051 			mix.ctl = SOUND_MIXER_NRDEVICES;	/* XXXXX */
1052 #else
1053 			sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1054 				uaudio_id_name(sc, dps, srcId),
1055 				AudioNbassboost);
1056 			mix.ctlunit = "";
1057 #endif
1058 			break;
1059 		case LOUDNESS_CONTROL:
1060 			mix.type = MIX_ON_OFF;
1061 #if defined(__FreeBSD__)
1062 			mix.ctl = SOUND_MIXER_LOUD;	/* Is this correct ? */
1063 #else
1064 			sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1065 				uaudio_id_name(sc, dps, srcId),
1066 				AudioNloudness);
1067 			mix.ctlunit = "";
1068 #endif
1069 			break;
1070 		}
1071 		uaudio_mixer_add_ctl(sc, &mix);
1072 	}
1073 }
1074 
1075 void
1076 uaudio_add_processing_updown(struct uaudio_softc *sc, usb_descriptor_t *v,
1077 			     usb_descriptor_t **dps)
1078 {
1079 	struct usb_audio_processing_unit *d =
1080 	    (struct usb_audio_processing_unit *)v;
1081 	struct usb_audio_processing_unit_1 *d1 =
1082 	    (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
1083 	struct usb_audio_processing_unit_updown *ud =
1084 	    (struct usb_audio_processing_unit_updown *)
1085 		&d1->bmControls[d1->bControlSize];
1086 	struct mixerctl mix;
1087 	int i;
1088 
1089 	DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
1090 		    d->bUnitId, ud->bNrModes));
1091 
1092 	if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
1093 		DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
1094 		return;
1095 	}
1096 
1097 	mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1098 	mix.nchan = 1;
1099 	mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
1100 #if !defined(__FreeBSD__)
1101 	mix.class = -1;
1102 #endif
1103 	mix.type = MIX_ON_OFF;	/* XXX */
1104 #if !defined(__FreeBSD__)
1105 	mix.ctlunit = "";
1106 	sprintf(mix.ctlname, "pro%d-mode", d->bUnitId);
1107 #endif
1108 
1109 	for (i = 0; i < ud->bNrModes; i++) {
1110 		DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n",
1111 			    i, UGETW(ud->waModes[i])));
1112 		/* XXX */
1113 	}
1114 	uaudio_mixer_add_ctl(sc, &mix);
1115 }
1116 
1117 void
1118 uaudio_add_processing(struct uaudio_softc *sc, usb_descriptor_t *v,
1119 		      usb_descriptor_t **dps)
1120 {
1121 	struct usb_audio_processing_unit *d =
1122 	    (struct usb_audio_processing_unit *)v;
1123 	struct usb_audio_processing_unit_1 *d1 =
1124 	    (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
1125 	int ptype = UGETW(d->wProcessType);
1126 	struct mixerctl mix;
1127 
1128 	DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
1129 		    "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins));
1130 
1131 	if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
1132 		mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1133 		mix.nchan = 1;
1134 		mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
1135 #if !defined(__FreeBSD__)
1136 		mix.class = -1;
1137 #endif
1138 		mix.type = MIX_ON_OFF;
1139 #if !defined(__FreeBSD__)
1140 		mix.ctlunit = "";
1141 		sprintf(mix.ctlname, "pro%d.%d-enable", d->bUnitId, ptype);
1142 #endif
1143 		uaudio_mixer_add_ctl(sc, &mix);
1144 	}
1145 
1146 	switch(ptype) {
1147 	case UPDOWNMIX_PROCESS:
1148 		uaudio_add_processing_updown(sc, v, dps);
1149 		break;
1150 	case DOLBY_PROLOGIC_PROCESS:
1151 	case P3D_STEREO_EXTENDER_PROCESS:
1152 	case REVERBATION_PROCESS:
1153 	case CHORUS_PROCESS:
1154 	case DYN_RANGE_COMP_PROCESS:
1155 	default:
1156 #ifdef USB_DEBUG
1157 		printf("uaudio_add_processing: unit %d, type=%d not impl.\n",
1158 		       d->bUnitId, ptype);
1159 #endif
1160 		break;
1161 	}
1162 }
1163 
1164 void
1165 uaudio_add_extension(struct uaudio_softc *sc, usb_descriptor_t *v,
1166 		     usb_descriptor_t **dps)
1167 {
1168 	struct usb_audio_extension_unit *d =
1169 	    (struct usb_audio_extension_unit *)v;
1170 	struct usb_audio_extension_unit_1 *d1 =
1171 	    (struct usb_audio_extension_unit_1 *)&d->baSourceId[d->bNrInPins];
1172 	struct mixerctl mix;
1173 
1174 	DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
1175 		    d->bUnitId, d->bNrInPins));
1176 
1177 	if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU)
1178 		return;
1179 
1180 	if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
1181 		mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1182 		mix.nchan = 1;
1183 		mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
1184 #if !defined(__FreeBSD__)
1185 		mix.class = -1;
1186 #endif
1187 		mix.type = MIX_ON_OFF;
1188 #if !defined(__FreeBSD__)
1189 		mix.ctlunit = "";
1190 		sprintf(mix.ctlname, "ext%d-enable", d->bUnitId);
1191 #endif
1192 		uaudio_mixer_add_ctl(sc, &mix);
1193 	}
1194 }
1195 
1196 usbd_status
1197 uaudio_identify(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1198 {
1199 	usbd_status err;
1200 
1201 	err = uaudio_identify_ac(sc, cdesc);
1202 	if (err)
1203 		return (err);
1204 	return (uaudio_identify_as(sc, cdesc));
1205 }
1206 
1207 void
1208 uaudio_add_alt(struct uaudio_softc *sc, struct as_info *ai)
1209 {
1210 	size_t len = sizeof(*ai) * (sc->sc_nalts + 1);
1211 	struct as_info *nai = sc->sc_nalts == 0 ?
1212 	  malloc(len, M_USBDEV, M_NOWAIT) :
1213 	  realloc(sc->sc_alts, len, M_USBDEV, M_NOWAIT);
1214 
1215 	if (nai == NULL) {
1216 		printf("uaudio_add_alt: no memory\n");
1217 		return;
1218 	}
1219 
1220 	sc->sc_alts = nai;
1221 	DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%d\n",
1222 		    ai->alt, ai->encoding));
1223 	sc->sc_alts[sc->sc_nalts++] = *ai;
1224 }
1225 
1226 usbd_status
1227 uaudio_process_as(struct uaudio_softc *sc, char *buf, int *offsp,
1228 		  int size, usb_interface_descriptor_t *id)
1229 #define offs (*offsp)
1230 {
1231 	struct usb_audio_streaming_interface_descriptor *asid;
1232 	struct usb_audio_streaming_type1_descriptor *asf1d;
1233 	usb_endpoint_descriptor_audio_t *ed;
1234 	struct usb_audio_streaming_endpoint_descriptor *sed;
1235 	int format, chan, prec, enc;
1236 	int dir, type;
1237 	struct as_info ai;
1238 
1239 	asid = (void *)(buf + offs);
1240 	if (asid->bDescriptorType != UDESC_CS_INTERFACE ||
1241 	    asid->bDescriptorSubtype != AS_GENERAL)
1242 		return (USBD_INVAL);
1243 	offs += asid->bLength;
1244 	if (offs > size)
1245 		return (USBD_INVAL);
1246 	asf1d = (void *)(buf + offs);
1247 	if (asf1d->bDescriptorType != UDESC_CS_INTERFACE ||
1248 	    asf1d->bDescriptorSubtype != FORMAT_TYPE)
1249 		return (USBD_INVAL);
1250 	offs += asf1d->bLength;
1251 	if (offs > size)
1252 		return (USBD_INVAL);
1253 
1254 	if (asf1d->bFormatType != FORMAT_TYPE_I) {
1255 		printf("%s: ignored setting with type %d format\n",
1256 		       USBDEVNAME(sc->sc_dev), UGETW(asid->wFormatTag));
1257 		return (USBD_NORMAL_COMPLETION);
1258 	}
1259 
1260 	ed = (void *)(buf + offs);
1261 	if (ed->bDescriptorType != UDESC_ENDPOINT)
1262 		return (USBD_INVAL);
1263 	DPRINTF(("uaudio_process_as: endpoint bLength=%d bDescriptorType=%d "
1264 		 "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d "
1265 		 "bInterval=%d bRefresh=%d bSynchAddress=%d\n",
1266 		 ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
1267 		 ed->bmAttributes, UGETW(ed->wMaxPacketSize),
1268 		 ed->bInterval, ed->bRefresh, ed->bSynchAddress));
1269 	offs += ed->bLength;
1270 	if (offs > size)
1271 		return (USBD_INVAL);
1272 	if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
1273 		return (USBD_INVAL);
1274 
1275 	dir = UE_GET_DIR(ed->bEndpointAddress);
1276 	type = UE_GET_ISO_TYPE(ed->bmAttributes);
1277 	if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) &&
1278 	    dir == UE_DIR_IN && type == UE_ISO_ADAPT)
1279 		type = UE_ISO_ASYNC;
1280 
1281 	/* We can't handle endpoints that need a sync pipe yet. */
1282 	if (dir == UE_DIR_IN ? type == UE_ISO_ADAPT : type == UE_ISO_ASYNC) {
1283 		printf("%s: ignored %sput endpoint of type %s\n",
1284 		       USBDEVNAME(sc->sc_dev),
1285 		       dir == UE_DIR_IN ? "in" : "out",
1286 		       dir == UE_DIR_IN ? "adaptive" : "async");
1287 		return (USBD_NORMAL_COMPLETION);
1288 	}
1289 
1290 	sed = (void *)(buf + offs);
1291 	if (sed->bDescriptorType != UDESC_CS_ENDPOINT ||
1292 	    sed->bDescriptorSubtype != AS_GENERAL)
1293 		return (USBD_INVAL);
1294 	offs += sed->bLength;
1295 	if (offs > size)
1296 		return (USBD_INVAL);
1297 
1298 	format = UGETW(asid->wFormatTag);
1299 	chan = asf1d->bNrChannels;
1300 	prec = asf1d->bBitResolution;
1301 	if (prec != 8 && prec != 16) {
1302 #ifdef USB_DEBUG
1303 		printf("%s: ignored setting with precision %d\n",
1304 		       USBDEVNAME(sc->sc_dev), prec);
1305 #endif
1306 		return (USBD_NORMAL_COMPLETION);
1307 	}
1308 	switch (format) {
1309 	case UA_FMT_PCM:
1310 		sc->sc_altflags |= prec == 8 ? HAS_8 : HAS_16;
1311 		enc = AUDIO_ENCODING_SLINEAR_LE;
1312 		break;
1313 	case UA_FMT_PCM8:
1314 		enc = AUDIO_ENCODING_ULINEAR_LE;
1315 		sc->sc_altflags |= HAS_8U;
1316 		break;
1317 	case UA_FMT_ALAW:
1318 		enc = AUDIO_ENCODING_ALAW;
1319 		sc->sc_altflags |= HAS_ALAW;
1320 		break;
1321 	case UA_FMT_MULAW:
1322 		enc = AUDIO_ENCODING_ULAW;
1323 		sc->sc_altflags |= HAS_MULAW;
1324 		break;
1325 	default:
1326 		printf("%s: ignored setting with format %d\n",
1327 		       USBDEVNAME(sc->sc_dev), format);
1328 		return (USBD_NORMAL_COMPLETION);
1329 	}
1330 	DPRINTFN(1,("uaudio_identify: alt=%d enc=%d chan=%d prec=%d\n",
1331 		    id->bAlternateSetting, enc, chan, prec));
1332 	ai.alt = id->bAlternateSetting;
1333 	ai.encoding = enc;
1334 	ai.idesc = id;
1335 	ai.edesc = ed;
1336 	ai.asf1desc = asf1d;
1337 	uaudio_add_alt(sc, &ai);
1338 	sc->sc_chan.terminal = asid->bTerminalLink; /* XXX */
1339 	sc->sc_chan.dir |= dir == UE_DIR_OUT ? AUMODE_PLAY : AUMODE_RECORD;
1340 	return (USBD_NORMAL_COMPLETION);
1341 }
1342 #undef offs
1343 
1344 usbd_status
1345 uaudio_identify_as(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1346 {
1347 	usb_interface_descriptor_t *id;
1348 	usbd_status err;
1349 	char *buf;
1350 	int size, offs;
1351 
1352 	size = UGETW(cdesc->wTotalLength);
1353 	buf = (char *)cdesc;
1354 
1355 	/* Locate the AudioStreaming interface descriptor. */
1356 	offs = 0;
1357 	id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM);
1358 	if (id == NULL)
1359 		return (USBD_INVAL);
1360 
1361 	sc->sc_chan.terminal = -1;
1362 	sc->sc_chan.dir = 0;
1363 
1364 	/* Loop through all the alternate settings. */
1365 	while (offs <= size) {
1366 		DPRINTFN(2, ("uaudio_identify: interface %d\n",
1367 		    id->bInterfaceNumber));
1368 		switch (id->bNumEndpoints) {
1369 		case 0:
1370 			DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n",
1371 				     id->bAlternateSetting));
1372 			sc->sc_nullalt = id->bAlternateSetting;
1373 			break;
1374 		case 1:
1375 			err = uaudio_process_as(sc, buf, &offs, size, id);
1376 			break;
1377 		default:
1378 #ifdef USB_DEBUG
1379 			printf("%s: ignored audio interface with %d "
1380 			       "endpoints\n",
1381 			       USBDEVNAME(sc->sc_dev), id->bNumEndpoints);
1382 #endif
1383 			break;
1384 		}
1385 		id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM);
1386 		if (id == NULL)
1387 			break;
1388 	}
1389 	if (offs > size)
1390 		return (USBD_INVAL);
1391 	DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts));
1392 	if (sc->sc_chan.terminal < 0) {
1393 		printf("%s: no useable endpoint found\n",
1394 		       USBDEVNAME(sc->sc_dev));
1395 		return (USBD_INVAL);
1396 	}
1397 
1398 #ifndef NO_RECORDING
1399 	if (sc->sc_chan.dir == (AUMODE_PLAY | AUMODE_RECORD))
1400 		sc->sc_props |= AUDIO_PROP_FULLDUPLEX;
1401 #endif
1402 	return (USBD_NORMAL_COMPLETION);
1403 }
1404 
1405 usbd_status
1406 uaudio_identify_ac(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1407 {
1408 	usb_interface_descriptor_t *id;
1409 	struct usb_audio_control_descriptor *acdp;
1410 	usb_descriptor_t *dp, *dps[256];
1411 	char *buf, *ibuf, *ibufend;
1412 	int size, offs, aclen, ndps, i;
1413 
1414 	size = UGETW(cdesc->wTotalLength);
1415 	buf = (char *)cdesc;
1416 
1417 	/* Locate the AudioControl interface descriptor. */
1418 	offs = 0;
1419 	id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL);
1420 	if (id == NULL)
1421 		return (USBD_INVAL);
1422 	if (offs + sizeof *acdp > size)
1423 		return (USBD_INVAL);
1424 	sc->sc_ac_iface = id->bInterfaceNumber;
1425 	DPRINTFN(2,("uaudio_identify: AC interface is %d\n", sc->sc_ac_iface));
1426 
1427 	/* A class-specific AC interface header should follow. */
1428 	ibuf = buf + offs;
1429 	acdp = (struct usb_audio_control_descriptor *)ibuf;
1430 	if (acdp->bDescriptorType != UDESC_CS_INTERFACE ||
1431 	    acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)
1432 		return (USBD_INVAL);
1433 	aclen = UGETW(acdp->wTotalLength);
1434 	if (offs + aclen > size)
1435 		return (USBD_INVAL);
1436 
1437 	if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) &&
1438 	     UGETW(acdp->bcdADC) != UAUDIO_VERSION)
1439 		return (USBD_INVAL);
1440 
1441 	sc->sc_audio_rev = UGETW(acdp->bcdADC);
1442 	DPRINTFN(2,("uaudio_identify: found AC header, vers=%03x, len=%d\n",
1443 		 sc->sc_audio_rev, aclen));
1444 
1445 	sc->sc_nullalt = -1;
1446 
1447 	/* Scan through all the AC specific descriptors */
1448 	ibufend = ibuf + aclen;
1449 	dp = (usb_descriptor_t *)ibuf;
1450 	ndps = 0;
1451 	memset(dps, 0, sizeof dps);
1452 	for (;;) {
1453 		ibuf += dp->bLength;
1454 		if (ibuf >= ibufend)
1455 			break;
1456 		dp = (usb_descriptor_t *)ibuf;
1457 		if (ibuf + dp->bLength > ibufend)
1458 			return (USBD_INVAL);
1459 		if (dp->bDescriptorType != UDESC_CS_INTERFACE) {
1460 			printf("uaudio_identify: skip desc type=0x%02x\n",
1461 			       dp->bDescriptorType);
1462 			continue;
1463 		}
1464 		i = ((struct usb_audio_input_terminal *)dp)->bTerminalId;
1465 		dps[i] = dp;
1466 		if (i > ndps)
1467 			ndps = i;
1468 	}
1469 	ndps++;
1470 
1471 	for (i = 0; i < ndps; i++) {
1472 		dp = dps[i];
1473 		if (dp == NULL)
1474 			continue;
1475 		DPRINTF(("uaudio_identify: subtype=%d\n",
1476 			 dp->bDescriptorSubtype));
1477 		switch (dp->bDescriptorSubtype) {
1478 		case UDESCSUB_AC_HEADER:
1479 			printf("uaudio_identify: unexpected AC header\n");
1480 			break;
1481 		case UDESCSUB_AC_INPUT:
1482 			uaudio_add_input(sc, dp, dps);
1483 			break;
1484 		case UDESCSUB_AC_OUTPUT:
1485 			uaudio_add_output(sc, dp, dps);
1486 			break;
1487 		case UDESCSUB_AC_MIXER:
1488 			uaudio_add_mixer(sc, dp, dps);
1489 			break;
1490 		case UDESCSUB_AC_SELECTOR:
1491 			uaudio_add_selector(sc, dp, dps);
1492 			break;
1493 		case UDESCSUB_AC_FEATURE:
1494 			uaudio_add_feature(sc, dp, dps);
1495 			break;
1496 		case UDESCSUB_AC_PROCESSING:
1497 			uaudio_add_processing(sc, dp, dps);
1498 			break;
1499 		case UDESCSUB_AC_EXTENSION:
1500 			uaudio_add_extension(sc, dp, dps);
1501 			break;
1502 		default:
1503 			printf("uaudio_identify: bad AC desc subtype=0x%02x\n",
1504 			       dp->bDescriptorSubtype);
1505 			break;
1506 		}
1507 	}
1508 	return (USBD_NORMAL_COMPLETION);
1509 }
1510 
1511 #if defined(__NetBSD__) || defined(__OpenBSD__)
1512 int
1513 uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi)
1514 {
1515 	struct uaudio_softc *sc = addr;
1516 	struct mixerctl *mc;
1517 	int n, nctls;
1518 
1519 	DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi->index));
1520 	if (sc->sc_dying)
1521 		return (EIO);
1522 
1523 	n = mi->index;
1524 	nctls = sc->sc_nctls;
1525 
1526 	if (n < 0 || n >= nctls) {
1527 		switch (n - nctls) {
1528 		case UAC_OUTPUT:
1529 			mi->type = AUDIO_MIXER_CLASS;
1530 			mi->mixer_class = nctls + UAC_OUTPUT;
1531 			mi->next = mi->prev = AUDIO_MIXER_LAST;
1532 			strcpy(mi->label.name, AudioCoutputs);
1533 			return (0);
1534 		case UAC_INPUT:
1535 			mi->type = AUDIO_MIXER_CLASS;
1536 			mi->mixer_class = nctls + UAC_INPUT;
1537 			mi->next = mi->prev = AUDIO_MIXER_LAST;
1538 			strcpy(mi->label.name, AudioCinputs);
1539 			return (0);
1540 		case UAC_EQUAL:
1541 			mi->type = AUDIO_MIXER_CLASS;
1542 			mi->mixer_class = nctls + UAC_EQUAL;
1543 			mi->next = mi->prev = AUDIO_MIXER_LAST;
1544 			strcpy(mi->label.name, AudioCequalization);
1545 			return (0);
1546 		default:
1547 			return (ENXIO);
1548 		}
1549 	}
1550 	mc = &sc->sc_ctls[n];
1551 	strncpy(mi->label.name, mc->ctlname, MAX_AUDIO_DEV_LEN);
1552 	mi->mixer_class = mc->class;
1553 	mi->next = mi->prev = AUDIO_MIXER_LAST;	/* XXX */
1554 	switch (mc->type) {
1555 	case MIX_ON_OFF:
1556 		mi->type = AUDIO_MIXER_ENUM;
1557 		mi->un.e.num_mem = 2;
1558 		strcpy(mi->un.e.member[0].label.name, AudioNoff);
1559 		mi->un.e.member[0].ord = 0;
1560 		strcpy(mi->un.e.member[1].label.name, AudioNon);
1561 		mi->un.e.member[1].ord = 1;
1562 		break;
1563 	default:
1564 		mi->type = AUDIO_MIXER_VALUE;
1565 		strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN);
1566 		mi->un.v.num_channels = mc->nchan;
1567 		mi->un.v.delta = mc->delta;
1568 		break;
1569 	}
1570 	return (0);
1571 }
1572 
1573 int
1574 uaudio_open(void *addr, int flags)
1575 {
1576 	struct uaudio_softc *sc = addr;
1577 
1578         DPRINTF(("uaudio_open: sc=%p\n", sc));
1579 	if (sc->sc_dying)
1580 		return (EIO);
1581 
1582 	if (sc->sc_chan.terminal < 0)
1583 		return (ENXIO);
1584 
1585 	if ((flags & FREAD) && !(sc->sc_chan.dir & AUMODE_RECORD))
1586 		return (EACCES);
1587 	if ((flags & FWRITE) && !(sc->sc_chan.dir & AUMODE_PLAY))
1588 		return (EACCES);
1589 
1590         sc->sc_chan.intr = 0;
1591 
1592         return (0);
1593 }
1594 
1595 /*
1596  * Close function is called at splaudio().
1597  */
1598 void
1599 uaudio_close(void *addr)
1600 {
1601 	struct uaudio_softc *sc = addr;
1602 
1603 	if (sc->sc_dying)
1604 		return (EIO);
1605 
1606 	DPRINTF(("uaudio_close: sc=%p\n", sc));
1607 	uaudio_halt_in_dma(sc);
1608 	uaudio_halt_out_dma(sc);
1609 
1610 	sc->sc_chan.intr = 0;
1611 }
1612 
1613 int
1614 uaudio_drain(void *addr)
1615 {
1616 	struct uaudio_softc *sc = addr;
1617 
1618 	if (sc->sc_dying)
1619 		return (EIO);
1620 
1621 	usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
1622 
1623 	return (0);
1624 }
1625 
1626 int
1627 uaudio_halt_out_dma(void *addr)
1628 {
1629 	struct uaudio_softc *sc = addr;
1630 
1631 	if (sc->sc_dying)
1632 		return (EIO);
1633 
1634 	DPRINTF(("uaudio_halt_out_dma: enter\n"));
1635 	if (sc->sc_chan.pipe != NULL) {
1636 		uaudio_chan_close(sc, &sc->sc_chan);
1637 		sc->sc_chan.pipe = 0;
1638 		uaudio_chan_free_buffers(sc, &sc->sc_chan);
1639 	}
1640         return (0);
1641 }
1642 
1643 int
1644 uaudio_halt_in_dma(void *addr)
1645 {
1646 	struct uaudio_softc *sc = addr;
1647 
1648 	DPRINTF(("uaudio_halt_in_dma: enter\n"));
1649 	if (sc->sc_chan.pipe != NULL) {
1650 		uaudio_chan_close(sc, &sc->sc_chan);
1651 		sc->sc_chan.pipe = 0;
1652 		uaudio_chan_free_buffers(sc, &sc->sc_chan);
1653 	}
1654         return (0);
1655 }
1656 
1657 int
1658 uaudio_getdev(void *addr, struct audio_device *retp)
1659 {
1660 	struct uaudio_softc *sc = addr;
1661 
1662 	DPRINTF(("uaudio_mixer_getdev:\n"));
1663 	if (sc->sc_dying)
1664 		return (EIO);
1665 
1666 	*retp = uaudio_device;
1667         return (0);
1668 }
1669 
1670 /*
1671  * Make sure the block size is large enough to hold all outstanding transfers.
1672  */
1673 int
1674 uaudio_round_blocksize(void *addr, int blk)
1675 {
1676 	struct uaudio_softc *sc = addr;
1677 	int bpf;
1678 
1679 	if (sc->sc_dying)
1680 		return (EIO);
1681 
1682 	bpf = sc->sc_chan.bytes_per_frame + sc->sc_chan.sample_size;
1683 	/* XXX */
1684 	bpf *= UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
1685 
1686 	bpf = (bpf + 15) &~ 15;
1687 
1688 	if (blk < bpf)
1689 		blk = bpf;
1690 
1691 #ifdef DIAGNOSTIC
1692 	if (blk <= 0) {
1693 		printf("uaudio_round_blocksize: blk=%d\n", blk);
1694 		blk = 512;
1695 	}
1696 #endif
1697 
1698 	DPRINTFN(1,("uaudio_round_blocksize: blk=%d\n", blk));
1699 	return (blk);
1700 }
1701 
1702 int
1703 uaudio_get_props(void *addr)
1704 {
1705 	struct uaudio_softc *sc = addr;
1706 
1707 	return (sc->sc_props);
1708 }
1709 #endif	/* NetBSD or OpenBSD */
1710 
1711 
1712 int
1713 uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue,
1714 	   int wIndex, int len)
1715 {
1716 	usb_device_request_t req;
1717 	u_int8_t data[4];
1718 	usbd_status err;
1719 	int val;
1720 
1721 	if (sc->sc_dying)
1722 		return (EIO);
1723 
1724 	if (wValue == -1)
1725 		return (0);
1726 
1727 	req.bmRequestType = type;
1728 	req.bRequest = which;
1729 	USETW(req.wValue, wValue);
1730 	USETW(req.wIndex, wIndex);
1731 	USETW(req.wLength, len);
1732 	DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
1733 		    "wIndex=0x%04x len=%d\n",
1734 		    type, which, wValue, wIndex, len));
1735 	err = usbd_do_request(sc->sc_udev, &req, &data);
1736 	if (err) {
1737 		DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
1738 		return (-1);
1739 	}
1740 	switch (len) {
1741 	case 1:
1742 		val = data[0];
1743 		break;
1744 	case 2:
1745 		val = data[0] | (data[1] << 8);
1746 		break;
1747 	default:
1748 		DPRINTF(("uaudio_get: bad length=%d\n", len));
1749 		return (-1);
1750 	}
1751 	DPRINTFN(2,("uaudio_get: val=%d\n", val));
1752 	return (val);
1753 }
1754 
1755 void
1756 uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue,
1757 	   int wIndex, int len, int val)
1758 {
1759 	usb_device_request_t req;
1760 	u_int8_t data[4];
1761 	usbd_status err;
1762 
1763 	if (sc->sc_dying)
1764 		return;
1765 
1766 	if (wValue == -1)
1767 		return;
1768 
1769 	req.bmRequestType = type;
1770 	req.bRequest = which;
1771 	USETW(req.wValue, wValue);
1772 	USETW(req.wIndex, wIndex);
1773 	USETW(req.wLength, len);
1774 	switch (len) {
1775 	case 1:
1776 		data[0] = val;
1777 		break;
1778 	case 2:
1779 		data[0] = val;
1780 		data[1] = val >> 8;
1781 		break;
1782 	default:
1783 		return;
1784 	}
1785 	DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
1786 		    "wIndex=0x%04x len=%d, val=%d\n",
1787 		    type, which, wValue, wIndex, len, val & 0xffff));
1788 	err = usbd_do_request(sc->sc_udev, &req, &data);
1789 #ifdef USB_DEBUG
1790 	if (err)
1791 		DPRINTF(("uaudio_set: err=%d\n", err));
1792 #endif
1793 }
1794 
1795 int
1796 uaudio_signext(int type, int val)
1797 {
1798 	if (!MIX_UNSIGNED(type)) {
1799 		if (MIX_SIZE(type) == 2)
1800 			val = (int16_t)val;
1801 		else
1802 			val = (int8_t)val;
1803 	}
1804 	return (val);
1805 }
1806 
1807 #if defined(__NetBSD__) || defined(__OpenBSD__)
1808 int
1809 uaudio_value2bsd(struct mixerctl *mc, int val)
1810 {
1811 	DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ",
1812 		     mc->type, val, mc->minval, mc->maxval));
1813 	if (mc->type == MIX_ON_OFF)
1814 		val = val != 0;
1815 	else
1816 		val = ((uaudio_signext(mc->type, val) - mc->minval) * 256
1817 			+ mc->mul/2) / mc->mul;
1818 	DPRINTFN(5, ("val'=%d\n", val));
1819 	return (val);
1820 }
1821 #endif
1822 
1823 int
1824 uaudio_bsd2value(struct mixerctl *mc, int val)
1825 {
1826 	DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ",
1827 		    mc->type, val, mc->minval, mc->maxval));
1828 	if (mc->type == MIX_ON_OFF)
1829 		val = val != 0;
1830 	else
1831 		val = (val + mc->delta/2) * mc->mul / 256 + mc->minval;
1832 	DPRINTFN(5, ("val'=%d\n", val));
1833 	return (val);
1834 }
1835 
1836 #if defined(__NetBSD__) || defined(__OpenBSD__)
1837 int
1838 uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc,
1839 	       int chan)
1840 {
1841 	int val;
1842 
1843 	DPRINTFN(5,("uaudio_ctl_get: which=%d chan=%d\n", which, chan));
1844 	val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan],
1845 			 mc->wIndex, MIX_SIZE(mc->type));
1846 	return (uaudio_value2bsd(mc, val));
1847 }
1848 #endif
1849 
1850 void
1851 uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc,
1852 	       int chan, int val)
1853 {
1854 	val = uaudio_bsd2value(mc, val);
1855 	uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan],
1856 		   mc->wIndex, MIX_SIZE(mc->type), val);
1857 }
1858 
1859 #if defined(__NetBSD__) || defined(__OpenBSD__)
1860 int
1861 uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1862 {
1863 	struct uaudio_softc *sc = addr;
1864 	struct mixerctl *mc;
1865 	int i, n, vals[MIX_MAX_CHAN], val;
1866 
1867 	DPRINTFN(2,("uaudio_mixer_get_port: index=%d\n", cp->dev));
1868 
1869 	if (sc->sc_dying)
1870 		return (EIO);
1871 
1872 	n = cp->dev;
1873 	if (n < 0 || n >= sc->sc_nctls)
1874 		return (ENXIO);
1875 	mc = &sc->sc_ctls[n];
1876 
1877 	if (mc->type == MIX_ON_OFF) {
1878 		if (cp->type != AUDIO_MIXER_ENUM)
1879 			return (EINVAL);
1880 		cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
1881 	} else {
1882 		if (cp->type != AUDIO_MIXER_VALUE)
1883 			return (EINVAL);
1884 		if (cp->un.value.num_channels != 1 &&
1885 		    cp->un.value.num_channels != mc->nchan)
1886 			return (EINVAL);
1887 		for (i = 0; i < mc->nchan; i++)
1888 			vals[i] = uaudio_ctl_get(sc, GET_CUR, mc, i);
1889 		if (cp->un.value.num_channels == 1 && mc->nchan != 1) {
1890 			for (val = 0, i = 0; i < mc->nchan; i++)
1891 				val += vals[i];
1892 			vals[0] = val / mc->nchan;
1893 		}
1894 		for (i = 0; i < cp->un.value.num_channels; i++)
1895 			cp->un.value.level[i] = vals[i];
1896 	}
1897 
1898 	return (0);
1899 }
1900 
1901 int
1902 uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1903 {
1904 	struct uaudio_softc *sc = addr;
1905 	struct mixerctl *mc;
1906 	int i, n, vals[MIX_MAX_CHAN];
1907 
1908 	DPRINTFN(2,("uaudio_mixer_set_port: index = %d\n", cp->dev));
1909 	if (sc->sc_dying)
1910 		return (EIO);
1911 
1912 	n = cp->dev;
1913 	if (n < 0 || n >= sc->sc_nctls)
1914 		return (ENXIO);
1915 	mc = &sc->sc_ctls[n];
1916 
1917 	if (mc->type == MIX_ON_OFF) {
1918 		if (cp->type != AUDIO_MIXER_ENUM)
1919 			return (EINVAL);
1920 		uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
1921 	} else {
1922 		if (cp->type != AUDIO_MIXER_VALUE)
1923 			return (EINVAL);
1924 		if (cp->un.value.num_channels == 1)
1925 			for (i = 0; i < mc->nchan; i++)
1926 				vals[i] = cp->un.value.level[0];
1927 		else if (cp->un.value.num_channels == mc->nchan)
1928 			for (i = 0; i < mc->nchan; i++)
1929 				vals[i] = cp->un.value.level[i];
1930 		else
1931 			return (EINVAL);
1932 		for (i = 0; i < mc->nchan; i++)
1933 			uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]);
1934 	}
1935 	return (0);
1936 }
1937 
1938 int
1939 uaudio_trigger_input(void *addr, void *start, void *end, int blksize,
1940 		     void (*intr)(void *), void *arg,
1941 		     struct audio_params *param)
1942 {
1943 	struct uaudio_softc *sc = addr;
1944 	struct chan *ch = &sc->sc_chan;
1945 	usbd_status err;
1946 	int i, s;
1947 
1948 	if (sc->sc_dying)
1949 		return (EIO);
1950 
1951 	DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p "
1952 		    "blksize=%d\n", sc, start, end, blksize));
1953 
1954 	uaudio_chan_set_param(ch, param, start, end, blksize);
1955 	DPRINTFN(3,("uaudio_trigger_input: sample_size=%d bytes/frame=%d "
1956 		    "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
1957 		    ch->fraction));
1958 
1959 	err = uaudio_chan_alloc_buffers(sc, ch);
1960 	if (err)
1961 		return (EIO);
1962 
1963 	err = uaudio_chan_open(sc, ch);
1964 	if (err) {
1965 		uaudio_chan_free_buffers(sc, ch);
1966 		return (EIO);
1967 	}
1968 
1969 	sc->sc_chan.intr = intr;
1970 	sc->sc_chan.arg = arg;
1971 
1972 	s = splusb();
1973 	for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
1974 		uaudio_chan_rtransfer(ch);
1975 	splx(s);
1976 
1977         return (0);
1978 }
1979 
1980 int
1981 uaudio_trigger_output(void *addr, void *start, void *end, int blksize,
1982 		      void (*intr)(void *), void *arg,
1983 		      struct audio_params *param)
1984 {
1985 	struct uaudio_softc *sc = addr;
1986 	struct chan *ch = &sc->sc_chan;
1987 	usbd_status err;
1988 	int i, s;
1989 
1990 	if (sc->sc_dying)
1991 		return (EIO);
1992 
1993 	DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p "
1994 		    "blksize=%d\n", sc, start, end, blksize));
1995 
1996 	uaudio_chan_set_param(ch, param, start, end, blksize);
1997 	DPRINTFN(3,("uaudio_trigger_output: sample_size=%d bytes/frame=%d "
1998 		    "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
1999 		    ch->fraction));
2000 
2001 	err = uaudio_chan_alloc_buffers(sc, ch);
2002 	if (err)
2003 		return (EIO);
2004 
2005 	err = uaudio_chan_open(sc, ch);
2006 	if (err) {
2007 		uaudio_chan_free_buffers(sc, ch);
2008 		return (EIO);
2009 	}
2010 
2011 	sc->sc_chan.intr = intr;
2012 	sc->sc_chan.arg = arg;
2013 
2014 	s = splusb();
2015 	for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
2016 		uaudio_chan_ptransfer(ch);
2017 	splx(s);
2018 
2019         return (0);
2020 }
2021 #endif	/* NetBSD or OpenBSD */
2022 
2023 /* Set up a pipe for a channel. */
2024 usbd_status
2025 uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
2026 {
2027 	struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
2028 	int endpt = as->edesc->bEndpointAddress;
2029 	usbd_status err;
2030 
2031 	if (sc->sc_dying)
2032 		return (EIO);
2033 
2034 	DPRINTF(("uaudio_open_chan: endpt=0x%02x, speed=%d, alt=%d\n",
2035 		 endpt, ch->sample_rate, as->alt));
2036 
2037 	/* Set alternate interface corresponding to the mode. */
2038 	err = usbd_set_interface(as->ifaceh, as->alt);
2039 	if (err)
2040 		return (err);
2041 
2042 	/* Some devices do not support this request, so ignore errors. */
2043 #ifdef USB_DEBUG
2044 	err = uaudio_set_speed(sc, endpt, ch->sample_rate);
2045 	if (err)
2046 		DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n",
2047 			 usbd_errstr(err)));
2048 #else
2049 	(void)uaudio_set_speed(sc, endpt, ch->sample_rate);
2050 #endif
2051 
2052 	DPRINTF(("uaudio_open_chan: create pipe to 0x%02x\n", endpt));
2053 	err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
2054 	return (err);
2055 }
2056 
2057 void
2058 uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
2059 {
2060 	struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
2061 
2062 	if (sc->sc_dying)
2063 		return ;
2064 
2065 	if (sc->sc_nullalt >= 0) {
2066 		DPRINTF(("uaudio_close_chan: set null alt=%d\n",
2067 			 sc->sc_nullalt));
2068 		usbd_set_interface(as->ifaceh, sc->sc_nullalt);
2069 	}
2070 	usbd_abort_pipe(ch->pipe);
2071 	usbd_close_pipe(ch->pipe);
2072 }
2073 
2074 usbd_status
2075 uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch)
2076 {
2077 	usbd_xfer_handle xfer;
2078 	void *buf;
2079 	int i, size;
2080 
2081 	size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES;
2082 	for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
2083 		xfer = usbd_alloc_xfer(sc->sc_udev);
2084 		if (xfer == 0)
2085 			goto bad;
2086 		ch->chanbufs[i].xfer = xfer;
2087 		buf = usbd_alloc_buffer(xfer, size);
2088 		if (buf == 0) {
2089 			i++;
2090 			goto bad;
2091 		}
2092 		ch->chanbufs[i].buffer = buf;
2093 		ch->chanbufs[i].chan = ch;
2094 	}
2095 
2096 	return (USBD_NORMAL_COMPLETION);
2097 
2098 bad:
2099 	while (--i >= 0)
2100 		/* implicit buffer free */
2101 		usbd_free_xfer(ch->chanbufs[i].xfer);
2102 	return (USBD_NOMEM);
2103 }
2104 
2105 void
2106 uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch)
2107 {
2108 	int i;
2109 
2110 	for (i = 0; i < UAUDIO_NCHANBUFS; i++)
2111 		usbd_free_xfer(ch->chanbufs[i].xfer);
2112 }
2113 
2114 /* Called at splusb() */
2115 void
2116 uaudio_chan_ptransfer(struct chan *ch)
2117 {
2118 	struct chanbuf *cb;
2119 	int i, n, size, residue, total;
2120 
2121 	if (ch->sc->sc_dying)
2122 		return;
2123 
2124 	/* Pick the next channel buffer. */
2125 	cb = &ch->chanbufs[ch->curchanbuf];
2126 	if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
2127 		ch->curchanbuf = 0;
2128 
2129 	/* Compute the size of each frame in the next transfer. */
2130 	residue = ch->residue;
2131 	total = 0;
2132 	for (i = 0; i < UAUDIO_NFRAMES; i++) {
2133 		size = ch->bytes_per_frame;
2134 		residue += ch->fraction;
2135 		if (residue >= USB_FRAMES_PER_SECOND) {
2136 			if (!ch->nofrac)
2137 				size += ch->sample_size;
2138 			residue -= USB_FRAMES_PER_SECOND;
2139 		}
2140 		cb->sizes[i] = size;
2141 		total += size;
2142 	}
2143 	ch->residue = residue;
2144 	cb->size = total;
2145 
2146 	/*
2147 	 * Transfer data from upper layer buffer to channel buffer, taking
2148 	 * care of wrapping the upper layer buffer.
2149 	 */
2150 	n = min(total, ch->end - ch->cur);
2151 	memcpy(cb->buffer, ch->cur, n);
2152 	ch->cur += n;
2153 	if (ch->cur >= ch->end)
2154 		ch->cur = ch->start;
2155 	if (total > n) {
2156 		total -= n;
2157 		memcpy(cb->buffer + n, ch->cur, total);
2158 		ch->cur += total;
2159 	}
2160 
2161 #ifdef USB_DEBUG
2162 	if (uaudiodebug > 8) {
2163 		DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03d\n",
2164 			 cb->buffer, ch->residue));
2165 		for (i = 0; i < UAUDIO_NFRAMES; i++) {
2166 			DPRINTF(("   [%d] length %d\n", i, cb->sizes[i]));
2167 		}
2168 	}
2169 #endif
2170 
2171 	DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer));
2172 	/* Fill the request */
2173 	usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
2174 			     UAUDIO_NFRAMES, USBD_NO_COPY,
2175 			     uaudio_chan_pintr);
2176 
2177 	(void)usbd_transfer(cb->xfer);
2178 }
2179 
2180 void
2181 uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv,
2182 		  usbd_status status)
2183 {
2184 	struct chanbuf *cb = priv;
2185 	struct chan *ch = cb->chan;
2186 	u_int32_t count;
2187 	int s;
2188 
2189 	/* Return if we are aborting. */
2190 	if (status == USBD_CANCELLED)
2191 		return;
2192 
2193 	usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
2194 	DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n",
2195 		    count, ch->transferred));
2196 #ifdef DIAGNOSTIC
2197 	if (count != cb->size) {
2198 		printf("uaudio_chan_pintr: count(%d) != size(%d)\n",
2199 		       count, cb->size);
2200 	}
2201 #endif
2202 
2203 	ch->transferred += cb->size;
2204 #if defined(__FreeBSD__)
2205 	/* s = spltty(); */
2206 	s = splhigh();
2207 	chn_intr(ch->pcm_ch);
2208 	splx(s);
2209 #else
2210 	s = splaudio();
2211 	/* Call back to upper layer */
2212 	while (ch->transferred >= ch->blksize) {
2213 		ch->transferred -= ch->blksize;
2214 		DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)\n",
2215 			    ch->intr, ch->arg));
2216 		ch->intr(ch->arg);
2217 	}
2218 	splx(s);
2219 #endif
2220 
2221 	/* start next transfer */
2222 	uaudio_chan_ptransfer(ch);
2223 }
2224 
2225 /* Called at splusb() */
2226 void
2227 uaudio_chan_rtransfer(struct chan *ch)
2228 {
2229 	struct chanbuf *cb;
2230 	int i, size, residue, total;
2231 
2232 	if (ch->sc->sc_dying)
2233 		return;
2234 
2235 	/* Pick the next channel buffer. */
2236 	cb = &ch->chanbufs[ch->curchanbuf];
2237 	if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
2238 		ch->curchanbuf = 0;
2239 
2240 	/* Compute the size of each frame in the next transfer. */
2241 	residue = ch->residue;
2242 	total = 0;
2243 	for (i = 0; i < UAUDIO_NFRAMES; i++) {
2244 		size = ch->bytes_per_frame;
2245 		residue += ch->fraction;
2246 		if (residue >= USB_FRAMES_PER_SECOND) {
2247 			if (!ch->nofrac)
2248 				size += ch->sample_size;
2249 			residue -= USB_FRAMES_PER_SECOND;
2250 		}
2251 		cb->sizes[i] = size;
2252 		total += size;
2253 	}
2254 	ch->residue = residue;
2255 	cb->size = total;
2256 
2257 #ifdef USB_DEBUG
2258 	if (uaudiodebug > 8) {
2259 		DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03d\n",
2260 			 cb->buffer, ch->residue));
2261 		for (i = 0; i < UAUDIO_NFRAMES; i++) {
2262 			DPRINTF(("   [%d] length %d\n", i, cb->sizes[i]));
2263 		}
2264 	}
2265 #endif
2266 
2267 	DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer));
2268 	/* Fill the request */
2269 	usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
2270 			     UAUDIO_NFRAMES, USBD_NO_COPY,
2271 			     uaudio_chan_rintr);
2272 
2273 	(void)usbd_transfer(cb->xfer);
2274 }
2275 
2276 void
2277 uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv,
2278 		  usbd_status status)
2279 {
2280 	struct chanbuf *cb = priv;
2281 	struct chan *ch = cb->chan;
2282 	u_int32_t count;
2283 	int s, n;
2284 
2285 	/* Return if we are aborting. */
2286 	if (status == USBD_CANCELLED)
2287 		return;
2288 
2289 	usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
2290 	DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n",
2291 		    count, ch->transferred));
2292 
2293 	if (count < cb->size) {
2294 		/* if the device fails to keep up, copy last byte */
2295 		u_char b = count ? cb->buffer[count-1] : 0;
2296 		while (count < cb->size)
2297 			cb->buffer[count++] = b;
2298 	}
2299 
2300 #ifdef DIAGNOSTIC
2301 	if (count != cb->size) {
2302 		printf("uaudio_chan_rintr: count(%d) != size(%d)\n",
2303 		       count, cb->size);
2304 	}
2305 #endif
2306 
2307 	/*
2308 	 * Transfer data from channel buffer to upper layer buffer, taking
2309 	 * care of wrapping the upper layer buffer.
2310 	 */
2311 	n = min(count, ch->end - ch->cur);
2312 	memcpy(ch->cur, cb->buffer, n);
2313 	ch->cur += n;
2314 	if (ch->cur >= ch->end)
2315 		ch->cur = ch->start;
2316 	if (count > n) {
2317 		memcpy(ch->cur, cb->buffer + n, count - n);
2318 		ch->cur += count - n;
2319 	}
2320 
2321 	/* Call back to upper layer */
2322 	ch->transferred += cb->size;
2323 #if defined(__FreeBSD__)
2324 	s = spltty();
2325 	chn_intr(ch->pcm_ch);
2326 	splx(s);
2327 #else
2328 	s = splaudio();
2329 	while (ch->transferred >= ch->blksize) {
2330 		ch->transferred -= ch->blksize;
2331 		DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)\n",
2332 			    ch->intr, ch->arg));
2333 		ch->intr(ch->arg);
2334 	}
2335 	splx(s);
2336 #endif
2337 
2338 	/* start next transfer */
2339 	uaudio_chan_rtransfer(ch);
2340 }
2341 
2342 #if defined(__NetBSD__) || defined(__OpenBSD__)
2343 void
2344 uaudio_chan_set_param(struct chan *ch, struct audio_params *param,
2345 		      u_char *start, u_char *end, int blksize)
2346 {
2347 	int samples_per_frame, sample_size;
2348 
2349 	sample_size = param->precision * param->channels / 8;
2350 	samples_per_frame = param->sample_rate / USB_FRAMES_PER_SECOND;
2351 	ch->fraction = param->sample_rate % USB_FRAMES_PER_SECOND;
2352 	ch->sample_size = sample_size;
2353 	ch->sample_rate = param->sample_rate;
2354 	ch->bytes_per_frame = samples_per_frame * sample_size;
2355 	ch->residue = 0;
2356 
2357 	ch->start = start;
2358 	ch->end = end;
2359 	ch->cur = start;
2360 	ch->blksize = blksize;
2361 	ch->transferred = 0;
2362 
2363 	ch->curchanbuf = 0;
2364 }
2365 
2366 int
2367 uaudio_set_params(void *addr, int setmode, int usemode,
2368 		  struct audio_params *play, struct audio_params *rec)
2369 {
2370 	struct uaudio_softc *sc = addr;
2371 	int flags = sc->sc_altflags;
2372 	int factor;
2373 	int enc, i, j;
2374 	void (*swcode)(void *, u_char *buf, int cnt);
2375 	struct audio_params *p;
2376 	int mode;
2377 
2378 	if (sc->sc_dying)
2379 		return (EIO);
2380 
2381 	if (sc->sc_chan.pipe != NULL)
2382 		return (EBUSY);
2383 
2384 	for (mode = AUMODE_RECORD; mode != -1;
2385 	     mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
2386 		if ((setmode & mode) == 0)
2387 			continue;
2388 		if ((sc->sc_chan.dir & mode) == 0)
2389 			continue;
2390 
2391 		p = mode == AUMODE_PLAY ? play : rec;
2392 
2393 		factor = 1;
2394 		swcode = 0;
2395 		enc = p->encoding;
2396 		switch (enc) {
2397 		case AUDIO_ENCODING_SLINEAR_BE:
2398 			if (p->precision == 16) {
2399 				swcode = swap_bytes;
2400 				enc = AUDIO_ENCODING_SLINEAR_LE;
2401 			} else if (p->precision == 8 && !(flags & HAS_8)) {
2402 				swcode = change_sign8;
2403 				enc = AUDIO_ENCODING_ULINEAR_LE;
2404 			}
2405 			break;
2406 		case AUDIO_ENCODING_SLINEAR_LE:
2407 			if (p->precision == 8 && !(flags & HAS_8)) {
2408 				swcode = change_sign8;
2409 				enc = AUDIO_ENCODING_ULINEAR_LE;
2410 			}
2411 			break;
2412 		case AUDIO_ENCODING_ULINEAR_BE:
2413 			if (p->precision == 16) {
2414 				if (mode == AUMODE_PLAY)
2415 					swcode = swap_bytes_change_sign16_le;
2416 				else
2417 					swcode = change_sign16_swap_bytes_le;
2418 				enc = AUDIO_ENCODING_SLINEAR_LE;
2419 			} else if (p->precision == 8 && !(flags & HAS_8U)) {
2420 				swcode = change_sign8;
2421 				enc = AUDIO_ENCODING_SLINEAR_LE;
2422 			}
2423 			break;
2424 		case AUDIO_ENCODING_ULINEAR_LE:
2425 			if (p->precision == 16) {
2426 				swcode = change_sign16_le;
2427 				enc = AUDIO_ENCODING_SLINEAR_LE;
2428 			} else if (p->precision == 8 && !(flags & HAS_8U)) {
2429 				swcode = change_sign8;
2430 				enc = AUDIO_ENCODING_SLINEAR_LE;
2431 			}
2432 			break;
2433 		case AUDIO_ENCODING_ULAW:
2434 			if (!(flags & HAS_MULAW)) {
2435 				if (mode == AUMODE_PLAY &&
2436 				    (flags & HAS_16)) {
2437 					swcode = mulaw_to_slinear16_le;
2438 					factor = 2;
2439 					enc = AUDIO_ENCODING_SLINEAR_LE;
2440 				} else if (flags & HAS_8U) {
2441 					if (mode == AUMODE_PLAY)
2442 						swcode = mulaw_to_ulinear8;
2443 					else
2444 						swcode = ulinear8_to_mulaw;
2445 					enc = AUDIO_ENCODING_ULINEAR_LE;
2446 				} else if (flags & HAS_8) {
2447 					if (mode == AUMODE_PLAY)
2448 						swcode = mulaw_to_slinear8;
2449 					else
2450 						swcode = slinear8_to_mulaw;
2451 					enc = AUDIO_ENCODING_SLINEAR_LE;
2452 				} else
2453 					return (EINVAL);
2454 			}
2455 			break;
2456 		case AUDIO_ENCODING_ALAW:
2457 			if (!(flags & HAS_ALAW)) {
2458 				if (mode == AUMODE_PLAY &&
2459 				    (flags & HAS_16)) {
2460 					swcode = alaw_to_slinear16_le;
2461 					factor = 2;
2462 					enc = AUDIO_ENCODING_SLINEAR_LE;
2463 				} else if (flags & HAS_8U) {
2464 					if (mode == AUMODE_PLAY)
2465 						swcode = alaw_to_ulinear8;
2466 					else
2467 						swcode = ulinear8_to_alaw;
2468 					enc = AUDIO_ENCODING_ULINEAR_LE;
2469 				} else if (flags & HAS_8) {
2470 					if (mode == AUMODE_PLAY)
2471 						swcode = alaw_to_slinear8;
2472 					else
2473 						swcode = slinear8_to_alaw;
2474 					enc = AUDIO_ENCODING_SLINEAR_LE;
2475 				} else
2476 					return (EINVAL);
2477 			}
2478 			break;
2479 		default:
2480 			return (EINVAL);
2481 		}
2482 		/* XXX do some other conversions... */
2483 
2484 		DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n",
2485 			 p->channels, p->precision, enc, p->sample_rate));
2486 
2487 		for (i = 0; i < sc->sc_nalts; i++) {
2488 			struct usb_audio_streaming_type1_descriptor *a1d =
2489 				sc->sc_alts[i].asf1desc;
2490 			if (p->channels == a1d->bNrChannels &&
2491 			    p->precision == a1d->bBitResolution &&
2492 			    enc == sc->sc_alts[i].encoding &&
2493 			    (mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) ==
2494 			    UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) {
2495 				if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
2496 					DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
2497 					    UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
2498 					if (UA_SAMP_LO(a1d) < p->sample_rate &&
2499 					    p->sample_rate < UA_SAMP_HI(a1d))
2500 						goto found;
2501 				} else {
2502 					for (j = 0; j < a1d->bSamFreqType; j++) {
2503 						DPRINTFN(2,("uaudio_set_params: disc #"
2504 						    "%d: %d\n", j, UA_GETSAMP(a1d, j)));
2505 						/* XXX allow for some slack */
2506 						if (UA_GETSAMP(a1d, j) ==
2507 						    p->sample_rate)
2508 							goto found;
2509 					}
2510 				}
2511 			}
2512 		}
2513 		return (EINVAL);
2514 
2515 	found:
2516 		p->sw_code = swcode;
2517 		p->factor  = factor;
2518 		if (usemode == mode)
2519 			sc->sc_curaltidx = i;
2520 	}
2521 
2522 	DPRINTF(("uaudio_set_params: use altidx=%d, altno=%d\n",
2523 		 sc->sc_curaltidx,
2524 		 sc->sc_alts[sc->sc_curaltidx].idesc->bAlternateSetting));
2525 
2526 	return (0);
2527 }
2528 #endif /* NetBSD or OpenBSD */
2529 
2530 usbd_status
2531 uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed)
2532 {
2533 	usb_device_request_t req;
2534 	u_int8_t data[3];
2535 
2536 	DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%u\n", endpt, speed));
2537 	req.bmRequestType = UT_WRITE_CLASS_ENDPOINT;
2538 	req.bRequest = SET_CUR;
2539 	USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
2540 	USETW(req.wIndex, endpt);
2541 	USETW(req.wLength, 3);
2542 	data[0] = speed;
2543 	data[1] = speed >> 8;
2544 	data[2] = speed >> 16;
2545 
2546 	return (usbd_do_request(sc->sc_udev, &req, &data));
2547 }
2548 
2549 
2550 #if defined(__FreeBSD__)
2551 /************************************************************/
2552 void
2553 uaudio_init_params(struct uaudio_softc *sc, struct chan *ch)
2554 {
2555 	int i, j, enc;
2556 	int samples_per_frame, sample_size;
2557 
2558 	switch(ch->format & 0x0000FFFF) {
2559 	case AFMT_U8:
2560 		enc = AUDIO_ENCODING_ULINEAR_LE;
2561 		ch->precision = 8;
2562 		break;
2563 	case AFMT_S8:
2564 		enc = AUDIO_ENCODING_SLINEAR_LE;
2565 		ch->precision = 8;
2566 		break;
2567 	case AFMT_A_LAW:	/* ? */
2568 		enc = AUDIO_ENCODING_ALAW;
2569 		ch->precision = 8;
2570 		break;
2571 	case AFMT_MU_LAW:	/* ? */
2572 		enc = AUDIO_ENCODING_ULAW;
2573 		ch->precision = 8;
2574 		break;
2575 	case AFMT_S16_LE:
2576 		enc = AUDIO_ENCODING_SLINEAR_LE;
2577 		ch->precision = 16;
2578 		break;
2579 	case AFMT_S16_BE:
2580 		enc = AUDIO_ENCODING_SLINEAR_BE;
2581 		ch->precision = 16;
2582 		break;
2583 	case AFMT_U16_LE:
2584 		enc = AUDIO_ENCODING_ULINEAR_LE;
2585 		ch->precision = 16;
2586 		break;
2587 	case AFMT_U16_BE:
2588 		enc = AUDIO_ENCODING_ULINEAR_BE;
2589 		ch->precision = 16;
2590 		break;
2591 	default:
2592 		enc = 0;
2593 		ch->precision = 16;
2594 		printf("Unknown format %x\n", ch->format);
2595 	}
2596 
2597 	if (ch->format & AFMT_STEREO) {
2598 		ch->channels = 2;
2599 	} else {
2600 		ch->channels = 1;
2601 	}
2602 
2603 /*	for (mode =  ......	 */
2604 		for (i = 0; i < sc->sc_nalts; i++) {
2605 			struct usb_audio_streaming_type1_descriptor *a1d =
2606 				sc->sc_alts[i].asf1desc;
2607 			if (ch->channels == a1d->bNrChannels &&
2608 			    ch->precision == a1d->bBitResolution &&
2609 #if 1
2610 			    enc == sc->sc_alts[i].encoding) {
2611 #else
2612 			    enc == sc->sc_alts[i].encoding &&
2613 			    (mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) ==
2614 			    UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) {
2615 #endif
2616 				if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
2617 					DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
2618 					    UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
2619 					if (UA_SAMP_LO(a1d) < ch->sample_rate &&
2620 					    ch->sample_rate < UA_SAMP_HI(a1d)) {
2621 						sc->sc_curaltidx = i;
2622 						goto found;
2623 					}
2624 				} else {
2625 					for (j = 0; j < a1d->bSamFreqType; j++) {
2626 						DPRINTFN(2,("uaudio_set_params: disc #"
2627 						    "%d: %d\n", j, UA_GETSAMP(a1d, j)));
2628 						/* XXX allow for some slack */
2629 						if (UA_GETSAMP(a1d, j) ==
2630 						    ch->sample_rate) {
2631 							sc->sc_curaltidx = i;
2632 							goto found;
2633 						}
2634 					}
2635 				}
2636 			}
2637 		}
2638 		/* return (EINVAL); */
2639 
2640 	found:
2641 #if 0 /* XXX */
2642 		p->sw_code = swcode;
2643 		p->factor  = factor;
2644 		if (usemode == mode)
2645 			sc->sc_curaltidx = i;
2646 #endif
2647 /*	} */
2648 
2649 	sample_size = ch->precision * ch->channels / 8;
2650 	samples_per_frame = ch->sample_rate / USB_FRAMES_PER_SECOND;
2651 	ch->fraction = ch->sample_rate % USB_FRAMES_PER_SECOND;
2652 	ch->sample_size = sample_size;
2653 	ch->bytes_per_frame = samples_per_frame * sample_size;
2654 	ch->residue = 0;
2655 
2656 	ch->cur = ch->start;
2657 	ch->transferred = 0;
2658 	ch->curchanbuf = 0;
2659 }
2660 
2661 void
2662 uaudio_query_formats(device_t dev, u_int32_t *pfmt, u_int32_t *rfmt)
2663 {
2664 	int i, pn=0, rn=0;
2665 	int prec, dir;
2666 	u_int32_t fmt;
2667 	struct uaudio_softc *sc;
2668 
2669 	struct usb_audio_streaming_type1_descriptor *a1d;
2670 
2671 	sc = device_get_softc(dev);
2672 
2673 	for (i = 0; i < sc->sc_nalts; i++) {
2674 		fmt = 0;
2675 		a1d = sc->sc_alts[i].asf1desc;
2676 		prec = a1d->bBitResolution;	/* precision */
2677 
2678 		switch (sc->sc_alts[i].encoding) {
2679 		case AUDIO_ENCODING_ULINEAR_LE:
2680 			if (prec == 8) {
2681 				fmt = AFMT_U8;
2682 			} else if (prec == 16) {
2683 				fmt = AFMT_U16_LE;
2684 			}
2685 			break;
2686 		case AUDIO_ENCODING_SLINEAR_LE:
2687 			if (prec == 8) {
2688 				fmt = AFMT_S8;
2689 			} else if (prec == 16) {
2690 				fmt = AFMT_S16_LE;
2691 			}
2692 			break;
2693 		case AUDIO_ENCODING_ULINEAR_BE:
2694 			if (prec == 16) {
2695 				fmt = AFMT_U16_BE;
2696 			}
2697 			break;
2698 		case AUDIO_ENCODING_SLINEAR_BE:
2699 			if (prec == 16) {
2700 				fmt = AFMT_S16_BE;
2701 			}
2702 			break;
2703 		case AUDIO_ENCODING_ALAW:
2704 			if (prec == 8) {
2705 				fmt = AFMT_A_LAW;
2706 			}
2707 			break;
2708 		case AUDIO_ENCODING_ULAW:
2709 			if (prec == 8) {
2710 				fmt = AFMT_MU_LAW;
2711 			}
2712 			break;
2713 		}
2714 
2715 		if (fmt != 0) {
2716 			if (a1d->bNrChannels == 2) {	/* stereo/mono */
2717 				fmt |= AFMT_STEREO;
2718 			} else if (a1d->bNrChannels != 1) {
2719 				fmt = 0;
2720 			}
2721 		}
2722 
2723 		if (fmt != 0) {
2724 			dir= UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
2725 			if (dir == UE_DIR_OUT) {
2726 				pfmt[pn++] = fmt;
2727 			} else if (dir == UE_DIR_IN) {
2728 				rfmt[rn++] = fmt;
2729 			}
2730 		}
2731 
2732 		if ((pn > 8*2) || (rn > 8*2))
2733 			break;
2734 	}
2735 	pfmt[pn] = 0;
2736 	rfmt[rn] = 0;
2737 	return;
2738 }
2739 
2740 void
2741 uaudio_chan_set_param_pcm_dma_buff(device_t dev, u_char *start, u_char *end,
2742 		struct pcm_channel *pc)
2743 {
2744 	struct uaudio_softc *sc;
2745 	struct chan *ch;
2746 
2747 	sc = device_get_softc(dev);
2748 	ch = &sc->sc_chan;
2749 
2750 	ch->start = start;
2751 	ch->end = end;
2752 
2753 	ch->pcm_ch = pc;
2754 
2755 	return;
2756 }
2757 
2758 void
2759 uaudio_chan_set_param_blocksize(device_t dev, u_int32_t blocksize)
2760 {
2761 	struct uaudio_softc *sc;
2762 	struct chan *ch;
2763 
2764 	sc = device_get_softc(dev);
2765 	ch = &sc->sc_chan;
2766 
2767 	ch->blksize = blocksize;
2768 
2769 	return;
2770 }
2771 
2772 void
2773 uaudio_chan_set_param_speed(device_t dev, u_int32_t speed)
2774 {
2775 	struct uaudio_softc *sc;
2776 	struct chan *ch;
2777 
2778 	sc = device_get_softc(dev);
2779 	ch = &sc->sc_chan;
2780 
2781 	ch->sample_rate = speed;
2782 
2783 	return;
2784 }
2785 
2786 int
2787 uaudio_chan_getptr(device_t dev)
2788 {
2789 	struct uaudio_softc *sc;
2790 	struct chan *ch;
2791 	int ptr;
2792 
2793 	sc = device_get_softc(dev);
2794 	ch = &sc->sc_chan;
2795 
2796 	ptr = ch->cur - ch->start;
2797 
2798 	return ptr;
2799 }
2800 
2801 void
2802 uaudio_chan_set_param_format(device_t dev, u_int32_t format)
2803 {
2804 	struct uaudio_softc *sc;
2805 	struct chan *ch;
2806 
2807 	sc = device_get_softc(dev);
2808 	ch = &sc->sc_chan;
2809 
2810 	ch->format = format;
2811 
2812 	return;
2813 }
2814 
2815 int
2816 uaudio_halt_out_dma(device_t dev)
2817 {
2818 	struct uaudio_softc *sc;
2819 
2820 	sc = device_get_softc(dev);
2821 
2822 	DPRINTF(("uaudio_halt_out_dma: enter\n"));
2823 	if (sc->sc_chan.pipe != NULL) {
2824 		uaudio_chan_close(sc, &sc->sc_chan);
2825 		sc->sc_chan.pipe = 0;
2826 		uaudio_chan_free_buffers(sc, &sc->sc_chan);
2827 	}
2828         return (0);
2829 }
2830 
2831 int
2832 uaudio_trigger_output(device_t dev)
2833 {
2834 	struct uaudio_softc *sc;
2835 	struct chan *ch;
2836 	usbd_status err;
2837 	int i, s;
2838 
2839 	sc = device_get_softc(dev);
2840 	ch = &sc->sc_chan;
2841 
2842 	if (sc->sc_dying)
2843 		return (EIO);
2844 
2845 	uaudio_init_params(sc, ch);
2846 
2847 	err = uaudio_chan_alloc_buffers(sc, ch);
2848 	if (err)
2849 		return (EIO);
2850 
2851 	err = uaudio_chan_open(sc, ch);
2852 	if (err) {
2853 		uaudio_chan_free_buffers(sc, ch);
2854 		return (EIO);
2855 	}
2856 
2857 	s = splusb();
2858 	for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
2859 		uaudio_chan_ptransfer(ch);
2860 	splx(s);
2861 
2862         return (0);
2863 }
2864 
2865 u_int32_t
2866 uaudio_query_mix_info(device_t dev)
2867 {
2868 	int i;
2869 	u_int32_t mask = 0;
2870 	struct uaudio_softc *sc;
2871 	struct mixerctl *mc;
2872 
2873 	sc = device_get_softc(dev);
2874 	for (i=0; i < sc->sc_nctls; i++) {
2875 		mc = &sc->sc_ctls[i];
2876 		if (mc->ctl != SOUND_MIXER_NRDEVICES) {
2877 			/* Set device mask bits.
2878 			   See /usr/include/machine/soundcard.h */
2879 			mask |= (1 << mc->ctl);
2880 		}
2881 	}
2882 	return mask;
2883 }
2884 
2885 void
2886 uaudio_mixer_set(device_t dev, unsigned type, unsigned left, unsigned right)
2887 {
2888 	int i;
2889 	struct uaudio_softc *sc;
2890 	struct mixerctl *mc;
2891 
2892 	sc = device_get_softc(dev);
2893 	for (i=0; i < sc->sc_nctls; i++) {
2894 		mc = &sc->sc_ctls[i];
2895 		if (mc->ctl == type) {
2896 			if (mc->nchan == 2) {
2897 				/* set Right */
2898 				uaudio_ctl_set(sc, SET_CUR, mc, 1, (int)(right*256)/100);
2899 			}
2900 			/* set Left or Mono */
2901 			uaudio_ctl_set(sc, SET_CUR, mc, 0, (int)(left*256)/100);
2902 		}
2903 	}
2904 	return;
2905 }
2906 
2907 Static int
2908 audio_attach_mi(device_t dev)
2909 {
2910 	device_t child;
2911 	struct sndcard_func *func;
2912 
2913 	/* Attach the children. */
2914 	/* PCM Audio */
2915 	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
2916 	if (func == NULL)
2917 		return (ENOMEM);
2918 	bzero(func, sizeof(*func));
2919 	func->func = SCF_PCM;
2920 	child = device_add_child(dev, "pcm", -1);
2921 	device_set_ivars(child, func);
2922 
2923 	bus_generic_attach(dev);
2924 
2925 	return 0; /* XXXXX */
2926 }
2927 
2928 DRIVER_MODULE(uaudio, uhub, uaudio_driver, uaudio_devclass, usbd_driver_load, 0);
2929 MODULE_VERSION(uaudio, 1);
2930 
2931 #endif
2932