Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Jun 2006 11:20:17 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 99746 for review
Message-ID:  <200606211120.k5LBKHrq067422@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=99746

Change 99746 by hselasky@hselasky_mini_itx on 2006/06/21 11:20:13

	Finished converthing the USB audio system. The old "uaudio" driver was 
	in a horrible state. I hope that things are now better. High speed 
	devices should be supported. I had to cut down on the sample rate 
	selection. It is now all fixed. The locking should be right. Loading 
	of mixer registers are now all asynchronous. Cleaned up function naming.
	Everything that has got to do with PCM is named "uaudio_chan". Everything 
	that has got to do with the mixer is named "uaudio_mixer". A lot of 
	possible buffer overflows were caught. And one possible division by zero. 
	Please test!

Affected files ...

.. //depot/projects/usb/src/sys/dev/sound/pcm/mixer.c#2 edit
.. //depot/projects/usb/src/sys/dev/sound/pcm/mixer.h#2 edit
.. //depot/projects/usb/src/sys/dev/sound/usb/uaudio.c#2 edit
.. //depot/projects/usb/src/sys/dev/sound/usb/uaudio.h#2 edit
.. //depot/projects/usb/src/sys/dev/sound/usb/uaudio_pcm.c#2 edit
.. //depot/projects/usb/src/sys/dev/sound/usb/uaudioreg.h#2 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/sound/pcm/mixer.c#2 (text+ko) ====

@@ -234,6 +234,8 @@
 	if (MIXER_INIT(m))
 		goto bad;
 
+	snd_mtxlock(m->lock);
+
 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
 		v = snd_mixerdefaults[i];
 
@@ -249,6 +251,8 @@
 
 	mixer_setrecsrc(m, SOUND_MASK_MIC);
 
+	snd_mtxunlock(m->lock);
+
 	unit = device_get_unit(dev);
 	pdev = make_dev(&mixer_cdevsw, PCMMKMINOR(unit, SND_DEV_CTL, 0),
 		 UID_ROOT, GID_WHEEL, 0666, "mixer%d", unit);
@@ -293,8 +297,14 @@
 
 	mixer_setrecsrc(m, SOUND_MASK_MIC);
 
+	snd_mtxunlock(m->lock);
+
+	/*
+	 * MIXER_UNINIT() can sleep!
+	 */
 	MIXER_UNINIT(m);
 
+	snd_mtxlock(m->lock);
 	snd_mtxfree(m->lock);
 	kobj_delete((kobj_t)m, M_MIXER);
 
@@ -429,6 +439,17 @@
 	snd_mtxunlock(m->lock);
 }
 
+/*
+ * allow the sound driver to use
+ * the mixer lock to protect its
+ * mixer data:
+ */
+struct mtx *
+mixer_get_lock(struct snd_mixer *m)
+{
+	return m->lock;
+}
+
 /* ----------------------------------------------------------------------- */
 
 static int

==== //depot/projects/usb/src/sys/dev/sound/pcm/mixer.h#2 (text+ko) ====

@@ -40,6 +40,7 @@
 u_int32_t mix_getdevs(struct snd_mixer *m);
 u_int32_t mix_getrecdevs(struct snd_mixer *m);
 void *mix_getdevinfo(struct snd_mixer *m);
+struct mtx * mixer_get_lock(struct snd_mixer *m);
 
 /*
  * this is a kludge to allow hiding of the struct snd_mixer definition

==== //depot/projects/usb/src/sys/dev/sound/usb/uaudio.c#2 (text+ko) ====

@@ -44,11 +44,6 @@
  *                  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 $
@@ -57,222 +52,193 @@
  *  $NetBSD: uaudio.c,v 1.97 2005/02/24 08:19:38 martin Exp $
  */
 
+#include <sys/cdefs.h>
 #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
+#include <sys/reboot.h>	/* for bootverbose */
+
+#include <dev/usb/usb_port.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_subr.h>
+#include <dev/usb/usb_quirks.h>
 
-#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/pcm/sound.h>
 #include <dev/sound/chip.h>
 #include "feeder_if.h"
-#endif
 
-#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) logprintf x; } while (0)
-#define DPRINTFN(n,x)	do { if (uaudiodebug>(n)) logprintf x; } while (0)
-int	uaudiodebug = 0;
-#if defined(__FreeBSD__)
+#define DPRINTF(n,fmt,...)	\
+  do { if (uaudio_debug > (n)) {		\
+      printf("%s: " fmt, __FUNCTION__,## __VA_ARGS__); } } while (0)
+
+static int uaudio_debug = 0;
 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
+	   &uaudio_debug, 0, "uaudio debug level");
 #else
-#define DPRINTF(x)
-#define DPRINTFN(n,x)
+#define DPRINTF(...)
 #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
+static u_int32_t uaudio_default_rate = 96000;
+static u_int8_t  uaudio_default_bits = 32;
+static u_int8_t  uaudio_default_channels = 2;
+
+#define UAUDIO_NCHANBUFS        2 /* number of outstanding request */
+#define UAUDIO_NFRAMES         25 /* ms of sound in each request */
+#define UAUDIO_RECURSE_LIMIT   24 /* rounds */
+#define UAUDIO_DEFAULT_BUFSZ  (16*1024) /* bytes */
+
+
 
+#define MAKE_WORD(h,l) (((h) << 8) | (l))
+#define BIT_TEST(bm,bno) (((bm)[(bno) / 8] >> (7 - ((bno) % 8))) & 1)
 
+struct uaudio_mixer_node {
+	int32_t		minval;
+	int32_t		maxval;
 #define MIX_MAX_CHAN 8
-struct mixerctl {
-	uint16_t	wValue[MIX_MAX_CHAN]; /* using nchan */
-	uint16_t	wIndex;
-	uint8_t		nchan;
-	uint8_t		type;
+	int32_t		wValue[MIX_MAX_CHAN]; /* using nchan */
+	u_int32_t	delta;
+	u_int32_t	mul;
+	u_int32_t	ctl;
+
+	u_int16_t	wData[MIX_MAX_CHAN]; /* using nchan */
+	u_int16_t	wIndex;
+
+	u_int8_t	update[(MIX_MAX_CHAN+7)/8];
+	u_int8_t	nchan;
+	u_int8_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_UNKNOWN     6
+#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))
+	u_int8_t	slctrtype[MAX_SELECTOR_INPUT_PIN];
+	u_int8_t	class;
 
-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 uaudio_mixer_node *next;
 };
 
-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;
+struct uaudio_chan {
+	struct pcmchan_caps pcm_cap; /* capabilities */
+	struct usbd_memory_wait mem_wait;
 
-	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 */
+	struct snd_dbuf *pcm_buf;
+  const struct usbd_config *usb_cfg;
+	struct mtx * pcm_mtx; /* lock protecting this structure */
+	struct uaudio_softc * priv_sc;
+	struct pcm_channel * pcm_ch;
+	struct usbd_xfer * xfer[UAUDIO_NCHANBUFS];
+  const struct usb_audio_streaming_interface_descriptor *p_asid;
+  const struct usb_audio_streaming_type1_descriptor *p_asf1d;
+  const struct usb_audio_streaming_endpoint_descriptor *p_sed;
+  const usb_endpoint_descriptor_audio_t *p_ed1;
+  const usb_endpoint_descriptor_audio_t *p_ed2;
+  const struct uaudio_format *p_fmt;
 
-	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 */
+	u_int8_t * buf;		/* pointer to buffer */
+	u_int8_t * start;	/* upper layer buffer start */
+	u_int8_t * end;		/* upper layer buffer end */
+	u_int8_t * cur;		/* current position in upper layer buffer */
 
-	int	altidx;		/* currently used altidx */
+	u_int32_t block_size;
+	u_int32_t sample_rate;
+	u_int32_t format;
+	u_int32_t pcm_format[2];
 
-	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];
+	u_int16_t bytes_per_frame;
 
-	struct uaudio_softc *sc; /* our softc */
-#if defined(__FreeBSD__)
-	u_int32_t format;
-	int	precision;
-	int	channels;
-#endif
+	u_int8_t valid;
+	u_int8_t iface_index;
+	u_int8_t iface_alt_index;
 };
 
 struct uaudio_softc {
-	USBBASEDEVICE	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_ptr_t	sc_audiodev;
-	char		sc_dying;
-#if defined(__FreeBSD__)
-	struct sbuf	uaudio_sndstat;
-	int		uaudio_sndstat_flag;
-#endif
+	struct sbuf         sc_sndstat;
+	struct sndcard_func sc_sndcard_func;
+	struct uaudio_chan  sc_rec_chan;
+	struct uaudio_chan  sc_play_chan;
+	struct usbd_memory_wait sc_mixer_mem;
+
+	struct usbd_device * sc_udev;
+	struct usbd_xfer * sc_mixer_xfer[1];
+	struct mtx * sc_mixer_lock;
+	struct uaudio_mixer_node * sc_mixer_root;
+	struct uaudio_mixer_node * sc_mixer_curr;
+
+	u_int32_t	sc_buffer_size;
+	u_int32_t	sc_mix_info;
+	u_int32_t	sc_recsrc_info;
+
+	u_int16_t	sc_audio_rev;
+	u_int16_t	sc_mixer_count;
+
+	u_int8_t	sc_sndstat_valid;
+	u_int8_t	sc_mixer_iface_index;
+	u_int8_t	sc_mixer_iface_no;
+	u_int8_t	sc_mixer_chan;
+	u_int8_t	sc_pcm_registered : 1;
+	u_int8_t	sc_mixer_init : 1;
+	u_int8_t	sc_unused : 6;
 };
 
-struct terminal_list {
-	int size;
-	uint16_t terminals[1];
+struct uaudio_search_result {
+	u_int8_t bit_input[(256+7)/8];
+	u_int8_t bit_output[(256+7)/8];
+	u_int8_t bit_visited[(256+7)/8];
+	u_int8_t recurse_level;
+	u_int8_t id_max;
 };
-#define TERMINAL_LIST_SIZE(N)	(offsetof(struct terminal_list, terminals) \
-				+ sizeof(uint16_t) * (N))
 
-struct io_terminal {
+struct uaudio_terminal_node {
 	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 */
+	    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_0 *mu;
+	    const struct usb_audio_selector_unit *su;
+	    const struct usb_audio_feature_unit *fu;
+	    const struct usb_audio_processing_unit_0 *pu;
+	    const struct usb_audio_extension_unit_0 *eu;
+	} u;
+	struct uaudio_search_result usr;
+	struct uaudio_terminal_node *root;
+};
+
+struct uaudio_format {
+	u_int16_t wFormat;
+	u_int8_t  bPrecision;
+	u_int32_t freebsd_fmt;
+	const char * description;
+};
+
+static const struct uaudio_format uaudio_formats[] = {
+
+    {UA_FMT_PCM8,  8, AFMT_U8,      "8-bit U-LE PCM" },
+    {UA_FMT_PCM8, 16, AFMT_U16_LE, "16-bit U-LE PCM" },
+    {UA_FMT_PCM8, 24, AFMT_U24_LE, "24-bit U-LE PCM" },
+    {UA_FMT_PCM8, 32, AFMT_U32_LE, "32-bit U-LE PCM" },
+
+    {UA_FMT_PCM,   8, AFMT_S8,      "8-bit S-LE PCM" },
+    {UA_FMT_PCM,  16, AFMT_S16_LE, "16-bit S-LE PCM" },
+    {UA_FMT_PCM,  24, AFMT_S24_LE, "24-bit S-LE PCM" },
+    {UA_FMT_PCM,  32, AFMT_S32_LE, "32-bit S-LE PCM" },
+
+    {UA_FMT_ALAW,  8, AFMT_A_LAW,  "8-bit A-Law" },
+    {UA_FMT_MULAW, 8, AFMT_MU_LAW, "8-bit mu-Law" },
+
+    {0,0,0,NULL}
 };
 
 #define UAC_OUTPUT	0
@@ -280,4268 +246,2832 @@
 #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"
+static const char *uac_names[] = {
+    "outputs", "inputs", "equalization", "record"
+};
 #endif
-Static const char *uac_names[] = {
-	AudioCoutputs, AudioCinputs, AudioCequalization, AudioCrecord,
-};
+
+/* prototypes */
+
+static device_probe_t uaudio_probe;
+static device_attach_t uaudio_attach;
+static device_detach_t uaudio_detach;
+
+#ifdef USB_DEBUG
+static void
+uaudio_chan_dump_ep_desc(const usb_endpoint_descriptor_audio_t *ed);
 #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_chan_fill_info_sub(struct uaudio_softc *sc, struct usbd_device *udev,
+			  u_int32_t rate, u_int16_t fps, u_int8_t channels, 
+			  u_int8_t bit_resolution);
+
+static void
+uaudio_chan_fill_info(struct uaudio_softc *sc, struct usbd_device *udev);
 
-Static void	uaudio_add_alt(struct uaudio_softc *, const struct as_info *);
+static void
+uaudio_chan_play_callback(struct usbd_xfer *xfer);
 
-Static const usb_interface_descriptor_t *uaudio_find_iface
-	(const char *, int, int *, int);
+static void
+uaudio_chan_record_callback(struct usbd_xfer *xfer);
 
-Static void	uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *);
+static void
+uaudio_mixer_add_ctl_sub(struct uaudio_softc *sc, 
+			 struct uaudio_mixer_node *mc);
+static void
+uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct uaudio_mixer_node *mc);
 
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static char	*uaudio_id_name
-	(struct uaudio_softc *, const struct io_terminal *, int);
-#endif
+static void
+uaudio_mixer_add_input(struct uaudio_softc *sc, 
+		       const struct uaudio_terminal_node *iot, int id);
+static void
+uaudio_mixer_add_output(struct uaudio_softc *sc, 
+			const struct uaudio_terminal_node *iot, int id);
+static void
+uaudio_mixer_add_mixer(struct uaudio_softc *sc, 
+		       const struct uaudio_terminal_node *iot, int id);
+static void
+uaudio_mixer_add_selector(struct uaudio_softc *sc, 
+			  const struct uaudio_terminal_node *iot, int id);
+static u_int32_t
+uaudio_mixer_feature_get_bmaControls(const struct usb_audio_feature_unit *d, 
+				     u_int8_t index);
+static void
+uaudio_mixer_add_feature(struct uaudio_softc *sc, 
+			 const struct uaudio_terminal_node *iot, int id);
+static void
+uaudio_mixer_add_processing_updown(struct uaudio_softc *sc, 
+				   const struct uaudio_terminal_node *iot, 
+				   int id);
+static void
+uaudio_mixer_add_processing(struct uaudio_softc *sc, 
+			    const struct uaudio_terminal_node *iot, int id);
+static void
+uaudio_mixer_add_extension(struct uaudio_softc *sc, 
+			   const struct uaudio_terminal_node *iot, int id);
+static const void *
+uaudio_mixer_verify_desc(const void *arg, u_int32_t len);
 
 #ifdef USB_DEBUG
-Static void	uaudio_dump_cluster(const struct usb_audio_cluster *);
+static void
+uaudio_mixer_dump_cluster(u_int8_t id, const struct uaudio_terminal_node *iot);
 #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);
+
+static struct usb_audio_cluster
+uaudio_mixer_get_cluster(u_int8_t id, const struct uaudio_terminal_node *iot);
+
 #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 const int uaudio_feature_name(const struct io_terminal *,
-		    struct mixerctl *);
-#else
-Static const char *uaudio_feature_name
-	(const struct io_terminal *, struct mixerctl *);
+static const char *
+uaudio_mixer_get_terminal_name(u_int16_t terminal_type);
 #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 u_int16_t
+uaudio_mixer_determine_class(const struct uaudio_terminal_node *iot, 
+			     struct uaudio_mixer_node *mix);
+static const u_int16_t 
+uaudio_mixer_feature_name(const struct uaudio_terminal_node *iot, 
+			  struct uaudio_mixer_node *mix);
 
-Static usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int);
+static const struct uaudio_terminal_node *
+uaudio_mixer_get_input(const struct uaudio_terminal_node *iot, u_int8_t index);
 
-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 *);
+static const struct uaudio_terminal_node *
+uaudio_mixer_get_output(const struct uaudio_terminal_node *iot, 
+			u_int8_t index);
+static void
+uaudio_mixer_find_inputs_sub(struct uaudio_terminal_node *root, 
+			     const u_int8_t *p_id, u_int8_t n_id, 
+			     struct uaudio_search_result *info);
+static void
+uaudio_mixer_find_outputs_sub(struct uaudio_terminal_node *root, u_int8_t id, 
+			      u_int8_t n_id,
+			      struct uaudio_search_result *info);
+static void
+uaudio_mixer_fill_info(struct uaudio_softc *sc, struct usbd_device *udev, 
+		       void *desc);
+static u_int16_t
+uaudio_mixer_get(struct usbd_device *udev, u_int8_t what,
+		 struct uaudio_mixer_node *mc);
+static void
+uaudio_mixer_write_cfg_callback(struct usbd_xfer *xfer);
 
-#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 usbd_status
+uaudio_set_speed(struct usbd_device *udev, u_int8_t endpt, u_int32_t speed);
 
-Static void	uaudio_chan_ptransfer(struct chan *);
-Static void	uaudio_chan_pintr
-	(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static int
+uaudio_mixer_signext(u_int8_t type, int val);
 
-Static void	uaudio_chan_rtransfer(struct chan *);
-Static void	uaudio_chan_rintr
-	(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static int
+uaudio_mixer_bsd2value(struct uaudio_mixer_node *mc, int32_t val);
 
-#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 void
+uaudio_mixer_ctl_set(struct uaudio_softc *sc, struct uaudio_mixer_node *mc,
+		     u_int8_t chan, int32_t val);
+static void
+uaudio_mixer_init(struct uaudio_softc *sc);
 
-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 const struct usbd_config uaudio_cfg_record_full_speed[UAUDIO_NCHANBUFS] = {
+    [0] = {
+      .type      = UE_ISOCHRONOUS,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .bufsize   = 0, /* use "wMaxPacketSize * frames" */
+      .frames    = UAUDIO_NFRAMES,
+      .flags     = USBD_SHORT_XFER_OK,
+      .callback  = &uaudio_chan_record_callback,
+    },
 
-Static struct audio_device uaudio_device = {
-	"USB audio",
-	"",
-	"uaudio"
+    [1] = {
+      .type      = UE_ISOCHRONOUS,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .bufsize   = 0, /* use "wMaxPacketSize * frames" */
+      .frames    = UAUDIO_NFRAMES,
+      .flags     = USBD_SHORT_XFER_OK,
+      .callback  = &uaudio_chan_record_callback,
+    },
 };
 
-#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);
+static const struct usbd_config uaudio_cfg_record_high_speed[UAUDIO_NCHANBUFS] = {
+    [0] = {
+      .type      = UE_ISOCHRONOUS,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .bufsize   = 0, /* use "wMaxPacketSize * frames" */
+      .frames    = (UAUDIO_NFRAMES * 8),
+      .flags     = USBD_SHORT_XFER_OK,
+      .callback  = &uaudio_chan_record_callback,
+    },
 
-/* for NetBSD compatibirity */
-#define	AUMODE_PLAY	0x01
-#define	AUMODE_RECORD	0x02
+    [1] = {
+      .type      = UE_ISOCHRONOUS,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .bufsize   = 0, /* use "wMaxPacketSize * frames" */
+      .frames    = (UAUDIO_NFRAMES * 8),
+      .flags     = USBD_SHORT_XFER_OK,
+      .callback  = &uaudio_chan_record_callback,
+    },
+};
 
-#define	AUDIO_PROP_FULLDUPLEX	0x01
+static const struct usbd_config uaudio_cfg_play_full_speed[UAUDIO_NCHANBUFS] = {
+    [0] = {
+      .type      = UE_ISOCHRONOUS,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_OUT,
+      .bufsize   = 0, /* use "wMaxPacketSize * frames" */
+      .frames    = UAUDIO_NFRAMES,
+      .flags     = USBD_SHORT_XFER_OK,
+      .callback  = &uaudio_chan_play_callback,
+    },
 
-#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
+    [1] = {
+      .type      = UE_ISOCHRONOUS,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_OUT,
+      .bufsize   = 0, /* use "wMaxPacketSize * frames" */
+      .frames    = UAUDIO_NFRAMES,
+      .flags     = USBD_SHORT_XFER_OK,
+      .callback  = &uaudio_chan_play_callback,
+    },
+};
 
-#endif	/* FreeBSD */
+static const struct usbd_config uaudio_cfg_play_high_speed[UAUDIO_NCHANBUFS] = {
+    [0] = {
+      .type      = UE_ISOCHRONOUS,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_OUT,
+      .bufsize   = 0, /* use "wMaxPacketSize * frames" */
+      .frames    = (UAUDIO_NFRAMES * 8),
+      .flags     = USBD_SHORT_XFER_OK,
+      .callback  = &uaudio_chan_play_callback,
+    },
 
+    [1] = {
+      .type      = UE_ISOCHRONOUS,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_OUT,
+      .bufsize   = 0, /* use "wMaxPacketSize * frames" */
+      .frames    = (UAUDIO_NFRAMES * 8),
+      .flags     = USBD_SHORT_XFER_OK,
+      .callback  = &uaudio_chan_play_callback,
+    },
+};
 
-#if defined(__NetBSD__) || defined(__OpenBSD__)
+static const struct usbd_config uaudio_mixer_config[1] = {
+    [0] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = (sizeof(usb_device_request_t) + 4),
+      .callback  = &uaudio_mixer_write_cfg_callback,
+      .timeout   = 1000, /* 1 second */
+    },
+};
 
-USB_DECLARE_DRIVER(uaudio);
 
-#elif defined(__FreeBSD__)
+static devclass_t uaudio_devclass;
 
-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
+static device_method_t uaudio_methods[] = {
+    DEVMETHOD(device_probe, uaudio_probe),
+    DEVMETHOD(device_attach, uaudio_attach),
+    DEVMETHOD(device_detach, uaudio_detach),
+    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),
+    { 0, 0 }
+};
 
+static driver_t uaudio_driver = {
+    .name    = "uaudio",
+    .methods = uaudio_methods,
+    .size    = sizeof(struct uaudio_softc),
+};
 
-USB_MATCH(uaudio)
+static int
+uaudio_probe(device_t dev)
 {
-	USB_MATCH_START(uaudio, uaa);
+	struct usb_attach_arg *uaa = device_get_ivars(dev);
 	usb_interface_descriptor_t *id;
 
-	if (uaa->iface == NULL)
-		return UMATCH_NONE;
+	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;
+
+	/* 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)
+static int
+uaudio_attach(device_t dev)
 {
-	USB_ATTACH_START(uaudio, sc, uaa);
+	struct usb_attach_arg *uaa = device_get_ivars(dev);
+	struct uaudio_softc *sc = device_get_softc(dev);
 	usb_interface_descriptor_t *id;
-	usb_config_descriptor_t *cdesc;
-	char devinfo[1024];
-	usbd_status err;
-	int i, j, found;
+	device_t child;
+
+	sc->sc_play_chan.priv_sc = sc;
+	sc->sc_rec_chan.priv_sc = sc;
+	sc->sc_udev = uaa->device;
+
+	usbd_set_desc(dev, uaa->device);
+
+	id = usbd_get_interface_descriptor(uaa->iface);
+
+	uaudio_chan_fill_info(sc, uaa->device);
 
-#if defined(__FreeBSD__)
-	usbd_devinfo(uaa->device, 0, devinfo);
-	USB_ATTACH_SETUP;
-#else
-	usbd_devinfo(uaa->device, 0, devinfo, sizeof(devinfo));
-	printf(": %s\n", devinfo);
-#endif
+	uaudio_mixer_fill_info(sc, uaa->device, id);
 
-	sc->sc_udev = uaa->device;
+	sc->sc_mixer_iface_index = uaa->iface_index;
+	sc->sc_mixer_iface_no = id->bInterfaceNumber;
 
-	cdesc = usbd_get_config_descriptor(sc->sc_udev);
-	if (cdesc == NULL) {
-		printf("%s: failed to get configuration descriptor\n",
-		       USBDEVNAME(sc->sc_dev));
-		USB_ATTACH_ERROR_RETURN;
-	}
+	DPRINTF(0, "audio rev %d.%02x\n", 
+		sc->sc_audio_rev >> 8, 
+		sc->sc_audio_rev & 0xff);
 
-	err = uaudio_identify(sc, cdesc);
-	if (err) {
-		printf("%s: audio descriptors make no sense, error=%d\n",
-		       USBDEVNAME(sc->sc_dev), err);
-		USB_ATTACH_ERROR_RETURN;
-	}
+	DPRINTF(0, "%d mixer controls\n", 
+		sc->sc_mixer_count);
 
-	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;

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606211120.k5LBKHrq067422>