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>