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 $: */
5 * Copyright (c) 1999 The NetBSD Foundation, Inc.
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Lennart Augustsson (lennart@augustsson.net) at
10 * Carlstedt Research & Technology.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
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.
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
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>
57 #include <sys/reboot.h> /* for bootverbose */
58 #include <sys/select.h>
60 #if defined(__NetBSD__) || defined(__OpenBSD__)
61 #include <sys/device.h>
62 #elif defined(__FreeBSD__)
63 #include <sys/module.h>
68 #include <sys/sysctl.h>
70 #if defined(__NetBSD__) || defined(__OpenBSD__)
71 #include <sys/audioio.h>
72 #include <dev/audio_if.h>
73 #include <dev/mulaw.h>
74 #include <dev/auconv.h>
75 #elif defined(__FreeBSD__)
76 #include <dev/sound/pcm/sound.h> /* XXXXX */
77 #include <dev/sound/chip.h>
80 #include <dev/usb/usb.h>
81 #include <dev/usb/usbdi.h>
82 #include <dev/usb/usbdi_util.h>
83 #include <dev/usb/usb_quirks.h>
85 #include <dev/sound/usb/uaudioreg.h>
86 #include <dev/sound/usb/uaudio.h>
89 #define DPRINTF(x) if (uaudiodebug) logprintf x
90 #define DPRINTFN(n,x) if (uaudiodebug>(n)) logprintf x
92 SYSCTL_NODE(_hw_usb, OID_AUTO, uaudio, CTLFLAG_RW, 0, "USB uaudio");
93 SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, debug, CTLFLAG_RW,
94 &uaudiodebug, 0, "uaudio debug level");
100 #define UAUDIO_NCHANBUFS 6 /* number of outstanding request */
101 #define UAUDIO_NFRAMES 20 /* ms of sound in each request */
104 #define MIX_MAX_CHAN 8
106 u_int16_t wValue[MIX_MAX_CHAN]; /* using nchan */
111 #define MIX_SIGNED_16 2
112 #define MIX_UNSIGNED_16 3
113 #define MIX_SIGNED_8 4
114 #define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1)
115 #define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16)
119 #if defined(__FreeBSD__) /* XXXXX */
123 char ctlname[MAX_AUDIO_DEV_LEN];
127 #define MAKE(h,l) (((h) << 8) | (l))
132 usbd_interface_handle ifaceh;
133 usb_interface_descriptor_t *idesc;
134 usb_endpoint_descriptor_audio_t *edesc;
135 struct usb_audio_streaming_type1_descriptor *asf1desc;
139 int terminal; /* terminal id */
140 #if defined(__NetBSD__) || defined(__OpenBSD__)
141 void (*intr)(void *); /* dma completion intr handler */
142 void *arg; /* arg for intr() */
144 struct pcm_channel *pcm_ch;
146 usbd_pipe_handle pipe;
147 int dir; /* direction */
151 u_int bytes_per_frame;
152 u_int fraction; /* fraction/1000 is the extra samples/frame */
153 u_int residue; /* accumulates the fractional samples */
155 u_char *start; /* upper layer buffer start */
156 u_char *end; /* upper layer buffer end */
157 u_char *cur; /* current position in upper layer buffer */
158 int blksize; /* chunk size to report up */
159 int transferred; /* transferred bytes not reported up */
161 char nofrac; /* don't do sample rate adjustment */
166 usbd_xfer_handle xfer;
168 u_int16_t sizes[UAUDIO_NFRAMES];
170 } chanbufs[UAUDIO_NCHANBUFS];
172 struct uaudio_softc *sc; /* our softc */
173 #if defined(__FreeBSD__)
180 struct uaudio_softc {
181 USBBASEDEVICE sc_dev; /* base device */
182 usbd_device_handle sc_udev; /* USB device */
184 char sc_dead; /* The device is dead -- kill it */
186 int sc_ac_iface; /* Audio Control interface */
187 usbd_interface_handle sc_ac_ifaceh;
197 struct as_info *sc_alts;
205 #define HAS_ALAW 0x08
206 #define HAS_MULAW 0x10
208 struct mixerctl *sc_ctls;
211 device_ptr_t sc_audiodev;
219 Static usbd_status uaudio_identify_ac(struct uaudio_softc *sc,
220 usb_config_descriptor_t *cdesc);
221 Static usbd_status uaudio_identify_as(struct uaudio_softc *sc,
222 usb_config_descriptor_t *cdesc);
223 Static usbd_status uaudio_process_as(struct uaudio_softc *sc,
224 char *buf, int *offsp, int size,
225 usb_interface_descriptor_t *id);
227 Static void uaudio_add_alt(struct uaudio_softc *sc,
230 Static usb_interface_descriptor_t *uaudio_find_iface(char *buf,
231 int size, int *offsp, int subtype);
233 Static void uaudio_mixer_add_ctl(struct uaudio_softc *sc,
234 struct mixerctl *mp);
236 #if defined(__NetBSD__) || defined(__OpenBSD__)
237 Static char *uaudio_id_name(struct uaudio_softc *sc,
238 usb_descriptor_t **dps, int id);
241 Static struct usb_audio_cluster uaudio_get_cluster(int id,
242 usb_descriptor_t **dps);
243 Static void uaudio_add_input(struct uaudio_softc *sc,
244 usb_descriptor_t *v, usb_descriptor_t **dps);
245 Static void uaudio_add_output(struct uaudio_softc *sc,
246 usb_descriptor_t *v, usb_descriptor_t **dps);
247 Static void uaudio_add_mixer(struct uaudio_softc *sc,
248 usb_descriptor_t *v, usb_descriptor_t **dps);
249 Static void uaudio_add_selector(struct uaudio_softc *sc,
250 usb_descriptor_t *v, usb_descriptor_t **dps);
251 Static void uaudio_add_feature(struct uaudio_softc *sc,
252 usb_descriptor_t *v, usb_descriptor_t **dps);
253 Static void uaudio_add_processing_updown(struct uaudio_softc *sc,
254 usb_descriptor_t *v, usb_descriptor_t **dps);
255 Static void uaudio_add_processing(struct uaudio_softc *sc,
256 usb_descriptor_t *v, usb_descriptor_t **dps);
257 Static void uaudio_add_extension(struct uaudio_softc *sc,
258 usb_descriptor_t *v, usb_descriptor_t **dps);
259 Static usbd_status uaudio_identify(struct uaudio_softc *sc,
260 usb_config_descriptor_t *cdesc);
262 Static int uaudio_signext(int type, int val);
263 #if defined(__NetBSD__) || defined(__OpenBSD__)
264 Static int uaudio_value2bsd(struct mixerctl *mc, int val);
266 Static int uaudio_bsd2value(struct mixerctl *mc, int val);
267 Static int uaudio_get(struct uaudio_softc *sc, int type,
268 int which, int wValue, int wIndex, int len);
269 #if defined(__NetBSD__) || defined(__OpenBSD__)
270 Static int uaudio_ctl_get(struct uaudio_softc *sc, int which,
271 struct mixerctl *mc, int chan);
273 Static void uaudio_set(struct uaudio_softc *sc, int type,
274 int which, int wValue, int wIndex, int l, int v);
275 Static void uaudio_ctl_set(struct uaudio_softc *sc, int which,
276 struct mixerctl *mc, int chan, int val);
278 Static usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int);
280 Static usbd_status uaudio_chan_open(struct uaudio_softc *sc,
282 Static void uaudio_chan_close(struct uaudio_softc *sc,
284 Static usbd_status uaudio_chan_alloc_buffers(struct uaudio_softc *,
286 Static void uaudio_chan_free_buffers(struct uaudio_softc *,
289 #if defined(__NetBSD__) || defined(__OpenBSD__)
290 Static void uaudio_chan_set_param(struct chan *ch,
291 struct audio_params *param, u_char *start,
292 u_char *end, int blksize);
295 Static void uaudio_chan_ptransfer(struct chan *ch);
296 Static void uaudio_chan_pintr(usbd_xfer_handle xfer,
297 usbd_private_handle priv, usbd_status status);
299 Static void uaudio_chan_rtransfer(struct chan *ch);
300 Static void uaudio_chan_rintr(usbd_xfer_handle xfer,
301 usbd_private_handle priv, usbd_status status);
303 #if defined(__NetBSD__) || defined(__OpenBSD__)
304 Static int uaudio_open(void *, int);
305 Static void uaudio_close(void *);
306 Static int uaudio_drain(void *);
307 Static int uaudio_query_encoding(void *, struct audio_encoding *);
308 Static int uaudio_set_params(void *, int, int,
309 struct audio_params *, struct audio_params *);
310 Static int uaudio_round_blocksize(void *, int);
311 Static int uaudio_trigger_output(void *, void *, void *,
312 int, void (*)(void *), void *,
313 struct audio_params *);
314 Static int uaudio_trigger_input (void *, void *, void *,
315 int, void (*)(void *), void *,
316 struct audio_params *);
317 Static int uaudio_halt_in_dma(void *);
318 Static int uaudio_halt_out_dma(void *);
319 Static int uaudio_getdev(void *, struct audio_device *);
320 Static int uaudio_mixer_set_port(void *, mixer_ctrl_t *);
321 Static int uaudio_mixer_get_port(void *, mixer_ctrl_t *);
322 Static int uaudio_query_devinfo(void *, mixer_devinfo_t *);
323 Static int uaudio_get_props(void *);
325 Static struct audio_hw_if uaudio_hw_if = {
329 uaudio_query_encoding,
331 uaudio_round_blocksize,
342 uaudio_mixer_set_port,
343 uaudio_mixer_get_port,
344 uaudio_query_devinfo,
350 uaudio_trigger_output,
351 uaudio_trigger_input,
354 Static struct audio_device uaudio_device = {
360 #elif defined(__FreeBSD__)
361 Static int audio_attach_mi(device_t);
362 Static void uaudio_init_params(struct uaudio_softc * sc, struct chan *ch);
364 /* for NetBSD compatibirity */
365 #define AUMODE_PLAY 0x01
366 #define AUMODE_RECORD 0x02
368 #define AUDIO_PROP_FULLDUPLEX 0x01
370 #define AUDIO_ENCODING_ULAW 1
371 #define AUDIO_ENCODING_ALAW 2
372 #define AUDIO_ENCODING_SLINEAR_LE 6
373 #define AUDIO_ENCODING_SLINEAR_BE 7
374 #define AUDIO_ENCODING_ULINEAR_LE 8
375 #define AUDIO_ENCODING_ULINEAR_BE 9
380 #if defined(__NetBSD__) || defined(__OpenBSD__)
382 USB_DECLARE_DRIVER(uaudio);
384 #elif defined(__FreeBSD__)
386 USB_DECLARE_DRIVER_INIT(uaudio,
387 DEVMETHOD(device_suspend, bus_generic_suspend),
388 DEVMETHOD(device_resume, bus_generic_resume),
389 DEVMETHOD(device_shutdown, bus_generic_shutdown),
390 DEVMETHOD(bus_print_child, bus_generic_print_child)
397 USB_MATCH_START(uaudio, uaa);
398 usb_interface_descriptor_t *id;
400 if (uaa->iface == NULL)
401 return (UMATCH_NONE);
403 id = usbd_get_interface_descriptor(uaa->iface);
404 /* Trigger on the control interface. */
406 id->bInterfaceClass != UICLASS_AUDIO ||
407 id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL ||
408 (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
409 return (UMATCH_NONE);
411 return (UMATCH_IFACECLASS_IFACESUBCLASS);
416 USB_ATTACH_START(uaudio, sc, uaa);
417 usb_interface_descriptor_t *id;
418 usb_config_descriptor_t *cdesc;
423 usbd_devinfo(uaa->device, 0, devinfo);
426 #if !defined(__FreeBSD__)
427 printf(": %s\n", devinfo);
430 sc->sc_udev = uaa->device;
432 cdesc = usbd_get_config_descriptor(sc->sc_udev);
434 printf("%s: failed to get configuration descriptor\n",
435 USBDEVNAME(sc->sc_dev));
436 USB_ATTACH_ERROR_RETURN;
439 err = uaudio_identify(sc, cdesc);
441 printf("%s: audio descriptors make no sense, error=%d\n",
442 USBDEVNAME(sc->sc_dev), err);
443 USB_ATTACH_ERROR_RETURN;
446 sc->sc_ac_ifaceh = uaa->iface;
447 /* Pick up the AS interface. */
448 for (i = 0; i < uaa->nifaces; i++) {
449 if (uaa->ifaces[i] == NULL)
451 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
455 for (j = 0; j < sc->sc_nalts; j++) {
456 if (id->bInterfaceNumber ==
457 sc->sc_alts[j].idesc->bInterfaceNumber) {
458 sc->sc_alts[j].ifaceh = uaa->ifaces[i];
463 uaa->ifaces[i] = NULL;
466 for (j = 0; j < sc->sc_nalts; j++) {
467 if (sc->sc_alts[j].ifaceh == NULL) {
468 printf("%s: alt %d missing AS interface(s)\n",
469 USBDEVNAME(sc->sc_dev), j);
470 USB_ATTACH_ERROR_RETURN;
474 printf("%s: audio rev %d.%02x\n", USBDEVNAME(sc->sc_dev),
475 sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
479 if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
480 sc->sc_chan.nofrac = 1;
485 printf("%s: %d mixer controls\n", USBDEVNAME(sc->sc_dev),
488 #if !defined(__FreeBSD__)
489 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
493 DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
494 #if defined(__OpenBSD__)
495 audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
496 #elif defined(__NetBSD__)
497 sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
498 #elif defined(__FreeBSD__)
500 if (audio_attach_mi(sc->sc_dev)) {
501 printf("audio_attach_mi failed\n");
502 USB_ATTACH_ERROR_RETURN;
506 USB_ATTACH_SUCCESS_RETURN;
509 #if defined(__NetBSD__) || defined(__OpenBSD__)
511 uaudio_activate(device_ptr_t self, enum devact act)
513 struct uaudio_softc *sc = (struct uaudio_softc *)self;
521 case DVACT_DEACTIVATE:
522 if (sc->sc_audiodev != NULL)
523 rv = config_deactivate(sc->sc_audiodev);
531 #if defined(__NetBSD__) || defined(__OpenBSD__)
533 uaudio_detach(device_ptr_t self, int flags)
535 struct uaudio_softc *sc = (struct uaudio_softc *)self;
538 /* Wait for outstanding requests to complete. */
539 usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
541 if (sc->sc_audiodev != NULL)
542 rv = config_detach(sc->sc_audiodev, flags);
544 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
549 #elif defined(__FreeBSD__)
553 USB_DETACH_START(uaudio, sc);
558 /* Wait for outstanding requests to complete. */
559 usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
563 return bus_generic_detach(sc->sc_dev);
567 #if defined(__NetBSD__) || defined(__OpenBSD__)
569 uaudio_query_encoding(void *addr, struct audio_encoding *fp)
571 struct uaudio_softc *sc = addr;
572 int flags = sc->sc_altflags;
578 if (sc->sc_nalts == 0 || flags == 0)
584 strcpy(fp->name, AudioEulinear);
585 fp->encoding = AUDIO_ENCODING_ULINEAR;
587 fp->flags = flags&HAS_8U ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
590 strcpy(fp->name, AudioEmulaw);
591 fp->encoding = AUDIO_ENCODING_ULAW;
593 fp->flags = flags&HAS_MULAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
596 strcpy(fp->name, AudioEalaw);
597 fp->encoding = AUDIO_ENCODING_ALAW;
599 fp->flags = flags&HAS_ALAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
602 strcpy(fp->name, AudioEslinear);
603 fp->encoding = AUDIO_ENCODING_SLINEAR;
605 fp->flags = flags&HAS_8 ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
608 strcpy(fp->name, AudioEslinear_le);
609 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
614 strcpy(fp->name, AudioEulinear_le);
615 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
617 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
620 strcpy(fp->name, AudioEslinear_be);
621 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
623 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
626 strcpy(fp->name, AudioEulinear_be);
627 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
629 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
637 usb_interface_descriptor_t *
638 uaudio_find_iface(char *buf, int size, int *offsp, int subtype)
640 usb_interface_descriptor_t *d;
642 while (*offsp < size) {
643 d = (void *)(buf + *offsp);
644 *offsp += d->bLength;
645 if (d->bDescriptorType == UDESC_INTERFACE &&
646 d->bInterfaceClass == UICLASS_AUDIO &&
647 d->bInterfaceSubClass == subtype)
654 uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc)
657 size_t len = sizeof(*mc) * (sc->sc_nctls + 1);
658 struct mixerctl *nmc = sc->sc_nctls == 0 ?
659 malloc(len, M_USBDEV, M_NOWAIT) :
660 realloc(sc->sc_ctls, len, M_USBDEV, M_NOWAIT);
663 printf("uaudio_mixer_add_ctl: no memory\n");
669 if (mc->type != MIX_ON_OFF) {
670 /* Determine min and max values. */
671 mc->minval = uaudio_signext(mc->type,
672 uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
673 mc->wValue[0], mc->wIndex,
674 MIX_SIZE(mc->type)));
675 mc->maxval = 1 + uaudio_signext(mc->type,
676 uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE,
677 mc->wValue[0], mc->wIndex,
678 MIX_SIZE(mc->type)));
679 mc->mul = mc->maxval - mc->minval;
682 res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
683 mc->wValue[0], mc->wIndex,
686 mc->delta = (res * 256 + mc->mul/2) / mc->mul;
692 sc->sc_ctls[sc->sc_nctls++] = *mc;
695 if (uaudiodebug > 2) {
697 DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc->wValue[0]));
698 for (i = 1; i < mc->nchan; i++)
699 DPRINTF((",%04x", mc->wValue[i]));
700 #if defined(__FreeBSD__)
701 DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' "
703 mc->wIndex, mc->type, mc->ctl,
704 mc->minval, mc->maxval));
706 DPRINTF((" wIndex=%04x type=%d ctl='%d' "
708 mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
709 mc->minval, mc->maxval));
715 #if defined(__NetBSD__) || defined(__OpenBSD__)
717 uaudio_id_name(struct uaudio_softc *sc, usb_descriptor_t **dps, int id)
720 sprintf(buf, "i%d", id);
725 struct usb_audio_cluster
726 uaudio_get_cluster(int id, usb_descriptor_t **dps)
728 struct usb_audio_cluster r;
729 usb_descriptor_t *dp;
732 for (i = 0; i < 25; i++) { /* avoid infinite loops */
736 switch (dp->bDescriptorSubtype) {
737 case UDESCSUB_AC_INPUT:
738 #define p ((struct usb_audio_input_terminal *)dp)
739 r.bNrChannels = p->bNrChannels;
740 USETW(r.wChannelConfig, UGETW(p->wChannelConfig));
741 r.iChannelNames = p->iChannelNames;
744 case UDESCSUB_AC_OUTPUT:
745 #define p ((struct usb_audio_output_terminal *)dp)
749 case UDESCSUB_AC_MIXER:
750 #define p ((struct usb_audio_mixer_unit *)dp)
751 r = *(struct usb_audio_cluster *)
752 &p->baSourceId[p->bNrInPins];
755 case UDESCSUB_AC_SELECTOR:
756 /* XXX This is not really right */
757 #define p ((struct usb_audio_selector_unit *)dp)
758 id = p->baSourceId[0];
761 case UDESCSUB_AC_FEATURE:
762 #define p ((struct usb_audio_feature_unit *)dp)
766 case UDESCSUB_AC_PROCESSING:
767 #define p ((struct usb_audio_processing_unit *)dp)
768 r = *(struct usb_audio_cluster *)
769 &p->baSourceId[p->bNrInPins];
772 case UDESCSUB_AC_EXTENSION:
773 #define p ((struct usb_audio_extension_unit *)dp)
774 r = *(struct usb_audio_cluster *)
775 &p->baSourceId[p->bNrInPins];
783 printf("uaudio_get_cluster: bad data\n");
784 memset(&r, 0, sizeof r);
790 uaudio_add_input(struct uaudio_softc *sc, usb_descriptor_t *v,
791 usb_descriptor_t **dps)
794 struct usb_audio_input_terminal *d =
795 (struct usb_audio_input_terminal *)v;
797 DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x "
798 "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
799 "iChannelNames=%d iTerminal=%d\n",
800 d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
801 d->bNrChannels, UGETW(d->wChannelConfig),
802 d->iChannelNames, d->iTerminal));
807 uaudio_add_output(struct uaudio_softc *sc, usb_descriptor_t *v,
808 usb_descriptor_t **dps)
811 struct usb_audio_output_terminal *d =
812 (struct usb_audio_output_terminal *)v;
814 DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x "
815 "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
816 d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
817 d->bSourceId, d->iTerminal));
822 uaudio_add_mixer(struct uaudio_softc *sc, usb_descriptor_t *v,
823 usb_descriptor_t **dps)
825 struct usb_audio_mixer_unit *d = (struct usb_audio_mixer_unit *)v;
826 struct usb_audio_mixer_unit_1 *d1;
827 int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k;
831 DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n",
832 d->bUnitId, d->bNrInPins));
834 /* Compute the number of input channels */
836 for (i = 0; i < d->bNrInPins; i++)
837 ichs += uaudio_get_cluster(d->baSourceId[i], dps).bNrChannels;
839 /* and the number of output channels */
840 d1 = (struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins];
841 ochs = d1->bNrChannels;
842 DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%d\n", ichs, ochs));
845 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
846 #if !defined(__FreeBSD__)
849 mix.type = MIX_SIGNED_16;
850 #if !defined(__FreeBSD__) /* XXXXX */
851 mix.ctlunit = AudioNvolume;
854 #define BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1)
855 for (p = i = 0; i < d->bNrInPins; i++) {
856 chs = uaudio_get_cluster(d->baSourceId[i], dps).bNrChannels;
858 for (c = 0; c < chs; c++) {
860 for (o = 0; o < ochs; o++) {
861 bno = (p + c) * ochs + o;
868 if (mc == chs && chs <= MIX_MAX_CHAN) {
870 for (c = 0; c < chs; c++)
871 for (o = 0; o < ochs; o++) {
872 bno = (p + c) * ochs + o;
877 #if !defined(__FreeBSD__)
878 sprintf(mix.ctlname, "mix%d-%s", d->bUnitId,
879 uaudio_id_name(sc, dps, d->baSourceId[i]));
882 uaudio_mixer_add_ctl(sc, &mix);
893 uaudio_add_selector(struct uaudio_softc *sc, usb_descriptor_t *v,
894 usb_descriptor_t **dps)
897 struct usb_audio_selector_unit *d =
898 (struct usb_audio_selector_unit *)v;
900 DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n",
901 d->bUnitId, d->bNrInPins));
903 printf("uaudio_add_selector: NOT IMPLEMENTED\n");
907 uaudio_add_feature(struct uaudio_softc *sc, usb_descriptor_t *v,
908 usb_descriptor_t **dps)
910 struct usb_audio_feature_unit *d = (struct usb_audio_feature_unit *)v;
911 uByte *ctls = d->bmaControls;
912 int ctlsize = d->bControlSize;
913 int nchan = (d->bLength - 7) / ctlsize;
914 #if !defined(__FreeBSD__)
915 int srcId = d->bSourceId;
917 u_int fumask, mmask, cmask;
919 int chan, ctl, i, unit;
921 #define GET(i) (ctls[(i)*ctlsize] | \
922 (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
925 /* Figure out what we can control */
926 for (cmask = 0, chan = 1; chan < nchan; chan++) {
927 DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%x\n",
932 #if !defined(__FreeBSD__)
933 DPRINTFN(1,("uaudio_add_feature: bUnitId=%d bSourceId=%d, "
934 "%d channels, mmask=0x%04x, cmask=0x%04x\n",
935 d->bUnitId, srcId, nchan, mmask, cmask));
938 if (nchan > MIX_MAX_CHAN)
939 nchan = MIX_MAX_CHAN;
941 mix.wIndex = MAKE(unit, sc->sc_ac_iface);
942 for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) {
943 fumask = FU_MASK(ctl);
944 DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04x\n",
946 if (mmask & fumask) {
948 mix.wValue[0] = MAKE(ctl, 0);
949 } else if (cmask & fumask) {
950 mix.nchan = nchan - 1;
951 for (i = 1; i < nchan; i++) {
953 mix.wValue[i-1] = MAKE(ctl, i);
955 mix.wValue[i-1] = -1;
962 #if !defined(__FreeBSD__)
963 mix.class = -1; /* XXX */
967 mix.type = MIX_ON_OFF;
968 #if defined(__FreeBSD__)
969 mix.ctl = SOUND_MIXER_NRDEVICES;
971 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
972 uaudio_id_name(sc, dps, srcId),
978 mix.type = MIX_SIGNED_16;
979 #if defined(__FreeBSD__)
980 /* mix.ctl = SOUND_MIXER_VOLUME; */
981 mix.ctl = SOUND_MIXER_PCM;
983 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
984 uaudio_id_name(sc, dps, srcId),
986 mix.ctlunit = AudioNvolume;
990 mix.type = MIX_SIGNED_8;
991 #if defined(__FreeBSD__)
992 mix.ctl = SOUND_MIXER_BASS;
994 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
995 uaudio_id_name(sc, dps, srcId),
997 mix.ctlunit = AudioNbass;
1001 mix.type = MIX_SIGNED_8;
1002 #if defined(__FreeBSD__)
1003 mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
1005 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1006 uaudio_id_name(sc, dps, srcId),
1008 mix.ctlunit = AudioNmid;
1011 case TREBLE_CONTROL:
1012 mix.type = MIX_SIGNED_8;
1013 #if defined(__FreeBSD__)
1014 mix.ctl = SOUND_MIXER_TREBLE;
1016 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1017 uaudio_id_name(sc, dps, srcId),
1019 mix.ctlunit = AudioNtreble;
1022 case GRAPHIC_EQUALIZER_CONTROL:
1023 continue; /* XXX don't add anything */
1026 mix.type = MIX_ON_OFF;
1027 #if defined(__FreeBSD__)
1028 mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
1030 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1031 uaudio_id_name(sc, dps, srcId),
1037 mix.type = MIX_UNSIGNED_16;
1038 #if defined(__FreeBSD__)
1039 mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
1041 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1042 uaudio_id_name(sc, dps, srcId),
1044 mix.ctlunit = "4 ms";
1047 case BASS_BOOST_CONTROL:
1048 mix.type = MIX_ON_OFF;
1049 #if defined(__FreeBSD__)
1050 mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
1052 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1053 uaudio_id_name(sc, dps, srcId),
1058 case LOUDNESS_CONTROL:
1059 mix.type = MIX_ON_OFF;
1060 #if defined(__FreeBSD__)
1061 mix.ctl = SOUND_MIXER_LOUD; /* Is this correct ? */
1063 sprintf(mix.ctlname, "fea%d-%s-%s", unit,
1064 uaudio_id_name(sc, dps, srcId),
1070 uaudio_mixer_add_ctl(sc, &mix);
1075 uaudio_add_processing_updown(struct uaudio_softc *sc, usb_descriptor_t *v,
1076 usb_descriptor_t **dps)
1078 struct usb_audio_processing_unit *d =
1079 (struct usb_audio_processing_unit *)v;
1080 struct usb_audio_processing_unit_1 *d1 =
1081 (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
1082 struct usb_audio_processing_unit_updown *ud =
1083 (struct usb_audio_processing_unit_updown *)
1084 &d1->bmControls[d1->bControlSize];
1085 struct mixerctl mix;
1088 DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
1089 d->bUnitId, ud->bNrModes));
1091 if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
1092 DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
1096 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1098 mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
1099 #if !defined(__FreeBSD__)
1102 mix.type = MIX_ON_OFF; /* XXX */
1103 #if !defined(__FreeBSD__)
1105 sprintf(mix.ctlname, "pro%d-mode", d->bUnitId);
1108 for (i = 0; i < ud->bNrModes; i++) {
1109 DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n",
1110 i, UGETW(ud->waModes[i])));
1113 uaudio_mixer_add_ctl(sc, &mix);
1117 uaudio_add_processing(struct uaudio_softc *sc, usb_descriptor_t *v,
1118 usb_descriptor_t **dps)
1120 struct usb_audio_processing_unit *d =
1121 (struct usb_audio_processing_unit *)v;
1122 struct usb_audio_processing_unit_1 *d1 =
1123 (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
1124 int ptype = UGETW(d->wProcessType);
1125 struct mixerctl mix;
1127 DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
1128 "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins));
1130 if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
1131 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1133 mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
1134 #if !defined(__FreeBSD__)
1137 mix.type = MIX_ON_OFF;
1138 #if !defined(__FreeBSD__)
1140 sprintf(mix.ctlname, "pro%d.%d-enable", d->bUnitId, ptype);
1142 uaudio_mixer_add_ctl(sc, &mix);
1146 case UPDOWNMIX_PROCESS:
1147 uaudio_add_processing_updown(sc, v, dps);
1149 case DOLBY_PROLOGIC_PROCESS:
1150 case P3D_STEREO_EXTENDER_PROCESS:
1151 case REVERBATION_PROCESS:
1152 case CHORUS_PROCESS:
1153 case DYN_RANGE_COMP_PROCESS:
1156 printf("uaudio_add_processing: unit %d, type=%d not impl.\n",
1164 uaudio_add_extension(struct uaudio_softc *sc, usb_descriptor_t *v,
1165 usb_descriptor_t **dps)
1167 struct usb_audio_extension_unit *d =
1168 (struct usb_audio_extension_unit *)v;
1169 struct usb_audio_extension_unit_1 *d1 =
1170 (struct usb_audio_extension_unit_1 *)&d->baSourceId[d->bNrInPins];
1171 struct mixerctl mix;
1173 DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
1174 d->bUnitId, d->bNrInPins));
1176 if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU)
1179 if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
1180 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1182 mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
1183 #if !defined(__FreeBSD__)
1186 mix.type = MIX_ON_OFF;
1187 #if !defined(__FreeBSD__)
1189 sprintf(mix.ctlname, "ext%d-enable", d->bUnitId);
1191 uaudio_mixer_add_ctl(sc, &mix);
1196 uaudio_identify(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1200 err = uaudio_identify_ac(sc, cdesc);
1203 return (uaudio_identify_as(sc, cdesc));
1207 uaudio_add_alt(struct uaudio_softc *sc, struct as_info *ai)
1209 size_t len = sizeof(*ai) * (sc->sc_nalts + 1);
1210 struct as_info *nai = sc->sc_nalts == 0 ?
1211 malloc(len, M_USBDEV, M_NOWAIT) :
1212 realloc(sc->sc_alts, len, M_USBDEV, M_NOWAIT);
1215 printf("uaudio_add_alt: no memory\n");
1220 DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%d\n",
1221 ai->alt, ai->encoding));
1222 sc->sc_alts[sc->sc_nalts++] = *ai;
1226 uaudio_process_as(struct uaudio_softc *sc, char *buf, int *offsp,
1227 int size, usb_interface_descriptor_t *id)
1228 #define offs (*offsp)
1230 struct usb_audio_streaming_interface_descriptor *asid;
1231 struct usb_audio_streaming_type1_descriptor *asf1d;
1232 usb_endpoint_descriptor_audio_t *ed;
1233 struct usb_audio_streaming_endpoint_descriptor *sed;
1234 int format, chan, prec, enc;
1238 asid = (void *)(buf + offs);
1239 if (asid->bDescriptorType != UDESC_CS_INTERFACE ||
1240 asid->bDescriptorSubtype != AS_GENERAL)
1241 return (USBD_INVAL);
1242 offs += asid->bLength;
1244 return (USBD_INVAL);
1245 asf1d = (void *)(buf + offs);
1246 if (asf1d->bDescriptorType != UDESC_CS_INTERFACE ||
1247 asf1d->bDescriptorSubtype != FORMAT_TYPE)
1248 return (USBD_INVAL);
1249 offs += asf1d->bLength;
1251 return (USBD_INVAL);
1253 if (asf1d->bFormatType != FORMAT_TYPE_I) {
1254 printf("%s: ignored setting with type %d format\n",
1255 USBDEVNAME(sc->sc_dev), UGETW(asid->wFormatTag));
1256 return (USBD_NORMAL_COMPLETION);
1259 ed = (void *)(buf + offs);
1260 if (ed->bDescriptorType != UDESC_ENDPOINT)
1261 return (USBD_INVAL);
1262 DPRINTF(("uaudio_process_as: endpoint bLength=%d bDescriptorType=%d "
1263 "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d "
1264 "bInterval=%d bRefresh=%d bSynchAddress=%d\n",
1265 ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
1266 ed->bmAttributes, UGETW(ed->wMaxPacketSize),
1267 ed->bInterval, ed->bRefresh, ed->bSynchAddress));
1268 offs += ed->bLength;
1270 return (USBD_INVAL);
1271 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
1272 return (USBD_INVAL);
1274 dir = UE_GET_DIR(ed->bEndpointAddress);
1275 type = UE_GET_ISO_TYPE(ed->bmAttributes);
1276 if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) &&
1277 dir == UE_DIR_IN && type == UE_ISO_ADAPT)
1278 type = UE_ISO_ASYNC;
1280 /* We can't handle endpoints that need a sync pipe yet. */
1281 if (dir == UE_DIR_IN ? type == UE_ISO_ADAPT : type == UE_ISO_ASYNC) {
1282 printf("%s: ignored %sput endpoint of type %s\n",
1283 USBDEVNAME(sc->sc_dev),
1284 dir == UE_DIR_IN ? "in" : "out",
1285 dir == UE_DIR_IN ? "adaptive" : "async");
1286 return (USBD_NORMAL_COMPLETION);
1289 sed = (void *)(buf + offs);
1290 if (sed->bDescriptorType != UDESC_CS_ENDPOINT ||
1291 sed->bDescriptorSubtype != AS_GENERAL)
1292 return (USBD_INVAL);
1293 offs += sed->bLength;
1295 return (USBD_INVAL);
1297 format = UGETW(asid->wFormatTag);
1298 chan = asf1d->bNrChannels;
1299 prec = asf1d->bBitResolution;
1300 if (prec != 8 && prec != 16) {
1302 printf("%s: ignored setting with precision %d\n",
1303 USBDEVNAME(sc->sc_dev), prec);
1305 return (USBD_NORMAL_COMPLETION);
1309 sc->sc_altflags |= prec == 8 ? HAS_8 : HAS_16;
1310 enc = AUDIO_ENCODING_SLINEAR_LE;
1313 enc = AUDIO_ENCODING_ULINEAR_LE;
1314 sc->sc_altflags |= HAS_8U;
1317 enc = AUDIO_ENCODING_ALAW;
1318 sc->sc_altflags |= HAS_ALAW;
1321 enc = AUDIO_ENCODING_ULAW;
1322 sc->sc_altflags |= HAS_MULAW;
1325 printf("%s: ignored setting with format %d\n",
1326 USBDEVNAME(sc->sc_dev), format);
1327 return (USBD_NORMAL_COMPLETION);
1329 DPRINTFN(1,("uaudio_identify: alt=%d enc=%d chan=%d prec=%d\n",
1330 id->bAlternateSetting, enc, chan, prec));
1331 ai.alt = id->bAlternateSetting;
1335 ai.asf1desc = asf1d;
1336 uaudio_add_alt(sc, &ai);
1337 sc->sc_chan.terminal = asid->bTerminalLink; /* XXX */
1338 sc->sc_chan.dir |= dir == UE_DIR_OUT ? AUMODE_PLAY : AUMODE_RECORD;
1339 return (USBD_NORMAL_COMPLETION);
1344 uaudio_identify_as(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1346 usb_interface_descriptor_t *id;
1351 size = UGETW(cdesc->wTotalLength);
1352 buf = (char *)cdesc;
1354 /* Locate the AudioStreaming interface descriptor. */
1356 id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM);
1358 return (USBD_INVAL);
1360 sc->sc_chan.terminal = -1;
1361 sc->sc_chan.dir = 0;
1363 /* Loop through all the alternate settings. */
1364 while (offs <= size) {
1365 DPRINTFN(2, ("uaudio_identify: interface %d\n",
1366 id->bInterfaceNumber));
1367 switch (id->bNumEndpoints) {
1369 DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n",
1370 id->bAlternateSetting));
1371 sc->sc_nullalt = id->bAlternateSetting;
1374 err = uaudio_process_as(sc, buf, &offs, size, id);
1378 printf("%s: ignored audio interface with %d "
1380 USBDEVNAME(sc->sc_dev), id->bNumEndpoints);
1384 id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM);
1389 return (USBD_INVAL);
1390 DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts));
1391 if (sc->sc_chan.terminal < 0) {
1392 printf("%s: no useable endpoint found\n",
1393 USBDEVNAME(sc->sc_dev));
1394 return (USBD_INVAL);
1397 #ifndef NO_RECORDING
1398 if (sc->sc_chan.dir == (AUMODE_PLAY | AUMODE_RECORD))
1399 sc->sc_props |= AUDIO_PROP_FULLDUPLEX;
1401 return (USBD_NORMAL_COMPLETION);
1405 uaudio_identify_ac(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1407 usb_interface_descriptor_t *id;
1408 struct usb_audio_control_descriptor *acdp;
1409 usb_descriptor_t *dp, *dps[256];
1410 char *buf, *ibuf, *ibufend;
1411 int size, offs, aclen, ndps, i;
1413 size = UGETW(cdesc->wTotalLength);
1414 buf = (char *)cdesc;
1416 /* Locate the AudioControl interface descriptor. */
1418 id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL);
1420 return (USBD_INVAL);
1421 if (offs + sizeof *acdp > size)
1422 return (USBD_INVAL);
1423 sc->sc_ac_iface = id->bInterfaceNumber;
1424 DPRINTFN(2,("uaudio_identify: AC interface is %d\n", sc->sc_ac_iface));
1426 /* A class-specific AC interface header should follow. */
1428 acdp = (struct usb_audio_control_descriptor *)ibuf;
1429 if (acdp->bDescriptorType != UDESC_CS_INTERFACE ||
1430 acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)
1431 return (USBD_INVAL);
1432 aclen = UGETW(acdp->wTotalLength);
1433 if (offs + aclen > size)
1434 return (USBD_INVAL);
1436 if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) &&
1437 UGETW(acdp->bcdADC) != UAUDIO_VERSION)
1438 return (USBD_INVAL);
1440 sc->sc_audio_rev = UGETW(acdp->bcdADC);
1441 DPRINTFN(2,("uaudio_identify: found AC header, vers=%03x, len=%d\n",
1442 sc->sc_audio_rev, aclen));
1444 sc->sc_nullalt = -1;
1446 /* Scan through all the AC specific descriptors */
1447 ibufend = ibuf + aclen;
1448 dp = (usb_descriptor_t *)ibuf;
1450 memset(dps, 0, sizeof dps);
1452 ibuf += dp->bLength;
1453 if (ibuf >= ibufend)
1455 dp = (usb_descriptor_t *)ibuf;
1456 if (ibuf + dp->bLength > ibufend)
1457 return (USBD_INVAL);
1458 if (dp->bDescriptorType != UDESC_CS_INTERFACE) {
1459 printf("uaudio_identify: skip desc type=0x%02x\n",
1460 dp->bDescriptorType);
1463 i = ((struct usb_audio_input_terminal *)dp)->bTerminalId;
1470 for (i = 0; i < ndps; i++) {
1474 DPRINTF(("uaudio_identify: subtype=%d\n",
1475 dp->bDescriptorSubtype));
1476 switch (dp->bDescriptorSubtype) {
1477 case UDESCSUB_AC_HEADER:
1478 printf("uaudio_identify: unexpected AC header\n");
1480 case UDESCSUB_AC_INPUT:
1481 uaudio_add_input(sc, dp, dps);
1483 case UDESCSUB_AC_OUTPUT:
1484 uaudio_add_output(sc, dp, dps);
1486 case UDESCSUB_AC_MIXER:
1487 uaudio_add_mixer(sc, dp, dps);
1489 case UDESCSUB_AC_SELECTOR:
1490 uaudio_add_selector(sc, dp, dps);
1492 case UDESCSUB_AC_FEATURE:
1493 uaudio_add_feature(sc, dp, dps);
1495 case UDESCSUB_AC_PROCESSING:
1496 uaudio_add_processing(sc, dp, dps);
1498 case UDESCSUB_AC_EXTENSION:
1499 uaudio_add_extension(sc, dp, dps);
1502 printf("uaudio_identify: bad AC desc subtype=0x%02x\n",
1503 dp->bDescriptorSubtype);
1507 return (USBD_NORMAL_COMPLETION);
1510 #if defined(__NetBSD__) || defined(__OpenBSD__)
1512 uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi)
1514 struct uaudio_softc *sc = addr;
1515 struct mixerctl *mc;
1518 DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi->index));
1523 nctls = sc->sc_nctls;
1525 if (n < 0 || n >= nctls) {
1526 switch (n - nctls) {
1528 mi->type = AUDIO_MIXER_CLASS;
1529 mi->mixer_class = nctls + UAC_OUTPUT;
1530 mi->next = mi->prev = AUDIO_MIXER_LAST;
1531 strcpy(mi->label.name, AudioCoutputs);
1534 mi->type = AUDIO_MIXER_CLASS;
1535 mi->mixer_class = nctls + UAC_INPUT;
1536 mi->next = mi->prev = AUDIO_MIXER_LAST;
1537 strcpy(mi->label.name, AudioCinputs);
1540 mi->type = AUDIO_MIXER_CLASS;
1541 mi->mixer_class = nctls + UAC_EQUAL;
1542 mi->next = mi->prev = AUDIO_MIXER_LAST;
1543 strcpy(mi->label.name, AudioCequalization);
1549 mc = &sc->sc_ctls[n];
1550 strncpy(mi->label.name, mc->ctlname, MAX_AUDIO_DEV_LEN);
1551 mi->mixer_class = mc->class;
1552 mi->next = mi->prev = AUDIO_MIXER_LAST; /* XXX */
1555 mi->type = AUDIO_MIXER_ENUM;
1556 mi->un.e.num_mem = 2;
1557 strcpy(mi->un.e.member[0].label.name, AudioNoff);
1558 mi->un.e.member[0].ord = 0;
1559 strcpy(mi->un.e.member[1].label.name, AudioNon);
1560 mi->un.e.member[1].ord = 1;
1563 mi->type = AUDIO_MIXER_VALUE;
1564 strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN);
1565 mi->un.v.num_channels = mc->nchan;
1566 mi->un.v.delta = mc->delta;
1573 uaudio_open(void *addr, int flags)
1575 struct uaudio_softc *sc = addr;
1577 DPRINTF(("uaudio_open: sc=%p\n", sc));
1581 if (sc->sc_chan.terminal < 0)
1584 if ((flags & FREAD) && !(sc->sc_chan.dir & AUMODE_RECORD))
1586 if ((flags & FWRITE) && !(sc->sc_chan.dir & AUMODE_PLAY))
1589 sc->sc_chan.intr = 0;
1595 * Close function is called at splaudio().
1598 uaudio_close(void *addr)
1600 struct uaudio_softc *sc = addr;
1605 DPRINTF(("uaudio_close: sc=%p\n", sc));
1606 uaudio_halt_in_dma(sc);
1607 uaudio_halt_out_dma(sc);
1609 sc->sc_chan.intr = 0;
1613 uaudio_drain(void *addr)
1615 struct uaudio_softc *sc = addr;
1620 usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
1626 uaudio_halt_out_dma(void *addr)
1628 struct uaudio_softc *sc = addr;
1633 DPRINTF(("uaudio_halt_out_dma: enter\n"));
1634 if (sc->sc_chan.pipe != NULL) {
1635 uaudio_chan_close(sc, &sc->sc_chan);
1636 sc->sc_chan.pipe = 0;
1637 uaudio_chan_free_buffers(sc, &sc->sc_chan);
1643 uaudio_halt_in_dma(void *addr)
1645 struct uaudio_softc *sc = addr;
1647 DPRINTF(("uaudio_halt_in_dma: enter\n"));
1648 if (sc->sc_chan.pipe != NULL) {
1649 uaudio_chan_close(sc, &sc->sc_chan);
1650 sc->sc_chan.pipe = 0;
1651 uaudio_chan_free_buffers(sc, &sc->sc_chan);
1657 uaudio_getdev(void *addr, struct audio_device *retp)
1659 struct uaudio_softc *sc = addr;
1661 DPRINTF(("uaudio_mixer_getdev:\n"));
1665 *retp = uaudio_device;
1670 * Make sure the block size is large enough to hold all outstanding transfers.
1673 uaudio_round_blocksize(void *addr, int blk)
1675 struct uaudio_softc *sc = addr;
1681 bpf = sc->sc_chan.bytes_per_frame + sc->sc_chan.sample_size;
1683 bpf *= UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
1685 bpf = (bpf + 15) &~ 15;
1692 printf("uaudio_round_blocksize: blk=%d\n", blk);
1697 DPRINTFN(1,("uaudio_round_blocksize: blk=%d\n", blk));
1702 uaudio_get_props(void *addr)
1704 struct uaudio_softc *sc = addr;
1706 return (sc->sc_props);
1708 #endif /* NetBSD or OpenBSD */
1712 uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue,
1713 int wIndex, int len)
1715 usb_device_request_t req;
1726 req.bmRequestType = type;
1727 req.bRequest = which;
1728 USETW(req.wValue, wValue);
1729 USETW(req.wIndex, wIndex);
1730 USETW(req.wLength, len);
1731 DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
1732 "wIndex=0x%04x len=%d\n",
1733 type, which, wValue, wIndex, len));
1734 err = usbd_do_request(sc->sc_udev, &req, &data);
1736 DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
1744 val = data[0] | (data[1] << 8);
1747 DPRINTF(("uaudio_get: bad length=%d\n", len));
1750 DPRINTFN(2,("uaudio_get: val=%d\n", val));
1755 uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue,
1756 int wIndex, int len, int val)
1758 usb_device_request_t req;
1768 req.bmRequestType = type;
1769 req.bRequest = which;
1770 USETW(req.wValue, wValue);
1771 USETW(req.wIndex, wIndex);
1772 USETW(req.wLength, len);
1784 DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
1785 "wIndex=0x%04x len=%d, val=%d\n",
1786 type, which, wValue, wIndex, len, val & 0xffff));
1787 err = usbd_do_request(sc->sc_udev, &req, &data);
1790 DPRINTF(("uaudio_set: err=%d\n", err));
1795 uaudio_signext(int type, int val)
1797 if (!MIX_UNSIGNED(type)) {
1798 if (MIX_SIZE(type) == 2)
1806 #if defined(__NetBSD__) || defined(__OpenBSD__)
1808 uaudio_value2bsd(struct mixerctl *mc, int val)
1810 DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ",
1811 mc->type, val, mc->minval, mc->maxval));
1812 if (mc->type == MIX_ON_OFF)
1815 val = ((uaudio_signext(mc->type, val) - mc->minval) * 256
1816 + mc->mul/2) / mc->mul;
1817 DPRINTFN(5, ("val'=%d\n", val));
1823 uaudio_bsd2value(struct mixerctl *mc, int val)
1825 DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ",
1826 mc->type, val, mc->minval, mc->maxval));
1827 if (mc->type == MIX_ON_OFF)
1830 val = (val + mc->delta/2) * mc->mul / 256 + mc->minval;
1831 DPRINTFN(5, ("val'=%d\n", val));
1835 #if defined(__NetBSD__) || defined(__OpenBSD__)
1837 uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc,
1842 DPRINTFN(5,("uaudio_ctl_get: which=%d chan=%d\n", which, chan));
1843 val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan],
1844 mc->wIndex, MIX_SIZE(mc->type));
1845 return (uaudio_value2bsd(mc, val));
1850 uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc,
1853 val = uaudio_bsd2value(mc, val);
1854 uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan],
1855 mc->wIndex, MIX_SIZE(mc->type), val);
1858 #if defined(__NetBSD__) || defined(__OpenBSD__)
1860 uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1862 struct uaudio_softc *sc = addr;
1863 struct mixerctl *mc;
1864 int i, n, vals[MIX_MAX_CHAN], val;
1866 DPRINTFN(2,("uaudio_mixer_get_port: index=%d\n", cp->dev));
1872 if (n < 0 || n >= sc->sc_nctls)
1874 mc = &sc->sc_ctls[n];
1876 if (mc->type == MIX_ON_OFF) {
1877 if (cp->type != AUDIO_MIXER_ENUM)
1879 cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
1881 if (cp->type != AUDIO_MIXER_VALUE)
1883 if (cp->un.value.num_channels != 1 &&
1884 cp->un.value.num_channels != mc->nchan)
1886 for (i = 0; i < mc->nchan; i++)
1887 vals[i] = uaudio_ctl_get(sc, GET_CUR, mc, i);
1888 if (cp->un.value.num_channels == 1 && mc->nchan != 1) {
1889 for (val = 0, i = 0; i < mc->nchan; i++)
1891 vals[0] = val / mc->nchan;
1893 for (i = 0; i < cp->un.value.num_channels; i++)
1894 cp->un.value.level[i] = vals[i];
1901 uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1903 struct uaudio_softc *sc = addr;
1904 struct mixerctl *mc;
1905 int i, n, vals[MIX_MAX_CHAN];
1907 DPRINTFN(2,("uaudio_mixer_set_port: index = %d\n", cp->dev));
1912 if (n < 0 || n >= sc->sc_nctls)
1914 mc = &sc->sc_ctls[n];
1916 if (mc->type == MIX_ON_OFF) {
1917 if (cp->type != AUDIO_MIXER_ENUM)
1919 uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
1921 if (cp->type != AUDIO_MIXER_VALUE)
1923 if (cp->un.value.num_channels == 1)
1924 for (i = 0; i < mc->nchan; i++)
1925 vals[i] = cp->un.value.level[0];
1926 else if (cp->un.value.num_channels == mc->nchan)
1927 for (i = 0; i < mc->nchan; i++)
1928 vals[i] = cp->un.value.level[i];
1931 for (i = 0; i < mc->nchan; i++)
1932 uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]);
1938 uaudio_trigger_input(void *addr, void *start, void *end, int blksize,
1939 void (*intr)(void *), void *arg,
1940 struct audio_params *param)
1942 struct uaudio_softc *sc = addr;
1943 struct chan *ch = &sc->sc_chan;
1950 DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p "
1951 "blksize=%d\n", sc, start, end, blksize));
1953 uaudio_chan_set_param(ch, param, start, end, blksize);
1954 DPRINTFN(3,("uaudio_trigger_input: sample_size=%d bytes/frame=%d "
1955 "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
1958 err = uaudio_chan_alloc_buffers(sc, ch);
1962 err = uaudio_chan_open(sc, ch);
1964 uaudio_chan_free_buffers(sc, ch);
1968 sc->sc_chan.intr = intr;
1969 sc->sc_chan.arg = arg;
1972 for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
1973 uaudio_chan_rtransfer(ch);
1980 uaudio_trigger_output(void *addr, void *start, void *end, int blksize,
1981 void (*intr)(void *), void *arg,
1982 struct audio_params *param)
1984 struct uaudio_softc *sc = addr;
1985 struct chan *ch = &sc->sc_chan;
1992 DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p "
1993 "blksize=%d\n", sc, start, end, blksize));
1995 uaudio_chan_set_param(ch, param, start, end, blksize);
1996 DPRINTFN(3,("uaudio_trigger_output: sample_size=%d bytes/frame=%d "
1997 "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
2000 err = uaudio_chan_alloc_buffers(sc, ch);
2004 err = uaudio_chan_open(sc, ch);
2006 uaudio_chan_free_buffers(sc, ch);
2010 sc->sc_chan.intr = intr;
2011 sc->sc_chan.arg = arg;
2014 for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
2015 uaudio_chan_ptransfer(ch);
2020 #endif /* NetBSD or OpenBSD */
2022 /* Set up a pipe for a channel. */
2024 uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
2026 struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
2027 int endpt = as->edesc->bEndpointAddress;
2033 DPRINTF(("uaudio_open_chan: endpt=0x%02x, speed=%d, alt=%d\n",
2034 endpt, ch->sample_rate, as->alt));
2036 /* Set alternate interface corresponding to the mode. */
2037 err = usbd_set_interface(as->ifaceh, as->alt);
2041 /* Some devices do not support this request, so ignore errors. */
2043 err = uaudio_set_speed(sc, endpt, ch->sample_rate);
2045 DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n",
2048 (void)uaudio_set_speed(sc, endpt, ch->sample_rate);
2051 DPRINTF(("uaudio_open_chan: create pipe to 0x%02x\n", endpt));
2052 err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
2057 uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
2059 struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
2064 if (sc->sc_nullalt >= 0) {
2065 DPRINTF(("uaudio_close_chan: set null alt=%d\n",
2067 usbd_set_interface(as->ifaceh, sc->sc_nullalt);
2069 usbd_abort_pipe(ch->pipe);
2070 usbd_close_pipe(ch->pipe);
2074 uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch)
2076 usbd_xfer_handle xfer;
2080 size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES;
2081 for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
2082 xfer = usbd_alloc_xfer(sc->sc_udev);
2085 ch->chanbufs[i].xfer = xfer;
2086 buf = usbd_alloc_buffer(xfer, size);
2091 ch->chanbufs[i].buffer = buf;
2092 ch->chanbufs[i].chan = ch;
2095 return (USBD_NORMAL_COMPLETION);
2099 /* implicit buffer free */
2100 usbd_free_xfer(ch->chanbufs[i].xfer);
2101 return (USBD_NOMEM);
2105 uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch)
2109 for (i = 0; i < UAUDIO_NCHANBUFS; i++)
2110 usbd_free_xfer(ch->chanbufs[i].xfer);
2113 /* Called at splusb() */
2115 uaudio_chan_ptransfer(struct chan *ch)
2118 int i, n, size, residue, total;
2120 if (ch->sc->sc_dying)
2123 /* Pick the next channel buffer. */
2124 cb = &ch->chanbufs[ch->curchanbuf];
2125 if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
2128 /* Compute the size of each frame in the next transfer. */
2129 residue = ch->residue;
2131 for (i = 0; i < UAUDIO_NFRAMES; i++) {
2132 size = ch->bytes_per_frame;
2133 residue += ch->fraction;
2134 if (residue >= USB_FRAMES_PER_SECOND) {
2136 size += ch->sample_size;
2137 residue -= USB_FRAMES_PER_SECOND;
2139 cb->sizes[i] = size;
2142 ch->residue = residue;
2146 * Transfer data from upper layer buffer to channel buffer, taking
2147 * care of wrapping the upper layer buffer.
2149 n = min(total, ch->end - ch->cur);
2150 memcpy(cb->buffer, ch->cur, n);
2152 if (ch->cur >= ch->end)
2153 ch->cur = ch->start;
2156 memcpy(cb->buffer + n, ch->cur, total);
2161 if (uaudiodebug > 8) {
2162 DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03d\n",
2163 cb->buffer, ch->residue));
2164 for (i = 0; i < UAUDIO_NFRAMES; i++) {
2165 DPRINTF((" [%d] length %d\n", i, cb->sizes[i]));
2170 DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer));
2171 /* Fill the request */
2172 usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
2173 UAUDIO_NFRAMES, USBD_NO_COPY,
2176 (void)usbd_transfer(cb->xfer);
2180 uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv,
2183 struct chanbuf *cb = priv;
2184 struct chan *ch = cb->chan;
2188 /* Return if we are aborting. */
2189 if (status == USBD_CANCELLED)
2192 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
2193 DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n",
2194 count, ch->transferred));
2196 if (count != cb->size) {
2197 printf("uaudio_chan_pintr: count(%d) != size(%d)\n",
2202 ch->transferred += cb->size;
2203 #if defined(__FreeBSD__)
2206 chn_intr(ch->pcm_ch);
2210 /* Call back to upper layer */
2211 while (ch->transferred >= ch->blksize) {
2212 ch->transferred -= ch->blksize;
2213 DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)\n",
2214 ch->intr, ch->arg));
2220 /* start next transfer */
2221 uaudio_chan_ptransfer(ch);
2224 /* Called at splusb() */
2226 uaudio_chan_rtransfer(struct chan *ch)
2229 int i, size, residue, total;
2231 if (ch->sc->sc_dying)
2234 /* Pick the next channel buffer. */
2235 cb = &ch->chanbufs[ch->curchanbuf];
2236 if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
2239 /* Compute the size of each frame in the next transfer. */
2240 residue = ch->residue;
2242 for (i = 0; i < UAUDIO_NFRAMES; i++) {
2243 size = ch->bytes_per_frame;
2244 residue += ch->fraction;
2245 if (residue >= USB_FRAMES_PER_SECOND) {
2247 size += ch->sample_size;
2248 residue -= USB_FRAMES_PER_SECOND;
2250 cb->sizes[i] = size;
2253 ch->residue = residue;
2257 if (uaudiodebug > 8) {
2258 DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03d\n",
2259 cb->buffer, ch->residue));
2260 for (i = 0; i < UAUDIO_NFRAMES; i++) {
2261 DPRINTF((" [%d] length %d\n", i, cb->sizes[i]));
2266 DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer));
2267 /* Fill the request */
2268 usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
2269 UAUDIO_NFRAMES, USBD_NO_COPY,
2272 (void)usbd_transfer(cb->xfer);
2276 uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv,
2279 struct chanbuf *cb = priv;
2280 struct chan *ch = cb->chan;
2284 /* Return if we are aborting. */
2285 if (status == USBD_CANCELLED)
2288 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
2289 DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n",
2290 count, ch->transferred));
2292 if (count < cb->size) {
2293 /* if the device fails to keep up, copy last byte */
2294 u_char b = count ? cb->buffer[count-1] : 0;
2295 while (count < cb->size)
2296 cb->buffer[count++] = b;
2300 if (count != cb->size) {
2301 printf("uaudio_chan_rintr: count(%d) != size(%d)\n",
2307 * Transfer data from channel buffer to upper layer buffer, taking
2308 * care of wrapping the upper layer buffer.
2310 n = min(count, ch->end - ch->cur);
2311 memcpy(ch->cur, cb->buffer, n);
2313 if (ch->cur >= ch->end)
2314 ch->cur = ch->start;
2316 memcpy(ch->cur, cb->buffer + n, count - n);
2317 ch->cur += count - n;
2320 /* Call back to upper layer */
2321 ch->transferred += cb->size;
2322 #if defined(__FreeBSD__)
2324 chn_intr(ch->pcm_ch);
2328 while (ch->transferred >= ch->blksize) {
2329 ch->transferred -= ch->blksize;
2330 DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)\n",
2331 ch->intr, ch->arg));
2337 /* start next transfer */
2338 uaudio_chan_rtransfer(ch);
2341 #if defined(__NetBSD__) || defined(__OpenBSD__)
2343 uaudio_chan_set_param(struct chan *ch, struct audio_params *param,
2344 u_char *start, u_char *end, int blksize)
2346 int samples_per_frame, sample_size;
2348 sample_size = param->precision * param->channels / 8;
2349 samples_per_frame = param->sample_rate / USB_FRAMES_PER_SECOND;
2350 ch->fraction = param->sample_rate % USB_FRAMES_PER_SECOND;
2351 ch->sample_size = sample_size;
2352 ch->sample_rate = param->sample_rate;
2353 ch->bytes_per_frame = samples_per_frame * sample_size;
2359 ch->blksize = blksize;
2360 ch->transferred = 0;
2366 uaudio_set_params(void *addr, int setmode, int usemode,
2367 struct audio_params *play, struct audio_params *rec)
2369 struct uaudio_softc *sc = addr;
2370 int flags = sc->sc_altflags;
2373 void (*swcode)(void *, u_char *buf, int cnt);
2374 struct audio_params *p;
2380 if (sc->sc_chan.pipe != NULL)
2383 for (mode = AUMODE_RECORD; mode != -1;
2384 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
2385 if ((setmode & mode) == 0)
2387 if ((sc->sc_chan.dir & mode) == 0)
2390 p = mode == AUMODE_PLAY ? play : rec;
2396 case AUDIO_ENCODING_SLINEAR_BE:
2397 if (p->precision == 16) {
2398 swcode = swap_bytes;
2399 enc = AUDIO_ENCODING_SLINEAR_LE;
2400 } else if (p->precision == 8 && !(flags & HAS_8)) {
2401 swcode = change_sign8;
2402 enc = AUDIO_ENCODING_ULINEAR_LE;
2405 case AUDIO_ENCODING_SLINEAR_LE:
2406 if (p->precision == 8 && !(flags & HAS_8)) {
2407 swcode = change_sign8;
2408 enc = AUDIO_ENCODING_ULINEAR_LE;
2411 case AUDIO_ENCODING_ULINEAR_BE:
2412 if (p->precision == 16) {
2413 if (mode == AUMODE_PLAY)
2414 swcode = swap_bytes_change_sign16_le;
2416 swcode = change_sign16_swap_bytes_le;
2417 enc = AUDIO_ENCODING_SLINEAR_LE;
2418 } else if (p->precision == 8 && !(flags & HAS_8U)) {
2419 swcode = change_sign8;
2420 enc = AUDIO_ENCODING_SLINEAR_LE;
2423 case AUDIO_ENCODING_ULINEAR_LE:
2424 if (p->precision == 16) {
2425 swcode = change_sign16_le;
2426 enc = AUDIO_ENCODING_SLINEAR_LE;
2427 } else if (p->precision == 8 && !(flags & HAS_8U)) {
2428 swcode = change_sign8;
2429 enc = AUDIO_ENCODING_SLINEAR_LE;
2432 case AUDIO_ENCODING_ULAW:
2433 if (!(flags & HAS_MULAW)) {
2434 if (mode == AUMODE_PLAY &&
2436 swcode = mulaw_to_slinear16_le;
2438 enc = AUDIO_ENCODING_SLINEAR_LE;
2439 } else if (flags & HAS_8U) {
2440 if (mode == AUMODE_PLAY)
2441 swcode = mulaw_to_ulinear8;
2443 swcode = ulinear8_to_mulaw;
2444 enc = AUDIO_ENCODING_ULINEAR_LE;
2445 } else if (flags & HAS_8) {
2446 if (mode == AUMODE_PLAY)
2447 swcode = mulaw_to_slinear8;
2449 swcode = slinear8_to_mulaw;
2450 enc = AUDIO_ENCODING_SLINEAR_LE;
2455 case AUDIO_ENCODING_ALAW:
2456 if (!(flags & HAS_ALAW)) {
2457 if (mode == AUMODE_PLAY &&
2459 swcode = alaw_to_slinear16_le;
2461 enc = AUDIO_ENCODING_SLINEAR_LE;
2462 } else if (flags & HAS_8U) {
2463 if (mode == AUMODE_PLAY)
2464 swcode = alaw_to_ulinear8;
2466 swcode = ulinear8_to_alaw;
2467 enc = AUDIO_ENCODING_ULINEAR_LE;
2468 } else if (flags & HAS_8) {
2469 if (mode == AUMODE_PLAY)
2470 swcode = alaw_to_slinear8;
2472 swcode = slinear8_to_alaw;
2473 enc = AUDIO_ENCODING_SLINEAR_LE;
2481 /* XXX do some other conversions... */
2483 DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n",
2484 p->channels, p->precision, enc, p->sample_rate));
2486 for (i = 0; i < sc->sc_nalts; i++) {
2487 struct usb_audio_streaming_type1_descriptor *a1d =
2488 sc->sc_alts[i].asf1desc;
2489 if (p->channels == a1d->bNrChannels &&
2490 p->precision == a1d->bBitResolution &&
2491 enc == sc->sc_alts[i].encoding &&
2492 (mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) ==
2493 UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) {
2494 if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
2495 DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
2496 UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
2497 if (UA_SAMP_LO(a1d) < p->sample_rate &&
2498 p->sample_rate < UA_SAMP_HI(a1d))
2501 for (j = 0; j < a1d->bSamFreqType; j++) {
2502 DPRINTFN(2,("uaudio_set_params: disc #"
2503 "%d: %d\n", j, UA_GETSAMP(a1d, j)));
2504 /* XXX allow for some slack */
2505 if (UA_GETSAMP(a1d, j) ==
2515 p->sw_code = swcode;
2517 if (usemode == mode)
2518 sc->sc_curaltidx = i;
2521 DPRINTF(("uaudio_set_params: use altidx=%d, altno=%d\n",
2523 sc->sc_alts[sc->sc_curaltidx].idesc->bAlternateSetting));
2527 #endif /* NetBSD or OpenBSD */
2530 uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed)
2532 usb_device_request_t req;
2535 DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%u\n", endpt, speed));
2536 req.bmRequestType = UT_WRITE_CLASS_ENDPOINT;
2537 req.bRequest = SET_CUR;
2538 USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
2539 USETW(req.wIndex, endpt);
2540 USETW(req.wLength, 3);
2542 data[1] = speed >> 8;
2543 data[2] = speed >> 16;
2545 return (usbd_do_request(sc->sc_udev, &req, &data));
2549 #if defined(__FreeBSD__)
2550 /************************************************************/
2552 uaudio_init_params(struct uaudio_softc *sc, struct chan *ch)
2555 int samples_per_frame, sample_size;
2557 switch(ch->format & 0x0000FFFF) {
2559 enc = AUDIO_ENCODING_ULINEAR_LE;
2563 enc = AUDIO_ENCODING_SLINEAR_LE;
2566 case AFMT_A_LAW: /* ? */
2567 enc = AUDIO_ENCODING_ALAW;
2570 case AFMT_MU_LAW: /* ? */
2571 enc = AUDIO_ENCODING_ULAW;
2575 enc = AUDIO_ENCODING_SLINEAR_LE;
2579 enc = AUDIO_ENCODING_SLINEAR_BE;
2583 enc = AUDIO_ENCODING_ULINEAR_LE;
2587 enc = AUDIO_ENCODING_ULINEAR_BE;
2593 printf("Unknown format %x\n", ch->format);
2596 if (ch->format & AFMT_STEREO) {
2602 /* for (mode = ...... */
2603 for (i = 0; i < sc->sc_nalts; i++) {
2604 struct usb_audio_streaming_type1_descriptor *a1d =
2605 sc->sc_alts[i].asf1desc;
2606 if (ch->channels == a1d->bNrChannels &&
2607 ch->precision == a1d->bBitResolution &&
2609 enc == sc->sc_alts[i].encoding) {
2611 enc == sc->sc_alts[i].encoding &&
2612 (mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) ==
2613 UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) {
2615 if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
2616 DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
2617 UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
2618 if (UA_SAMP_LO(a1d) < ch->sample_rate &&
2619 ch->sample_rate < UA_SAMP_HI(a1d)) {
2620 sc->sc_curaltidx = i;
2624 for (j = 0; j < a1d->bSamFreqType; j++) {
2625 DPRINTFN(2,("uaudio_set_params: disc #"
2626 "%d: %d\n", j, UA_GETSAMP(a1d, j)));
2627 /* XXX allow for some slack */
2628 if (UA_GETSAMP(a1d, j) ==
2630 sc->sc_curaltidx = i;
2637 /* return (EINVAL); */
2641 p->sw_code = swcode;
2643 if (usemode == mode)
2644 sc->sc_curaltidx = i;
2648 sample_size = ch->precision * ch->channels / 8;
2649 samples_per_frame = ch->sample_rate / USB_FRAMES_PER_SECOND;
2650 ch->fraction = ch->sample_rate % USB_FRAMES_PER_SECOND;
2651 ch->sample_size = sample_size;
2652 ch->bytes_per_frame = samples_per_frame * sample_size;
2655 ch->cur = ch->start;
2656 ch->transferred = 0;
2661 uaudio_query_formats(device_t dev, u_int32_t *pfmt, u_int32_t *rfmt)
2666 struct uaudio_softc *sc;
2668 struct usb_audio_streaming_type1_descriptor *a1d;
2670 sc = device_get_softc(dev);
2672 for (i = 0; i < sc->sc_nalts; i++) {
2674 a1d = sc->sc_alts[i].asf1desc;
2675 prec = a1d->bBitResolution; /* precision */
2677 switch (sc->sc_alts[i].encoding) {
2678 case AUDIO_ENCODING_ULINEAR_LE:
2681 } else if (prec == 16) {
2685 case AUDIO_ENCODING_SLINEAR_LE:
2688 } else if (prec == 16) {
2692 case AUDIO_ENCODING_ULINEAR_BE:
2697 case AUDIO_ENCODING_SLINEAR_BE:
2702 case AUDIO_ENCODING_ALAW:
2707 case AUDIO_ENCODING_ULAW:
2715 if (a1d->bNrChannels == 2) { /* stereo/mono */
2717 } else if (a1d->bNrChannels != 1) {
2723 dir= UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
2724 if (dir == UE_DIR_OUT) {
2726 } else if (dir == UE_DIR_IN) {
2731 if ((pn > 8*2) || (rn > 8*2))
2740 uaudio_chan_set_param_pcm_dma_buff(device_t dev, u_char *start, u_char *end,
2741 struct pcm_channel *pc)
2743 struct uaudio_softc *sc;
2746 sc = device_get_softc(dev);
2758 uaudio_chan_set_param_blocksize(device_t dev, u_int32_t blocksize)
2760 struct uaudio_softc *sc;
2763 sc = device_get_softc(dev);
2766 ch->blksize = blocksize;
2772 uaudio_chan_set_param_speed(device_t dev, u_int32_t speed)
2774 struct uaudio_softc *sc;
2777 sc = device_get_softc(dev);
2780 ch->sample_rate = speed;
2786 uaudio_chan_getptr(device_t dev)
2788 struct uaudio_softc *sc;
2792 sc = device_get_softc(dev);
2795 ptr = ch->cur - ch->start;
2801 uaudio_chan_set_param_format(device_t dev, u_int32_t format)
2803 struct uaudio_softc *sc;
2806 sc = device_get_softc(dev);
2809 ch->format = format;
2815 uaudio_halt_out_dma(device_t dev)
2817 struct uaudio_softc *sc;
2819 sc = device_get_softc(dev);
2821 DPRINTF(("uaudio_halt_out_dma: enter\n"));
2822 if (sc->sc_chan.pipe != NULL) {
2823 uaudio_chan_close(sc, &sc->sc_chan);
2824 sc->sc_chan.pipe = 0;
2825 uaudio_chan_free_buffers(sc, &sc->sc_chan);
2831 uaudio_trigger_output(device_t dev)
2833 struct uaudio_softc *sc;
2838 sc = device_get_softc(dev);
2844 uaudio_init_params(sc, ch);
2846 err = uaudio_chan_alloc_buffers(sc, ch);
2850 err = uaudio_chan_open(sc, ch);
2852 uaudio_chan_free_buffers(sc, ch);
2857 for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
2858 uaudio_chan_ptransfer(ch);
2865 uaudio_query_mix_info(device_t dev)
2869 struct uaudio_softc *sc;
2870 struct mixerctl *mc;
2872 sc = device_get_softc(dev);
2873 for (i=0; i < sc->sc_nctls; i++) {
2874 mc = &sc->sc_ctls[i];
2875 if (mc->ctl != SOUND_MIXER_NRDEVICES) {
2876 /* Set device mask bits.
2877 See /usr/include/machine/soundcard.h */
2878 mask |= (1 << mc->ctl);
2885 uaudio_mixer_set(device_t dev, unsigned type, unsigned left, unsigned right)
2888 struct uaudio_softc *sc;
2889 struct mixerctl *mc;
2891 sc = device_get_softc(dev);
2892 for (i=0; i < sc->sc_nctls; i++) {
2893 mc = &sc->sc_ctls[i];
2894 if (mc->ctl == type) {
2895 if (mc->nchan == 2) {
2897 uaudio_ctl_set(sc, SET_CUR, mc, 1, (int)(right*256)/100);
2899 /* set Left or Mono */
2900 uaudio_ctl_set(sc, SET_CUR, mc, 0, (int)(left*256)/100);
2907 audio_attach_mi(device_t dev)
2910 struct sndcard_func *func;
2912 /* Attach the children. */
2914 func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
2917 bzero(func, sizeof(*func));
2918 func->func = SCF_PCM;
2919 child = device_add_child(dev, "pcm", -1);
2920 device_set_ivars(child, func);
2922 bus_generic_attach(dev);
2924 return 0; /* XXXXX */
2927 DRIVER_MODULE(uaudio, uhub, uaudio_driver, uaudio_devclass, usbd_driver_load, 0);
2928 MODULE_VERSION(uaudio, 1);