summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2009-02-23 21:07:20 +0000
committerthompsa <thompsa@FreeBSD.org>2009-02-23 21:07:20 +0000
commitde29f650e65ee47a3b0430555b28f248cbceb4da (patch)
tree950fd630ee5efc2483a3c62d06f19a6246f5a15c /sys/dev/sound
parent40c2eac6aa3328ce690020e0325867fd0ee36d1c (diff)
downloadFreeBSD-src-de29f650e65ee47a3b0430555b28f248cbceb4da.zip
FreeBSD-src-de29f650e65ee47a3b0430555b28f248cbceb4da.tar.gz
Move two missed usb drivers out to the graveyard location under sys/legacy/dev.
Diffstat (limited to 'sys/dev/sound')
-rw-r--r--sys/dev/sound/usb/uaudio.c4662
-rw-r--r--sys/dev/sound/usb/uaudio.h56
-rw-r--r--sys/dev/sound/usb/uaudio_pcm.c481
-rw-r--r--sys/dev/sound/usb/uaudioreg.h404
4 files changed, 0 insertions, 5603 deletions
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
deleted file mode 100644
index 758d6cd..0000000
--- a/sys/dev/sound/usb/uaudio.c
+++ /dev/null
@@ -1,4662 +0,0 @@
-/* $NetBSD: uaudio.c,v 1.91 2004/11/05 17:46:14 kent Exp $ */
-/* $FreeBSD$ */
-
-/*-
- * Copyright (c) 1999 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (lennart@augustsson.net) at
- * Carlstedt Research & Technology.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * USB audio specs: http://www.usb.org/developers/devclass_docs/audio10.pdf
- * http://www.usb.org/developers/devclass_docs/frmts10.pdf
- * http://www.usb.org/developers/devclass_docs/termt10.pdf
- */
-
-#include <sys/cdefs.h>
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-__KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.91 2004/11/05 17:46:14 kent Exp $");
-#endif
-
-/*
- * Also merged:
- * $NetBSD: uaudio.c,v 1.94 2005/01/15 15:19:53 kent Exp $
- * $NetBSD: uaudio.c,v 1.95 2005/01/16 06:02:19 dsainty Exp $
- * $NetBSD: uaudio.c,v 1.96 2005/01/16 12:46:00 kent Exp $
- * $NetBSD: uaudio.c,v 1.97 2005/02/24 08:19:38 martin Exp $
- * $NetBSD: uaudio.c,v 1.102 2006/04/14 17:00:55 christos Exp $
- * $NetBSD: uaudio.c,v 1.103 2006/05/11 19:09:25 mrg Exp $
- * $NetBSD: uaudio.c,v 1.105 2006/10/04 16:00:15 christos Exp $
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-#include <sys/device.h>
-#include <sys/ioctl.h>
-#endif
-#include <sys/tty.h>
-#include <sys/file.h>
-#include <sys/reboot.h> /* for bootverbose */
-#include <sys/select.h>
-#include <sys/proc.h>
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-#include <sys/device.h>
-#elif defined(__FreeBSD__)
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#endif
-#include <sys/poll.h>
-#if defined(__FreeBSD__)
-#include <sys/sysctl.h>
-#include <sys/sbuf.h>
-#endif
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-#include <sys/audioio.h>
-#include <dev/audio_if.h>
-#include <dev/audiovar.h>
-#include <dev/mulaw.h>
-#include <dev/auconv.h>
-#elif defined(__FreeBSD__)
-#include <dev/sound/pcm/sound.h> /* XXXXX */
-#include <dev/sound/chip.h>
-#include "feeder_if.h"
-#endif
-
-#include <dev/usb/usb_port.h>
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usb_quirks.h>
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-#include <dev/usb/uaudioreg.h>
-#elif defined(__FreeBSD__)
-#include <dev/sound/usb/uaudioreg.h>
-#include <dev/sound/usb/uaudio.h>
-#endif
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-/* #define UAUDIO_DEBUG */
-#else
-/* #define USB_DEBUG */
-#endif
-/* #define UAUDIO_MULTIPLE_ENDPOINTS */
-#ifdef USB_DEBUG
-#define DPRINTF(x) do { if (uaudiodebug) printf x; } while (0)
-#define DPRINTFN(n,x) do { if (uaudiodebug>(n)) printf x; } while (0)
-int uaudiodebug = 0;
-#if defined(__FreeBSD__)
-SYSCTL_NODE(_hw_usb, OID_AUTO, uaudio, CTLFLAG_RW, 0, "USB uaudio");
-SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, debug, CTLFLAG_RW,
- &uaudiodebug, 0, "uaudio debug level");
-#endif
-#else
-#define DPRINTF(x)
-#define DPRINTFN(n,x)
-#endif
-
-#define UAUDIO_NCHANBUFS 6 /* number of outstanding request */
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-#define UAUDIO_NFRAMES 10 /* ms of sound in each request */
-#elif defined(__FreeBSD__)
-#define UAUDIO_NFRAMES 20 /* ms of sound in each request */
-#endif
-
-
-#define MIX_MAX_CHAN 8
-struct mixerctl {
- uint16_t wValue[MIX_MAX_CHAN]; /* using nchan */
- uint16_t wIndex;
- uint8_t nchan;
- uint8_t type;
-#define MIX_ON_OFF 1
-#define MIX_SIGNED_16 2
-#define MIX_UNSIGNED_16 3
-#define MIX_SIGNED_8 4
-#define MIX_SELECTOR 5
-#define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1)
-#define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16)
- int minval, maxval;
- u_int delta;
- u_int mul;
-#if defined(__FreeBSD__) /* XXXXX */
- unsigned ctl;
-#define MAX_SELECTOR_INPUT_PIN 256
- uint8_t slctrtype[MAX_SELECTOR_INPUT_PIN];
-#endif
- uint8_t class;
-#if !defined(__FreeBSD__)
- char ctlname[MAX_AUDIO_DEV_LEN];
- char *ctlunit;
-#endif
-};
-#define MAKE(h,l) (((h) << 8) | (l))
-
-struct as_info {
- uint8_t alt;
- uint8_t encoding;
- uint8_t attributes; /* Copy of bmAttributes of
- * usb_audio_streaming_endpoint_descriptor
- */
- usbd_interface_handle ifaceh;
- const usb_interface_descriptor_t *idesc;
- const usb_endpoint_descriptor_audio_t *edesc;
- const usb_endpoint_descriptor_audio_t *edesc1;
- const struct usb_audio_streaming_type1_descriptor *asf1desc;
- int sc_busy; /* currently used */
-};
-
-struct chan {
-#if defined(__NetBSD__) || defined(__OpenBSD__)
- void (*intr)(void *); /* DMA completion intr handler */
- void *arg; /* arg for intr() */
-#else
- struct pcm_channel *pcm_ch;
-#endif
- usbd_pipe_handle pipe;
- usbd_pipe_handle sync_pipe;
-
- u_int sample_size;
- u_int sample_rate;
- u_int bytes_per_frame;
- u_int fraction; /* fraction/1000 is the extra samples/frame */
- u_int residue; /* accumulates the fractional samples */
-
- u_char *start; /* upper layer buffer start */
- u_char *end; /* upper layer buffer end */
- u_char *cur; /* current position in upper layer buffer */
- int blksize; /* chunk size to report up */
- int transferred; /* transferred bytes not reported up */
-
- int altidx; /* currently used altidx */
-
- int curchanbuf;
- struct chanbuf {
- struct chan *chan;
- usbd_xfer_handle xfer;
- u_char *buffer;
- u_int16_t sizes[UAUDIO_NFRAMES];
- u_int16_t offsets[UAUDIO_NFRAMES];
- u_int16_t size;
- } chanbufs[UAUDIO_NCHANBUFS];
-
- struct uaudio_softc *sc; /* our softc */
-#if defined(__FreeBSD__)
- u_int32_t format;
- int precision;
- int channels;
-#endif
-};
-
-struct uaudio_softc {
- device_t sc_dev; /* base device */
- usbd_device_handle sc_udev; /* USB device */
- int sc_ac_iface; /* Audio Control interface */
- usbd_interface_handle sc_ac_ifaceh;
- struct chan sc_playchan; /* play channel */
- struct chan sc_recchan; /* record channel */
- int sc_nullalt;
- int sc_audio_rev;
- struct as_info *sc_alts; /* alternate settings */
- int sc_nalts; /* # of alternate settings */
- int sc_altflags;
-#define HAS_8 0x01
-#define HAS_16 0x02
-#define HAS_8U 0x04
-#define HAS_ALAW 0x08
-#define HAS_MULAW 0x10
-#define UA_NOFRAC 0x20 /* don't do sample rate adjustment */
-#define HAS_24 0x40
-#define HAS_32 0x80
- int sc_mode; /* play/record capability */
- struct mixerctl *sc_ctls; /* mixer controls */
- int sc_nctls; /* # of mixer controls */
- device_t sc_audiodev;
- char sc_dying;
-#if defined(__FreeBSD__)
- struct sbuf uaudio_sndstat;
- int uaudio_sndstat_flag;
- int async;
-#endif
- int sc_vendor;
- int sc_product;
- int sc_release;
-};
-
-struct terminal_list {
- int size;
- uint16_t terminals[1];
-};
-#define TERMINAL_LIST_SIZE(N) (offsetof(struct terminal_list, terminals) \
- + sizeof(uint16_t) * (N))
-
-struct io_terminal {
- union {
- const usb_descriptor_t *desc;
- const struct usb_audio_input_terminal *it;
- const struct usb_audio_output_terminal *ot;
- const struct usb_audio_mixer_unit *mu;
- const struct usb_audio_selector_unit *su;
- const struct usb_audio_feature_unit *fu;
- const struct usb_audio_processing_unit *pu;
- const struct usb_audio_extension_unit *eu;
- } d;
- int inputs_size;
- struct terminal_list **inputs; /* list of source input terminals */
- struct terminal_list *output; /* list of destination output terminals */
- int direct; /* directly connected to an output terminal */
-};
-
-#define UAC_OUTPUT 0
-#define UAC_INPUT 1
-#define UAC_EQUAL 2
-#define UAC_RECORD 3
-#define UAC_NCLASSES 4
-#ifdef USB_DEBUG
-#if defined(__FreeBSD__)
-#define AudioCinputs "inputs"
-#define AudioCoutputs "outputs"
-#define AudioCrecord "record"
-#define AudioCequalization "equalization"
-#endif
-static const char *uac_names[] = {
- AudioCoutputs, AudioCinputs, AudioCequalization, AudioCrecord,
-};
-#endif
-
-static usbd_status uaudio_identify_ac
- (struct uaudio_softc *, const usb_config_descriptor_t *);
-static usbd_status uaudio_identify_as
- (struct uaudio_softc *, const usb_config_descriptor_t *);
-static usbd_status uaudio_process_as
- (struct uaudio_softc *, const char *, int *, int,
- const usb_interface_descriptor_t *);
-
-static void uaudio_add_alt(struct uaudio_softc *, const struct as_info *);
-
-static const usb_interface_descriptor_t *uaudio_find_iface
- (const char *, int, int *, int);
-
-static void uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *);
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static char *uaudio_id_name
- (struct uaudio_softc *, const struct io_terminal *, int);
-#endif
-
-#ifdef USB_DEBUG
-static void uaudio_dump_cluster(const struct usb_audio_cluster *);
-#endif
-static struct usb_audio_cluster uaudio_get_cluster
- (int, const struct io_terminal *);
-static void uaudio_add_input
- (struct uaudio_softc *, const struct io_terminal *, int);
-static void uaudio_add_output
- (struct uaudio_softc *, const struct io_terminal *, int);
-static void uaudio_add_mixer
- (struct uaudio_softc *, const struct io_terminal *, int);
-static void uaudio_add_selector
- (struct uaudio_softc *, const struct io_terminal *, int);
-#ifdef USB_DEBUG
-static const char *uaudio_get_terminal_name(int);
-#endif
-static int uaudio_determine_class
- (const struct io_terminal *, struct mixerctl *);
-#if defined(__FreeBSD__)
-static int uaudio_feature_name(const struct io_terminal *,
- struct mixerctl *);
-#else
-static const char *uaudio_feature_name
- (const struct io_terminal *, struct mixerctl *);
-#endif
-static void uaudio_add_feature
- (struct uaudio_softc *, const struct io_terminal *, int);
-static void uaudio_add_processing_updown
- (struct uaudio_softc *, const struct io_terminal *, int);
-static void uaudio_add_processing
- (struct uaudio_softc *, const struct io_terminal *, int);
-static void uaudio_add_extension
- (struct uaudio_softc *, const struct io_terminal *, int);
-static struct terminal_list *uaudio_merge_terminal_list
- (const struct io_terminal *);
-static struct terminal_list *uaudio_io_terminaltype
- (int, struct io_terminal *, int);
-static usbd_status uaudio_identify
- (struct uaudio_softc *, const usb_config_descriptor_t *);
-
-static int uaudio_signext(int, int);
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static int uaudio_value2bsd(struct mixerctl *, int);
-#endif
-static int uaudio_bsd2value(struct mixerctl *, int);
-static int uaudio_get(struct uaudio_softc *, int, int, int, int, int);
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static int uaudio_ctl_get
- (struct uaudio_softc *, int, struct mixerctl *, int);
-#endif
-static void uaudio_set
- (struct uaudio_softc *, int, int, int, int, int, int);
-static void uaudio_ctl_set
- (struct uaudio_softc *, int, struct mixerctl *, int, int);
-
-static usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int);
-
-static usbd_status uaudio_chan_open(struct uaudio_softc *, struct chan *);
-static void uaudio_chan_close(struct uaudio_softc *, struct chan *);
-static usbd_status uaudio_chan_alloc_buffers
- (struct uaudio_softc *, struct chan *);
-static void uaudio_chan_free_buffers(struct uaudio_softc *, struct chan *);
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static void uaudio_chan_init
- (struct chan *, int, const struct audio_params *, int);
-static void uaudio_chan_set_param(struct chan *, u_char *, u_char *, int);
-#endif
-
-static void uaudio_chan_ptransfer(struct chan *);
-static void uaudio_chan_pintr
- (usbd_xfer_handle, usbd_private_handle, usbd_status);
-
-static void uaudio_chan_rtransfer(struct chan *);
-static void uaudio_chan_rintr
- (usbd_xfer_handle, usbd_private_handle, usbd_status);
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static int uaudio_open(void *, int);
-static void uaudio_close(void *);
-static int uaudio_drain(void *);
-static int uaudio_query_encoding(void *, struct audio_encoding *);
-static void uaudio_get_minmax_rates
- (int, const struct as_info *, const struct audio_params *,
- int, u_long *, u_long *);
-static int uaudio_match_alt_sub
- (int, const struct as_info *, const struct audio_params *, int, u_long);
-static int uaudio_match_alt_chan
- (int, const struct as_info *, struct audio_params *, int);
-static int uaudio_match_alt
- (int, const struct as_info *, struct audio_params *, int);
-static int uaudio_set_params
- (void *, int, int, struct audio_params *, struct audio_params *);
-static int uaudio_round_blocksize(void *, int);
-static int uaudio_trigger_output
- (void *, void *, void *, int, void (*)(void *), void *,
- struct audio_params *);
-static int uaudio_trigger_input
- (void *, void *, void *, int, void (*)(void *), void *,
- struct audio_params *);
-static int uaudio_halt_in_dma(void *);
-static int uaudio_halt_out_dma(void *);
-static int uaudio_getdev(void *, struct audio_device *);
-static int uaudio_mixer_set_port(void *, mixer_ctrl_t *);
-static int uaudio_mixer_get_port(void *, mixer_ctrl_t *);
-static int uaudio_query_devinfo(void *, mixer_devinfo_t *);
-static int uaudio_get_props(void *);
-
-static const struct audio_hw_if uaudio_hw_if = {
- uaudio_open,
- uaudio_close,
- uaudio_drain,
- uaudio_query_encoding,
- uaudio_set_params,
- uaudio_round_blocksize,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- uaudio_halt_out_dma,
- uaudio_halt_in_dma,
- NULL,
- uaudio_getdev,
- NULL,
- uaudio_mixer_set_port,
- uaudio_mixer_get_port,
- uaudio_query_devinfo,
- NULL,
- NULL,
- NULL,
- NULL,
- uaudio_get_props,
- uaudio_trigger_output,
- uaudio_trigger_input,
- NULL,
-};
-
-static struct audio_device uaudio_device = {
- "USB audio",
- "",
- "uaudio"
-};
-
-#elif defined(__FreeBSD__)
-static int audio_attach_mi(device_t);
-static int uaudio_init_params(struct uaudio_softc * sc, struct chan *ch, int mode);
-static int uaudio_sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose);
-
-/* for NetBSD compatibirity */
-#define AUMODE_PLAY 0x01
-#define AUMODE_RECORD 0x02
-
-#define AUDIO_PROP_FULLDUPLEX 0x01
-
-#define AUDIO_ENCODING_ULAW 1
-#define AUDIO_ENCODING_ALAW 2
-#define AUDIO_ENCODING_SLINEAR_LE 6
-#define AUDIO_ENCODING_SLINEAR_BE 7
-#define AUDIO_ENCODING_ULINEAR_LE 8
-#define AUDIO_ENCODING_ULINEAR_BE 9
-
-#endif /* FreeBSD */
-
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-
-USB_DECLARE_DRIVER(uaudio);
-
-#elif defined(__FreeBSD__)
-
-USB_DECLARE_DRIVER_INIT(uaudio,
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(bus_print_child, bus_generic_print_child)
- );
-#endif
-
-
-USB_MATCH(uaudio)
-{
- USB_MATCH_START(uaudio, uaa);
- usb_interface_descriptor_t *id;
-
- if (uaa->iface == NULL)
- return UMATCH_NONE;
-
- id = usbd_get_interface_descriptor(uaa->iface);
- /* Trigger on the control interface. */
- if (id == NULL ||
- id->bInterfaceClass != UICLASS_AUDIO ||
- id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL ||
- (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
- return UMATCH_NONE;
-
- return UMATCH_IFACECLASS_IFACESUBCLASS;
-}
-
-USB_ATTACH(uaudio)
-{
- USB_ATTACH_START(uaudio, sc, uaa);
- usb_interface_descriptor_t *id;
- usb_config_descriptor_t *cdesc;
-#if !defined(__FreeBSD__)
- char devinfo[1024];
-#endif
- usbd_status err;
- int i, j, found;
-
-#if defined(__FreeBSD__)
- sc->sc_dev = self;
-#else
- usbd_devinfo(uaa->device, 0, devinfo, sizeof(devinfo));
- printf(": %s\n", devinfo);
-#endif
-
- sc->sc_udev = uaa->device;
- sc->sc_vendor = uaa->vendor;
- sc->sc_product = uaa->product;
- sc->sc_release = uaa->release;
-#if defined(__FreeBSD__)
- if (resource_int_value(device_get_name(sc->sc_dev),
- device_get_unit(sc->sc_dev), "async", &i) == 0 && i != 0)
- sc->async = 1;
- else
- sc->async = 0;
-#endif
-
- cdesc = usbd_get_config_descriptor(sc->sc_udev);
- if (cdesc == NULL) {
- printf("%s: failed to get configuration descriptor\n",
- device_get_nameunit(sc->sc_dev));
- return ENXIO;
- }
-
- err = uaudio_identify(sc, cdesc);
- if (err) {
- printf("%s: audio descriptors make no sense, error=%d\n",
- device_get_nameunit(sc->sc_dev), err);
- return ENXIO;
- }
-
- sc->sc_ac_ifaceh = uaa->iface;
- /* Pick up the AS interface. */
- for (i = 0; i < uaa->nifaces; i++) {
- if (uaa->ifaces[i] == NULL)
- continue;
- id = usbd_get_interface_descriptor(uaa->ifaces[i]);
- if (id == NULL)
- continue;
- found = 0;
- for (j = 0; j < sc->sc_nalts; j++) {
- if (id->bInterfaceNumber ==
- sc->sc_alts[j].idesc->bInterfaceNumber) {
- sc->sc_alts[j].ifaceh = uaa->ifaces[i];
- found = 1;
- }
- }
- if (found)
- uaa->ifaces[i] = NULL;
- }
-
- for (j = 0; j < sc->sc_nalts; j++) {
- if (sc->sc_alts[j].ifaceh == NULL) {
- printf("%s: alt %d missing AS interface(s)\n",
- device_get_nameunit(sc->sc_dev), j);
- return ENXIO;
- }
- }
-
- printf("%s: audio rev %d.%02x\n", device_get_nameunit(sc->sc_dev),
- sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
-
- sc->sc_playchan.sc = sc->sc_recchan.sc = sc;
- sc->sc_playchan.altidx = -1;
- sc->sc_recchan.altidx = -1;
-
- if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
- sc->sc_altflags |= UA_NOFRAC;
-
-#ifndef USB_DEBUG
- if (bootverbose)
-#endif
- printf("%s: %d mixer controls\n", device_get_nameunit(sc->sc_dev),
- sc->sc_nctls);
-
-#if !defined(__FreeBSD__)
- usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
- USBDEV(sc->sc_dev));
-#endif
-
- DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
-#if defined(__OpenBSD__)
- audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
-#elif defined(__NetBSD__)
- sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
-#elif defined(__FreeBSD__)
- sc->sc_dying = 0;
- if (audio_attach_mi(sc->sc_dev)) {
- printf("audio_attach_mi failed\n");
- return ENXIO;
- }
-#endif
-
-#if defined(__FreeBSD__)
- SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->sc_dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)),
- OID_AUTO, "async", CTLFLAG_RW, &sc->async, 0,
- "Asynchronous USB request");
-#endif
- return 0;
-}
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-int
-uaudio_activate(device_t self, enum devact act)
-{
- struct uaudio_softc *sc;
- int rv;
-
- sc = (struct uaudio_softc *)self;
- rv = 0;
- switch (act) {
- case DVACT_ACTIVATE:
- return EOPNOTSUPP;
-
- case DVACT_DEACTIVATE:
- if (sc->sc_audiodev != NULL)
- rv = config_deactivate(sc->sc_audiodev);
- sc->sc_dying = 1;
- break;
- }
- return rv;
-}
-#endif
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-int
-uaudio_detach(device_t self, int flags)
-{
- struct uaudio_softc *sc;
- int rv;
-
- sc = (struct uaudio_softc *)self;
- rv = 0;
- /* Wait for outstanding requests to complete. */
- usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
-
- if (sc->sc_audiodev != NULL)
- rv = config_detach(sc->sc_audiodev, flags);
-
- usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
- USBDEV(sc->sc_dev));
-
- return rv;
-}
-#elif defined(__FreeBSD__)
-
-USB_DETACH(uaudio)
-{
- struct sndcard_func *func;
- device_t *devlist = NULL;
- int err, i, devcount;
-
- USB_DETACH_START(uaudio, sc);
-
- sbuf_delete(&(sc->uaudio_sndstat));
- sc->uaudio_sndstat_flag = 0;
-
- sc->sc_dying = 1;
-
-#if 0 /* XXX */
- /* Wait for outstanding requests to complete. */
- usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
-#endif
-
- err = bus_generic_detach(sc->sc_dev);
-
- if (err == 0 &&
- device_get_children(sc->sc_dev, &devlist, &devcount) == 0) {
- for (i = 0; devlist != NULL && i < devcount; i++) {
- func = device_get_ivars(devlist[i]);
- if (func != NULL && func->func == SCF_PCM &&
- func->varinfo == NULL) {
- device_set_ivars(devlist[i], NULL);
- free(func, M_DEVBUF);
- device_delete_child(sc->sc_dev, devlist[i]);
- }
- }
- free(devlist, M_TEMP);
- }
-
- return err;
-}
-#endif
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static int
-uaudio_query_encoding(void *addr, struct audio_encoding *fp)
-{
- struct uaudio_softc *sc;
- int flags;
- int idx;
-
- sc = addr;
- flags = sc->sc_altflags;
- if (sc->sc_dying)
- return EIO;
-
- if (sc->sc_nalts == 0 || flags == 0)
- return ENXIO;
-
- idx = fp->index;
- switch (idx) {
- case 0:
- strlcpy(fp->name, AudioEulinear, sizeof(fp->name));
- fp->encoding = AUDIO_ENCODING_ULINEAR;
- fp->precision = 8;
- fp->flags = flags&HAS_8U ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
- return (0);
- case 1:
- strlcpy(fp->name, AudioEmulaw, sizeof(fp->name));
- fp->encoding = AUDIO_ENCODING_ULAW;
- fp->precision = 8;
- fp->flags = flags&HAS_MULAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
- return (0);
- case 2:
- strlcpy(fp->name, AudioEalaw, sizeof(fp->name));
- fp->encoding = AUDIO_ENCODING_ALAW;
- fp->precision = 8;
- fp->flags = flags&HAS_ALAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
- return (0);
- case 3:
- strlcpy(fp->name, AudioEslinear, sizeof(fp->name));
- fp->encoding = AUDIO_ENCODING_SLINEAR;
- fp->precision = 8;
- fp->flags = flags&HAS_8 ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
- return (0);
- case 4:
- strlcpy(fp->name, AudioEslinear_le, sizeof(fp->name));
- fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
- fp->precision = 16;
- fp->flags = 0;
- return (0);
- case 5:
- strlcpy(fp->name, AudioEulinear_le, sizeof(fp->name));
- fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
- fp->precision = 16;
- fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
- return (0);
- case 6:
- strlcpy(fp->name, AudioEslinear_be, sizeof(fp->name));
- fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
- fp->precision = 16;
- fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
- return (0);
- case 7:
- strlcpy(fp->name, AudioEulinear_be, sizeof(fp->name));
- fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
- fp->precision = 16;
- fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
- return (0);
- default:
- return (EINVAL);
- }
-}
-#endif
-
-static const usb_interface_descriptor_t *
-uaudio_find_iface(const char *buf, int size, int *offsp, int subtype)
-{
- const usb_interface_descriptor_t *d;
-
- while (*offsp < size) {
- d = (const void *)(buf + *offsp);
- *offsp += d->bLength;
- if (d->bDescriptorType == UDESC_INTERFACE &&
- d->bInterfaceClass == UICLASS_AUDIO &&
- d->bInterfaceSubClass == subtype)
- return d;
- }
- return NULL;
-}
-
-static void
-uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc)
-{
- int res;
- size_t len;
- struct mixerctl *nmc;
-
-#if defined(__FreeBSD__)
- if (mc->class < UAC_NCLASSES) {
- DPRINTF(("%s: adding %s.%d\n",
- __func__, uac_names[mc->class], mc->ctl));
- } else {
- DPRINTF(("%s: adding %d\n", __func__, mc->ctl));
- }
-#else
- if (mc->class < UAC_NCLASSES) {
- DPRINTF(("%s: adding %s.%s\n",
- __func__, uac_names[mc->class], mc->ctlname));
- } else {
- DPRINTF(("%s: adding %s\n", __func__, mc->ctlname));
- }
-#endif
- len = sizeof(*mc) * (sc->sc_nctls + 1);
- nmc = malloc(len, M_USBDEV, M_NOWAIT);
- if (nmc == NULL) {
- printf("uaudio_mixer_add_ctl: no memory\n");
- return;
- }
- /* Copy old data, if there was any */
- if (sc->sc_nctls != 0) {
- memcpy(nmc, sc->sc_ctls, sizeof(*mc) * (sc->sc_nctls));
- free(sc->sc_ctls, M_USBDEV);
- }
- sc->sc_ctls = nmc;
-
- mc->delta = 0;
- if (mc->type == MIX_ON_OFF) {
- mc->minval = 0;
- mc->maxval = 1;
- } else if (mc->type == MIX_SELECTOR) {
- ;
- } else {
- /* Determine min and max values. */
- mc->minval = uaudio_signext(mc->type,
- uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
- mc->wValue[0], mc->wIndex,
- MIX_SIZE(mc->type)));
- mc->maxval = 1 + uaudio_signext(mc->type,
- uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE,
- mc->wValue[0], mc->wIndex,
- MIX_SIZE(mc->type)));
- mc->mul = mc->maxval - mc->minval;
- if (mc->mul == 0)
- mc->mul = 1;
- res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
- mc->wValue[0], mc->wIndex,
- MIX_SIZE(mc->type));
- if (res > 0)
- mc->delta = (res * 255 + mc->mul/2) / mc->mul;
- }
-
- sc->sc_ctls[sc->sc_nctls++] = *mc;
-
-#ifdef USB_DEBUG
- if (uaudiodebug > 2) {
- int i;
- DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc->wValue[0]));
- for (i = 1; i < mc->nchan; i++)
- DPRINTF((",%04x", mc->wValue[i]));
-#if defined(__FreeBSD__)
- DPRINTF((" wIndex=%04x type=%d ctl='%d' "
- "min=%d max=%d\n",
- mc->wIndex, mc->type, mc->ctl,
- mc->minval, mc->maxval));
-#else
- DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' "
- "min=%d max=%d\n",
- mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
- mc->minval, mc->maxval));
-#endif
- }
-#endif
-}
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static char *
-uaudio_id_name(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
-{
- static char buf[32];
-
- snprintf(buf, sizeof(buf), "i%d", id);
- return buf;
-}
-#endif
-
-#ifdef USB_DEBUG
-static void
-uaudio_dump_cluster(const struct usb_audio_cluster *cl)
-{
- static const char *channel_names[16] = {
- "LEFT", "RIGHT", "CENTER", "LFE",
- "LEFT_SURROUND", "RIGHT_SURROUND", "LEFT_CENTER", "RIGHT_CENTER",
- "SURROUND", "LEFT_SIDE", "RIGHT_SIDE", "TOP",
- "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15",
- };
- int cc, i, first;
-
- cc = UGETW(cl->wChannelConfig);
- printf("cluster: bNrChannels=%u wChannelConfig=0x%.4x",
- cl->bNrChannels, cc);
- first = TRUE;
- for (i = 0; cc != 0; i++) {
- if (cc & 1) {
- printf("%c%s", first ? '<' : ',', channel_names[i]);
- first = FALSE;
- }
- cc = cc >> 1;
- }
- printf("> iChannelNames=%u", cl->iChannelNames);
-}
-#endif
-
-static struct usb_audio_cluster
-uaudio_get_cluster(int id, const struct io_terminal *iot)
-{
- struct usb_audio_cluster r;
- const usb_descriptor_t *dp;
- int i;
-
- for (i = 0; i < 25; i++) { /* avoid infinite loops */
- dp = iot[id].d.desc;
- if (dp == 0)
- goto bad;
- switch (dp->bDescriptorSubtype) {
- case UDESCSUB_AC_INPUT:
- r.bNrChannels = iot[id].d.it->bNrChannels;
- USETW(r.wChannelConfig, UGETW(iot[id].d.it->wChannelConfig));
- r.iChannelNames = iot[id].d.it->iChannelNames;
- return r;
- case UDESCSUB_AC_OUTPUT:
- id = iot[id].d.ot->bSourceId;
- break;
- case UDESCSUB_AC_MIXER:
- r = *(const struct usb_audio_cluster *)
- &iot[id].d.mu->baSourceId[iot[id].d.mu->bNrInPins];
- return r;
- case UDESCSUB_AC_SELECTOR:
- /* XXX This is not really right */
- id = iot[id].d.su->baSourceId[0];
- break;
- case UDESCSUB_AC_FEATURE:
- id = iot[id].d.fu->bSourceId;
- break;
- case UDESCSUB_AC_PROCESSING:
- r = *(const struct usb_audio_cluster *)
- &iot[id].d.pu->baSourceId[iot[id].d.pu->bNrInPins];
- return r;
- case UDESCSUB_AC_EXTENSION:
- r = *(const struct usb_audio_cluster *)
- &iot[id].d.eu->baSourceId[iot[id].d.eu->bNrInPins];
- return r;
- default:
- goto bad;
- }
- }
- bad:
- printf("uaudio_get_cluster: bad data\n");
- memset(&r, 0, sizeof r);
- return r;
-
-}
-
-static void
-uaudio_add_input(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
-{
-#ifdef USB_DEBUG
- const struct usb_audio_input_terminal *d = iot[id].d.it;
-
- DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x "
- "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
- "iChannelNames=%d iTerminal=%d\n",
- d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
- d->bNrChannels, UGETW(d->wChannelConfig),
- d->iChannelNames, d->iTerminal));
-#endif
-}
-
-static void
-uaudio_add_output(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
-{
-#ifdef USB_DEBUG
- const struct usb_audio_output_terminal *d;
-
- d = iot[id].d.ot;
- DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x "
- "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
- d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
- d->bSourceId, d->iTerminal));
-#endif
-}
-
-static void
-uaudio_add_mixer(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
-{
- const struct usb_audio_mixer_unit *d = iot[id].d.mu;
- const struct usb_audio_mixer_unit_1 *d1;
- int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k;
- const uByte *bm;
- struct mixerctl mix;
-
- DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n",
- d->bUnitId, d->bNrInPins));
-
- /* Compute the number of input channels */
- ichs = 0;
- for (i = 0; i < d->bNrInPins; i++)
- ichs += uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels;
-
- /* and the number of output channels */
- d1 = (const struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins];
- ochs = d1->bNrChannels;
- DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%d\n", ichs, ochs));
-
- bm = d1->bmControls;
- mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
- uaudio_determine_class(&iot[id], &mix);
- mix.type = MIX_SIGNED_16;
-#if !defined(__FreeBSD__) /* XXXXX */
- mix.ctlunit = AudioNvolume;
-#endif
-
-#define BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1)
- for (p = i = 0; i < d->bNrInPins; i++) {
- chs = uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels;
- mc = 0;
- for (c = 0; c < chs; c++) {
- mo = 0;
- for (o = 0; o < ochs; o++) {
- bno = (p + c) * ochs + o;
- if (BIT(bno))
- mo++;
- }
- if (mo == 1)
- mc++;
- }
- if (mc == chs && chs <= MIX_MAX_CHAN) {
- k = 0;
- for (c = 0; c < chs; c++)
- for (o = 0; o < ochs; o++) {
- bno = (p + c) * ochs + o;
- if (BIT(bno))
- mix.wValue[k++] =
- MAKE(p+c+1, o+1);
- }
-#if !defined(__FreeBSD__)
- snprintf(mix.ctlname, sizeof(mix.ctlname), "mix%d-%s",
- d->bUnitId, uaudio_id_name(sc, iot,
- d->baSourceId[i]));
-#endif
- mix.nchan = chs;
- uaudio_mixer_add_ctl(sc, &mix);
- } else {
- /* XXX */
- }
-#undef BIT
- p += chs;
- }
-
-}
-
-static void
-uaudio_add_selector(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
-{
- const struct usb_audio_selector_unit *d;
- struct mixerctl mix;
-#if !defined(__FreeBSD__)
- int i, wp;
-#else
- int i;
- struct mixerctl dummy;
-#endif
-
- d = iot[id].d.su;
- DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n",
- d->bUnitId, d->bNrInPins));
- mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
- mix.wValue[0] = MAKE(0, 0);
- uaudio_determine_class(&iot[id], &mix);
- mix.nchan = 1;
- mix.type = MIX_SELECTOR;
-#if defined(__FreeBSD__)
- mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
- mix.minval = 1;
- mix.maxval = d->bNrInPins;
- mix.mul = mix.maxval - mix.minval;
- for (i = 0; i < MAX_SELECTOR_INPUT_PIN; i++) {
- mix.slctrtype[i] = SOUND_MIXER_NRDEVICES;
- }
- for (i = mix.minval; i <= mix.maxval; i++) {
- mix.slctrtype[i - 1] = uaudio_feature_name(&iot[d->baSourceId[i - 1]], &dummy);
- }
-#else
- mix.ctlunit = "";
- mix.minval = 1;
- mix.maxval = d->bNrInPins;
- mix.mul = mix.maxval - mix.minval;
- wp = snprintf(mix.ctlname, MAX_AUDIO_DEV_LEN, "sel%d-", d->bUnitId);
- for (i = 1; i <= d->bNrInPins; i++) {
- wp += snprintf(mix.ctlname + wp, MAX_AUDIO_DEV_LEN - wp,
- "i%d", d->baSourceId[i - 1]);
- if (wp > MAX_AUDIO_DEV_LEN - 1)
- break;
- }
-#endif
- uaudio_mixer_add_ctl(sc, &mix);
-}
-
-#ifdef USB_DEBUG
-static const char *
-uaudio_get_terminal_name(int terminal_type)
-{
- static char buf[100];
-
- switch (terminal_type) {
- /* USB terminal types */
- case UAT_UNDEFINED: return "UAT_UNDEFINED";
- case UAT_STREAM: return "UAT_STREAM";
- case UAT_VENDOR: return "UAT_VENDOR";
- /* input terminal types */
- case UATI_UNDEFINED: return "UATI_UNDEFINED";
- case UATI_MICROPHONE: return "UATI_MICROPHONE";
- case UATI_DESKMICROPHONE: return "UATI_DESKMICROPHONE";
- case UATI_PERSONALMICROPHONE: return "UATI_PERSONALMICROPHONE";
- case UATI_OMNIMICROPHONE: return "UATI_OMNIMICROPHONE";
- case UATI_MICROPHONEARRAY: return "UATI_MICROPHONEARRAY";
- case UATI_PROCMICROPHONEARR: return "UATI_PROCMICROPHONEARR";
- /* output terminal types */
- case UATO_UNDEFINED: return "UATO_UNDEFINED";
- case UATO_SPEAKER: return "UATO_SPEAKER";
- case UATO_HEADPHONES: return "UATO_HEADPHONES";
- case UATO_DISPLAYAUDIO: return "UATO_DISPLAYAUDIO";
- case UATO_DESKTOPSPEAKER: return "UATO_DESKTOPSPEAKER";
- case UATO_ROOMSPEAKER: return "UATO_ROOMSPEAKER";
- case UATO_COMMSPEAKER: return "UATO_COMMSPEAKER";
- case UATO_SUBWOOFER: return "UATO_SUBWOOFER";
- /* bidir terminal types */
- case UATB_UNDEFINED: return "UATB_UNDEFINED";
- case UATB_HANDSET: return "UATB_HANDSET";
- case UATB_HEADSET: return "UATB_HEADSET";
- case UATB_SPEAKERPHONE: return "UATB_SPEAKERPHONE";
- case UATB_SPEAKERPHONEESUP: return "UATB_SPEAKERPHONEESUP";
- case UATB_SPEAKERPHONEECANC: return "UATB_SPEAKERPHONEECANC";
- /* telephony terminal types */
- case UATT_UNDEFINED: return "UATT_UNDEFINED";
- case UATT_PHONELINE: return "UATT_PHONELINE";
- case UATT_TELEPHONE: return "UATT_TELEPHONE";
- case UATT_DOWNLINEPHONE: return "UATT_DOWNLINEPHONE";
- /* external terminal types */
- case UATE_UNDEFINED: return "UATE_UNDEFINED";
- case UATE_ANALOGCONN: return "UATE_ANALOGCONN";
- case UATE_LINECONN: return "UATE_LINECONN";
- case UATE_LEGACYCONN: return "UATE_LEGACYCONN";
- case UATE_DIGITALAUIFC: return "UATE_DIGITALAUIFC";
- case UATE_SPDIF: return "UATE_SPDIF";
- case UATE_1394DA: return "UATE_1394DA";
- case UATE_1394DV: return "UATE_1394DV";
- /* embedded function terminal types */
- case UATF_UNDEFINED: return "UATF_UNDEFINED";
- case UATF_CALIBNOISE: return "UATF_CALIBNOISE";
- case UATF_EQUNOISE: return "UATF_EQUNOISE";
- case UATF_CDPLAYER: return "UATF_CDPLAYER";
- case UATF_DAT: return "UATF_DAT";
- case UATF_DCC: return "UATF_DCC";
- case UATF_MINIDISK: return "UATF_MINIDISK";
- case UATF_ANALOGTAPE: return "UATF_ANALOGTAPE";
- case UATF_PHONOGRAPH: return "UATF_PHONOGRAPH";
- case UATF_VCRAUDIO: return "UATF_VCRAUDIO";
- case UATF_VIDEODISCAUDIO: return "UATF_VIDEODISCAUDIO";
- case UATF_DVDAUDIO: return "UATF_DVDAUDIO";
- case UATF_TVTUNERAUDIO: return "UATF_TVTUNERAUDIO";
- case UATF_SATELLITE: return "UATF_SATELLITE";
- case UATF_CABLETUNER: return "UATF_CABLETUNER";
- case UATF_DSS: return "UATF_DSS";
- case UATF_RADIORECV: return "UATF_RADIORECV";
- case UATF_RADIOXMIT: return "UATF_RADIOXMIT";
- case UATF_MULTITRACK: return "UATF_MULTITRACK";
- case UATF_SYNTHESIZER: return "UATF_SYNTHESIZER";
- default:
- snprintf(buf, sizeof(buf), "unknown type (0x%.4x)", terminal_type);
- return buf;
- }
-}
-#endif
-
-static int
-uaudio_determine_class(const struct io_terminal *iot, struct mixerctl *mix)
-{
- int terminal_type;
-
- if (iot == NULL || iot->output == NULL) {
- mix->class = UAC_OUTPUT;
- return 0;
- }
- terminal_type = 0;
- if (iot->output->size == 1)
- terminal_type = iot->output->terminals[0];
- /*
- * If the only output terminal is USB,
- * the class is UAC_RECORD.
- */
- if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) {
- mix->class = UAC_RECORD;
- if (iot->inputs_size == 1
- && iot->inputs[0] != NULL
- && iot->inputs[0]->size == 1)
- return iot->inputs[0]->terminals[0];
- else
- return 0;
- }
- /*
- * If the ultimate destination of the unit is just one output
- * terminal and the unit is connected to the output terminal
- * directly, the class is UAC_OUTPUT.
- */
- if (terminal_type != 0 && iot->direct) {
- mix->class = UAC_OUTPUT;
- return terminal_type;
- }
- /*
- * If the unit is connected to just one input terminal,
- * the class is UAC_INPUT.
- */
- if (iot->inputs_size == 1 && iot->inputs[0] != NULL
- && iot->inputs[0]->size == 1) {
- mix->class = UAC_INPUT;
- return iot->inputs[0]->terminals[0];
- }
- /*
- * Otherwise, the class is UAC_OUTPUT.
- */
- mix->class = UAC_OUTPUT;
- return terminal_type;
-}
-
-#if defined(__FreeBSD__)
-static int
-uaudio_feature_name(const struct io_terminal *iot, struct mixerctl *mix)
-{
- int terminal_type;
-
- terminal_type = uaudio_determine_class(iot, mix);
- if (mix->class == UAC_RECORD && terminal_type == 0)
- return SOUND_MIXER_IMIX;
- DPRINTF(("%s: terminal_type=%s\n", __func__,
- uaudio_get_terminal_name(terminal_type)));
- switch (terminal_type) {
- case UAT_STREAM:
- return SOUND_MIXER_PCM;
-
- case UATI_MICROPHONE:
- case UATI_DESKMICROPHONE:
- case UATI_PERSONALMICROPHONE:
- case UATI_OMNIMICROPHONE:
- case UATI_MICROPHONEARRAY:
- case UATI_PROCMICROPHONEARR:
- return SOUND_MIXER_MIC;
-
- case UATO_SPEAKER:
- case UATO_DESKTOPSPEAKER:
- case UATO_ROOMSPEAKER:
- case UATO_COMMSPEAKER:
- return SOUND_MIXER_SPEAKER;
-
- case UATE_ANALOGCONN:
- case UATE_LINECONN:
- case UATE_LEGACYCONN:
- return SOUND_MIXER_LINE;
-
- case UATE_DIGITALAUIFC:
- case UATE_SPDIF:
- case UATE_1394DA:
- case UATE_1394DV:
- return SOUND_MIXER_ALTPCM;
-
- case UATF_CDPLAYER:
- return SOUND_MIXER_CD;
-
- case UATF_SYNTHESIZER:
- return SOUND_MIXER_SYNTH;
-
- case UATF_VIDEODISCAUDIO:
- case UATF_DVDAUDIO:
- case UATF_TVTUNERAUDIO:
- return SOUND_MIXER_VIDEO;
-
-/* telephony terminal types */
- case UATT_UNDEFINED:
- case UATT_PHONELINE:
- case UATT_TELEPHONE:
- case UATT_DOWNLINEPHONE:
- return SOUND_MIXER_PHONEIN;
-/* return SOUND_MIXER_PHONEOUT;*/
-
- case UATF_RADIORECV:
- case UATF_RADIOXMIT:
- return SOUND_MIXER_RADIO;
-
- case UAT_UNDEFINED:
- case UAT_VENDOR:
- case UATI_UNDEFINED:
-/* output terminal types */
- case UATO_UNDEFINED:
- case UATO_DISPLAYAUDIO:
- case UATO_SUBWOOFER:
- case UATO_HEADPHONES:
-/* bidir terminal types */
- case UATB_UNDEFINED:
- case UATB_HANDSET:
- case UATB_HEADSET:
- case UATB_SPEAKERPHONE:
- case UATB_SPEAKERPHONEESUP:
- case UATB_SPEAKERPHONEECANC:
-/* external terminal types */
- case UATE_UNDEFINED:
-/* embedded function terminal types */
- case UATF_UNDEFINED:
- case UATF_CALIBNOISE:
- case UATF_EQUNOISE:
- case UATF_DAT:
- case UATF_DCC:
- case UATF_MINIDISK:
- case UATF_ANALOGTAPE:
- case UATF_PHONOGRAPH:
- case UATF_VCRAUDIO:
- case UATF_SATELLITE:
- case UATF_CABLETUNER:
- case UATF_DSS:
- case UATF_MULTITRACK:
- case 0xffff:
- default:
- DPRINTF(("%s: 'master' for 0x%.4x\n", __func__, terminal_type));
- return SOUND_MIXER_VOLUME;
- }
- return SOUND_MIXER_VOLUME;
-}
-#else
-static const char *
-uaudio_feature_name(const struct io_terminal *iot, struct mixerctl *mix)
-{
- int terminal_type;
-
- terminal_type = uaudio_determine_class(iot, mix);
- if (mix->class == UAC_RECORD && terminal_type == 0)
- return AudioNmixerout;
- DPRINTF(("%s: terminal_type=%s\n", __func__,
- uaudio_get_terminal_name(terminal_type)));
- switch (terminal_type) {
- case UAT_STREAM:
- return AudioNdac;
-
- case UATI_MICROPHONE:
- case UATI_DESKMICROPHONE:
- case UATI_PERSONALMICROPHONE:
- case UATI_OMNIMICROPHONE:
- case UATI_MICROPHONEARRAY:
- case UATI_PROCMICROPHONEARR:
- return AudioNmicrophone;
-
- case UATO_SPEAKER:
- case UATO_DESKTOPSPEAKER:
- case UATO_ROOMSPEAKER:
- case UATO_COMMSPEAKER:
- return AudioNspeaker;
-
- case UATO_HEADPHONES:
- return AudioNheadphone;
-
- case UATO_SUBWOOFER:
- return AudioNlfe;
-
- /* telephony terminal types */
- case UATT_UNDEFINED:
- case UATT_PHONELINE:
- case UATT_TELEPHONE:
- case UATT_DOWNLINEPHONE:
- return "phone";
-
- case UATE_ANALOGCONN:
- case UATE_LINECONN:
- case UATE_LEGACYCONN:
- return AudioNline;
-
- case UATE_DIGITALAUIFC:
- case UATE_SPDIF:
- case UATE_1394DA:
- case UATE_1394DV:
- return AudioNaux;
-
- case UATF_CDPLAYER:
- return AudioNcd;
-
- case UATF_SYNTHESIZER:
- return AudioNfmsynth;
-
- case UATF_VIDEODISCAUDIO:
- case UATF_DVDAUDIO:
- case UATF_TVTUNERAUDIO:
- return AudioNvideo;
-
- case UAT_UNDEFINED:
- case UAT_VENDOR:
- case UATI_UNDEFINED:
-/* output terminal types */
- case UATO_UNDEFINED:
- case UATO_DISPLAYAUDIO:
-/* bidir terminal types */
- case UATB_UNDEFINED:
- case UATB_HANDSET:
- case UATB_HEADSET:
- case UATB_SPEAKERPHONE:
- case UATB_SPEAKERPHONEESUP:
- case UATB_SPEAKERPHONEECANC:
-/* external terminal types */
- case UATE_UNDEFINED:
-/* embedded function terminal types */
- case UATF_UNDEFINED:
- case UATF_CALIBNOISE:
- case UATF_EQUNOISE:
- case UATF_DAT:
- case UATF_DCC:
- case UATF_MINIDISK:
- case UATF_ANALOGTAPE:
- case UATF_PHONOGRAPH:
- case UATF_VCRAUDIO:
- case UATF_SATELLITE:
- case UATF_CABLETUNER:
- case UATF_DSS:
- case UATF_RADIORECV:
- case UATF_RADIOXMIT:
- case UATF_MULTITRACK:
- case 0xffff:
- default:
- DPRINTF(("%s: 'master' for 0x%.4x\n", __func__, terminal_type));
- return AudioNmaster;
- }
- return AudioNmaster;
-}
-#endif
-
-static void
-uaudio_add_feature(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
-{
- const struct usb_audio_feature_unit *d;
- const uByte *ctls;
- int ctlsize;
- int nchan;
- u_int fumask, mmask, cmask;
- struct mixerctl mix;
- int chan, ctl, i, unit;
-#if defined(__FreeBSD__)
- int mixernumber;
-#else
- const char *mixername;
-#endif
-
-#define GET(i) (ctls[(i)*ctlsize] | \
- (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
- d = iot[id].d.fu;
- ctls = d->bmaControls;
- ctlsize = d->bControlSize;
- nchan = (d->bLength - 7) / ctlsize;
- mmask = GET(0);
- /* Figure out what we can control */
- for (cmask = 0, chan = 1; chan < nchan; chan++) {
- DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%x\n",
- chan, GET(chan)));
- cmask |= GET(chan);
- }
-
-#if !defined(__FreeBSD__)
- DPRINTFN(1,("uaudio_add_feature: bUnitId=%d, "
- "%d channels, mmask=0x%04x, cmask=0x%04x\n",
- d->bUnitId, nchan, mmask, cmask));
-#endif
-
- if (nchan > MIX_MAX_CHAN)
- nchan = MIX_MAX_CHAN;
- unit = d->bUnitId;
- mix.wIndex = MAKE(unit, sc->sc_ac_iface);
- for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) {
- fumask = FU_MASK(ctl);
- DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04x\n",
- ctl, fumask));
- if (mmask & fumask) {
- mix.nchan = 1;
- mix.wValue[0] = MAKE(ctl, 0);
- } else if (cmask & fumask) {
- mix.nchan = nchan - 1;
- for (i = 1; i < nchan; i++) {
- if (GET(i) & fumask)
- mix.wValue[i-1] = MAKE(ctl, i);
- else
- mix.wValue[i-1] = -1;
- }
- } else {
- continue;
- }
-#undef GET
-
-#if defined(__FreeBSD__)
- mixernumber = uaudio_feature_name(&iot[id], &mix);
-#else
- mixername = uaudio_feature_name(&iot[id], &mix);
-#endif
- switch (ctl) {
- case MUTE_CONTROL:
- mix.type = MIX_ON_OFF;
-#if defined(__FreeBSD__)
- mix.ctl = SOUND_MIXER_NRDEVICES;
-#else
- mix.ctlunit = "";
- snprintf(mix.ctlname, sizeof(mix.ctlname),
- "%s.%s", mixername, AudioNmute);
-#endif
- break;
- case VOLUME_CONTROL:
- mix.type = MIX_SIGNED_16;
-#if defined(__FreeBSD__)
- mix.ctl = mixernumber;
-#else
- mix.ctlunit = AudioNvolume;
- strlcpy(mix.ctlname, mixername, sizeof(mix.ctlname));
-#endif
- break;
- case BASS_CONTROL:
- mix.type = MIX_SIGNED_8;
-#if defined(__FreeBSD__)
- mix.ctl = SOUND_MIXER_BASS;
-#else
- mix.ctlunit = AudioNbass;
- snprintf(mix.ctlname, sizeof(mix.ctlname),
- "%s.%s", mixername, AudioNbass);
-#endif
- break;
- case MID_CONTROL:
- mix.type = MIX_SIGNED_8;
-#if defined(__FreeBSD__)
- mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
-#else
- mix.ctlunit = AudioNmid;
- snprintf(mix.ctlname, sizeof(mix.ctlname),
- "%s.%s", mixername, AudioNmid);
-#endif
- break;
- case TREBLE_CONTROL:
- mix.type = MIX_SIGNED_8;
-#if defined(__FreeBSD__)
- mix.ctl = SOUND_MIXER_TREBLE;
-#else
- mix.ctlunit = AudioNtreble;
- snprintf(mix.ctlname, sizeof(mix.ctlname),
- "%s.%s", mixername, AudioNtreble);
-#endif
- break;
- case GRAPHIC_EQUALIZER_CONTROL:
- continue; /* XXX don't add anything */
- break;
- case AGC_CONTROL:
- mix.type = MIX_ON_OFF;
-#if defined(__FreeBSD__)
- mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
-#else
- mix.ctlunit = "";
- snprintf(mix.ctlname, sizeof(mix.ctlname), "%s.%s",
- mixername, AudioNagc);
-#endif
- break;
- case DELAY_CONTROL:
- mix.type = MIX_UNSIGNED_16;
-#if defined(__FreeBSD__)
- mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
-#else
- mix.ctlunit = "4 ms";
- snprintf(mix.ctlname, sizeof(mix.ctlname),
- "%s.%s", mixername, AudioNdelay);
-#endif
- break;
- case BASS_BOOST_CONTROL:
- mix.type = MIX_ON_OFF;
-#if defined(__FreeBSD__)
- mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
-#else
- mix.ctlunit = "";
- snprintf(mix.ctlname, sizeof(mix.ctlname),
- "%s.%s", mixername, AudioNbassboost);
-#endif
- break;
- case LOUDNESS_CONTROL:
- mix.type = MIX_ON_OFF;
-#if defined(__FreeBSD__)
- mix.ctl = SOUND_MIXER_LOUD; /* Is this correct ? */
-#else
- mix.ctlunit = "";
- snprintf(mix.ctlname, sizeof(mix.ctlname),
- "%s.%s", mixername, AudioNloudness);
-#endif
- break;
- }
- uaudio_mixer_add_ctl(sc, &mix);
- }
-}
-
-static void
-uaudio_add_processing_updown(struct uaudio_softc *sc,
- const struct io_terminal *iot, int id)
-{
- const struct usb_audio_processing_unit *d;
- const struct usb_audio_processing_unit_1 *d1;
- const struct usb_audio_processing_unit_updown *ud;
- struct mixerctl mix;
- int i;
-
- d = iot[id].d.pu;
- d1 = (const struct usb_audio_processing_unit_1 *)
- &d->baSourceId[d->bNrInPins];
- ud = (const struct usb_audio_processing_unit_updown *)
- &d1->bmControls[d1->bControlSize];
- DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
- d->bUnitId, ud->bNrModes));
-
- if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
- DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
- return;
- }
-
- mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
- mix.nchan = 1;
- mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
- uaudio_determine_class(&iot[id], &mix);
- mix.type = MIX_ON_OFF; /* XXX */
-#if !defined(__FreeBSD__)
- mix.ctlunit = "";
- snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d-mode", d->bUnitId);
-#endif
-
- for (i = 0; i < ud->bNrModes; i++) {
- DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n",
- i, UGETW(ud->waModes[i])));
- /* XXX */
- }
- uaudio_mixer_add_ctl(sc, &mix);
-}
-
-static void
-uaudio_add_processing(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
-{
- const struct usb_audio_processing_unit *d;
- const struct usb_audio_processing_unit_1 *d1;
- int ptype;
- struct mixerctl mix;
-
- d = iot[id].d.pu;
- d1 = (const struct usb_audio_processing_unit_1 *)
- &d->baSourceId[d->bNrInPins];
- ptype = UGETW(d->wProcessType);
- DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
- "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins));
-
- if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
- mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
- mix.nchan = 1;
- mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
- uaudio_determine_class(&iot[id], &mix);
- mix.type = MIX_ON_OFF;
-#if !defined(__FreeBSD__)
- mix.ctlunit = "";
- snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d.%d-enable",
- d->bUnitId, ptype);
-#endif
- uaudio_mixer_add_ctl(sc, &mix);
- }
-
- switch(ptype) {
- case UPDOWNMIX_PROCESS:
- uaudio_add_processing_updown(sc, iot, id);
- break;
- case DOLBY_PROLOGIC_PROCESS:
- case P3D_STEREO_EXTENDER_PROCESS:
- case REVERBATION_PROCESS:
- case CHORUS_PROCESS:
- case DYN_RANGE_COMP_PROCESS:
- default:
-#ifdef USB_DEBUG
- printf("uaudio_add_processing: unit %d, type=%d not impl.\n",
- d->bUnitId, ptype);
-#endif
- break;
- }
-}
-
-static void
-uaudio_add_extension(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
-{
- const struct usb_audio_extension_unit *d;
- const struct usb_audio_extension_unit_1 *d1;
- struct mixerctl mix;
-
- d = iot[id].d.eu;
- d1 = (const struct usb_audio_extension_unit_1 *)
- &d->baSourceId[d->bNrInPins];
- DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
- d->bUnitId, d->bNrInPins));
-
- if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU)
- return;
-
- if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
- mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
- mix.nchan = 1;
- mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
- uaudio_determine_class(&iot[id], &mix);
- mix.type = MIX_ON_OFF;
-#if !defined(__FreeBSD__)
- mix.ctlunit = "";
- snprintf(mix.ctlname, sizeof(mix.ctlname), "ext%d-enable",
- d->bUnitId);
-#endif
- uaudio_mixer_add_ctl(sc, &mix);
- }
-}
-
-static struct terminal_list*
-uaudio_merge_terminal_list(const struct io_terminal *iot)
-{
- struct terminal_list *tml;
- uint16_t *ptm;
- int i, len;
-
- len = 0;
- if (iot->inputs == NULL)
- return NULL;
- for (i = 0; i < iot->inputs_size; i++) {
- if (iot->inputs[i] != NULL)
- len += iot->inputs[i]->size;
- }
- tml = malloc(TERMINAL_LIST_SIZE(len), M_TEMP, M_NOWAIT);
- if (tml == NULL) {
- printf("uaudio_merge_terminal_list: no memory\n");
- return NULL;
- }
- tml->size = 0;
- ptm = tml->terminals;
- for (i = 0; i < iot->inputs_size; i++) {
- if (iot->inputs[i] == NULL)
- continue;
- if (iot->inputs[i]->size > len)
- break;
- memcpy(ptm, iot->inputs[i]->terminals,
- iot->inputs[i]->size * sizeof(uint16_t));
- tml->size += iot->inputs[i]->size;
- ptm += iot->inputs[i]->size;
- len -= iot->inputs[i]->size;
- }
- return tml;
-}
-
-static struct terminal_list *
-uaudio_io_terminaltype(int outtype, struct io_terminal *iot, int id)
-{
- struct terminal_list *tml;
- struct io_terminal *it;
- int src_id, i;
-
- it = &iot[id];
- if (it->output != NULL) {
- /* already has outtype? */
- for (i = 0; i < it->output->size; i++)
- if (it->output->terminals[i] == outtype)
- return uaudio_merge_terminal_list(it);
- tml = malloc(TERMINAL_LIST_SIZE(it->output->size + 1),
- M_TEMP, M_NOWAIT);
- if (tml == NULL) {
- printf("uaudio_io_terminaltype: no memory\n");
- return uaudio_merge_terminal_list(it);
- }
- memcpy(tml, it->output, TERMINAL_LIST_SIZE(it->output->size));
- tml->terminals[it->output->size] = outtype;
- tml->size++;
- free(it->output, M_TEMP);
- it->output = tml;
- if (it->inputs != NULL) {
- for (i = 0; i < it->inputs_size; i++)
- if (it->inputs[i] != NULL)
- free(it->inputs[i], M_TEMP);
- free(it->inputs, M_TEMP);
- }
- it->inputs_size = 0;
- it->inputs = NULL;
- } else { /* end `iot[id] != NULL' */
- it->inputs_size = 0;
- it->inputs = NULL;
- it->output = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
- if (it->output == NULL) {
- printf("uaudio_io_terminaltype: no memory\n");
- return NULL;
- }
- it->output->terminals[0] = outtype;
- it->output->size = 1;
- it->direct = FALSE;
- }
-
- switch (it->d.desc->bDescriptorSubtype) {
- case UDESCSUB_AC_INPUT:
- it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
- if (it->inputs == NULL) {
- printf("uaudio_io_terminaltype: no memory\n");
- return NULL;
- }
- tml = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
- if (tml == NULL) {
- printf("uaudio_io_terminaltype: no memory\n");
- free(it->inputs, M_TEMP);
- it->inputs = NULL;
- return NULL;
- }
- it->inputs[0] = tml;
- tml->terminals[0] = UGETW(it->d.it->wTerminalType);
- tml->size = 1;
- it->inputs_size = 1;
- return uaudio_merge_terminal_list(it);
- case UDESCSUB_AC_FEATURE:
- src_id = it->d.fu->bSourceId;
- it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
- if (it->inputs == NULL) {
- printf("uaudio_io_terminaltype: no memory\n");
- return uaudio_io_terminaltype(outtype, iot, src_id);
- }
- it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
- it->inputs_size = 1;
- return uaudio_merge_terminal_list(it);
- case UDESCSUB_AC_OUTPUT:
- it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
- if (it->inputs == NULL) {
- printf("uaudio_io_terminaltype: no memory\n");
- return NULL;
- }
- src_id = it->d.ot->bSourceId;
- it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
- it->inputs_size = 1;
- iot[src_id].direct = TRUE;
- return NULL;
- case UDESCSUB_AC_MIXER:
- it->inputs_size = 0;
- it->inputs = malloc(sizeof(struct terminal_list *)
- * it->d.mu->bNrInPins, M_TEMP, M_NOWAIT);
- if (it->inputs == NULL) {
- printf("uaudio_io_terminaltype: no memory\n");
- return NULL;
- }
- for (i = 0; i < it->d.mu->bNrInPins; i++) {
- src_id = it->d.mu->baSourceId[i];
- it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
- src_id);
- it->inputs_size++;
- }
- return uaudio_merge_terminal_list(it);
- case UDESCSUB_AC_SELECTOR:
- it->inputs_size = 0;
- it->inputs = malloc(sizeof(struct terminal_list *)
- * it->d.su->bNrInPins, M_TEMP, M_NOWAIT);
- if (it->inputs == NULL) {
- printf("uaudio_io_terminaltype: no memory\n");
- return NULL;
- }
- for (i = 0; i < it->d.su->bNrInPins; i++) {
- src_id = it->d.su->baSourceId[i];
- it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
- src_id);
- it->inputs_size++;
- }
- return uaudio_merge_terminal_list(it);
- case UDESCSUB_AC_PROCESSING:
- it->inputs_size = 0;
- it->inputs = malloc(sizeof(struct terminal_list *)
- * it->d.pu->bNrInPins, M_TEMP, M_NOWAIT);
- if (it->inputs == NULL) {
- printf("uaudio_io_terminaltype: no memory\n");
- return NULL;
- }
- for (i = 0; i < it->d.pu->bNrInPins; i++) {
- src_id = it->d.pu->baSourceId[i];
- it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
- src_id);
- it->inputs_size++;
- }
- return uaudio_merge_terminal_list(it);
- case UDESCSUB_AC_EXTENSION:
- it->inputs_size = 0;
- it->inputs = malloc(sizeof(struct terminal_list *)
- * it->d.eu->bNrInPins, M_TEMP, M_NOWAIT);
- if (it->inputs == NULL) {
- printf("uaudio_io_terminaltype: no memory\n");
- return NULL;
- }
- for (i = 0; i < it->d.eu->bNrInPins; i++) {
- src_id = it->d.eu->baSourceId[i];
- it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
- src_id);
- it->inputs_size++;
- }
- return uaudio_merge_terminal_list(it);
- case UDESCSUB_AC_HEADER:
- default:
- return NULL;
- }
-}
-
-static usbd_status
-uaudio_identify(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
-{
- usbd_status err;
-
- err = uaudio_identify_ac(sc, cdesc);
- if (err)
- return err;
- return uaudio_identify_as(sc, cdesc);
-}
-
-static void
-uaudio_add_alt(struct uaudio_softc *sc, const struct as_info *ai)
-{
- size_t len;
- struct as_info *nai;
-
- len = sizeof(*ai) * (sc->sc_nalts + 1);
- nai = malloc(len, M_USBDEV, M_NOWAIT);
- if (nai == NULL) {
- printf("uaudio_add_alt: no memory\n");
- return;
- }
- /* Copy old data, if there was any */
- if (sc->sc_nalts != 0) {
- memcpy(nai, sc->sc_alts, sizeof(*ai) * (sc->sc_nalts));
- free(sc->sc_alts, M_USBDEV);
- }
- sc->sc_alts = nai;
- DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%d\n",
- ai->alt, ai->encoding));
- sc->sc_alts[sc->sc_nalts++] = *ai;
-}
-
-static usbd_status
-uaudio_process_as(struct uaudio_softc *sc, const char *buf, int *offsp,
- int size, const usb_interface_descriptor_t *id)
-#define offs (*offsp)
-{
- const struct usb_audio_streaming_interface_descriptor *asid;
- const struct usb_audio_streaming_type1_descriptor *asf1d;
- const usb_endpoint_descriptor_audio_t *ed;
- const usb_endpoint_descriptor_audio_t *epdesc1;
- const struct usb_audio_streaming_endpoint_descriptor *sed;
- int format, chan, prec, enc;
- int dir, type, sync;
- struct as_info ai;
- const char *format_str;
-
- asid = (const void *)(buf + offs);
-
- if (asid->bDescriptorType != UDESC_CS_INTERFACE ||
- asid->bDescriptorSubtype != AS_GENERAL)
- return USBD_INVAL;
- DPRINTF(("uaudio_process_as: asid: bTerminakLink=%d wFormatTag=%d\n",
- asid->bTerminalLink, UGETW(asid->wFormatTag)));
- offs += asid->bLength;
- if (offs > size)
- return USBD_INVAL;
-
- asf1d = (const void *)(buf + offs);
- if (asf1d->bDescriptorType != UDESC_CS_INTERFACE ||
- asf1d->bDescriptorSubtype != FORMAT_TYPE)
- return USBD_INVAL;
- offs += asf1d->bLength;
- if (offs > size)
- return USBD_INVAL;
-
- if (asf1d->bFormatType != FORMAT_TYPE_I) {
- printf("%s: ignored setting with type %d format\n",
- device_get_nameunit(sc->sc_dev), UGETW(asid->wFormatTag));
- return USBD_NORMAL_COMPLETION;
- }
-
- ed = (const void *)(buf + offs);
- if (ed->bDescriptorType != UDESC_ENDPOINT)
- return USBD_INVAL;
- DPRINTF(("uaudio_process_as: endpoint[0] bLength=%d bDescriptorType=%d "
- "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d "
- "bInterval=%d bRefresh=%d bSynchAddress=%d\n",
- ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
- ed->bmAttributes, UGETW(ed->wMaxPacketSize),
- ed->bInterval, ed->bRefresh, ed->bSynchAddress));
- offs += ed->bLength;
- if (offs > size)
- return USBD_INVAL;
- if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
- return USBD_INVAL;
-
- dir = UE_GET_DIR(ed->bEndpointAddress);
- type = UE_GET_ISO_TYPE(ed->bmAttributes);
- if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) &&
- dir == UE_DIR_IN && type == UE_ISO_ADAPT)
- type = UE_ISO_ASYNC;
-
- /* We can't handle endpoints that need a sync pipe yet. */
- sync = FALSE;
- if (dir == UE_DIR_IN && type == UE_ISO_ADAPT) {
- sync = TRUE;
-#ifndef UAUDIO_MULTIPLE_ENDPOINTS
- printf("%s: ignored input endpoint of type adaptive\n",
- device_get_nameunit(sc->sc_dev));
- return USBD_NORMAL_COMPLETION;
-#endif
- }
- if (dir != UE_DIR_IN && type == UE_ISO_ASYNC) {
- sync = TRUE;
-#ifndef UAUDIO_MULTIPLE_ENDPOINTS
- printf("%s: ignored output endpoint of type async\n",
- device_get_nameunit(sc->sc_dev));
- return USBD_NORMAL_COMPLETION;
-#endif
- }
-
- sed = (const void *)(buf + offs);
- if (sed->bDescriptorType != UDESC_CS_ENDPOINT ||
- sed->bDescriptorSubtype != AS_GENERAL)
- return USBD_INVAL;
- DPRINTF((" streadming_endpoint: offset=%d bLength=%d\n", offs, sed->bLength));
- offs += sed->bLength;
- if (offs > size)
- return USBD_INVAL;
-
-#ifdef UAUDIO_MULTIPLE_ENDPOINTS
- if (sync && id->bNumEndpoints <= 1) {
- printf("%s: a sync-pipe endpoint but no other endpoint\n",
- device_get_nameunit(sc->sc_dev));
- return USBD_INVAL;
- }
-#endif
- if (!sync && id->bNumEndpoints > 1) {
- printf("%s: non sync-pipe endpoint but multiple endpoints\n",
- device_get_nameunit(sc->sc_dev));
- return USBD_INVAL;
- }
- epdesc1 = NULL;
- if (id->bNumEndpoints > 1) {
- epdesc1 = (const void*)(buf + offs);
- if (epdesc1->bDescriptorType != UDESC_ENDPOINT)
- return USBD_INVAL;
- DPRINTF(("uaudio_process_as: endpoint[1] bLength=%d "
- "bDescriptorType=%d bEndpointAddress=%d "
- "bmAttributes=0x%x wMaxPacketSize=%d bInterval=%d "
- "bRefresh=%d bSynchAddress=%d\n",
- epdesc1->bLength, epdesc1->bDescriptorType,
- epdesc1->bEndpointAddress, epdesc1->bmAttributes,
- UGETW(epdesc1->wMaxPacketSize), epdesc1->bInterval,
- epdesc1->bRefresh, epdesc1->bSynchAddress));
- offs += epdesc1->bLength;
- if (offs > size)
- return USBD_INVAL;
- if (epdesc1->bSynchAddress != 0) {
- printf("%s: invalid endpoint: bSynchAddress=0\n",
- device_get_nameunit(sc->sc_dev));
- return USBD_INVAL;
- }
- if (UE_GET_XFERTYPE(epdesc1->bmAttributes) != UE_ISOCHRONOUS) {
- printf("%s: invalid endpoint: bmAttributes=0x%x\n",
- device_get_nameunit(sc->sc_dev), epdesc1->bmAttributes);
- return USBD_INVAL;
- }
- if (epdesc1->bEndpointAddress != ed->bSynchAddress) {
- printf("%s: invalid endpoint addresses: "
- "ep[0]->bSynchAddress=0x%x "
- "ep[1]->bEndpointAddress=0x%x\n",
- device_get_nameunit(sc->sc_dev), ed->bSynchAddress,
- epdesc1->bEndpointAddress);
- return USBD_INVAL;
- }
- /* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */
- }
-
- format = UGETW(asid->wFormatTag);
- chan = asf1d->bNrChannels;
- prec = asf1d->bBitResolution;
- if (prec != 8 && prec != 16 && prec != 24 && prec != 32) {
- printf("%s: ignored setting with precision %d\n",
- device_get_nameunit(sc->sc_dev), prec);
- return USBD_NORMAL_COMPLETION;
- }
- switch (format) {
- case UA_FMT_PCM:
- if (prec == 8) {
- sc->sc_altflags |= HAS_8;
- } else if (prec == 16) {
- sc->sc_altflags |= HAS_16;
- } else if (prec == 24) {
- sc->sc_altflags |= HAS_24;
- } else if (prec == 32) {
- sc->sc_altflags |= HAS_32;
- }
- enc = AUDIO_ENCODING_SLINEAR_LE;
- format_str = "pcm";
- break;
- case UA_FMT_PCM8:
- enc = AUDIO_ENCODING_ULINEAR_LE;
- sc->sc_altflags |= HAS_8U;
- format_str = "pcm8";
- break;
- case UA_FMT_ALAW:
- enc = AUDIO_ENCODING_ALAW;
- sc->sc_altflags |= HAS_ALAW;
- format_str = "alaw";
- break;
- case UA_FMT_MULAW:
- enc = AUDIO_ENCODING_ULAW;
- sc->sc_altflags |= HAS_MULAW;
- format_str = "mulaw";
- break;
- case UA_FMT_IEEE_FLOAT:
- default:
- printf("%s: ignored setting with format %d\n",
- device_get_nameunit(sc->sc_dev), format);
- return USBD_NORMAL_COMPLETION;
- }
-#ifdef USB_DEBUG
- printf("%s: %s: %dch, %d/%dbit, %s,", device_get_nameunit(sc->sc_dev),
- dir == UE_DIR_IN ? "recording" : "playback",
- chan, prec, asf1d->bSubFrameSize * 8, format_str);
- if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
- printf(" %d-%dHz\n", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
- } else {
- int r;
- printf(" %d", UA_GETSAMP(asf1d, 0));
- for (r = 1; r < asf1d->bSamFreqType; r++)
- printf(",%d", UA_GETSAMP(asf1d, r));
- printf("Hz\n");
- }
-#endif
-#if defined(__FreeBSD__)
- if (sc->uaudio_sndstat_flag != 0) {
- sbuf_printf(&(sc->uaudio_sndstat), "\n\t");
- sbuf_printf(&(sc->uaudio_sndstat),
- "mode %d:(%s) %dch, %d/%dbit, %s,",
- id->bAlternateSetting,
- dir == UE_DIR_IN ? "input" : "output",
- chan, prec, asf1d->bSubFrameSize * 8, format_str);
- if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
- sbuf_printf(&(sc->uaudio_sndstat), " %d-%dHz",
- UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
- } else {
- int r;
- sbuf_printf(&(sc->uaudio_sndstat),
- " %d", UA_GETSAMP(asf1d, 0));
- for (r = 1; r < asf1d->bSamFreqType; r++)
- sbuf_printf(&(sc->uaudio_sndstat),
- ",%d", UA_GETSAMP(asf1d, r));
- sbuf_printf(&(sc->uaudio_sndstat), "Hz");
- }
- }
-#endif
- ai.alt = id->bAlternateSetting;
- ai.encoding = enc;
- ai.attributes = sed->bmAttributes;
- ai.idesc = id;
- ai.edesc = ed;
- ai.edesc1 = epdesc1;
- ai.asf1desc = asf1d;
- ai.sc_busy = 0;
- ai.ifaceh = NULL;
- uaudio_add_alt(sc, &ai);
-#ifdef USB_DEBUG
- if (ai.attributes & UA_SED_FREQ_CONTROL)
- DPRINTFN(1, ("uaudio_process_as: FREQ_CONTROL\n"));
- if (ai.attributes & UA_SED_PITCH_CONTROL)
- DPRINTFN(1, ("uaudio_process_as: PITCH_CONTROL\n"));
-#endif
- sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD;
-
- return USBD_NORMAL_COMPLETION;
-}
-#undef offs
-
-static usbd_status
-uaudio_identify_as(struct uaudio_softc *sc,
- const usb_config_descriptor_t *cdesc)
-{
- const usb_interface_descriptor_t *id;
- const char *buf;
- int size, offs;
-
- size = UGETW(cdesc->wTotalLength);
- buf = (const char *)cdesc;
-
- /* Locate the AudioStreaming interface descriptor. */
- offs = 0;
- id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM);
- if (id == NULL)
- return USBD_INVAL;
-
-#if defined(__FreeBSD__)
- sc->uaudio_sndstat_flag = 0;
- if (sbuf_new(&(sc->uaudio_sndstat), NULL, 4096, SBUF_AUTOEXTEND) != NULL)
- sc->uaudio_sndstat_flag = 1;
-#endif
- /* Loop through all the alternate settings. */
- while (offs <= size) {
- DPRINTFN(2, ("uaudio_identify: interface=%d offset=%d\n",
- id->bInterfaceNumber, offs));
- switch (id->bNumEndpoints) {
- case 0:
- DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n",
- id->bAlternateSetting));
- sc->sc_nullalt = id->bAlternateSetting;
- break;
- case 1:
-#ifdef UAUDIO_MULTIPLE_ENDPOINTS
- case 2:
-#endif
- uaudio_process_as(sc, buf, &offs, size, id);
- break;
- default:
- printf("%s: ignored audio interface with %d "
- "endpoints\n",
- device_get_nameunit(sc->sc_dev), id->bNumEndpoints);
- break;
- }
- id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM);
- if (id == NULL)
- break;
- }
-#if defined(__FreeBSD__)
- sbuf_finish(&(sc->uaudio_sndstat));
-#endif
- if (offs > size)
- return USBD_INVAL;
- DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts));
-
- if (sc->sc_mode == 0) {
- printf("%s: no usable endpoint found\n",
- device_get_nameunit(sc->sc_dev));
- return USBD_INVAL;
- }
-
- return USBD_NORMAL_COMPLETION;
-}
-
-static usbd_status
-uaudio_identify_ac(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
-{
- struct io_terminal* iot;
- const usb_interface_descriptor_t *id;
- const struct usb_audio_control_descriptor *acdp;
- const usb_descriptor_t *dp;
- const struct usb_audio_output_terminal *pot;
- struct terminal_list *tml;
- const char *buf, *ibuf, *ibufend;
- int size, offs, aclen, ndps, i, j;
-
- size = UGETW(cdesc->wTotalLength);
- buf = (const char *)cdesc;
-
- /* Locate the AudioControl interface descriptor. */
- offs = 0;
- id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL);
- if (id == NULL)
- return USBD_INVAL;
- if (offs + sizeof *acdp > size)
- return USBD_INVAL;
- sc->sc_ac_iface = id->bInterfaceNumber;
- DPRINTFN(2,("uaudio_identify_ac: AC interface is %d\n", sc->sc_ac_iface));
-
- /* A class-specific AC interface header should follow. */
- ibuf = buf + offs;
- acdp = (const struct usb_audio_control_descriptor *)ibuf;
- if (acdp->bDescriptorType != UDESC_CS_INTERFACE ||
- acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)
- return USBD_INVAL;
- aclen = UGETW(acdp->wTotalLength);
- if (offs + aclen > size)
- return USBD_INVAL;
-
- if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) &&
- UGETW(acdp->bcdADC) != UAUDIO_VERSION)
- return USBD_INVAL;
-
- sc->sc_audio_rev = UGETW(acdp->bcdADC);
- DPRINTFN(2,("uaudio_identify_ac: found AC header, vers=%03x, len=%d\n",
- sc->sc_audio_rev, aclen));
-
- sc->sc_nullalt = -1;
-
- /* Scan through all the AC specific descriptors */
- ibufend = ibuf + aclen;
- dp = (const usb_descriptor_t *)ibuf;
- ndps = 0;
- iot = malloc(sizeof(struct io_terminal) * 256, M_TEMP, M_NOWAIT | M_ZERO);
- if (iot == NULL) {
- printf("%s: no memory\n", __func__);
- return USBD_NOMEM;
- }
- for (;;) {
- ibuf += dp->bLength;
- if (ibuf >= ibufend)
- break;
- dp = (const usb_descriptor_t *)ibuf;
- if (ibuf + dp->bLength > ibufend) {
- free(iot, M_TEMP);
- return USBD_INVAL;
- }
- if (dp->bDescriptorType != UDESC_CS_INTERFACE) {
- printf("uaudio_identify_ac: skip desc type=0x%02x\n",
- dp->bDescriptorType);
- continue;
- }
- i = ((const struct usb_audio_input_terminal *)dp)->bTerminalId;
- iot[i].d.desc = dp;
- if (i > ndps)
- ndps = i;
- }
- ndps++;
-
- /* construct io_terminal */
- for (i = 0; i < ndps; i++) {
- dp = iot[i].d.desc;
- if (dp == NULL)
- continue;
- if (dp->bDescriptorSubtype != UDESCSUB_AC_OUTPUT)
- continue;
- pot = iot[i].d.ot;
- tml = uaudio_io_terminaltype(UGETW(pot->wTerminalType), iot, i);
- if (tml != NULL)
- free(tml, M_TEMP);
- }
-
-#ifdef USB_DEBUG
- for (i = 0; i < 256; i++) {
- struct usb_audio_cluster cluster;
-
- if (iot[i].d.desc == NULL)
- continue;
- printf("id %d:\t", i);
- switch (iot[i].d.desc->bDescriptorSubtype) {
- case UDESCSUB_AC_INPUT:
- printf("AC_INPUT type=%s\n", uaudio_get_terminal_name
- (UGETW(iot[i].d.it->wTerminalType)));
- printf("\t");
- cluster = uaudio_get_cluster(i, iot);
- uaudio_dump_cluster(&cluster);
- printf("\n");
- break;
- case UDESCSUB_AC_OUTPUT:
- printf("AC_OUTPUT type=%s ", uaudio_get_terminal_name
- (UGETW(iot[i].d.ot->wTerminalType)));
- printf("src=%d\n", iot[i].d.ot->bSourceId);
- break;
- case UDESCSUB_AC_MIXER:
- printf("AC_MIXER src=");
- for (j = 0; j < iot[i].d.mu->bNrInPins; j++)
- printf("%d ", iot[i].d.mu->baSourceId[j]);
- printf("\n\t");
- cluster = uaudio_get_cluster(i, iot);
- uaudio_dump_cluster(&cluster);
- printf("\n");
- break;
- case UDESCSUB_AC_SELECTOR:
- printf("AC_SELECTOR src=");
- for (j = 0; j < iot[i].d.su->bNrInPins; j++)
- printf("%d ", iot[i].d.su->baSourceId[j]);
- printf("\n");
- break;
- case UDESCSUB_AC_FEATURE:
- printf("AC_FEATURE src=%d\n", iot[i].d.fu->bSourceId);
- break;
- case UDESCSUB_AC_PROCESSING:
- printf("AC_PROCESSING src=");
- for (j = 0; j < iot[i].d.pu->bNrInPins; j++)
- printf("%d ", iot[i].d.pu->baSourceId[j]);
- printf("\n\t");
- cluster = uaudio_get_cluster(i, iot);
- uaudio_dump_cluster(&cluster);
- printf("\n");
- break;
- case UDESCSUB_AC_EXTENSION:
- printf("AC_EXTENSION src=");
- for (j = 0; j < iot[i].d.eu->bNrInPins; j++)
- printf("%d ", iot[i].d.eu->baSourceId[j]);
- printf("\n\t");
- cluster = uaudio_get_cluster(i, iot);
- uaudio_dump_cluster(&cluster);
- printf("\n");
- break;
- default:
- printf("unknown audio control (subtype=%d)\n",
- iot[i].d.desc->bDescriptorSubtype);
- }
- for (j = 0; j < iot[i].inputs_size; j++) {
- int k;
- printf("\tinput%d: ", j);
- tml = iot[i].inputs[j];
- if (tml == NULL) {
- printf("NULL\n");
- continue;
- }
- for (k = 0; k < tml->size; k++)
- printf("%s ", uaudio_get_terminal_name
- (tml->terminals[k]));
- printf("\n");
- }
- printf("\toutput: ");
- tml = iot[i].output;
- for (j = 0; j < tml->size; j++)
- printf("%s ", uaudio_get_terminal_name(tml->terminals[j]));
- printf("\n");
- }
-#endif
-
- for (i = 0; i < ndps; i++) {
- dp = iot[i].d.desc;
- if (dp == NULL)
- continue;
- DPRINTF(("uaudio_identify_ac: id=%d subtype=%d\n",
- i, dp->bDescriptorSubtype));
- switch (dp->bDescriptorSubtype) {
- case UDESCSUB_AC_HEADER:
- printf("uaudio_identify_ac: unexpected AC header\n");
- break;
- case UDESCSUB_AC_INPUT:
- uaudio_add_input(sc, iot, i);
- break;
- case UDESCSUB_AC_OUTPUT:
- uaudio_add_output(sc, iot, i);
- break;
- case UDESCSUB_AC_MIXER:
- uaudio_add_mixer(sc, iot, i);
- break;
- case UDESCSUB_AC_SELECTOR:
- uaudio_add_selector(sc, iot, i);
- break;
- case UDESCSUB_AC_FEATURE:
- uaudio_add_feature(sc, iot, i);
- break;
- case UDESCSUB_AC_PROCESSING:
- uaudio_add_processing(sc, iot, i);
- break;
- case UDESCSUB_AC_EXTENSION:
- uaudio_add_extension(sc, iot, i);
- break;
- default:
- printf("uaudio_identify_ac: bad AC desc subtype=0x%02x\n",
- dp->bDescriptorSubtype);
- break;
- }
- }
-
- /* delete io_terminal */
- for (i = 0; i < 256; i++) {
- if (iot[i].d.desc == NULL)
- continue;
- if (iot[i].inputs != NULL) {
- for (j = 0; j < iot[i].inputs_size; j++) {
- if (iot[i].inputs[j] != NULL)
- free(iot[i].inputs[j], M_TEMP);
- }
- free(iot[i].inputs, M_TEMP);
- }
- if (iot[i].output != NULL)
- free(iot[i].output, M_TEMP);
- iot[i].d.desc = NULL;
- }
- free(iot, M_TEMP);
-
- return USBD_NORMAL_COMPLETION;
-}
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static int
-uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi)
-{
- struct uaudio_softc *sc;
- struct mixerctl *mc;
- int n, nctls, i;
-
- sc = addr;
- DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi->index));
- if (sc->sc_dying)
- return EIO;
-
- n = mi->index;
- nctls = sc->sc_nctls;
-
- switch (n) {
- case UAC_OUTPUT:
- mi->type = AUDIO_MIXER_CLASS;
- mi->mixer_class = UAC_OUTPUT;
- mi->next = mi->prev = AUDIO_MIXER_LAST;
- strlcpy(mi->label.name, AudioCoutputs, sizeof(mi->label.name));
- return 0;
- case UAC_INPUT:
- mi->type = AUDIO_MIXER_CLASS;
- mi->mixer_class = UAC_INPUT;
- mi->next = mi->prev = AUDIO_MIXER_LAST;
- strlcpy(mi->label.name, AudioCinputs, sizeof(mi->label.name));
- return 0;
- case UAC_EQUAL:
- mi->type = AUDIO_MIXER_CLASS;
- mi->mixer_class = UAC_EQUAL;
- mi->next = mi->prev = AUDIO_MIXER_LAST;
- strlcpy(mi->label.name, AudioCequalization,
- sizeof(mi->label.name));
- return 0;
- case UAC_RECORD:
- mi->type = AUDIO_MIXER_CLASS;
- mi->mixer_class = UAC_RECORD;
- mi->next = mi->prev = AUDIO_MIXER_LAST;
- strlcpy(mi->label.name, AudioCrecord, sizeof(mi->label.name));
- return 0;
- default:
- break;
- }
-
- n -= UAC_NCLASSES;
- if (n < 0 || n >= nctls)
- return ENXIO;
-
- mc = &sc->sc_ctls[n];
- strlcpy(mi->label.name, mc->ctlname, sizeof(mi->label.name));
- mi->mixer_class = mc->class;
- mi->next = mi->prev = AUDIO_MIXER_LAST; /* XXX */
- switch (mc->type) {
- case MIX_ON_OFF:
- mi->type = AUDIO_MIXER_ENUM;
- mi->un.e.num_mem = 2;
- strlcpy(mi->un.e.member[0].label.name, AudioNoff,
- sizeof(mi->un.e.member[0].label.name));
- mi->un.e.member[0].ord = 0;
- strlcpy(mi->un.e.member[1].label.name, AudioNon,
- sizeof(mi->un.e.member[1].label.name));
- mi->un.e.member[1].ord = 1;
- break;
- case MIX_SELECTOR:
- mi->type = AUDIO_MIXER_ENUM;
- mi->un.e.num_mem = mc->maxval - mc->minval + 1;
- for (i = 0; i <= mc->maxval - mc->minval; i++) {
- snprintf(mi->un.e.member[i].label.name,
- sizeof(mi->un.e.member[i].label.name),
- "%d", i + mc->minval);
- mi->un.e.member[i].ord = i + mc->minval;
- }
- break;
- default:
- mi->type = AUDIO_MIXER_VALUE;
- strlcpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN);
- mi->un.v.num_channels = mc->nchan;
- mi->un.v.delta = mc->delta;
- break;
- }
- return 0;
-}
-
-static int
-uaudio_open(void *addr, int flags)
-{
- struct uaudio_softc *sc;
-
- sc = addr;
- DPRINTF(("uaudio_open: sc=%p\n", sc));
- if (sc->sc_dying)
- return EIO;
-
- if ((flags & FWRITE) && !(sc->sc_mode & AUMODE_PLAY))
- return EACCES;
- if ((flags & FREAD) && !(sc->sc_mode & AUMODE_RECORD))
- return EACCES;
-
- return 0;
-}
-
-/*
- * Close function is called at splaudio().
- */
-static void
-uaudio_close(void *addr)
-{
-}
-
-static int
-uaudio_drain(void *addr)
-{
- struct uaudio_softc *sc;
-
- sc = addr;
- usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
-
- return 0;
-}
-
-static int
-uaudio_halt_out_dma(void *addr)
-{
- struct uaudio_softc *sc;
-
- sc = addr;
- if (sc->sc_dying)
- return EIO;
-
- DPRINTF(("uaudio_halt_out_dma: enter\n"));
- if (sc->sc_playchan.pipe != NULL) {
- uaudio_chan_close(sc, &sc->sc_playchan);
- sc->sc_playchan.pipe = NULL;
- uaudio_chan_free_buffers(sc, &sc->sc_playchan);
- sc->sc_playchan.intr = NULL;
- }
- return 0;
-}
-
-static int
-uaudio_halt_in_dma(void *addr)
-{
- struct uaudio_softc *sc;
-
- DPRINTF(("uaudio_halt_in_dma: enter\n"));
- sc = addr;
- if (sc->sc_recchan.pipe != NULL) {
- uaudio_chan_close(sc, &sc->sc_recchan);
- sc->sc_recchan.pipe = NULL;
- uaudio_chan_free_buffers(sc, &sc->sc_recchan);
- sc->sc_recchan.intr = NULL;
- }
- return 0;
-}
-
-static int
-uaudio_getdev(void *addr, struct audio_device *retp)
-{
- struct uaudio_softc *sc;
-
- DPRINTF(("uaudio_mixer_getdev:\n"));
- sc = addr;
- if (sc->sc_dying)
- return EIO;
-
- *retp = uaudio_device;
- return 0;
-}
-
-/*
- * Make sure the block size is large enough to hold all outstanding transfers.
- */
-static int
-uaudio_round_blocksize(void *addr, int blk)
-{
- struct uaudio_softc *sc;
- int b;
-
- sc = addr;
- DPRINTF(("uaudio_round_blocksize: blk=%d mode=%s\n", blk,
- mode == AUMODE_PLAY ? "AUMODE_PLAY" : "AUMODE_RECORD"));
-
- /* chan.bytes_per_frame can be 0. */
- if (mode == AUMODE_PLAY || sc->sc_recchan.bytes_per_frame <= 0) {
- b = param->sample_rate * UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
-
- /*
- * This does not make accurate value in the case
- * of b % USB_FRAMES_PER_SECOND != 0
- */
- b /= USB_FRAMES_PER_SECOND;
-
- b *= param->precision / 8 * param->channels;
- } else {
- /*
- * use wMaxPacketSize in bytes_per_frame.
- * See uaudio_set_params() and uaudio_chan_init()
- */
- b = sc->sc_recchan.bytes_per_frame
- * UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
- }
-
- if (b <= 0)
- b = 1;
- blk = blk <= b ? b : blk / b * b;
-
-#ifdef DIAGNOSTIC
- if (blk <= 0) {
- printf("uaudio_round_blocksize: blk=%d\n", blk);
- blk = 512;
- }
-#endif
-
- DPRINTF(("uaudio_round_blocksize: resultant blk=%d\n", blk));
- return blk;
-}
-
-static int
-uaudio_get_props(void *addr)
-{
- return AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
-
-}
-#endif /* NetBSD or OpenBSD */
-
-static int
-uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue,
- int wIndex, int len)
-{
- usb_device_request_t req;
- uint8_t data[4];
- usbd_status err;
- int val;
-
-#if defined(__FreeBSD__)
- if (sc->sc_dying)
- return EIO;
-#endif
-
- if (wValue == -1)
- return 0;
-
- req.bmRequestType = type;
- req.bRequest = which;
- USETW(req.wValue, wValue);
- USETW(req.wIndex, wIndex);
- USETW(req.wLength, len);
- DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
- "wIndex=0x%04x len=%d\n",
- type, which, wValue, wIndex, len));
-#if defined(__FreeBSD__)
- if (sc->async != 0)
- err = usbd_do_request_async(sc->sc_udev, &req, data);
- else
-#endif
- err = usbd_do_request(sc->sc_udev, &req, data);
- if (err) {
- DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
- return -1;
- }
- switch (len) {
- case 1:
- val = data[0];
- break;
- case 2:
- val = data[0] | (data[1] << 8);
- break;
- default:
- DPRINTF(("uaudio_get: bad length=%d\n", len));
- return -1;
- }
- DPRINTFN(2,("uaudio_get: val=%d\n", val));
- return val;
-}
-
-static void
-uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue,
- int wIndex, int len, int val)
-{
- usb_device_request_t req;
- uint8_t data[4];
- usbd_status err;
-
-#if defined(__FreeBSD__)
- if (sc->sc_dying)
- return;
-#endif
-
- if (wValue == -1)
- return;
-
- req.bmRequestType = type;
- req.bRequest = which;
- USETW(req.wValue, wValue);
- USETW(req.wIndex, wIndex);
- USETW(req.wLength, len);
- switch (len) {
- case 1:
- data[0] = val;
- break;
- case 2:
- data[0] = val;
- data[1] = val >> 8;
- break;
- default:
- return;
- }
- DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
- "wIndex=0x%04x len=%d, val=%d\n",
- type, which, wValue, wIndex, len, val & 0xffff));
-#if defined(__FreeBSD__)
- if (sc->async != 0)
- err = usbd_do_request_async(sc->sc_udev, &req, data);
- else
-#endif
- err = usbd_do_request(sc->sc_udev, &req, data);
-#ifdef USB_DEBUG
- if (err)
- DPRINTF(("uaudio_set: err=%d\n", err));
-#endif
-}
-
-static int
-uaudio_signext(int type, int val)
-{
- if (!MIX_UNSIGNED(type)) {
- if (MIX_SIZE(type) == 2)
- val = (int16_t)val;
- else
- val = (int8_t)val;
- }
- return val;
-}
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static int
-uaudio_value2bsd(struct mixerctl *mc, int val)
-{
- DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ",
- mc->type, val, mc->minval, mc->maxval));
- if (mc->type == MIX_ON_OFF) {
- val = (val != 0);
- } else if (mc->type == MIX_SELECTOR) {
- if (val < mc->minval || val > mc->maxval)
- val = mc->minval;
- } else
- val = ((uaudio_signext(mc->type, val) - mc->minval) * 255
- + mc->mul/2) / mc->mul;
- DPRINTFN(5, ("val'=%d\n", val));
- return val;
-}
-#endif
-
-int
-uaudio_bsd2value(struct mixerctl *mc, int val)
-{
- DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ",
- mc->type, val, mc->minval, mc->maxval));
- if (mc->type == MIX_ON_OFF) {
- val = (val != 0);
- } else if (mc->type == MIX_SELECTOR) {
- if (val < mc->minval || val > mc->maxval)
- val = mc->minval;
- } else
- val = (val + mc->delta/2) * mc->mul / 255 + mc->minval;
- DPRINTFN(5, ("val'=%d\n", val));
- return val;
-}
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static int
-uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc,
- int chan)
-{
- int val;
-
- DPRINTFN(5,("uaudio_ctl_get: which=%d chan=%d\n", which, chan));
- val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan],
- mc->wIndex, MIX_SIZE(mc->type));
- return uaudio_value2bsd(mc, val);
-}
-#endif
-
-static void
-uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc,
- int chan, int val)
-{
- val = uaudio_bsd2value(mc, val);
- uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan],
- mc->wIndex, MIX_SIZE(mc->type), val);
-}
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static int
-uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp)
-{
- struct uaudio_softc *sc;
- struct mixerctl *mc;
- int i, n, vals[MIX_MAX_CHAN], val;
-
- DPRINTFN(2,("uaudio_mixer_get_port: index=%d\n", cp->dev));
- sc = addr;
- if (sc->sc_dying)
- return EIO;
-
- n = cp->dev - UAC_NCLASSES;
- if (n < 0 || n >= sc->sc_nctls)
- return ENXIO;
- mc = &sc->sc_ctls[n];
-
- if (mc->type == MIX_ON_OFF) {
- if (cp->type != AUDIO_MIXER_ENUM)
- return EINVAL;
- cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
- } else if (mc->type == MIX_SELECTOR) {
- if (cp->type != AUDIO_MIXER_ENUM)
- return EINVAL;
- cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
- } else {
- if (cp->type != AUDIO_MIXER_VALUE)
- return (EINVAL);
- if (cp->un.value.num_channels != 1 &&
- cp->un.value.num_channels != mc->nchan)
- return EINVAL;
- for (i = 0; i < mc->nchan; i++)
- vals[i] = uaudio_ctl_get(sc, GET_CUR, mc, i);
- if (cp->un.value.num_channels == 1 && mc->nchan != 1) {
- for (val = 0, i = 0; i < mc->nchan; i++)
- val += vals[i];
- vals[0] = val / mc->nchan;
- }
- for (i = 0; i < cp->un.value.num_channels; i++)
- cp->un.value.level[i] = vals[i];
- }
-
- return 0;
-}
-
-static int
-uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp)
-{
- struct uaudio_softc *sc;
- struct mixerctl *mc;
- int i, n, vals[MIX_MAX_CHAN];
-
- DPRINTFN(2,("uaudio_mixer_set_port: index = %d\n", cp->dev));
- sc = addr;
- if (sc->sc_dying)
- return EIO;
-
- n = cp->dev - UAC_NCLASSES;
- if (n < 0 || n >= sc->sc_nctls)
- return ENXIO;
- mc = &sc->sc_ctls[n];
-
- if (mc->type == MIX_ON_OFF) {
- if (cp->type != AUDIO_MIXER_ENUM)
- return EINVAL;
- uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
- } else if (mc->type == MIX_SELECTOR) {
- if (cp->type != AUDIO_MIXER_ENUM)
- return EINVAL;
- uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
- } else {
- if (cp->type != AUDIO_MIXER_VALUE)
- return EINVAL;
- if (cp->un.value.num_channels == 1)
- for (i = 0; i < mc->nchan; i++)
- vals[i] = cp->un.value.level[0];
- else if (cp->un.value.num_channels == mc->nchan)
- for (i = 0; i < mc->nchan; i++)
- vals[i] = cp->un.value.level[i];
- else
- return EINVAL;
- for (i = 0; i < mc->nchan; i++)
- uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]);
- }
- return 0;
-}
-
-static int
-uaudio_trigger_input(void *addr, void *start, void *end, int blksize,
- void (*intr)(void *), void *arg,
- struct audio_params *param)
-{
- struct uaudio_softc *sc;
- struct chan *ch;
- usbd_status err;
- int i, s;
-
- sc = addr;
- if (sc->sc_dying)
- return EIO;
-
- DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p "
- "blksize=%d\n", sc, start, end, blksize));
- ch = &sc->sc_recchan;
- uaudio_chan_set_param(ch, start, end, blksize);
- DPRINTFN(3,("uaudio_trigger_input: sample_size=%d bytes/frame=%d "
- "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
- ch->fraction));
-
- err = uaudio_chan_alloc_buffers(sc, ch);
- if (err)
- return EIO;
-
- err = uaudio_chan_open(sc, ch);
- if (err) {
- uaudio_chan_free_buffers(sc, ch);
- return EIO;
- }
-
- ch->intr = intr;
- ch->arg = arg;
-
- s = splusb();
- for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
- uaudio_chan_rtransfer(ch);
- splx(s);
-
- return 0;
-}
-
-static int
-uaudio_trigger_output(void *addr, void *start, void *end, int blksize,
- void (*intr)(void *), void *arg,
- struct audio_params *param)
-{
- struct uaudio_softc *sc;
- struct chan *ch;
- usbd_status err;
- int i, s;
-
- sc = addr;
- if (sc->sc_dying)
- return EIO;
-
- DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p "
- "blksize=%d\n", sc, start, end, blksize));
- ch = &sc->sc_playchan;
- uaudio_chan_set_param(ch, start, end, blksize);
- DPRINTFN(3,("uaudio_trigger_output: sample_size=%d bytes/frame=%d "
- "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
- ch->fraction));
-
- err = uaudio_chan_alloc_buffers(sc, ch);
- if (err)
- return EIO;
-
- err = uaudio_chan_open(sc, ch);
- if (err) {
- uaudio_chan_free_buffers(sc, ch);
- return EIO;
- }
-
- ch->intr = intr;
- ch->arg = arg;
-
- s = splusb();
- for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
- uaudio_chan_ptransfer(ch);
- splx(s);
-
- return 0;
-}
-#endif /* NetBSD or OpenBSD */
-
-/* Set up a pipe for a channel. */
-static usbd_status
-uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
-{
- struct as_info *as;
- int endpt;
-#if defined(__FreeBSD__)
- int locked;
-#endif
- usbd_status err;
-
-#if defined(__FreeBSD__)
- if (sc->sc_dying)
- return EIO;
-#endif
-
- as = &sc->sc_alts[ch->altidx];
- endpt = as->edesc->bEndpointAddress;
- DPRINTF(("uaudio_chan_open: endpt=0x%02x, speed=%d, alt=%d\n",
- endpt, ch->sample_rate, as->alt));
-
-#if defined(__FreeBSD__)
- locked = (ch->pcm_ch != NULL && mtx_owned(ch->pcm_ch->lock)) ? 1 : 0;
- if (locked)
- CHN_UNLOCK(ch->pcm_ch);
-#endif
- /* Set alternate interface corresponding to the mode. */
- err = usbd_set_interface(as->ifaceh, as->alt);
-#if defined(__FreeBSD__)
- if (locked)
- CHN_LOCK(ch->pcm_ch);
-#endif
- if (err)
- return err;
-
- /*
- * If just one sampling rate is supported,
- * no need to call uaudio_set_speed().
- * Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request.
- */
- if (as->asf1desc->bSamFreqType != 1) {
- err = uaudio_set_speed(sc, endpt, ch->sample_rate);
- if (err) {
- DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n",
- usbd_errstr(err)));
- }
- }
-
- ch->pipe = 0;
- ch->sync_pipe = 0;
- DPRINTF(("uaudio_chan_open: create pipe to 0x%02x\n", endpt));
- err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
- if (err)
- return err;
- if (as->edesc1 != NULL) {
- endpt = as->edesc1->bEndpointAddress;
- DPRINTF(("uaudio_chan_open: create sync-pipe to 0x%02x\n", endpt));
- err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->sync_pipe);
- }
- return err;
-}
-
-static void
-uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
-{
- struct as_info *as;
-#if defined(__FreeBSD__)
- int locked;
-
- if (sc->sc_dying)
- return ;
-#endif
-
- as = &sc->sc_alts[ch->altidx];
- as->sc_busy = 0;
-#if defined(__FreeBSD__)
- locked = (ch->pcm_ch != NULL && mtx_owned(ch->pcm_ch->lock)) ? 1 : 0;
- if (locked)
- CHN_UNLOCK(ch->pcm_ch);
-#endif
- if (sc->sc_nullalt >= 0) {
- DPRINTF(("uaudio_chan_close: set null alt=%d\n",
- sc->sc_nullalt));
- /*
- * The interface will be initialized later again, so an
- * error does not hurt.
- */
- (void)usbd_set_interface(as->ifaceh, sc->sc_nullalt);
- }
- if (ch->pipe) {
- usbd_abort_pipe(ch->pipe);
- usbd_close_pipe(ch->pipe);
- }
- if (ch->sync_pipe) {
- usbd_abort_pipe(ch->sync_pipe);
- usbd_close_pipe(ch->sync_pipe);
- }
-#if defined(__FreeBSD__)
- if (locked)
- CHN_LOCK(ch->pcm_ch);
-#endif
-}
-
-static usbd_status
-uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch)
-{
- usbd_xfer_handle xfer;
- void *buf;
- int i, size;
-
- size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES;
- for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
- xfer = usbd_alloc_xfer(sc->sc_udev);
- if (xfer == 0)
- goto bad;
- ch->chanbufs[i].xfer = xfer;
- buf = usbd_alloc_buffer(xfer, size);
- if (buf == 0) {
- i++;
- goto bad;
- }
- ch->chanbufs[i].buffer = buf;
- ch->chanbufs[i].chan = ch;
- }
-
- return USBD_NORMAL_COMPLETION;
-
-bad:
- while (--i >= 0)
- /* implicit buffer free */
- usbd_free_xfer(ch->chanbufs[i].xfer);
- return USBD_NOMEM;
-}
-
-static void
-uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch)
-{
- int i;
-
- for (i = 0; i < UAUDIO_NCHANBUFS; i++)
- usbd_free_xfer(ch->chanbufs[i].xfer);
-}
-
-/* Called at splusb() */
-static void
-uaudio_chan_ptransfer(struct chan *ch)
-{
- struct chanbuf *cb;
- int i, n, size, residue, total;
-
- if (ch->sc->sc_dying)
- return;
-
- /* Pick the next channel buffer. */
- cb = &ch->chanbufs[ch->curchanbuf];
- if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
- ch->curchanbuf = 0;
-
- /* Compute the size of each frame in the next transfer. */
- residue = ch->residue;
- total = 0;
- for (i = 0; i < UAUDIO_NFRAMES; i++) {
- size = ch->bytes_per_frame;
- residue += ch->fraction;
- if (residue >= USB_FRAMES_PER_SECOND) {
- if ((ch->sc->sc_altflags & UA_NOFRAC) == 0)
- size += ch->sample_size;
- residue -= USB_FRAMES_PER_SECOND;
- }
- cb->sizes[i] = size;
- total += size;
- }
- ch->residue = residue;
- cb->size = total;
-
- /*
- * Transfer data from upper layer buffer to channel buffer, taking
- * care of wrapping the upper layer buffer.
- */
- n = min(total, ch->end - ch->cur);
- memcpy(cb->buffer, ch->cur, n);
- ch->cur += n;
- if (ch->cur >= ch->end)
- ch->cur = ch->start;
- if (total > n) {
- total -= n;
- memcpy(cb->buffer + n, ch->cur, total);
- ch->cur += total;
- }
-
-#ifdef USB_DEBUG
- if (uaudiodebug > 8) {
- DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03d\n",
- cb->buffer, ch->residue));
- for (i = 0; i < UAUDIO_NFRAMES; i++) {
- DPRINTF((" [%d] length %d\n", i, cb->sizes[i]));
- }
- }
-#endif
-
- DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer));
- /* Fill the request */
- usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
- UAUDIO_NFRAMES, USBD_NO_COPY,
- uaudio_chan_pintr);
-
- (void)usbd_transfer(cb->xfer);
-}
-
-static void
-uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv,
- usbd_status status)
-{
- struct chanbuf *cb;
- struct chan *ch;
- u_int32_t count;
- int s;
-
- cb = priv;
- ch = cb->chan;
- /* Return if we are aborting. */
- if (status == USBD_CANCELLED)
- return;
-
- usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
- DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n",
- count, ch->transferred));
-#ifdef DIAGNOSTIC
- if (count != cb->size) {
- printf("uaudio_chan_pintr: count(%d) != size(%d)\n",
- count, cb->size);
- }
-#endif
-
- ch->transferred += cb->size;
-#if defined(__FreeBSD__)
- /* s = spltty(); */
- s = splhigh();
- chn_intr(ch->pcm_ch);
- splx(s);
-#else
- s = splaudio();
- /* Call back to upper layer */
- while (ch->transferred >= ch->blksize) {
- ch->transferred -= ch->blksize;
- DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)\n",
- ch->intr, ch->arg));
- ch->intr(ch->arg);
- }
- splx(s);
-#endif
-
- /* start next transfer */
- uaudio_chan_ptransfer(ch);
-}
-
-/* Called at splusb() */
-static void
-uaudio_chan_rtransfer(struct chan *ch)
-{
- struct chanbuf *cb;
- int i, size, residue, total;
-
- if (ch->sc->sc_dying)
- return;
-
- /* Pick the next channel buffer. */
- cb = &ch->chanbufs[ch->curchanbuf];
- if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
- ch->curchanbuf = 0;
-
- /* Compute the size of each frame in the next transfer. */
- residue = ch->residue;
- total = 0;
- for (i = 0; i < UAUDIO_NFRAMES; i++) {
- size = ch->bytes_per_frame;
- cb->sizes[i] = size;
- cb->offsets[i] = total;
- total += size;
- }
- ch->residue = residue;
- cb->size = total;
-
-#ifdef USB_DEBUG
- if (uaudiodebug > 8) {
- DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03d\n",
- cb->buffer, ch->residue));
- for (i = 0; i < UAUDIO_NFRAMES; i++) {
- DPRINTF((" [%d] length %d\n", i, cb->sizes[i]));
- }
- }
-#endif
-
- DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer));
- /* Fill the request */
- usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
- UAUDIO_NFRAMES, USBD_NO_COPY,
- uaudio_chan_rintr);
-
- (void)usbd_transfer(cb->xfer);
-}
-
-static void
-uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv,
- usbd_status status)
-{
- struct chanbuf *cb = priv;
- struct chan *ch = cb->chan;
- u_int32_t count;
- int s, i, n, frsize;
-
- /* Return if we are aborting. */
- if (status == USBD_CANCELLED)
- return;
-
- usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
- DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n",
- count, ch->transferred));
-
- /* count < cb->size is normal for asynchronous source */
-#ifdef DIAGNOSTIC
- if (count > cb->size) {
- printf("uaudio_chan_rintr: count(%d) > size(%d)\n",
- count, cb->size);
- }
-#endif
-
- /*
- * Transfer data from channel buffer to upper layer buffer, taking
- * care of wrapping the upper layer buffer.
- */
- for(i = 0; i < UAUDIO_NFRAMES; i++) {
- frsize = cb->sizes[i];
- n = min(frsize, ch->end - ch->cur);
- memcpy(ch->cur, cb->buffer + cb->offsets[i], n);
- ch->cur += n;
- if (ch->cur >= ch->end)
- ch->cur = ch->start;
- if (frsize > n) {
- memcpy(ch->cur, cb->buffer + cb->offsets[i] + n,
- frsize - n);
- ch->cur += frsize - n;
- }
- }
-
- /* Call back to upper layer */
- ch->transferred += count;
-#if defined(__FreeBSD__)
- s = spltty();
- chn_intr(ch->pcm_ch);
- splx(s);
-#else
- s = splaudio();
- while (ch->transferred >= ch->blksize) {
- ch->transferred -= ch->blksize;
- DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)\n",
- ch->intr, ch->arg));
- ch->intr(ch->arg);
- }
- splx(s);
-#endif
-
- /* start next transfer */
- uaudio_chan_rtransfer(ch);
-}
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-static void
-uaudio_chan_init(struct chan *ch, int altidx, const struct audio_params *param,
- int maxpktsize)
-{
- int samples_per_frame, sample_size;
-
- ch->altidx = altidx;
- sample_size = param->precision * param->factor * param->hw_channels / 8;
- samples_per_frame = param->hw_sample_rate / USB_FRAMES_PER_SECOND;
- ch->sample_size = sample_size;
- ch->sample_rate = param->hw_sample_rate;
- if (maxpktsize == 0) {
- ch->fraction = param->hw_sample_rate % USB_FRAMES_PER_SECOND;
- ch->bytes_per_frame = samples_per_frame * sample_size;
- } else {
- ch->fraction = 0;
- ch->bytes_per_frame = maxpktsize;
- }
- ch->residue = 0;
-}
-
-static void
-uaudio_chan_set_param(struct chan *ch, u_char *start, u_char *end, int blksize)
-{
- ch->start = start;
- ch->end = end;
- ch->cur = start;
- ch->blksize = blksize;
- ch->transferred = 0;
- ch->curchanbuf = 0;
-}
-
-static void
-uaudio_get_minmax_rates(int nalts, const struct as_info *alts,
- const struct audio_params *p, int mode,
- u_long *min, u_long *max)
-{
- const struct usb_audio_streaming_type1_descriptor *a1d;
- int i, j;
-
- *min = ULONG_MAX;
- *max = 0;
- for (i = 0; i < nalts; i++) {
- a1d = alts[i].asf1desc;
- if (alts[i].sc_busy)
- continue;
- if (p->hw_channels != a1d->bNrChannels)
- continue;
- if (p->hw_precision != a1d->bBitResolution)
- continue;
- if (p->hw_encoding != alts[i].encoding)
- continue;
- if (mode != UE_GET_DIR(alts[i].edesc->bEndpointAddress))
- continue;
- if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
- DPRINTFN(2,("uaudio_get_minmax_rates: cont %d-%d\n",
- UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
- if (UA_SAMP_LO(a1d) < *min)
- *min = UA_SAMP_LO(a1d);
- if (UA_SAMP_HI(a1d) > *max)
- *max = UA_SAMP_HI(a1d);
- } else {
- for (j = 0; j < a1d->bSamFreqType; j++) {
- DPRINTFN(2,("uaudio_get_minmax_rates: disc #%d: %d\n",
- j, UA_GETSAMP(a1d, j)));
- if (UA_GETSAMP(a1d, j) < *min)
- *min = UA_GETSAMP(a1d, j);
- if (UA_GETSAMP(a1d, j) > *max)
- *max = UA_GETSAMP(a1d, j);
- }
- }
- }
-}
-
-static int
-uaudio_match_alt_sub(int nalts, const struct as_info *alts,
- const struct audio_params *p, int mode, u_long rate)
-{
- const struct usb_audio_streaming_type1_descriptor *a1d;
- int i, j;
-
- DPRINTF(("uaudio_match_alt_sub: search for %luHz %dch\n",
- rate, p->hw_channels));
- for (i = 0; i < nalts; i++) {
- a1d = alts[i].asf1desc;
- if (alts[i].sc_busy)
- continue;
- if (p->hw_channels != a1d->bNrChannels)
- continue;
- if (p->hw_precision != a1d->bBitResolution)
- continue;
- if (p->hw_encoding != alts[i].encoding)
- continue;
- if (mode != UE_GET_DIR(alts[i].edesc->bEndpointAddress))
- continue;
- if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
- DPRINTFN(3,("uaudio_match_alt_sub: cont %d-%d\n",
- UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
- if (UA_SAMP_LO(a1d) <= rate && rate <= UA_SAMP_HI(a1d))
- return i;
- } else {
- for (j = 0; j < a1d->bSamFreqType; j++) {
- DPRINTFN(3,("uaudio_match_alt_sub: disc #%d: %d\n",
- j, UA_GETSAMP(a1d, j)));
- /* XXX allow for some slack */
- if (UA_GETSAMP(a1d, j) == rate)
- return i;
- }
- }
- }
- return -1;
-}
-
-static int
-uaudio_match_alt_chan(int nalts, const struct as_info *alts,
- struct audio_params *p, int mode)
-{
- int i, n;
- u_long min, max;
- u_long rate;
-
- /* Exact match */
- DPRINTF(("uaudio_match_alt_chan: examine %ldHz %dch %dbit.\n",
- p->sample_rate, p->hw_channels, p->hw_precision));
- i = uaudio_match_alt_sub(nalts, alts, p, mode, p->sample_rate);
- if (i >= 0)
- return i;
-
- uaudio_get_minmax_rates(nalts, alts, p, mode, &min, &max);
- DPRINTF(("uaudio_match_alt_chan: min=%lu max=%lu\n", min, max));
- if (max <= 0)
- return -1;
- /* Search for biggers */
- n = 2;
- while ((rate = p->sample_rate * n++) <= max) {
- i = uaudio_match_alt_sub(nalts, alts, p, mode, rate);
- if (i >= 0) {
- p->hw_sample_rate = rate;
- return i;
- }
- }
- if (p->sample_rate >= min) {
- i = uaudio_match_alt_sub(nalts, alts, p, mode, max);
- if (i >= 0) {
- p->hw_sample_rate = max;
- return i;
- }
- } else {
- i = uaudio_match_alt_sub(nalts, alts, p, mode, min);
- if (i >= 0) {
- p->hw_sample_rate = min;
- return i;
- }
- }
- return -1;
-}
-
-static int
-uaudio_match_alt(int nalts, const struct as_info *alts,
- struct audio_params *p, int mode)
-{
- int i, n;
-
- mode = mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN;
- i = uaudio_match_alt_chan(nalts, alts, p, mode);
- if (i >= 0)
- return i;
-
- for (n = p->channels + 1; n <= AUDIO_MAX_CHANNELS; n++) {
- p->hw_channels = n;
- i = uaudio_match_alt_chan(nalts, alts, p, mode);
- if (i >= 0)
- return i;
- }
-
- if (p->channels != 2)
- return -1;
- p->hw_channels = 1;
- return uaudio_match_alt_chan(nalts, alts, p, mode);
-}
-
-static int
-uaudio_set_params(void *addr, int setmode, int usemode,
- struct audio_params *play, struct audio_params *rec)
-{
- struct uaudio_softc *sc;
- int flags;
- int factor;
- int enc, i;
- int paltidx, raltidx;
- void (*swcode)(void *, u_char *buf, int cnt);
- struct audio_params *p;
- int mode;
-
- sc = addr;
- flags = sc->sc_altflags;
- paltidx = -1;
- raltidx = -1;
- if (sc->sc_dying)
- return EIO;
-
- if (((usemode & AUMODE_PLAY) && sc->sc_playchan.pipe != NULL) ||
- ((usemode & AUMODE_RECORD) && sc->sc_recchan.pipe != NULL))
- return EBUSY;
-
- if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1)
- sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 0;
- if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1)
- sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 0;
-
- /* Some uaudio devices are unidirectional. Don't try to find a
- matching mode for the unsupported direction. */
- setmode &= sc->sc_mode;
-
- for (mode = AUMODE_RECORD; mode != -1;
- mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
- if ((setmode & mode) == 0)
- continue;
-
- p = (mode == AUMODE_PLAY) ? play : rec;
-
- factor = 1;
- swcode = 0;
- enc = p->encoding;
- switch (enc) {
- case AUDIO_ENCODING_SLINEAR_BE:
- /* FALLTHROUGH */
- case AUDIO_ENCODING_SLINEAR_LE:
- if (enc == AUDIO_ENCODING_SLINEAR_BE
- && p->precision == 16 && (flags & HAS_16)) {
- swcode = swap_bytes;
- enc = AUDIO_ENCODING_SLINEAR_LE;
- } else if (p->precision == 8) {
- if (flags & HAS_8) {
- /* No conversion */
- } else if (flags & HAS_8U) {
- swcode = change_sign8;
- enc = AUDIO_ENCODING_ULINEAR_LE;
- } else if (flags & HAS_16) {
- factor = 2;
- p->hw_precision = 16;
- if (mode == AUMODE_PLAY)
- swcode = linear8_to_linear16_le;
- else
- swcode = linear16_to_linear8_le;
- }
- }
- break;
- case AUDIO_ENCODING_ULINEAR_BE:
- /* FALLTHROUGH */
- case AUDIO_ENCODING_ULINEAR_LE:
- if (p->precision == 16) {
- if (enc == AUDIO_ENCODING_ULINEAR_LE)
- swcode = change_sign16_le;
- else if (mode == AUMODE_PLAY)
- swcode = swap_bytes_change_sign16_le;
- else
- swcode = change_sign16_swap_bytes_le;
- enc = AUDIO_ENCODING_SLINEAR_LE;
- } else if (p->precision == 8) {
- if (flags & HAS_8U) {
- /* No conversion */
- } else if (flags & HAS_8) {
- swcode = change_sign8;
- enc = AUDIO_ENCODING_SLINEAR_LE;
- } else if (flags & HAS_16) {
- factor = 2;
- p->hw_precision = 16;
- enc = AUDIO_ENCODING_SLINEAR_LE;
- if (mode == AUMODE_PLAY)
- swcode = ulinear8_to_slinear16_le;
- else
- swcode = slinear16_to_ulinear8_le;
- }
- }
- break;
- case AUDIO_ENCODING_ULAW:
- if (flags & HAS_MULAW)
- break;
- if (flags & HAS_16) {
- if (mode == AUMODE_PLAY)
- swcode = mulaw_to_slinear16_le;
- else
- swcode = slinear16_to_mulaw_le;
- factor = 2;
- enc = AUDIO_ENCODING_SLINEAR_LE;
- p->hw_precision = 16;
- } else if (flags & HAS_8U) {
- if (mode == AUMODE_PLAY)
- swcode = mulaw_to_ulinear8;
- else
- swcode = ulinear8_to_mulaw;
- enc = AUDIO_ENCODING_ULINEAR_LE;
- } else if (flags & HAS_8) {
- if (mode == AUMODE_PLAY)
- swcode = mulaw_to_slinear8;
- else
- swcode = slinear8_to_mulaw;
- enc = AUDIO_ENCODING_SLINEAR_LE;
- } else
- return (EINVAL);
- break;
- case AUDIO_ENCODING_ALAW:
- if (flags & HAS_ALAW)
- break;
- if (mode == AUMODE_PLAY && (flags & HAS_16)) {
- swcode = alaw_to_slinear16_le;
- factor = 2;
- enc = AUDIO_ENCODING_SLINEAR_LE;
- p->hw_precision = 16;
- } else if (flags & HAS_8U) {
- if (mode == AUMODE_PLAY)
- swcode = alaw_to_ulinear8;
- else
- swcode = ulinear8_to_alaw;
- enc = AUDIO_ENCODING_ULINEAR_LE;
- } else if (flags & HAS_8) {
- if (mode == AUMODE_PLAY)
- swcode = alaw_to_slinear8;
- else
- swcode = slinear8_to_alaw;
- enc = AUDIO_ENCODING_SLINEAR_LE;
- } else
- return (EINVAL);
- break;
- default:
- return (EINVAL);
- }
- /* XXX do some other conversions... */
-
- DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n",
- p->channels, p->hw_precision, enc, p->sample_rate));
-
- p->hw_encoding = enc;
- i = uaudio_match_alt(sc->sc_nalts, sc->sc_alts, p, mode);
- if (i < 0)
- return (EINVAL);
-
- p->sw_code = swcode;
- p->factor = factor;
-
- if (mode == AUMODE_PLAY)
- paltidx = i;
- else
- raltidx = i;
- }
-
- if ((setmode & AUMODE_PLAY)) {
- /* XXX abort transfer if currently happening? */
- uaudio_chan_init(&sc->sc_playchan, paltidx, play, 0);
- }
- if ((setmode & AUMODE_RECORD)) {
- /* XXX abort transfer if currently happening? */
- uaudio_chan_init(&sc->sc_recchan, raltidx, rec,
- UGETW(sc->sc_alts[raltidx].edesc->wMaxPacketSize));
- }
-
- if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1)
- sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 1;
- if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1)
- sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 1;
-
- DPRINTF(("uaudio_set_params: use altidx=p%d/r%d, altno=p%d/r%d\n",
- sc->sc_playchan.altidx, sc->sc_recchan.altidx,
- (sc->sc_playchan.altidx >= 0)
- ?sc->sc_alts[sc->sc_playchan.altidx].idesc->bAlternateSetting
- : -1,
- (sc->sc_recchan.altidx >= 0)
- ? sc->sc_alts[sc->sc_recchan.altidx].idesc->bAlternateSetting
- : -1));
-
- return 0;
-}
-#endif /* NetBSD or OpenBSD */
-
-static usbd_status
-uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed)
-{
- usb_device_request_t req;
- uint8_t data[3];
-
- DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%u\n", endpt, speed));
- req.bmRequestType = UT_WRITE_CLASS_ENDPOINT;
- req.bRequest = SET_CUR;
- USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
- USETW(req.wIndex, endpt);
- USETW(req.wLength, 3);
- data[0] = speed;
- data[1] = speed >> 8;
- data[2] = speed >> 16;
-
-#if defined(__FreeBSD__)
- if (sc->async != 0)
- return usbd_do_request_async(sc->sc_udev, &req, data);
-#endif
- return usbd_do_request(sc->sc_udev, &req, data);
-}
-
-
-#if defined(__FreeBSD__)
-/************************************************************/
-int
-uaudio_init_params(struct uaudio_softc *sc, struct chan *ch, int mode)
-{
- int i, j, enc;
- int samples_per_frame, sample_size;
-
- if ((sc->sc_playchan.pipe != NULL) || (sc->sc_recchan.pipe != NULL))
- return (-1);
-
- switch(ch->format & 0x000FFFFF) {
- case AFMT_U8:
- enc = AUDIO_ENCODING_ULINEAR_LE;
- ch->precision = 8;
- break;
- case AFMT_S8:
- enc = AUDIO_ENCODING_SLINEAR_LE;
- ch->precision = 8;
- break;
- case AFMT_A_LAW: /* ? */
- enc = AUDIO_ENCODING_ALAW;
- ch->precision = 8;
- break;
- case AFMT_MU_LAW: /* ? */
- enc = AUDIO_ENCODING_ULAW;
- ch->precision = 8;
- break;
- case AFMT_S16_LE:
- enc = AUDIO_ENCODING_SLINEAR_LE;
- ch->precision = 16;
- break;
- case AFMT_S16_BE:
- enc = AUDIO_ENCODING_SLINEAR_BE;
- ch->precision = 16;
- break;
- case AFMT_U16_LE:
- enc = AUDIO_ENCODING_ULINEAR_LE;
- ch->precision = 16;
- break;
- case AFMT_U16_BE:
- enc = AUDIO_ENCODING_ULINEAR_BE;
- ch->precision = 16;
- break;
- case AFMT_S24_LE:
- enc = AUDIO_ENCODING_SLINEAR_LE;
- ch->precision = 24;
- break;
- case AFMT_S24_BE:
- enc = AUDIO_ENCODING_SLINEAR_BE;
- ch->precision = 24;
- break;
- case AFMT_U24_LE:
- enc = AUDIO_ENCODING_ULINEAR_LE;
- ch->precision = 24;
- break;
- case AFMT_U24_BE:
- enc = AUDIO_ENCODING_ULINEAR_BE;
- ch->precision = 24;
- break;
- case AFMT_S32_LE:
- enc = AUDIO_ENCODING_SLINEAR_LE;
- ch->precision = 32;
- break;
- case AFMT_S32_BE:
- enc = AUDIO_ENCODING_SLINEAR_BE;
- ch->precision = 32;
- break;
- case AFMT_U32_LE:
- enc = AUDIO_ENCODING_ULINEAR_LE;
- ch->precision = 32;
- break;
- case AFMT_U32_BE:
- enc = AUDIO_ENCODING_ULINEAR_BE;
- ch->precision = 32;
- break;
- default:
- enc = 0;
- ch->precision = 16;
- printf("Unknown format %x\n", ch->format);
- }
-
- if (ch->format & AFMT_STEREO) {
- ch->channels = 2;
- } else {
- ch->channels = 1;
- }
-
-/* for (mode = ...... */
- for (i = 0; i < sc->sc_nalts; i++) {
- const struct usb_audio_streaming_type1_descriptor *a1d =
- sc->sc_alts[i].asf1desc;
- if (ch->channels == a1d->bNrChannels &&
- ch->precision == a1d->bBitResolution &&
-#if 0
- enc == sc->sc_alts[i].encoding) {
-#else
- enc == sc->sc_alts[i].encoding &&
- (mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) ==
- UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) {
-#endif
- if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
- DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
- UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
- if (UA_SAMP_LO(a1d) <= ch->sample_rate &&
- ch->sample_rate <= UA_SAMP_HI(a1d)) {
- if (mode == AUMODE_PLAY)
- sc->sc_playchan.altidx = i;
- else
- sc->sc_recchan.altidx = i;
- goto found;
- }
- } else {
- for (j = 0; j < a1d->bSamFreqType; j++) {
- DPRINTFN(2,("uaudio_set_params: disc #"
- "%d: %d\n", j, UA_GETSAMP(a1d, j)));
- /* XXX allow for some slack */
- if (UA_GETSAMP(a1d, j) ==
- ch->sample_rate) {
- if (mode == AUMODE_PLAY)
- sc->sc_playchan.altidx = i;
- else
- sc->sc_recchan.altidx = i;
- goto found;
- }
- }
- }
- }
- }
- /* return (EINVAL); */
- if (mode == AUMODE_PLAY)
- printf("uaudio: This device can't play in rate=%d.\n", ch->sample_rate);
- else
- printf("uaudio: This device can't record in rate=%d.\n", ch->sample_rate);
- return (-1);
-
- found:
-#if 0 /* XXX */
- p->sw_code = swcode;
- p->factor = factor;
- if (usemode == mode)
- sc->sc_curaltidx = i;
-#endif
-/* } */
-
- sample_size = ch->precision * ch->channels / 8;
- samples_per_frame = ch->sample_rate / USB_FRAMES_PER_SECOND;
- ch->fraction = ch->sample_rate % USB_FRAMES_PER_SECOND;
- ch->sample_size = sample_size;
- ch->bytes_per_frame = samples_per_frame * sample_size;
- ch->residue = 0;
-
- ch->cur = ch->start;
- ch->transferred = 0;
- ch->curchanbuf = 0;
- return (0);
-}
-
-struct uaudio_conversion {
- uint8_t uaudio_fmt;
- uint8_t uaudio_prec;
- uint32_t freebsd_fmt;
-};
-
-const struct uaudio_conversion const accepted_conversion[] = {
- {AUDIO_ENCODING_ULINEAR_LE, 8, AFMT_U8},
- {AUDIO_ENCODING_ULINEAR_LE, 16, AFMT_U16_LE},
- {AUDIO_ENCODING_ULINEAR_LE, 24, AFMT_U24_LE},
- {AUDIO_ENCODING_ULINEAR_LE, 32, AFMT_U32_LE},
- {AUDIO_ENCODING_ULINEAR_BE, 16, AFMT_U16_BE},
- {AUDIO_ENCODING_ULINEAR_BE, 24, AFMT_U24_BE},
- {AUDIO_ENCODING_ULINEAR_BE, 32, AFMT_U32_BE},
- {AUDIO_ENCODING_SLINEAR_LE, 8, AFMT_S8},
- {AUDIO_ENCODING_SLINEAR_LE, 16, AFMT_S16_LE},
- {AUDIO_ENCODING_SLINEAR_LE, 24, AFMT_S24_LE},
- {AUDIO_ENCODING_SLINEAR_LE, 32, AFMT_S32_LE},
- {AUDIO_ENCODING_SLINEAR_BE, 16, AFMT_S16_BE},
- {AUDIO_ENCODING_SLINEAR_BE, 24, AFMT_S24_BE},
- {AUDIO_ENCODING_SLINEAR_BE, 32, AFMT_S32_BE},
- {AUDIO_ENCODING_ALAW, 8, AFMT_A_LAW},
- {AUDIO_ENCODING_ULAW, 8, AFMT_MU_LAW},
- {0,0,0}
-};
-
-unsigned
-uaudio_query_formats(device_t dev, int reqdir, unsigned maxfmt, struct pcmchan_caps *cap)
-{
- struct uaudio_softc *sc;
- const struct usb_audio_streaming_type1_descriptor *asf1d;
- const struct uaudio_conversion *iterator;
- unsigned fmtcount, foundcount;
- u_int32_t fmt;
- uint8_t format, numchan, subframesize, prec, dir, iscontinuous;
- int freq, freq_min, freq_max;
- char *numchannel_descr;
- char freq_descr[64];
- int i,r;
-
- sc = device_get_softc(dev);
- if (sc == NULL)
- return 0;
-
- cap->minspeed = cap->maxspeed = 0;
- foundcount = fmtcount = 0;
-
- for (i = 0; i < sc->sc_nalts; i++) {
- dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
-
- if ((dir == UE_DIR_OUT) != (reqdir == PCMDIR_PLAY))
- continue;
-
- asf1d = sc->sc_alts[i].asf1desc;
- format = sc->sc_alts[i].encoding;
-
- numchan = asf1d->bNrChannels;
- subframesize = asf1d->bSubFrameSize;
- prec = asf1d->bBitResolution; /* precision */
- iscontinuous = asf1d->bSamFreqType == UA_SAMP_CONTNUOUS;
-
- if (iscontinuous)
- snprintf(freq_descr, sizeof(freq_descr), "continous min %d max %d", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
- else
- snprintf(freq_descr, sizeof(freq_descr), "fixed frequency (%d listed formats)", asf1d->bSamFreqType);
-
- if (numchan == 1)
- numchannel_descr = " (mono)";
- else if (numchan == 2)
- numchannel_descr = " (stereo)";
- else
- numchannel_descr = "";
-
- if (bootverbose) {
- device_printf(dev, "uaudio_query_formats: found a native %s channel%s %s %dbit %dbytes/subframe X %d channels = %d bytes per sample\n",
- (dir==UE_DIR_OUT)?"playback":"record",
- numchannel_descr, freq_descr,
- prec, subframesize, numchan, subframesize*numchan);
- }
- /*
- * Now start rejecting the ones that don't map to FreeBSD
- */
-
- if (numchan != 1 && numchan != 2)
- continue;
-
- for (iterator = accepted_conversion ; iterator->uaudio_fmt != 0 ; iterator++)
- if (iterator->uaudio_fmt == format && iterator->uaudio_prec == prec)
- break;
-
- if (iterator->uaudio_fmt == 0)
- continue;
-
- fmt = iterator->freebsd_fmt;
-
- if (numchan == 2)
- fmt |= AFMT_STEREO;
-
- foundcount++;
-
- if (fmtcount >= maxfmt)
- continue;
-
- cap->fmtlist[fmtcount++] = fmt;
-
- if (iscontinuous) {
- freq_min = UA_SAMP_LO(asf1d);
- freq_max = UA_SAMP_HI(asf1d);
-
- if (cap->minspeed == 0 || freq_min < cap->minspeed)
- cap->minspeed = freq_min;
- if (cap->maxspeed == 0)
- cap->maxspeed = cap->minspeed;
- if (freq_max > cap->maxspeed)
- cap->maxspeed = freq_max;
- } else {
- for (r = 0; r < asf1d->bSamFreqType; r++) {
- freq = UA_GETSAMP(asf1d, r);
- if (cap->minspeed == 0 || freq < cap->minspeed)
- cap->minspeed = freq;
- if (cap->maxspeed == 0)
- cap->maxspeed = cap->minspeed;
- if (freq > cap->maxspeed)
- cap->maxspeed = freq;
- }
- }
- }
- cap->fmtlist[fmtcount] = 0;
- return foundcount;
-}
-
-void
-uaudio_chan_set_param_pcm_dma_buff(device_t dev, u_char *start, u_char *end,
- struct pcm_channel *pc, int dir)
-{
- struct uaudio_softc *sc;
- struct chan *ch;
-
- sc = device_get_softc(dev);
-#ifndef NO_RECORDING
- if (dir == PCMDIR_PLAY)
- ch = &sc->sc_playchan;
- else
- ch = &sc->sc_recchan;
-#else
- ch = &sc->sc_playchan;
-#endif
-
- ch->start = start;
- ch->end = end;
-
- ch->pcm_ch = pc;
-
- return;
-}
-
-void
-uaudio_chan_set_param_blocksize(device_t dev, u_int32_t blocksize, int dir)
-{
- struct uaudio_softc *sc;
- struct chan *ch;
-
- sc = device_get_softc(dev);
-#ifndef NO_RECORDING
- if (dir == PCMDIR_PLAY)
- ch = &sc->sc_playchan;
- else
- ch = &sc->sc_recchan;
-#else
- ch = &sc->sc_playchan;
-#endif
-
- ch->blksize = blocksize;
-
- return;
-}
-
-int
-uaudio_chan_set_param_speed(device_t dev, u_int32_t speed, int reqdir)
-{
- const struct uaudio_conversion *iterator;
- struct uaudio_softc *sc;
- struct chan *ch;
- int i, r, score, hiscore, bestspeed;
-
- sc = device_get_softc(dev);
-#ifndef NO_RECORDING
- if (reqdir == PCMDIR_PLAY)
- ch = &sc->sc_playchan;
- else
- ch = &sc->sc_recchan;
-#else
- ch = &sc->sc_playchan;
-#endif
- /*
- * We are successful if we find an endpoint that matches our selected format and it
- * supports the requested speed.
- */
- hiscore = 0;
- bestspeed = 1;
- for (i = 0; i < sc->sc_nalts; i++) {
- int dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
- int format = sc->sc_alts[i].encoding;
- const struct usb_audio_streaming_type1_descriptor *asf1d = sc->sc_alts[i].asf1desc;
- int iscontinuous = asf1d->bSamFreqType == UA_SAMP_CONTNUOUS;
-
- if ((dir == UE_DIR_OUT) != (reqdir == PCMDIR_PLAY))
- continue;
-
- for (iterator = accepted_conversion ; iterator->uaudio_fmt != 0 ; iterator++)
- if (iterator->uaudio_fmt != format || iterator->freebsd_fmt != (ch->format&0xfffffff))
- continue;
- if (iscontinuous) {
- if (speed >= UA_SAMP_LO(asf1d) && speed <= UA_SAMP_HI(asf1d)) {
- ch->sample_rate = speed;
- return speed;
- } else if (speed < UA_SAMP_LO(asf1d)) {
- score = 0xfff * speed / UA_SAMP_LO(asf1d);
- if (score > hiscore) {
- bestspeed = UA_SAMP_LO(asf1d);
- hiscore = score;
- }
- } else if (speed > UA_SAMP_HI(asf1d)) {
- score = 0xfff * UA_SAMP_HI(asf1d) / speed;
- if (score > hiscore) {
- bestspeed = UA_SAMP_HI(asf1d);
- hiscore = score;
- }
- }
- continue;
- }
- for (r = 0; r < asf1d->bSamFreqType; r++) {
- if (speed == UA_GETSAMP(asf1d, r)) {
- ch->sample_rate = speed;
- return speed;
- }
- if (speed > UA_GETSAMP(asf1d, r))
- score = 0xfff * UA_GETSAMP(asf1d, r) / speed;
- else
- score = 0xfff * speed / UA_GETSAMP(asf1d, r);
- if (score > hiscore) {
- bestspeed = UA_GETSAMP(asf1d, r);
- hiscore = score;
- }
- }
- }
- if (bestspeed != 1) {
- ch->sample_rate = bestspeed;
- return bestspeed;
- }
-
- return 0;
-}
-
-int
-uaudio_chan_getptr(device_t dev, int dir)
-{
- struct uaudio_softc *sc;
- struct chan *ch;
- int ptr;
-
- sc = device_get_softc(dev);
-#ifndef NO_RECORDING
- if (dir == PCMDIR_PLAY)
- ch = &sc->sc_playchan;
- else
- ch = &sc->sc_recchan;
-#else
- ch = &sc->sc_playchan;
-#endif
-
- ptr = ch->cur - ch->start;
-
- return ptr;
-}
-
-void
-uaudio_chan_set_param_format(device_t dev, u_int32_t format, int dir)
-{
- struct uaudio_softc *sc;
- struct chan *ch;
-
- sc = device_get_softc(dev);
-#ifndef NO_RECORDING
- if (dir == PCMDIR_PLAY)
- ch = &sc->sc_playchan;
- else
- ch = &sc->sc_recchan;
-#else
- ch = &sc->sc_playchan;
-#endif
-
- ch->format = format;
-
- return;
-}
-
-int
-uaudio_halt_out_dma(device_t dev)
-{
- struct uaudio_softc *sc;
-
- sc = device_get_softc(dev);
-
- DPRINTF(("uaudio_halt_out_dma: enter\n"));
- if (sc->sc_playchan.pipe != NULL) {
- uaudio_chan_close(sc, &sc->sc_playchan);
- sc->sc_playchan.pipe = 0;
- uaudio_chan_free_buffers(sc, &sc->sc_playchan);
- }
- return (0);
-}
-
-int
-uaudio_halt_in_dma(device_t dev)
-{
- struct uaudio_softc *sc;
-
- sc = device_get_softc(dev);
-
- if (sc->sc_dying)
- return (EIO);
-
- DPRINTF(("uaudio_halt_in_dma: enter\n"));
- if (sc->sc_recchan.pipe != NULL) {
- uaudio_chan_close(sc, &sc->sc_recchan);
- sc->sc_recchan.pipe = NULL;
- uaudio_chan_free_buffers(sc, &sc->sc_recchan);
-/* sc->sc_recchan.intr = NULL; */
- }
- return (0);
-}
-
-int
-uaudio_trigger_input(device_t dev)
-{
- struct uaudio_softc *sc;
- struct chan *ch;
- usbd_status err;
- int i, s;
-
- sc = device_get_softc(dev);
- ch = &sc->sc_recchan;
-
- if (sc->sc_dying)
- return (EIO);
-
-/* uaudio_chan_set_param(ch, start, end, blksize) */
- if (uaudio_init_params(sc, ch, AUMODE_RECORD))
- return (EIO);
-
- err = uaudio_chan_alloc_buffers(sc, ch);
- if (err)
- return (EIO);
-
- err = uaudio_chan_open(sc, ch);
- if (err) {
- uaudio_chan_free_buffers(sc, ch);
- return (EIO);
- }
-
-/* ch->intr = intr;
- ch->arg = arg; */
-
- s = splusb();
- for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
- uaudio_chan_rtransfer(ch);
- splx(s);
-
- return (0);
-}
-
-int
-uaudio_trigger_output(device_t dev)
-{
- struct uaudio_softc *sc;
- struct chan *ch;
- usbd_status err;
- int i, s;
-
- sc = device_get_softc(dev);
- ch = &sc->sc_playchan;
-
- if (sc->sc_dying)
- return (EIO);
-
- if (uaudio_init_params(sc, ch, AUMODE_PLAY))
- return (EIO);
-
- err = uaudio_chan_alloc_buffers(sc, ch);
- if (err)
- return (EIO);
-
- err = uaudio_chan_open(sc, ch);
- if (err) {
- uaudio_chan_free_buffers(sc, ch);
- return (EIO);
- }
-
- s = splusb();
- for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
- uaudio_chan_ptransfer(ch);
- splx(s);
-
- return (0);
-}
-
-u_int32_t
-uaudio_query_mix_info(device_t dev)
-{
- int i;
- u_int32_t mask = 0;
- struct uaudio_softc *sc;
- struct mixerctl *mc;
-
- sc = device_get_softc(dev);
- for (i=0; i < sc->sc_nctls; i++) {
- mc = &sc->sc_ctls[i];
- if (mc->ctl != SOUND_MIXER_NRDEVICES) {
- /* Set device mask bits.
- See /usr/include/machine/soundcard.h */
- mask |= (1 << mc->ctl);
- }
- }
- return mask;
-}
-
-u_int32_t
-uaudio_query_recsrc_info(device_t dev)
-{
- int i, rec_selector_id;
- u_int32_t mask = 0;
- struct uaudio_softc *sc;
- struct mixerctl *mc;
-
- sc = device_get_softc(dev);
- rec_selector_id = -1;
- for (i=0; i < sc->sc_nctls; i++) {
- mc = &sc->sc_ctls[i];
- if (mc->ctl == SOUND_MIXER_NRDEVICES &&
- mc->type == MIX_SELECTOR && mc->class == UAC_RECORD) {
- if (rec_selector_id == -1) {
- rec_selector_id = i;
- } else {
- printf("There are many selectors. Can't recognize which selector is a record source selector.\n");
- return mask;
- }
- }
- }
- if (rec_selector_id == -1)
- return mask;
- mc = &sc->sc_ctls[rec_selector_id];
- for (i = mc->minval; i <= mc->maxval; i++) {
- if (mc->slctrtype[i - 1] == SOUND_MIXER_NRDEVICES)
- continue;
- mask |= 1 << mc->slctrtype[i - 1];
- }
- return mask;
-}
-
-void
-uaudio_mixer_set(device_t dev, unsigned type, unsigned left, unsigned right)
-{
- int i;
- struct uaudio_softc *sc;
- struct mixerctl *mc;
-
- sc = device_get_softc(dev);
- for (i=0; i < sc->sc_nctls; i++) {
- mc = &sc->sc_ctls[i];
- if (mc->ctl == type) {
- if (mc->nchan == 2) {
- /* set Right */
- uaudio_ctl_set(sc, SET_CUR, mc, 1, (int)(right*255)/100);
- }
- /* set Left or Mono */
- uaudio_ctl_set(sc, SET_CUR, mc, 0, (int)(left*255)/100);
- }
- }
- return;
-}
-
-u_int32_t
-uaudio_mixer_setrecsrc(device_t dev, u_int32_t src)
-{
- int i, rec_selector_id;
- struct uaudio_softc *sc;
- struct mixerctl *mc;
-
- sc = device_get_softc(dev);
- rec_selector_id = -1;
- for (i=0; i < sc->sc_nctls; i++) {
- mc = &sc->sc_ctls[i];
- if (mc->ctl == SOUND_MIXER_NRDEVICES &&
- mc->type == MIX_SELECTOR && mc->class == UAC_RECORD) {
- if (rec_selector_id == -1) {
- rec_selector_id = i;
- } else {
- return src; /* Can't recognize which selector is record source selector */
- }
- }
- }
- if (rec_selector_id == -1)
- return src;
- mc = &sc->sc_ctls[rec_selector_id];
- for (i = mc->minval; i <= mc->maxval; i++) {
- if (src != (1 << mc->slctrtype[i - 1]))
- continue;
- uaudio_ctl_set(sc, SET_CUR, mc, 0, i);
- return (1 << mc->slctrtype[i - 1]);
- }
- uaudio_ctl_set(sc, SET_CUR, mc, 0, mc->minval);
- return (1 << mc->slctrtype[mc->minval - 1]);
-}
-
-static int
-uaudio_sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose)
-{
- struct snddev_info *d;
- struct pcm_channel *c;
- struct pcm_feeder *f;
- device_t pa_dev = device_get_parent(dev);
- struct uaudio_softc *sc = device_get_softc(pa_dev);
-
- if (verbose < 1)
- return 0;
-
- d = device_get_softc(dev);
- if (!d)
- return ENXIO;
-
- PCM_BUSYASSERT(d);
-
- if (CHN_EMPTY(d, channels.pcm)) {
- sbuf_printf(s, " (mixer only)");
- return 0;
- }
-
- sbuf_printf(s, " (%dp:%dv/%dr:%dv channels%s%s)",
- d->playcount, d->pvchancount,
- d->reccount, d->rvchancount,
- (d->flags & SD_F_SIMPLEX)? "" : " duplex",
-#ifdef USING_DEVFS
- (device_get_unit(dev) == snd_unit)? " default" : ""
-#else
- ""
-#endif
- );
-
- if (sc->uaudio_sndstat_flag != 0) {
- sbuf_cat(s, sbuf_data(&(sc->uaudio_sndstat)));
- }
-
- if (verbose <= 1)
- return 0;
-
- CHN_FOREACH(c, d, channels.pcm) {
-
- KASSERT(c->bufhard != NULL && c->bufsoft != NULL,
- ("hosed pcm channel setup"));
-
- sbuf_printf(s, "\n\t");
-
- /* it would be better to indent child channels */
- sbuf_printf(s, "%s[%s]: ", c->parentchannel? c->parentchannel->name : "", c->name);
- sbuf_printf(s, "spd %d", c->speed);
- if (c->speed != sndbuf_getspd(c->bufhard))
- sbuf_printf(s, "/%d", sndbuf_getspd(c->bufhard));
- sbuf_printf(s, ", fmt 0x%08x", c->format);
- if (c->format != sndbuf_getfmt(c->bufhard))
- sbuf_printf(s, "/0x%08x", sndbuf_getfmt(c->bufhard));
- sbuf_printf(s, ", flags 0x%08x, 0x%08x", c->flags, c->feederflags);
- if (c->pid != -1)
- sbuf_printf(s, ", pid %d", c->pid);
- sbuf_printf(s, "\n\t");
-
- sbuf_printf(s, "interrupts %d, ", c->interrupts);
- if (c->direction == PCMDIR_REC)
- sbuf_printf(s, "overruns %d, feed %u, hfree %d, sfree %d [b:%d/%d/%d|bs:%d/%d/%d]",
- c->xruns, c->feedcount, sndbuf_getfree(c->bufhard), sndbuf_getfree(c->bufsoft),
- sndbuf_getsize(c->bufhard), sndbuf_getblksz(c->bufhard),
- sndbuf_getblkcnt(c->bufhard),
- sndbuf_getsize(c->bufsoft), sndbuf_getblksz(c->bufsoft),
- sndbuf_getblkcnt(c->bufsoft));
- else
- sbuf_printf(s, "underruns %d, feed %u, ready %d [b:%d/%d/%d|bs:%d/%d/%d]",
- c->xruns, c->feedcount, sndbuf_getready(c->bufsoft),
- sndbuf_getsize(c->bufhard), sndbuf_getblksz(c->bufhard),
- sndbuf_getblkcnt(c->bufhard),
- sndbuf_getsize(c->bufsoft), sndbuf_getblksz(c->bufsoft),
- sndbuf_getblkcnt(c->bufsoft));
- sbuf_printf(s, "\n\t");
-
- sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "hardware" : "userland");
- sbuf_printf(s, " -> ");
- f = c->feeder;
- while (f->source != NULL)
- f = f->source;
- while (f != NULL) {
- sbuf_printf(s, "%s", f->class->name);
- if (f->desc->type == FEEDER_FMT)
- sbuf_printf(s, "(0x%08x -> 0x%08x)", f->desc->in, f->desc->out);
- if (f->desc->type == FEEDER_RATE)
- sbuf_printf(s, "(%d -> %d)", FEEDER_GET(f, FEEDRATE_SRC), FEEDER_GET(f, FEEDRATE_DST));
- if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER ||
- f->desc->type == FEEDER_VOLUME)
- sbuf_printf(s, "(0x%08x)", f->desc->out);
- sbuf_printf(s, " -> ");
- f = f->parent;
- }
- sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "userland" : "hardware");
- }
-
- return 0;
-}
-
-void
-uaudio_sndstat_register(device_t dev)
-{
- struct snddev_info *d = device_get_softc(dev);
- sndstat_register(dev, d->status, uaudio_sndstat_prepare_pcm);
-}
-
-int
-uaudio_get_vendor(device_t dev)
-{
- struct uaudio_softc *sc = device_get_softc(dev);
-
- if (sc == NULL)
- return 0;
-
- return sc->sc_vendor;
-}
-
-int
-uaudio_get_product(device_t dev)
-{
- struct uaudio_softc *sc = device_get_softc(dev);
-
- if (sc == NULL)
- return 0;
-
- return sc->sc_product;
-}
-
-int
-uaudio_get_release(device_t dev)
-{
- struct uaudio_softc *sc = device_get_softc(dev);
-
- if (sc == NULL)
- return 0;
-
- return sc->sc_release;
-}
-
-static int
-audio_attach_mi(device_t dev)
-{
- device_t child;
- struct sndcard_func *func;
-
- /* Attach the children. */
- /* PCM Audio */
- func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
- if (func == NULL)
- return (ENOMEM);
- func->func = SCF_PCM;
- child = device_add_child(dev, "pcm", -1);
- device_set_ivars(child, func);
-
- bus_generic_attach(dev);
-
- return 0; /* XXXXX */
-}
-
-DRIVER_MODULE(uaudio, uhub, uaudio_driver, uaudio_devclass, usbd_driver_load, 0);
-MODULE_VERSION(uaudio, 1);
-
-#endif
diff --git a/sys/dev/sound/usb/uaudio.h b/sys/dev/sound/usb/uaudio.h
deleted file mode 100644
index b73f7a5..0000000
--- a/sys/dev/sound/usb/uaudio.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* $FreeBSD$ */
-
-/*-
- * Copyright (c) 2000-2002 Hiroyuki Aizu <aizu@navi.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if 0
-#define NO_RECORDING /* XXX: some routines missing from uaudio.c */
-#endif
-
-/* Defined in uaudio.c, used in uaudio_pcm,c */
-
-void uaudio_chan_set_param_pcm_dma_buff(device_t dev, u_char *start,
- u_char *end, struct pcm_channel *pc, int dir);
-int uaudio_trigger_output(device_t dev);
-int uaudio_halt_out_dma(device_t dev);
-#ifndef NO_RECORDING
-int uaudio_trigger_input(device_t dev);
-int uaudio_halt_in_dma(device_t dev);
-#endif
-void uaudio_chan_set_param(device_t, u_char *, u_char *);
-void uaudio_chan_set_param_blocksize(device_t dev, u_int32_t blocksize, int dir);
-int uaudio_chan_set_param_speed(device_t dev, u_int32_t speed, int reqdir);
-void uaudio_chan_set_param_format(device_t dev, u_int32_t format,int dir);
-int uaudio_chan_getptr(device_t dev, int);
-void uaudio_mixer_set(device_t dev, unsigned type, unsigned left,
- unsigned right);
-u_int32_t uaudio_mixer_setrecsrc(device_t dev, u_int32_t src);
-u_int32_t uaudio_query_mix_info(device_t dev);
-u_int32_t uaudio_query_recsrc_info(device_t dev);
-unsigned uaudio_query_formats(device_t dev, int dir, unsigned maxfmt, struct pcmchan_caps *fmt);
-void uaudio_sndstat_register(device_t dev);
-int uaudio_get_vendor(device_t dev);
-int uaudio_get_product(device_t dev);
-int uaudio_get_release(device_t dev);
diff --git a/sys/dev/sound/usb/uaudio_pcm.c b/sys/dev/sound/usb/uaudio_pcm.c
deleted file mode 100644
index 618a0ed..0000000
--- a/sys/dev/sound/usb/uaudio_pcm.c
+++ /dev/null
@@ -1,481 +0,0 @@
-/* $FreeBSD$ */
-
-/*-
- * Copyright (c) 2000-2002 Hiroyuki Aizu <aizu@navi.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-
-#include <sys/soundcard.h>
-#include <dev/sound/pcm/sound.h>
-#include <dev/sound/chip.h>
-
-#include <dev/sound/usb/uaudio.h>
-
-#include "mixer_if.h"
-
-struct ua_info;
-
-struct ua_chinfo {
- struct ua_info *parent;
- struct pcm_channel *channel;
- struct snd_dbuf *buffer;
- u_char *buf;
- int dir, hwch;
- u_int32_t fmt, spd, blksz; /* XXXXX */
-};
-
-struct ua_info {
- device_t sc_dev;
- u_int32_t bufsz;
- struct ua_chinfo pch, rch;
-#define FORMAT_NUM 32
- u_int32_t ua_playfmt[FORMAT_NUM*2+1]; /* FORMAT_NUM format * (stereo or mono) + endptr */
- u_int32_t ua_recfmt[FORMAT_NUM*2+1]; /* FORMAT_NUM format * (stereo or mono) + endptr */
- struct pcmchan_caps ua_playcaps;
- struct pcmchan_caps ua_reccaps;
- int vendor, product, release;
-};
-
-#define UAUDIO_DEFAULT_BUFSZ 16*1024
-
-static const struct {
- int vendor;
- int product;
- int release;
- uint32_t dflags;
-} ua_quirks[] = {
- { 0x1130, 0xf211, 0x0101, SD_F_PSWAPLR },
-};
-
-/************************************************************/
-static void *
-ua_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
-{
- device_t pa_dev;
-
- struct ua_info *sc = devinfo;
- struct ua_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
-
- ch->parent = sc;
- ch->channel = c;
- ch->buffer = b;
- ch->dir = dir;
-
- pa_dev = device_get_parent(sc->sc_dev);
-
- ch->buf = malloc(sc->bufsz, M_DEVBUF, M_NOWAIT);
- if (ch->buf == NULL)
- return NULL;
- if (sndbuf_setup(b, ch->buf, sc->bufsz) != 0) {
- free(ch->buf, M_DEVBUF);
- return NULL;
- }
- uaudio_chan_set_param_pcm_dma_buff(pa_dev, ch->buf, ch->buf+sc->bufsz, ch->channel, dir);
- if (bootverbose)
- device_printf(pa_dev, "%s buf %p\n", (dir == PCMDIR_PLAY)?
- "play" : "rec", sndbuf_getbuf(ch->buffer));
-
- ch->dir = dir;
-#ifndef NO_RECORDING
- ch->hwch = 1;
- if (dir == PCMDIR_PLAY)
- ch->hwch = 2;
-#else
- ch->hwch = 2;
-#endif
-
- return ch;
-}
-
-static int
-ua_chan_free(kobj_t obj, void *data)
-{
- struct ua_chinfo *ua = data;
-
- if (ua->buf != NULL)
- free(ua->buf, M_DEVBUF);
- return 0;
-}
-
-static int
-ua_chan_setformat(kobj_t obj, void *data, u_int32_t format)
-{
- device_t pa_dev;
- struct ua_info *ua;
-
- struct ua_chinfo *ch = data;
-
- /*
- * At this point, no need to query as we shouldn't select an unsorted format
- */
- ua = ch->parent;
- pa_dev = device_get_parent(ua->sc_dev);
- uaudio_chan_set_param_format(pa_dev, format, ch->dir);
-
- ch->fmt = format;
- return 0;
-}
-
-static int
-ua_chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
-{
- struct ua_chinfo *ch;
- device_t pa_dev;
- int bestspeed;
-
- ch = data;
- pa_dev = device_get_parent(ch->parent->sc_dev);
-
- if ((bestspeed = uaudio_chan_set_param_speed(pa_dev, speed, ch->dir)))
- ch->spd = bestspeed;
-
- return ch->spd;
-}
-
-static int
-ua_chan_setfragments(kobj_t obj, void *data, u_int32_t blksz, u_int32_t blkcnt)
-{
- device_t pa_dev;
- struct ua_chinfo *ch = data;
- struct ua_info *ua = ch->parent;
-
- RANGE(blksz, 128, sndbuf_getmaxsize(ch->buffer) / 2);
- RANGE(blkcnt, 2, 512);
-
- while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
- if ((blkcnt >> 1) >= 2)
- blkcnt >>= 1;
- else if ((blksz >> 1) >= 128)
- blksz >>= 1;
- else
- break;
- }
-
- if ((sndbuf_getblksz(ch->buffer) != blksz ||
- sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
- sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
- device_printf(ua->sc_dev, "%s: failed blksz=%u blkcnt=%u\n",
- __func__, blksz, blkcnt);
-
- ch->blksz = sndbuf_getblksz(ch->buffer);
-
- pa_dev = device_get_parent(ua->sc_dev);
- uaudio_chan_set_param_pcm_dma_buff(pa_dev, ch->buf,
- ch->buf + sndbuf_getsize(ch->buffer), ch->channel, ch->dir);
- uaudio_chan_set_param_blocksize(pa_dev, ch->blksz, ch->dir);
-
- return 1;
-}
-
-static int
-ua_chan_setblocksize(kobj_t obj, void *data, u_int32_t blksz)
-{
- struct ua_chinfo *ch = data;
-
- ua_chan_setfragments(obj, data, blksz,
- sndbuf_getmaxsize(ch->buffer) / blksz);
-
- return ch->blksz;
-}
-
-static int
-ua_chan_trigger(kobj_t obj, void *data, int go)
-{
- device_t pa_dev;
- struct ua_info *ua;
- struct ua_chinfo *ch = data;
-
- if (!PCMTRIG_COMMON(go))
- return 0;
-
- ua = ch->parent;
- pa_dev = device_get_parent(ua->sc_dev);
-
- /* XXXXX */
- if (ch->dir == PCMDIR_PLAY) {
- if (go == PCMTRIG_START) {
- uaudio_trigger_output(pa_dev);
- } else {
- uaudio_halt_out_dma(pa_dev);
- }
- } else {
-#ifndef NO_RECORDING
- if (go == PCMTRIG_START)
- uaudio_trigger_input(pa_dev);
- else
- uaudio_halt_in_dma(pa_dev);
-#endif
- }
-
- return 0;
-}
-
-static int
-ua_chan_getptr(kobj_t obj, void *data)
-{
- device_t pa_dev;
- struct ua_info *ua;
- struct ua_chinfo *ch = data;
-
- ua = ch->parent;
- pa_dev = device_get_parent(ua->sc_dev);
-
- return uaudio_chan_getptr(pa_dev, ch->dir);
-}
-
-static struct pcmchan_caps *
-ua_chan_getcaps(kobj_t obj, void *data)
-{
- struct ua_chinfo *ch;
-
- ch = data;
- return (ch->dir == PCMDIR_PLAY) ? &(ch->parent->ua_playcaps) : &(ch->parent->ua_reccaps);
-}
-
-static kobj_method_t ua_chan_methods[] = {
- KOBJMETHOD(channel_init, ua_chan_init),
- KOBJMETHOD(channel_free, ua_chan_free),
- KOBJMETHOD(channel_setformat, ua_chan_setformat),
- KOBJMETHOD(channel_setspeed, ua_chan_setspeed),
- KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize),
- KOBJMETHOD(channel_setfragments, ua_chan_setfragments),
- KOBJMETHOD(channel_trigger, ua_chan_trigger),
- KOBJMETHOD(channel_getptr, ua_chan_getptr),
- KOBJMETHOD(channel_getcaps, ua_chan_getcaps),
- { 0, 0 }
-};
-
-CHANNEL_DECLARE(ua_chan);
-
-/************************************************************/
-static int
-ua_mixer_init(struct snd_mixer *m)
-{
- u_int32_t mask;
- device_t pa_dev;
- struct ua_info *ua = mix_getdevinfo(m);
-
- pa_dev = device_get_parent(ua->sc_dev);
-
- mask = uaudio_query_mix_info(pa_dev);
- if (!(mask & SOUND_MASK_PCM)) {
- /*
- * Emulate missing pcm mixer controller
- * through FEEDER_VOLUME
- */
- pcm_setflags(ua->sc_dev, pcm_getflags(ua->sc_dev) |
- SD_F_SOFTPCMVOL);
- }
- if (!(mask & SOUND_MASK_VOLUME)) {
- mix_setparentchild(m, SOUND_MIXER_VOLUME, SOUND_MASK_PCM);
- mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE);
- }
- mix_setdevs(m, mask);
-
- mask = uaudio_query_recsrc_info(pa_dev);
- mix_setrecdevs(m, mask);
-
- return 0;
-}
-
-static int
-ua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right)
-{
- device_t pa_dev;
- struct ua_info *ua = mix_getdevinfo(m);
-
- pa_dev = device_get_parent(ua->sc_dev);
- uaudio_mixer_set(pa_dev, type, left, right);
-
- return left | (right << 8);
-}
-
-static int
-ua_mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
-{
- device_t pa_dev;
- struct ua_info *ua = mix_getdevinfo(m);
-
- pa_dev = device_get_parent(ua->sc_dev);
- return uaudio_mixer_setrecsrc(pa_dev, src);
-}
-
-static kobj_method_t ua_mixer_methods[] = {
- KOBJMETHOD(mixer_init, ua_mixer_init),
- KOBJMETHOD(mixer_set, ua_mixer_set),
- KOBJMETHOD(mixer_setrecsrc, ua_mixer_setrecsrc),
-
- { 0, 0 }
-};
-MIXER_DECLARE(ua_mixer);
-/************************************************************/
-
-
-static int
-ua_probe(device_t dev)
-{
- char *s;
- struct sndcard_func *func;
-
- /* The parent device has already been probed. */
-
- func = device_get_ivars(dev);
- if (func == NULL || func->func != SCF_PCM)
- return (ENXIO);
-
- s = "USB Audio";
-
- device_set_desc(dev, s);
- return BUS_PROBE_DEFAULT;
-}
-
-static int
-ua_attach(device_t dev)
-{
- struct ua_info *ua;
- struct sndcard_func *func;
- char status[SND_STATUSLEN];
- device_t pa_dev;
- u_int32_t nplay, nrec, flags;
- int i;
-
- ua = malloc(sizeof(*ua), M_DEVBUF, M_WAITOK | M_ZERO);
- ua->sc_dev = dev;
-
- /* Mark for existence */
- func = device_get_ivars(dev);
- if (func != NULL)
- func->varinfo = (void *)ua;
-
- pa_dev = device_get_parent(dev);
- ua->vendor = uaudio_get_vendor(pa_dev);
- ua->product = uaudio_get_product(pa_dev);
- ua->release = uaudio_get_release(pa_dev);
-
- if (bootverbose)
- device_printf(dev,
- "USB Audio: "
- "vendor=0x%04x, product=0x%04x, release=0x%04x\n",
- ua->vendor, ua->product, ua->release);
-
- ua->bufsz = pcm_getbuffersize(dev, 4096, UAUDIO_DEFAULT_BUFSZ, 65536);
- if (bootverbose)
- device_printf(dev, "using a default buffer size of %jd\n", (intmax_t)ua->bufsz);
-
- if (mixer_init(dev, &ua_mixer_class, ua)) {
- goto bad;
- }
-
- snprintf(status, SND_STATUSLEN, "at ? %s", PCM_KLDSTRING(snd_uaudio));
-
- ua->ua_playcaps.fmtlist = ua->ua_playfmt;
- ua->ua_reccaps.fmtlist = ua->ua_recfmt;
- nplay = uaudio_query_formats(pa_dev, PCMDIR_PLAY, FORMAT_NUM * 2, &ua->ua_playcaps);
- nrec = uaudio_query_formats(pa_dev, PCMDIR_REC, FORMAT_NUM * 2, &ua->ua_reccaps);
-
- if (nplay > 1)
- nplay = 1;
- if (nrec > 1)
- nrec = 1;
-
- flags = pcm_getflags(dev);
- for (i = 0; i < (sizeof(ua_quirks) / sizeof(ua_quirks[0])); i++) {
- if (ua->vendor == ua_quirks[i].vendor &&
- ua->product == ua_quirks[i].product &&
- ua->release == ua_quirks[i].release)
- flags |= ua_quirks[i].dflags;
- }
- pcm_setflags(dev, flags);
-
-#ifndef NO_RECORDING
- if (pcm_register(dev, ua, nplay, nrec)) {
-#else
- if (pcm_register(dev, ua, nplay, 0)) {
-#endif
- goto bad;
- }
-
- sndstat_unregister(dev);
- uaudio_sndstat_register(dev);
-
- for (i = 0; i < nplay; i++) {
- pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua);
- }
-#ifndef NO_RECORDING
- for (i = 0; i < nrec; i++) {
- pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua);
- }
-#endif
- pcm_setstatus(dev, status);
-
- return 0;
-
-bad: free(ua, M_DEVBUF);
- return ENXIO;
-}
-
-static int
-ua_detach(device_t dev)
-{
- struct ua_info *sc;
- struct sndcard_func *func;
- int r;
-
- r = pcm_unregister(dev);
- if (r)
- return r;
-
- sc = pcm_getdevinfo(dev);
- free(sc, M_DEVBUF);
-
- /* Mark for deletion */
- func = device_get_ivars(dev);
- if (func != NULL)
- func->varinfo = NULL;
-
- return 0;
-}
-
-/************************************************************/
-
-static device_method_t ua_pcm_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ua_probe),
- DEVMETHOD(device_attach, ua_attach),
- DEVMETHOD(device_detach, ua_detach),
-
- { 0, 0 }
-};
-
-static driver_t ua_pcm_driver = {
- "pcm",
- ua_pcm_methods,
- PCM_SOFTC_SIZE,
-};
-
-
-DRIVER_MODULE(ua_pcm, uaudio, ua_pcm_driver, pcm_devclass, 0, 0);
-MODULE_DEPEND(ua_pcm, uaudio, 1, 1, 1);
-MODULE_DEPEND(ua_pcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
-MODULE_VERSION(ua_pcm, 1);
diff --git a/sys/dev/sound/usb/uaudioreg.h b/sys/dev/sound/usb/uaudioreg.h
deleted file mode 100644
index 3cc09ba..0000000
--- a/sys/dev/sound/usb/uaudioreg.h
+++ /dev/null
@@ -1,404 +0,0 @@
-/* $NetBSD: uaudioreg.h,v 1.12 2004/11/05 19:08:29 kent Exp $ */
-/* $FreeBSD$ */
-
-/*-
- * Copyright (c) 1999 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (lennart@augustsson.net) at
- * Carlstedt Research & Technology.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define UAUDIO_VERSION 0x100
-
-#define UDESC_CS_CONFIG 0x22
-#define UDESC_CS_STRING 0x23
-#define UDESC_CS_INTERFACE 0x24
-#define UDESC_CS_ENDPOINT 0x25
-
-#define UDESCSUB_AC_HEADER 1
-#define UDESCSUB_AC_INPUT 2
-#define UDESCSUB_AC_OUTPUT 3
-#define UDESCSUB_AC_MIXER 4
-#define UDESCSUB_AC_SELECTOR 5
-#define UDESCSUB_AC_FEATURE 6
-#define UDESCSUB_AC_PROCESSING 7
-#define UDESCSUB_AC_EXTENSION 8
-
-/* The first fields are identical to usb_endpoint_descriptor_t */
-typedef struct {
- uByte bLength;
- uByte bDescriptorType;
- uByte bEndpointAddress;
- uByte bmAttributes;
- uWord wMaxPacketSize;
- uByte bInterval;
- /*
- * The following two entries are only used by the Audio Class.
- * And according to the specs the Audio Class is the only one
- * allowed to extend the endpoint descriptor.
- * Who knows what goes on in the minds of the people in the USB
- * standardization? :-(
- */
- uByte bRefresh;
- uByte bSynchAddress;
-} UPACKED usb_endpoint_descriptor_audio_t;
-
-struct usb_audio_control_descriptor {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uWord bcdADC;
- uWord wTotalLength;
- uByte bInCollection;
- uByte baInterfaceNr[1];
-} UPACKED;
-
-struct usb_audio_streaming_interface_descriptor {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bTerminalLink;
- uByte bDelay;
- uWord wFormatTag;
-} UPACKED;
-
-struct usb_audio_streaming_endpoint_descriptor {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bmAttributes;
-#define UA_SED_FREQ_CONTROL 0x01
-#define UA_SED_PITCH_CONTROL 0x02
-#define UA_SED_MAXPACKETSONLY 0x80
- uByte bLockDelayUnits;
- uWord wLockDelay;
-} UPACKED;
-
-struct usb_audio_streaming_type1_descriptor {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bFormatType;
- uByte bNrChannels;
- uByte bSubFrameSize;
- uByte bBitResolution;
- uByte bSamFreqType;
-#define UA_SAMP_CONTNUOUS 0
- uByte tSamFreq[3*2]; /* room for low and high */
-#define UA_GETSAMP(p, n) ((p)->tSamFreq[(n)*3+0] | ((p)->tSamFreq[(n)*3+1] << 8) | ((p)->tSamFreq[(n)*3+2] << 16))
-#define UA_SAMP_LO(p) UA_GETSAMP(p, 0)
-#define UA_SAMP_HI(p) UA_GETSAMP(p, 1)
-} UPACKED;
-
-struct usb_audio_cluster {
- uByte bNrChannels;
- uWord wChannelConfig;
-#define UA_CHANNEL_LEFT 0x0001
-#define UA_CHANNEL_RIGHT 0x0002
-#define UA_CHANNEL_CENTER 0x0004
-#define UA_CHANNEL_LFE 0x0008
-#define UA_CHANNEL_L_SURROUND 0x0010
-#define UA_CHANNEL_R_SURROUND 0x0020
-#define UA_CHANNEL_L_CENTER 0x0040
-#define UA_CHANNEL_R_CENTER 0x0080
-#define UA_CHANNEL_SURROUND 0x0100
-#define UA_CHANNEL_L_SIDE 0x0200
-#define UA_CHANNEL_R_SIDE 0x0400
-#define UA_CHANNEL_TOP 0x0800
- uByte iChannelNames;
-} UPACKED;
-
-/* Shared by all units and terminals */
-struct usb_audio_unit {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bUnitId;
-};
-
-/* UDESCSUB_AC_INPUT */
-struct usb_audio_input_terminal {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bTerminalId;
- uWord wTerminalType;
- uByte bAssocTerminal;
- uByte bNrChannels;
- uWord wChannelConfig;
- uByte iChannelNames;
- uByte iTerminal;
-} UPACKED;
-
-/* UDESCSUB_AC_OUTPUT */
-struct usb_audio_output_terminal {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bTerminalId;
- uWord wTerminalType;
- uByte bAssocTerminal;
- uByte bSourceId;
- uByte iTerminal;
-} UPACKED;
-
-/* UDESCSUB_AC_MIXER */
-struct usb_audio_mixer_unit {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bUnitId;
- uByte bNrInPins;
- uByte baSourceId[255]; /* [bNrInPins] */
- /* struct usb_audio_mixer_unit_1 */
-} UPACKED;
-struct usb_audio_mixer_unit_1 {
- uByte bNrChannels;
- uWord wChannelConfig;
- uByte iChannelNames;
- uByte bmControls[255]; /* [bNrChannels] */
- /*uByte iMixer;*/
-} UPACKED;
-
-/* UDESCSUB_AC_SELECTOR */
-struct usb_audio_selector_unit {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bUnitId;
- uByte bNrInPins;
- uByte baSourceId[255]; /* [bNrInPins] */
- /* uByte iSelector; */
-} UPACKED;
-
-/* UDESCSUB_AC_FEATURE */
-struct usb_audio_feature_unit {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bUnitId;
- uByte bSourceId;
- uByte bControlSize;
- uByte bmaControls[255]; /* size for more than enough */
- /* uByte iFeature; */
-} UPACKED;
-
-/* UDESCSUB_AC_PROCESSING */
-struct usb_audio_processing_unit {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bUnitId;
- uWord wProcessType;
- uByte bNrInPins;
- uByte baSourceId[255]; /* [bNrInPins] */
- /* struct usb_audio_processing_unit_1 */
-} UPACKED;
-struct usb_audio_processing_unit_1{
- uByte bNrChannels;
- uWord wChannelConfig;
- uByte iChannelNames;
- uByte bControlSize;
- uByte bmControls[255]; /* [bControlSize] */
-#define UA_PROC_ENABLE_MASK 1
-} UPACKED;
-
-struct usb_audio_processing_unit_updown {
- uByte iProcessing;
- uByte bNrModes;
- uWord waModes[255]; /* [bNrModes] */
-} UPACKED;
-
-/* UDESCSUB_AC_EXTENSION */
-struct usb_audio_extension_unit {
- uByte bLength;
- uByte bDescriptorType;
- uByte bDescriptorSubtype;
- uByte bUnitId;
- uWord wExtensionCode;
- uByte bNrInPins;
- uByte baSourceId[255]; /* [bNrInPins] */
- /* struct usb_audio_extension_unit_1 */
-} UPACKED;
-struct usb_audio_extension_unit_1 {
- uByte bNrChannels;
- uWord wChannelConfig;
- uByte iChannelNames;
- uByte bControlSize;
- uByte bmControls[255]; /* [bControlSize] */
-#define UA_EXT_ENABLE_MASK 1
-#define UA_EXT_ENABLE 1
- /*uByte iExtension;*/
-} UPACKED;
-
-/* USB terminal types */
-#define UAT_UNDEFINED 0x0100
-#define UAT_STREAM 0x0101
-#define UAT_VENDOR 0x01ff
-/* input terminal types */
-#define UATI_UNDEFINED 0x0200
-#define UATI_MICROPHONE 0x0201
-#define UATI_DESKMICROPHONE 0x0202
-#define UATI_PERSONALMICROPHONE 0x0203
-#define UATI_OMNIMICROPHONE 0x0204
-#define UATI_MICROPHONEARRAY 0x0205
-#define UATI_PROCMICROPHONEARR 0x0206
-/* output terminal types */
-#define UATO_UNDEFINED 0x0300
-#define UATO_SPEAKER 0x0301
-#define UATO_HEADPHONES 0x0302
-#define UATO_DISPLAYAUDIO 0x0303
-#define UATO_DESKTOPSPEAKER 0x0304
-#define UATO_ROOMSPEAKER 0x0305
-#define UATO_COMMSPEAKER 0x0306
-#define UATO_SUBWOOFER 0x0307
-/* bidir terminal types */
-#define UATB_UNDEFINED 0x0400
-#define UATB_HANDSET 0x0401
-#define UATB_HEADSET 0x0402
-#define UATB_SPEAKERPHONE 0x0403
-#define UATB_SPEAKERPHONEESUP 0x0404
-#define UATB_SPEAKERPHONEECANC 0x0405
-/* telephony terminal types */
-#define UATT_UNDEFINED 0x0500
-#define UATT_PHONELINE 0x0501
-#define UATT_TELEPHONE 0x0502
-#define UATT_DOWNLINEPHONE 0x0503
-/* external terminal types */
-#define UATE_UNDEFINED 0x0600
-#define UATE_ANALOGCONN 0x0601
-#define UATE_DIGITALAUIFC 0x0602
-#define UATE_LINECONN 0x0603
-#define UATE_LEGACYCONN 0x0604
-#define UATE_SPDIF 0x0605
-#define UATE_1394DA 0x0606
-#define UATE_1394DV 0x0607
-/* embedded function terminal types */
-#define UATF_UNDEFINED 0x0700
-#define UATF_CALIBNOISE 0x0701
-#define UATF_EQUNOISE 0x0702
-#define UATF_CDPLAYER 0x0703
-#define UATF_DAT 0x0704
-#define UATF_DCC 0x0705
-#define UATF_MINIDISK 0x0706
-#define UATF_ANALOGTAPE 0x0707
-#define UATF_PHONOGRAPH 0x0708
-#define UATF_VCRAUDIO 0x0709
-#define UATF_VIDEODISCAUDIO 0x070a
-#define UATF_DVDAUDIO 0x070b
-#define UATF_TVTUNERAUDIO 0x070c
-#define UATF_SATELLITE 0x070d
-#define UATF_CABLETUNER 0x070e
-#define UATF_DSS 0x070f
-#define UATF_RADIORECV 0x0710
-#define UATF_RADIOXMIT 0x0711
-#define UATF_MULTITRACK 0x0712
-#define UATF_SYNTHESIZER 0x0713
-
-
-#define SET_CUR 0x01
-#define GET_CUR 0x81
-#define SET_MIN 0x02
-#define GET_MIN 0x82
-#define SET_MAX 0x03
-#define GET_MAX 0x83
-#define SET_RES 0x04
-#define GET_RES 0x84
-#define SET_MEM 0x05
-#define GET_MEM 0x85
-#define GET_STAT 0xff
-
-#define MUTE_CONTROL 0x01
-#define VOLUME_CONTROL 0x02
-#define BASS_CONTROL 0x03
-#define MID_CONTROL 0x04
-#define TREBLE_CONTROL 0x05
-#define GRAPHIC_EQUALIZER_CONTROL 0x06
-#define AGC_CONTROL 0x07
-#define DELAY_CONTROL 0x08
-#define BASS_BOOST_CONTROL 0x09
-#define LOUDNESS_CONTROL 0x0a
-
-#define FU_MASK(u) (1 << ((u)-1))
-
-#define MASTER_CHAN 0
-
-#define AS_GENERAL 1
-#define FORMAT_TYPE 2
-#define FORMAT_SPECIFIC 3
-
-#define UA_FMT_PCM 1
-#define UA_FMT_PCM8 2
-#define UA_FMT_IEEE_FLOAT 3
-#define UA_FMT_ALAW 4
-#define UA_FMT_MULAW 5
-#define UA_FMT_MPEG 0x1001
-#define UA_FMT_AC3 0x1002
-
-#define SAMPLING_FREQ_CONTROL 0x01
-#define PITCH_CONTROL 0x02
-
-#define FORMAT_TYPE_UNDEFINED 0
-#define FORMAT_TYPE_I 1
-#define FORMAT_TYPE_II 2
-#define FORMAT_TYPE_III 3
-
-#define UA_PROC_MASK(n) (1<< ((n)-1))
-#define PROCESS_UNDEFINED 0
-#define XX_ENABLE_CONTROL 1
-#define UPDOWNMIX_PROCESS 1
-#define UD_ENABLE_CONTROL 1
-#define UD_MODE_SELECT_CONTROL 2
-#define DOLBY_PROLOGIC_PROCESS 2
-#define DP_ENABLE_CONTROL 1
-#define DP_MODE_SELECT_CONTROL 2
-#define P3D_STEREO_EXTENDER_PROCESS 3
-#define P3D_ENABLE_CONTROL 1
-#define P3D_SPACIOUSNESS_CONTROL 2
-#define REVERBATION_PROCESS 4
-#define RV_ENABLE_CONTROL 1
-#define RV_LEVEL_CONTROL 2
-#define RV_TIME_CONTROL 3
-#define RV_FEEDBACK_CONTROL 4
-#define CHORUS_PROCESS 5
-#define CH_ENABLE_CONTROL 1
-#define CH_LEVEL_CONTROL 2
-#define CH_RATE_CONTROL 3
-#define CH_DEPTH_CONTROL 4
-#define DYN_RANGE_COMP_PROCESS 6
-#define DR_ENABLE_CONTROL 1
-#define DR_COMPRESSION_RATE_CONTROL 2
-#define DR_MAXAMPL_CONTROL 3
-#define DR_THRESHOLD_CONTROL 4
-#define DR_ATTACK_TIME_CONTROL 5
-#define DR_RELEASE_TIME_CONTROL 6
OpenPOWER on IntegriCloud