1 /* $NetBSD: uaudio.c,v 1.41 2001/01/23 14:04:13 augustss Exp $ */
2 /* $FreeBSD: src/sys/dev/sound/usb/uaudio.c,v 1.6.2.2 2002/11/06 21:18:17 joe Exp $: */
3 /* $DragonFly: src/sys/dev/sound/usb/uaudio.c,v 1.5 2004/02/12 00:00:19 dillon Exp $: */
6 * Copyright (c) 1999 The NetBSD Foundation, Inc.
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Lennart Augustsson (lennart@augustsson.net) at
11 * Carlstedt Research & Technology.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by the NetBSD
24 * Foundation, Inc. and its contributors.
25 * 4. Neither the name of The NetBSD Foundation nor the names of its
26 * contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
43 * USB audio specs: http://www.usb.org/developers/data/devclass/audio10.pdf
44 * http://www.usb.org/developers/data/devclass/frmts10.pdf
45 * http://www.usb.org/developers/data/devclass/termt10.pdf
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/malloc.h>
52 #if defined(__NetBSD__) || defined(__OpenBSD__)
53 #include <sys/device.h>
54 #include <sys/ioctl.h>
58 #include <sys/reboot.h> /* for bootverbose */
59 #include <sys/select.h>
61 #if defined(__NetBSD__) || defined(__OpenBSD__)
62 #include <sys/device.h>
63 #elif defined(__DragonFly__)
64 #include <sys/module.h>
69 #include <sys/sysctl.h>
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(__DragonFly__)
77 #include <dev/sound/pcm/sound.h> /* XXXXX */
78 #include <dev/sound/chip.h>
81 #include <bus/usb/usb.h>
82 #include <bus/usb/usbdi.h>
83 #include <bus/usb/usbdi_util.h>
84 #include <bus/usb/usb_quirks.h>
86 #include <dev/sound/usb/uaudioreg.h>
87 #include <dev/sound/usb/uaudio.h>
90 #define DPRINTF(x) if (uaudiodebug) logprintf x
91 #define DPRINTFN(n,x) if (uaudiodebug>(n)) logprintf x
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");
101 #define UAUDIO_NCHANBUFS 6 /* number of outstanding request */
102 #define UAUDIO_NFRAMES 20 /* ms of sound in each request */
105 #define MIX_MAX_CHAN 8
107 u_int16_t wValue[MIX_MAX_CHAN]; /* using nchan */
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)
120 #if defined(__DragonFly__) /* XXXXX */
124 char ctlname[MAX_AUDIO_DEV_LEN];
128 #define MAKE(h,l) (((h) << 8) | (l))
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;
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() */
145 struct pcm_channel *pcm_ch;
147 usbd_pipe_handle pipe;
148 int dir; /* direction */
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 */
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 */
162 char nofrac; /* don't do sample rate adjustment */
167 usbd_xfer_handle xfer;
169 u_int16_t sizes[UAUDIO_NFRAMES];
171 } chanbufs[UAUDIO_NCHANBUFS];
173 struct uaudio_softc *sc; /* our softc */
174 #if defined(__DragonFly__)
181 struct uaudio_softc {
182 USBBASEDEVICE sc_dev; /* base device */
183 usbd_device_handle sc_udev; /* USB device */
185 char sc_dead; /* The device is dead -- kill it */
187 int sc_ac_iface; /* Audio Control interface */
188 usbd_interface_handle sc_ac_ifaceh;
198 struct as_info *sc_alts;
206 #define HAS_ALAW 0x08
207 #define HAS_MULAW 0x10
209 struct mixerctl *sc_ctls;
212 device_ptr_t sc_audiodev;
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);
228 Static void uaudio_add_alt(struct uaudio_softc *sc,
231 Static usb_interface_descriptor_t *uaudio_find_iface(char *buf,
232 int size, int *offsp, int subtype);
234 Static void uaudio_mixer_add_ctl(struct uaudio_softc *sc,
235 struct mixerctl *mp);
237 #if defined(__NetBSD__) || defined(__OpenBSD__)
238 Static char *uaudio_id_name(struct uaudio_softc *sc,
239 usb_descriptor_t **dps, int id);
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);
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);
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);
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);
279 Static usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int);
281 Static usbd_status uaudio_chan_open(struct uaudio_softc *sc,
283 Static void uaudio_chan_close(struct uaudio_softc *sc,
285 Static usbd_status uaudio_chan_alloc_buffers(struct uaudio_softc *,
287 Static void uaudio_chan_free_buffers(struct uaudio_softc *,
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);
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);
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);
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 *);
326 Static struct audio_hw_if uaudio_hw_if = {
330 uaudio_query_encoding,
332 uaudio_round_blocksize,
343 uaudio_mixer_set_port,
344 uaudio_mixer_get_port,
345 uaudio_query_devinfo,
351 uaudio_trigger_output,
352 uaudio_trigger_input,
355 Static struct audio_device uaudio_device = {
361 #elif defined(__DragonFly__)
362 Static int audio_attach_mi(device_t);
363 Static void uaudio_init_params(struct uaudio_softc * sc, struct chan *ch);
365 /* for NetBSD compatibirity */
366 #define AUMODE_PLAY 0x01
367 #define AUMODE_RECORD 0x02
369 #define AUDIO_PROP_FULLDUPLEX 0x01
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
381 #if defined(__NetBSD__) || defined(__OpenBSD__)
383 USB_DECLARE_DRIVER(uaudio);
385 #elif defined(__DragonFly__)
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)
398 USB_MATCH_START(uaudio, uaa);
399 usb_interface_descriptor_t *id;
401 if (uaa->iface == NULL)
402 return (UMATCH_NONE);
404 id = usbd_get_interface_descriptor(uaa->iface);
405 /* Trigger on the control interface. */
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);
412 return (UMATCH_IFACECLASS_IFACESUBCLASS);
417 USB_ATTACH_START(uaudio, sc, uaa);
418 usb_interface_descriptor_t *id;
419 usb_config_descriptor_t *cdesc;
424 usbd_devinfo(uaa->device, 0, devinfo);
427 #if !defined(__DragonFly__)
428 printf(": %s\n", devinfo);
431 sc->sc_udev = uaa->device;
433 cdesc = usbd_get_config_descriptor(sc->sc_udev);
435 printf("%s: failed to get configuration descriptor\n",
436 USBDEVNAME(sc->sc_dev));
437 USB_ATTACH_ERROR_RETURN;
440 err = uaudio_identify(sc, cdesc);
442 printf("%s: audio descriptors make no sense, error=%d\n",
443 USBDEVNAME(sc->sc_dev), err);
444 USB_ATTACH_ERROR_RETURN;
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)
452 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
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];
464 uaa->ifaces[i] = NULL;
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;
475 printf("%s: audio rev %d.%02x\n", USBDEVNAME(sc->sc_dev),
476 sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
480 if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
481 sc->sc_chan.nofrac = 1;
486 printf("%s: %d mixer controls\n", USBDEVNAME(sc->sc_dev),
489 #if !defined(__DragonFly__)
490 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
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(__DragonFly__)
501 if (audio_attach_mi(sc->sc_dev)) {
502 printf("audio_attach_mi failed\n");
503 USB_ATTACH_ERROR_RETURN;
507 USB_ATTACH_SUCCESS_RETURN;
510 #if defined(__NetBSD__) || defined(__OpenBSD__)
512 uaudio_activate(device_ptr_t self, enum devact act)
514 struct uaudio_softc *sc = (struct uaudio_softc *)self;
522 case DVACT_DEACTIVATE:
523 if (sc->sc_audiodev != NULL)
524 rv = config_deactivate(sc->sc_audiodev);
532 #if defined(__NetBSD__) || defined(__OpenBSD__)
534 uaudio_detach(device_ptr_t self, int flags)
536 struct uaudio_softc *sc = (struct uaudio_softc *)self;
539 /* Wait for outstanding requests to complete. */
540 usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
542 if (sc->sc_audiodev != NULL)
543 rv = config_detach(sc->sc_audiodev, flags);
545 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
550 #elif defined(__DragonFly__)
554 USB_DETACH_START(uaudio, sc);
559 /* Wait for outstanding requests to complete. */
560 usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
564 return bus_generic_detach(sc->sc_dev);
568 #if defined(__NetBSD__) || defined(__OpenBSD__)
570 uaudio_query_encoding(void *addr, struct audio_encoding *fp)
572 struct uaudio_softc *sc = addr;
573 int flags = sc->sc_altflags;
579 if (sc->sc_nalts == 0 || flags == 0)
585 strcpy(fp->name, AudioEulinear);
586 fp->encoding = AUDIO_ENCODING_ULINEAR;
588 fp->flags = flags&HAS_8U ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
591 strcpy(fp->name, AudioEmulaw);
592 fp->encoding = AUDIO_ENCODING_ULAW;
594 fp->flags = flags&HAS_MULAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
597 strcpy(fp->name, AudioEalaw);
598 fp->encoding = AUDIO_ENCODING_ALAW;
600 fp->flags = flags&HAS_ALAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
603 strcpy(fp->name, AudioEslinear);
604 fp->encoding = AUDIO_ENCODING_SLINEAR;
606 fp->flags = flags&HAS_8 ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
609 strcpy(fp->name, AudioEslinear_le);
610 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
615 strcpy(fp->name, AudioEulinear_le);
616 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
618 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
621 strcpy(fp->name, AudioEslinear_be);
622 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
624 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
627 strcpy(fp->name, AudioEulinear_be);
628 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
630 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
638 usb_interface_descriptor_t *
639 uaudio_find_iface(char *buf, int size, int *offsp, int subtype)
641 usb_interface_descriptor_t *d;
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)
655 uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc)
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);
664 printf("uaudio_mixer_add_ctl: no memory\n");
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;
683 res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
684 mc->wValue[0], mc->wIndex,
687 mc->delta = (res * 256 + mc->mul/2) / mc->mul;
693 sc->sc_ctls[sc->sc_nctls++] = *mc;
696 if (uaudiodebug > 2) {
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(__DragonFly__)
702 DPRINTF((" wIndex=%04x type=%d "
704 mc->wIndex, mc->type,
705 mc->minval, mc->maxval));
707 DPRINTF((" wIndex=%04x type=%d ctl='%d' unit='%s'"
709 mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
710 mc->minval, mc->maxval));
716 #if defined(__NetBSD__) || defined(__OpenBSD__)
718 uaudio_id_name(struct uaudio_softc *sc, usb_descriptor_t **dps, int id)
721 sprintf(buf, "i%d", id);
726 struct usb_audio_cluster
727 uaudio_get_cluster(int id, usb_descriptor_t **dps)
729 struct usb_audio_cluster r;
730 usb_descriptor_t *dp;
733 for (i = 0; i < 25; i++) { /* avoid infinite loops */
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;
745 case UDESCSUB_AC_OUTPUT:
746 #define p ((struct usb_audio_output_terminal *)dp)
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];
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];
762 case UDESCSUB_AC_FEATURE:
763 #define p ((struct usb_audio_feature_unit *)dp)
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];
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];
784 printf("uaudio_get_cluster: bad data\n");
785 memset(&r, 0, sizeof r);
791 uaudio_add_input(struct uaudio_softc *sc, usb_descriptor_t *v,
792 usb_descriptor_t **dps)
795 struct usb_audio_input_terminal *d =
796 (struct usb_audio_input_terminal *)v;
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));
808 uaudio_add_output(struct uaudio_softc *sc, usb_descriptor_t *v,
809 usb_descriptor_t **dps)
812 struct usb_audio_output_terminal *d =
813 (struct usb_audio_output_terminal *)v;
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));
823 uaudio_add_mixer(struct uaudio_softc *sc, usb_descriptor_t *v,
824 usb_descriptor_t **dps)
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;
832 DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n",
833 d->bUnitId, d->bNrInPins));
835 /* Compute the number of input channels */
837 for (i = 0; i < d->bNrInPins; i++)
838 ichs += uaudio_get_cluster(d->baSourceId[i], dps).bNrChannels;
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));
846 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
847 #if !defined(__DragonFly__)
850 mix.type = MIX_SIGNED_16;
851 #if !defined(__DragonFly__) /* XXXXX */
852 mix.ctlunit = AudioNvolume;
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;
859 for (c = 0; c < chs; c++) {
861 for (o = 0; o < ochs; o++) {
862 bno = (p + c) * ochs + o;
869 if (mc == chs && chs <= MIX_MAX_CHAN) {
871 for (c = 0; c < chs; c++)
872 for (o = 0; o < ochs; o++) {
873 bno = (p + c) * ochs + o;
878 #if !defined(__DragonFly__)
879 sprintf(mix.ctlname, "mix%d-%s", d->bUnitId,
880 uaudio_id_name(sc, dps, d->baSourceId[i]));
883 uaudio_mixer_add_ctl(sc, &mix);
894 uaudio_add_selector(struct uaudio_softc *sc, usb_descriptor_t *v,
895 usb_descriptor_t **dps)
898 struct usb_audio_selector_unit *d =
899 (struct usb_audio_selector_unit *)v;
901 DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n",
902 d->bUnitId, d->bNrInPins));
904 printf("uaudio_add_selector: NOT IMPLEMENTED\n");
908 uaudio_add_feature(struct uaudio_softc *sc, usb_descriptor_t *v,
909 usb_descriptor_t **dps)
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(__DragonFly__)
916 int srcId = d->bSourceId;
918 u_int fumask, mmask, cmask;
920 int chan, ctl, i, unit;
922 #define GET(i) (ctls[(i)*ctlsize] | \
923 (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 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",
933 #if !defined(__DragonFly__)
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));
939 if (nchan > MIX_MAX_CHAN)
940 nchan = MIX_MAX_CHAN;
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",
947 if (mmask & fumask) {
949 mix.wValue[0] = MAKE(ctl, 0);
950 } else if (cmask & fumask) {
951 mix.nchan = nchan - 1;
952 for (i = 1; i < nchan; i++) {
954 mix.wValue[i-1] = MAKE(ctl, i);
956 mix.wValue[i-1] = -1;
963 #if !defined(__DragonFly__)
964 mix.class = -1; /* XXX */
968 mix.type = MIX_ON_OFF;
969 #if defined(__DragonFly__)
970 mix.ctl = SOUND_MIXER_NRDEVICES;
972 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
973 uaudio_id_name(sc, dps, srcId),
979 mix.type = MIX_SIGNED_16;
980 #if defined(__DragonFly__)
981 /* mix.ctl = SOUND_MIXER_VOLUME; */
982 mix.ctl = SOUND_MIXER_PCM;
984 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
985 uaudio_id_name(sc, dps, srcId),
987 mix.ctlunit = AudioNvolume;
991 mix.type = MIX_SIGNED_8;
992 #if defined(__DragonFly__)
993 mix.ctl = SOUND_MIXER_BASS;
995 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
996 uaudio_id_name(sc, dps, srcId),
998 mix.ctlunit = AudioNbass;
1002 mix.type = MIX_SIGNED_8;
1003 #if defined(__DragonFly__)
1004 mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
1006 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1007 uaudio_id_name(sc, dps, srcId),
1009 mix.ctlunit = AudioNmid;
1012 case TREBLE_CONTROL:
1013 mix.type = MIX_SIGNED_8;
1014 #if defined(__DragonFly__)
1015 mix.ctl = SOUND_MIXER_TREBLE;
1017 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1018 uaudio_id_name(sc, dps, srcId),
1020 mix.ctlunit = AudioNtreble;
1023 case GRAPHIC_EQUALIZER_CONTROL:
1024 continue; /* XXX don't add anything */
1027 mix.type = MIX_ON_OFF;
1028 #if defined(__DragonFly__)
1029 mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
1031 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1032 uaudio_id_name(sc, dps, srcId),
1038 mix.type = MIX_UNSIGNED_16;
1039 #if defined(__DragonFly__)
1040 mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
1042 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1043 uaudio_id_name(sc, dps, srcId),
1045 mix.ctlunit = "4 ms";
1048 case BASS_BOOST_CONTROL:
1049 mix.type = MIX_ON_OFF;
1050 #if defined(__DragonFly__)
1051 mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
1053 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1054 uaudio_id_name(sc, dps, srcId),
1059 case LOUDNESS_CONTROL:
1060 mix.type = MIX_ON_OFF;
1061 #if defined(__DragonFly__)
1062 mix.ctl = SOUND_MIXER_LOUD; /* Is this correct ? */
1064 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1065 uaudio_id_name(sc, dps, srcId),
1071 uaudio_mixer_add_ctl(sc, &mix);
1076 uaudio_add_processing_updown(struct uaudio_softc *sc, usb_descriptor_t *v,
1077 usb_descriptor_t **dps)
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;
1089 DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
1090 d->bUnitId, ud->bNrModes));
1092 if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
1093 DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
1097 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1099 mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
1100 #if !defined(__DragonFly__)
1103 mix.type = MIX_ON_OFF; /* XXX */
1104 #if !defined(__DragonFly__)
1106 sprintf(mix.ctlname, "pro%d-mode", d->bUnitId);
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])));
1114 uaudio_mixer_add_ctl(sc, &mix);
1118 uaudio_add_processing(struct uaudio_softc *sc, usb_descriptor_t *v,
1119 usb_descriptor_t **dps)
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;
1128 DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
1129 "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins));
1131 if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
1132 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1134 mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
1135 #if !defined(__DragonFly__)
1138 mix.type = MIX_ON_OFF;
1139 #if !defined(__DragonFly__)
1141 sprintf(mix.ctlname, "pro%d.%d-enable", d->bUnitId, ptype);
1143 uaudio_mixer_add_ctl(sc, &mix);
1147 case UPDOWNMIX_PROCESS:
1148 uaudio_add_processing_updown(sc, v, dps);
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:
1157 printf("uaudio_add_processing: unit %d, type=%d not impl.\n",
1165 uaudio_add_extension(struct uaudio_softc *sc, usb_descriptor_t *v,
1166 usb_descriptor_t **dps)
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;
1174 DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
1175 d->bUnitId, d->bNrInPins));
1177 if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU)
1180 if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
1181 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1183 mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
1184 #if !defined(__DragonFly__)
1187 mix.type = MIX_ON_OFF;
1188 #if !defined(__DragonFly__)
1190 sprintf(mix.ctlname, "ext%d-enable", d->bUnitId);
1192 uaudio_mixer_add_ctl(sc, &mix);
1197 uaudio_identify(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1201 err = uaudio_identify_ac(sc, cdesc);
1204 return (uaudio_identify_as(sc, cdesc));
1208 uaudio_add_alt(struct uaudio_softc *sc, struct as_info *ai)
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);
1216 printf("uaudio_add_alt: no memory\n");
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;
1227 uaudio_process_as(struct uaudio_softc *sc, char *buf, int *offsp,
1228 int size, usb_interface_descriptor_t *id)
1229 #define offs (*offsp)
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;
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;
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;
1252 return (USBD_INVAL);
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);
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;
1271 return (USBD_INVAL);
1272 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
1273 return (USBD_INVAL);
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;
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);
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;
1296 return (USBD_INVAL);
1298 format = UGETW(asid->wFormatTag);
1299 chan = asf1d->bNrChannels;
1300 prec = asf1d->bBitResolution;
1301 if (prec != 8 && prec != 16) {
1303 printf("%s: ignored setting with precision %d\n",
1304 USBDEVNAME(sc->sc_dev), prec);
1306 return (USBD_NORMAL_COMPLETION);
1310 sc->sc_altflags |= prec == 8 ? HAS_8 : HAS_16;
1311 enc = AUDIO_ENCODING_SLINEAR_LE;
1314 enc = AUDIO_ENCODING_ULINEAR_LE;
1315 sc->sc_altflags |= HAS_8U;
1318 enc = AUDIO_ENCODING_ALAW;
1319 sc->sc_altflags |= HAS_ALAW;
1322 enc = AUDIO_ENCODING_ULAW;
1323 sc->sc_altflags |= HAS_MULAW;
1326 printf("%s: ignored setting with format %d\n",
1327 USBDEVNAME(sc->sc_dev), format);
1328 return (USBD_NORMAL_COMPLETION);
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;
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);
1345 uaudio_identify_as(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1347 usb_interface_descriptor_t *id;
1352 size = UGETW(cdesc->wTotalLength);
1353 buf = (char *)cdesc;
1355 /* Locate the AudioStreaming interface descriptor. */
1357 id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM);
1359 return (USBD_INVAL);
1361 sc->sc_chan.terminal = -1;
1362 sc->sc_chan.dir = 0;
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) {
1370 DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n",
1371 id->bAlternateSetting));
1372 sc->sc_nullalt = id->bAlternateSetting;
1375 err = uaudio_process_as(sc, buf, &offs, size, id);
1379 printf("%s: ignored audio interface with %d "
1381 USBDEVNAME(sc->sc_dev), id->bNumEndpoints);
1385 id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM);
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);
1398 #ifndef NO_RECORDING
1399 if (sc->sc_chan.dir == (AUMODE_PLAY | AUMODE_RECORD))
1400 sc->sc_props |= AUDIO_PROP_FULLDUPLEX;
1402 return (USBD_NORMAL_COMPLETION);
1406 uaudio_identify_ac(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
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;
1414 size = UGETW(cdesc->wTotalLength);
1415 buf = (char *)cdesc;
1417 /* Locate the AudioControl interface descriptor. */
1419 id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL);
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));
1427 /* A class-specific AC interface header should follow. */
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);
1437 if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) &&
1438 UGETW(acdp->bcdADC) != UAUDIO_VERSION)
1439 return (USBD_INVAL);
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));
1445 sc->sc_nullalt = -1;
1447 /* Scan through all the AC specific descriptors */
1448 ibufend = ibuf + aclen;
1449 dp = (usb_descriptor_t *)ibuf;
1451 memset(dps, 0, sizeof dps);
1453 ibuf += dp->bLength;
1454 if (ibuf >= ibufend)
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);
1464 i = ((struct usb_audio_input_terminal *)dp)->bTerminalId;
1471 for (i = 0; i < ndps; i++) {
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");
1481 case UDESCSUB_AC_INPUT:
1482 uaudio_add_input(sc, dp, dps);
1484 case UDESCSUB_AC_OUTPUT:
1485 uaudio_add_output(sc, dp, dps);
1487 case UDESCSUB_AC_MIXER:
1488 uaudio_add_mixer(sc, dp, dps);
1490 case UDESCSUB_AC_SELECTOR:
1491 uaudio_add_selector(sc, dp, dps);
1493 case UDESCSUB_AC_FEATURE:
1494 uaudio_add_feature(sc, dp, dps);
1496 case UDESCSUB_AC_PROCESSING:
1497 uaudio_add_processing(sc, dp, dps);
1499 case UDESCSUB_AC_EXTENSION:
1500 uaudio_add_extension(sc, dp, dps);
1503 printf("uaudio_identify: bad AC desc subtype=0x%02x\n",
1504 dp->bDescriptorSubtype);
1508 return (USBD_NORMAL_COMPLETION);
1511 #if defined(__NetBSD__) || defined(__OpenBSD__)
1513 uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi)
1515 struct uaudio_softc *sc = addr;
1516 struct mixerctl *mc;
1519 DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi->index));
1524 nctls = sc->sc_nctls;
1526 if (n < 0 || n >= nctls) {
1527 switch (n - nctls) {
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);
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);
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);
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 */
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;
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;
1574 uaudio_open(void *addr, int flags)
1576 struct uaudio_softc *sc = addr;
1578 DPRINTF(("uaudio_open: sc=%p\n", sc));
1582 if (sc->sc_chan.terminal < 0)
1585 if ((flags & FREAD) && !(sc->sc_chan.dir & AUMODE_RECORD))
1587 if ((flags & FWRITE) && !(sc->sc_chan.dir & AUMODE_PLAY))
1590 sc->sc_chan.intr = 0;
1596 * Close function is called at splaudio().
1599 uaudio_close(void *addr)
1601 struct uaudio_softc *sc = addr;
1606 DPRINTF(("uaudio_close: sc=%p\n", sc));
1607 uaudio_halt_in_dma(sc);
1608 uaudio_halt_out_dma(sc);
1610 sc->sc_chan.intr = 0;
1614 uaudio_drain(void *addr)
1616 struct uaudio_softc *sc = addr;
1621 usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
1627 uaudio_halt_out_dma(void *addr)
1629 struct uaudio_softc *sc = addr;
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);
1644 uaudio_halt_in_dma(void *addr)
1646 struct uaudio_softc *sc = addr;
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);
1658 uaudio_getdev(void *addr, struct audio_device *retp)
1660 struct uaudio_softc *sc = addr;
1662 DPRINTF(("uaudio_mixer_getdev:\n"));
1666 *retp = uaudio_device;
1671 * Make sure the block size is large enough to hold all outstanding transfers.
1674 uaudio_round_blocksize(void *addr, int blk)
1676 struct uaudio_softc *sc = addr;
1682 bpf = sc->sc_chan.bytes_per_frame + sc->sc_chan.sample_size;
1684 bpf *= UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
1686 bpf = (bpf + 15) &~ 15;
1693 printf("uaudio_round_blocksize: blk=%d\n", blk);
1698 DPRINTFN(1,("uaudio_round_blocksize: blk=%d\n", blk));
1703 uaudio_get_props(void *addr)
1705 struct uaudio_softc *sc = addr;
1707 return (sc->sc_props);
1709 #endif /* NetBSD or OpenBSD */
1713 uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue,
1714 int wIndex, int len)
1716 usb_device_request_t req;
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);
1737 DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
1745 val = data[0] | (data[1] << 8);
1748 DPRINTF(("uaudio_get: bad length=%d\n", len));
1751 DPRINTFN(2,("uaudio_get: val=%d\n", val));
1756 uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue,
1757 int wIndex, int len, int val)
1759 usb_device_request_t req;
1769 req.bmRequestType = type;
1770 req.bRequest = which;
1771 USETW(req.wValue, wValue);
1772 USETW(req.wIndex, wIndex);
1773 USETW(req.wLength, len);
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);
1791 DPRINTF(("uaudio_set: err=%d\n", err));
1796 uaudio_signext(int type, int val)
1798 if (!MIX_UNSIGNED(type)) {
1799 if (MIX_SIZE(type) == 2)
1807 #if defined(__NetBSD__) || defined(__OpenBSD__)
1809 uaudio_value2bsd(struct mixerctl *mc, int val)
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)
1816 val = ((uaudio_signext(mc->type, val) - mc->minval) * 256
1817 + mc->mul/2) / mc->mul;
1818 DPRINTFN(5, ("val'=%d\n", val));
1824 uaudio_bsd2value(struct mixerctl *mc, int val)
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)
1831 val = (val + mc->delta/2) * mc->mul / 256 + mc->minval;
1832 DPRINTFN(5, ("val'=%d\n", val));
1836 #if defined(__NetBSD__) || defined(__OpenBSD__)
1838 uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc,
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));
1851 uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc,
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);
1859 #if defined(__NetBSD__) || defined(__OpenBSD__)
1861 uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1863 struct uaudio_softc *sc = addr;
1864 struct mixerctl *mc;
1865 int i, n, vals[MIX_MAX_CHAN], val;
1867 DPRINTFN(2,("uaudio_mixer_get_port: index=%d\n", cp->dev));
1873 if (n < 0 || n >= sc->sc_nctls)
1875 mc = &sc->sc_ctls[n];
1877 if (mc->type == MIX_ON_OFF) {
1878 if (cp->type != AUDIO_MIXER_ENUM)
1880 cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
1882 if (cp->type != AUDIO_MIXER_VALUE)
1884 if (cp->un.value.num_channels != 1 &&
1885 cp->un.value.num_channels != mc->nchan)
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++)
1892 vals[0] = val / mc->nchan;
1894 for (i = 0; i < cp->un.value.num_channels; i++)
1895 cp->un.value.level[i] = vals[i];
1902 uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1904 struct uaudio_softc *sc = addr;
1905 struct mixerctl *mc;
1906 int i, n, vals[MIX_MAX_CHAN];
1908 DPRINTFN(2,("uaudio_mixer_set_port: index = %d\n", cp->dev));
1913 if (n < 0 || n >= sc->sc_nctls)
1915 mc = &sc->sc_ctls[n];
1917 if (mc->type == MIX_ON_OFF) {
1918 if (cp->type != AUDIO_MIXER_ENUM)
1920 uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
1922 if (cp->type != AUDIO_MIXER_VALUE)
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];
1932 for (i = 0; i < mc->nchan; i++)
1933 uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]);
1939 uaudio_trigger_input(void *addr, void *start, void *end, int blksize,
1940 void (*intr)(void *), void *arg,
1941 struct audio_params *param)
1943 struct uaudio_softc *sc = addr;
1944 struct chan *ch = &sc->sc_chan;
1951 DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p "
1952 "blksize=%d\n", sc, start, end, blksize));
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,
1959 err = uaudio_chan_alloc_buffers(sc, ch);
1963 err = uaudio_chan_open(sc, ch);
1965 uaudio_chan_free_buffers(sc, ch);
1969 sc->sc_chan.intr = intr;
1970 sc->sc_chan.arg = arg;
1973 for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
1974 uaudio_chan_rtransfer(ch);
1981 uaudio_trigger_output(void *addr, void *start, void *end, int blksize,
1982 void (*intr)(void *), void *arg,
1983 struct audio_params *param)
1985 struct uaudio_softc *sc = addr;
1986 struct chan *ch = &sc->sc_chan;
1993 DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p "
1994 "blksize=%d\n", sc, start, end, blksize));
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,
2001 err = uaudio_chan_alloc_buffers(sc, ch);
2005 err = uaudio_chan_open(sc, ch);
2007 uaudio_chan_free_buffers(sc, ch);
2011 sc->sc_chan.intr = intr;
2012 sc->sc_chan.arg = arg;
2015 for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
2016 uaudio_chan_ptransfer(ch);
2021 #endif /* NetBSD or OpenBSD */
2023 /* Set up a pipe for a channel. */
2025 uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
2027 struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
2028 int endpt = as->edesc->bEndpointAddress;
2034 DPRINTF(("uaudio_open_chan: endpt=0x%02x, speed=%d, alt=%d\n",
2035 endpt, ch->sample_rate, as->alt));
2037 /* Set alternate interface corresponding to the mode. */
2038 err = usbd_set_interface(as->ifaceh, as->alt);
2042 /* Some devices do not support this request, so ignore errors. */
2044 err = uaudio_set_speed(sc, endpt, ch->sample_rate);
2046 DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n",
2049 (void)uaudio_set_speed(sc, endpt, ch->sample_rate);
2052 DPRINTF(("uaudio_open_chan: create pipe to 0x%02x\n", endpt));
2053 err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
2058 uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
2060 struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
2065 if (sc->sc_nullalt >= 0) {
2066 DPRINTF(("uaudio_close_chan: set null alt=%d\n",
2068 usbd_set_interface(as->ifaceh, sc->sc_nullalt);
2070 usbd_abort_pipe(ch->pipe);
2071 usbd_close_pipe(ch->pipe);
2075 uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch)
2077 usbd_xfer_handle xfer;
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);
2086 ch->chanbufs[i].xfer = xfer;
2087 buf = usbd_alloc_buffer(xfer, size);
2092 ch->chanbufs[i].buffer = buf;
2093 ch->chanbufs[i].chan = ch;
2096 return (USBD_NORMAL_COMPLETION);
2100 /* implicit buffer free */
2101 usbd_free_xfer(ch->chanbufs[i].xfer);
2102 return (USBD_NOMEM);
2106 uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch)
2110 for (i = 0; i < UAUDIO_NCHANBUFS; i++)
2111 usbd_free_xfer(ch->chanbufs[i].xfer);
2114 /* Called at splusb() */
2116 uaudio_chan_ptransfer(struct chan *ch)
2119 int i, n, size, residue, total;
2121 if (ch->sc->sc_dying)
2124 /* Pick the next channel buffer. */
2125 cb = &ch->chanbufs[ch->curchanbuf];
2126 if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
2129 /* Compute the size of each frame in the next transfer. */
2130 residue = ch->residue;
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) {
2137 size += ch->sample_size;
2138 residue -= USB_FRAMES_PER_SECOND;
2140 cb->sizes[i] = size;
2143 ch->residue = residue;
2147 * Transfer data from upper layer buffer to channel buffer, taking
2148 * care of wrapping the upper layer buffer.
2150 n = min(total, ch->end - ch->cur);
2151 memcpy(cb->buffer, ch->cur, n);
2153 if (ch->cur >= ch->end)
2154 ch->cur = ch->start;
2157 memcpy(cb->buffer + n, ch->cur, total);
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]));
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,
2177 (void)usbd_transfer(cb->xfer);
2181 uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv,
2184 struct chanbuf *cb = priv;
2185 struct chan *ch = cb->chan;
2189 /* Return if we are aborting. */
2190 if (status == USBD_CANCELLED)
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));
2197 if (count != cb->size) {
2198 printf("uaudio_chan_pintr: count(%d) != size(%d)\n",
2203 ch->transferred += cb->size;
2204 #if defined(__DragonFly__)
2207 chn_intr(ch->pcm_ch);
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));
2221 /* start next transfer */
2222 uaudio_chan_ptransfer(ch);
2225 /* Called at splusb() */
2227 uaudio_chan_rtransfer(struct chan *ch)
2230 int i, size, residue, total;
2232 if (ch->sc->sc_dying)
2235 /* Pick the next channel buffer. */
2236 cb = &ch->chanbufs[ch->curchanbuf];
2237 if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
2240 /* Compute the size of each frame in the next transfer. */
2241 residue = ch->residue;
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) {
2248 size += ch->sample_size;
2249 residue -= USB_FRAMES_PER_SECOND;
2251 cb->sizes[i] = size;
2254 ch->residue = residue;
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]));
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,
2273 (void)usbd_transfer(cb->xfer);
2277 uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv,
2280 struct chanbuf *cb = priv;
2281 struct chan *ch = cb->chan;
2285 /* Return if we are aborting. */
2286 if (status == USBD_CANCELLED)
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));
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;
2301 if (count != cb->size) {
2302 printf("uaudio_chan_rintr: count(%d) != size(%d)\n",
2308 * Transfer data from channel buffer to upper layer buffer, taking
2309 * care of wrapping the upper layer buffer.
2311 n = min(count, ch->end - ch->cur);
2312 memcpy(ch->cur, cb->buffer, n);
2314 if (ch->cur >= ch->end)
2315 ch->cur = ch->start;
2317 memcpy(ch->cur, cb->buffer + n, count - n);
2318 ch->cur += count - n;
2321 /* Call back to upper layer */
2322 ch->transferred += cb->size;
2323 #if defined(__DragonFly__)
2325 chn_intr(ch->pcm_ch);
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));
2338 /* start next transfer */
2339 uaudio_chan_rtransfer(ch);
2342 #if defined(__NetBSD__) || defined(__OpenBSD__)
2344 uaudio_chan_set_param(struct chan *ch, struct audio_params *param,
2345 u_char *start, u_char *end, int blksize)
2347 int samples_per_frame, sample_size;
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;
2360 ch->blksize = blksize;
2361 ch->transferred = 0;
2367 uaudio_set_params(void *addr, int setmode, int usemode,
2368 struct audio_params *play, struct audio_params *rec)
2370 struct uaudio_softc *sc = addr;
2371 int flags = sc->sc_altflags;
2374 void (*swcode)(void *, u_char *buf, int cnt);
2375 struct audio_params *p;
2381 if (sc->sc_chan.pipe != NULL)
2384 for (mode = AUMODE_RECORD; mode != -1;
2385 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
2386 if ((setmode & mode) == 0)
2388 if ((sc->sc_chan.dir & mode) == 0)
2391 p = mode == AUMODE_PLAY ? play : rec;
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;
2406 case AUDIO_ENCODING_SLINEAR_LE:
2407 if (p->precision == 8 && !(flags & HAS_8)) {
2408 swcode = change_sign8;
2409 enc = AUDIO_ENCODING_ULINEAR_LE;
2412 case AUDIO_ENCODING_ULINEAR_BE:
2413 if (p->precision == 16) {
2414 if (mode == AUMODE_PLAY)
2415 swcode = swap_bytes_change_sign16_le;
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;
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;
2433 case AUDIO_ENCODING_ULAW:
2434 if (!(flags & HAS_MULAW)) {
2435 if (mode == AUMODE_PLAY &&
2437 swcode = mulaw_to_slinear16_le;
2439 enc = AUDIO_ENCODING_SLINEAR_LE;
2440 } else if (flags & HAS_8U) {
2441 if (mode == AUMODE_PLAY)
2442 swcode = mulaw_to_ulinear8;
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;
2450 swcode = slinear8_to_mulaw;
2451 enc = AUDIO_ENCODING_SLINEAR_LE;
2456 case AUDIO_ENCODING_ALAW:
2457 if (!(flags & HAS_ALAW)) {
2458 if (mode == AUMODE_PLAY &&
2460 swcode = alaw_to_slinear16_le;
2462 enc = AUDIO_ENCODING_SLINEAR_LE;
2463 } else if (flags & HAS_8U) {
2464 if (mode == AUMODE_PLAY)
2465 swcode = alaw_to_ulinear8;
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;
2473 swcode = slinear8_to_alaw;
2474 enc = AUDIO_ENCODING_SLINEAR_LE;
2482 /* XXX do some other conversions... */
2484 DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n",
2485 p->channels, p->precision, enc, p->sample_rate));
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))
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) ==
2516 p->sw_code = swcode;
2518 if (usemode == mode)
2519 sc->sc_curaltidx = i;
2522 DPRINTF(("uaudio_set_params: use altidx=%d, altno=%d\n",
2524 sc->sc_alts[sc->sc_curaltidx].idesc->bAlternateSetting));
2528 #endif /* NetBSD or OpenBSD */
2531 uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed)
2533 usb_device_request_t req;
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);
2543 data[1] = speed >> 8;
2544 data[2] = speed >> 16;
2546 return (usbd_do_request(sc->sc_udev, &req, &data));
2550 #if defined(__DragonFly__)
2551 /************************************************************/
2553 uaudio_init_params(struct uaudio_softc *sc, struct chan *ch)
2556 int samples_per_frame, sample_size;
2558 switch(ch->format & 0x0000FFFF) {
2560 enc = AUDIO_ENCODING_ULINEAR_LE;
2564 enc = AUDIO_ENCODING_SLINEAR_LE;
2567 case AFMT_A_LAW: /* ? */
2568 enc = AUDIO_ENCODING_ALAW;
2571 case AFMT_MU_LAW: /* ? */
2572 enc = AUDIO_ENCODING_ULAW;
2576 enc = AUDIO_ENCODING_SLINEAR_LE;
2580 enc = AUDIO_ENCODING_SLINEAR_BE;
2584 enc = AUDIO_ENCODING_ULINEAR_LE;
2588 enc = AUDIO_ENCODING_ULINEAR_BE;
2594 printf("Unknown format %x\n", ch->format);
2597 if (ch->format & AFMT_STEREO) {
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 &&
2610 enc == sc->sc_alts[i].encoding) {
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)) {
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;
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) ==
2631 sc->sc_curaltidx = i;
2638 /* return (EINVAL); */
2642 p->sw_code = swcode;
2644 if (usemode == mode)
2645 sc->sc_curaltidx = i;
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;
2656 ch->cur = ch->start;
2657 ch->transferred = 0;
2662 uaudio_query_formats(device_t dev, u_int32_t *pfmt, u_int32_t *rfmt)
2667 struct uaudio_softc *sc;
2669 struct usb_audio_streaming_type1_descriptor *a1d;
2671 sc = device_get_softc(dev);
2673 for (i = 0; i < sc->sc_nalts; i++) {
2675 a1d = sc->sc_alts[i].asf1desc;
2676 prec = a1d->bBitResolution; /* precision */
2678 switch (sc->sc_alts[i].encoding) {
2679 case AUDIO_ENCODING_ULINEAR_LE:
2682 } else if (prec == 16) {
2686 case AUDIO_ENCODING_SLINEAR_LE:
2689 } else if (prec == 16) {
2693 case AUDIO_ENCODING_ULINEAR_BE:
2698 case AUDIO_ENCODING_SLINEAR_BE:
2703 case AUDIO_ENCODING_ALAW:
2708 case AUDIO_ENCODING_ULAW:
2716 if (a1d->bNrChannels == 2) { /* stereo/mono */
2718 } else if (a1d->bNrChannels != 1) {
2724 dir= UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
2725 if (dir == UE_DIR_OUT) {
2727 } else if (dir == UE_DIR_IN) {
2732 if ((pn > 8*2) || (rn > 8*2))
2741 uaudio_chan_set_param_pcm_dma_buff(device_t dev, u_char *start, u_char *end,
2742 struct pcm_channel *pc)
2744 struct uaudio_softc *sc;
2747 sc = device_get_softc(dev);
2759 uaudio_chan_set_param_blocksize(device_t dev, u_int32_t blocksize)
2761 struct uaudio_softc *sc;
2764 sc = device_get_softc(dev);
2767 ch->blksize = blocksize;
2773 uaudio_chan_set_param_speed(device_t dev, u_int32_t speed)
2775 struct uaudio_softc *sc;
2778 sc = device_get_softc(dev);
2781 ch->sample_rate = speed;
2787 uaudio_chan_getptr(device_t dev)
2789 struct uaudio_softc *sc;
2793 sc = device_get_softc(dev);
2796 ptr = ch->cur - ch->start;
2802 uaudio_chan_set_param_format(device_t dev, u_int32_t format)
2804 struct uaudio_softc *sc;
2807 sc = device_get_softc(dev);
2810 ch->format = format;
2816 uaudio_halt_out_dma(device_t dev)
2818 struct uaudio_softc *sc;
2820 sc = device_get_softc(dev);
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);
2832 uaudio_trigger_output(device_t dev)
2834 struct uaudio_softc *sc;
2839 sc = device_get_softc(dev);
2845 uaudio_init_params(sc, ch);
2847 err = uaudio_chan_alloc_buffers(sc, ch);
2851 err = uaudio_chan_open(sc, ch);
2853 uaudio_chan_free_buffers(sc, ch);
2858 for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
2859 uaudio_chan_ptransfer(ch);
2866 uaudio_query_mix_info(device_t dev)
2870 struct uaudio_softc *sc;
2871 struct mixerctl *mc;
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);
2886 uaudio_mixer_set(device_t dev, unsigned type, unsigned left, unsigned right)
2889 struct uaudio_softc *sc;
2890 struct mixerctl *mc;
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) {
2898 uaudio_ctl_set(sc, SET_CUR, mc, 1, (int)(right*256)/100);
2900 /* set Left or Mono */
2901 uaudio_ctl_set(sc, SET_CUR, mc, 0, (int)(left*256)/100);
2908 audio_attach_mi(device_t dev)
2911 struct sndcard_func *func;
2913 /* Attach the children. */
2915 func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
2918 bzero(func, sizeof(*func));
2919 func->func = SCF_PCM;
2920 child = device_add_child(dev, "pcm", -1);
2921 device_set_ivars(child, func);
2923 bus_generic_attach(dev);
2925 return 0; /* XXXXX */
2928 DRIVER_MODULE(uaudio, uhub, uaudio_driver, uaudio_devclass, usbd_driver_load, 0);
2929 MODULE_VERSION(uaudio, 1);