*
* Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
*
- * Many codes borrowed from audio.c by
+ * Many codes borrowed from audio.c by
* Alan Cox (alan@lxorguk.ukuu.org.uk)
* Thomas Sailer (sailer@ife.ee.ethz.ch)
*
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("USB Audio");
MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Generic,USB Audio}}");
+MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
module_param_array(index, int, boot_devs, 0444);
MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
module_param_array(id, charp, boot_devs, 0444);
MODULE_PARM_DESC(id, "ID string for the USB audio adapter.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
module_param_array(enable, bool, boot_devs, 0444);
MODULE_PARM_DESC(enable, "Enable USB audio adapter.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
module_param_array(vid, int, boot_devs, 0444);
MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
-MODULE_PARM_SYNTAX(vid, SNDRV_ENABLED ",allows:{{-1,0xffff}},base:16");
module_param_array(pid, int, boot_devs, 0444);
MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
-MODULE_PARM_SYNTAX(pid, SNDRV_ENABLED ",allows:{{-1,0xffff}},base:16");
module_param(nrpacks, int, 0444);
MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
-MODULE_PARM_SYNTAX(nrpacks, SNDRV_ENABLED ",allows:{{1,10}}");
module_param(async_unlink, bool, 0444);
MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
-MODULE_PARM_SYNTAX(async_unlink, SNDRV_BOOLEAN_TRUE_DESC);
/*
*
*/
-#define MAX_PACKS 10
+#define MAX_PACKS 10
#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
#define MAX_URBS 5 /* max. 20ms long packets */
#define SYNC_URBS 2 /* always two urbs for sync */
struct list_head list;
};
-#define chip_t snd_usb_stream_t
-
/*
* we keep the snd_usb_audio_t instances by ourselves for merging
if (! urb->bandwidth) {
int bustime;
bustime = usb_check_bandwidth(urb->dev, urb);
- if (bustime < 0)
+ if (bustime < 0)
return bustime;
printk("urb %d: bandwidth = %d (packets = %d)\n", ctx->index, bustime, urb->number_of_packets);
usb_claim_bandwidth(urb->dev, urb, bustime, 1);
}
-/*
+/*
* wait until all urbs are processed.
*/
static int wait_clear_urbs(snd_usb_substream_t *subs)
if (fmt->attributes & EP_CS_ATTR_PITCH_CONTROL) {
data[0] = 1;
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
- USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
+ USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
dev->devnum, iface, ep);
data[1] = rate >> 8;
data[2] = rate >> 16;
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
- USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
+ USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n",
dev->devnum, iface, fmt->altsetting, rate, ep);
if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot get freq at ep 0x%x\n",
+ snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n",
dev->devnum, iface, fmt->altsetting, ep);
- return err;
+ return 0; /* some devices don't support reading */
}
crate = data[0] | (data[1] << 8) | (data[2] << 16);
if (crate != rate) {
ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
if (ret < 0)
return ret;
-
+
format = params_format(hw_params);
rate = params_rate(hw_params);
channels = params_channels(hw_params);
snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
unsigned int rmin, rmax;
int changed;
-
+
hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max);
changed = 0;
rmin = rmax = 0;
snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
unsigned int rmin, rmax;
int changed;
-
+
hwc_debug("hw_rule_channels: (%d,%d)\n", it->min, it->max);
changed = 0;
rmin = rmax = 0;
u64 fbits;
u32 oldbits[2];
int changed;
-
+
hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]);
fbits = 0;
list_for_each(p, &subs->fmt_list) {
if (check_hw_params_convention(subs)) {
hwc_debug("setting extra hw constraints...\n");
- if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
hw_rule_rate, subs,
SNDRV_PCM_HW_PARAM_FORMAT,
SNDRV_PCM_HW_PARAM_CHANNELS,
-1)) < 0)
return err;
- if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
hw_rule_channels, subs,
SNDRV_PCM_HW_PARAM_FORMAT,
SNDRV_PCM_HW_PARAM_RATE,
static void proc_pcm_format_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
{
- snd_usb_stream_t *stream = snd_magic_cast(snd_usb_stream_t, entry->private_data, return);
-
+ snd_usb_stream_t *stream = entry->private_data;
+
snd_iprintf(buffer, "%s : %s\n", stream->chip->card->longname, stream->pcm->name);
if (stream->substream[SNDRV_PCM_STREAM_PLAYBACK].num_formats) {
free_substream(&stream->substream[0]);
free_substream(&stream->substream[1]);
list_del(&stream->list);
- snd_magic_kfree(stream);
+ kfree(stream);
}
static void snd_usb_audio_pcm_free(snd_pcm_t *pcm)
}
/* create a new pcm */
- as = snd_magic_kmalloc(snd_usb_stream_t, 0, GFP_KERNEL);
+ as = kmalloc(sizeof(*as), GFP_KERNEL);
if (! as)
return -ENOMEM;
memset(as, 0, sizeof(*as));
stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
&pcm);
if (err < 0) {
- snd_magic_kfree(as);
+ kfree(as);
return err;
}
as->pcm = pcm;
pcm->private_data = as;
pcm->private_free = snd_usb_audio_pcm_free;
- pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
+ pcm->info_flags = 0;
if (chip->pcm_devs > 0)
sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
else
}
+/*
+ * check if the device uses big-endian samples
+ */
+static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
+{
+ /* M-Audio */
+ if (dev->descriptor.idVendor == 0x0763) {
+ /* Quattro: captured data only */
+ if (dev->descriptor.idProduct == 0x2001 &&
+ fp->endpoint & USB_DIR_IN)
+ return 1;
+ /* Audiophile USB */
+ if (dev->descriptor.idProduct == 0x2003)
+ return 1;
+ }
+ return 0;
+}
+
/*
* parse the audio format type I descriptor
* and returns the corresponding pcm format
pcm_format = SNDRV_PCM_FORMAT_S8;
break;
case 2:
- /* M-Audio audiophile USB workaround */
- if (dev->descriptor.idVendor == 0x0763 &&
- dev->descriptor.idProduct == 0x2003)
+ if (is_big_endian_format(dev, fp))
pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
else
pcm_format = SNDRV_PCM_FORMAT_S16_LE;
break;
case 3:
- /* M-Audio audiophile USB workaround */
- if (dev->descriptor.idVendor == 0x0763 &&
- dev->descriptor.idProduct == 0x2003)
+ if (is_big_endian_format(dev, fp))
pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
else
pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
{
int nr_rates = fmt[offset];
if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
+ snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
dev->devnum, fp->iface, fp->altsetting);
return -1;
}
}
#endif
return 0;
-}
+}
static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
{
}
if (fmt[0] < 7) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid AS_GENERAL desc\n",
+ snd_printk(KERN_ERR "%d:%u:%d : invalid AS_GENERAL desc\n",
dev->devnum, iface_no, altno);
continue;
}
format = (fmt[6] << 8) | fmt[5]; /* remember the format value */
-
+
/* get format type */
fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, FORMAT_TYPE);
if (!fmt) {
- snd_printk(KERN_ERR "%d:%u:%d : no FORMAT_TYPE desc\n",
+ snd_printk(KERN_ERR "%d:%u:%d : no FORMAT_TYPE desc\n",
dev->devnum, iface_no, altno);
continue;
}
if (fmt[0] < 8) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
+ snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
dev->devnum, iface_no, altno);
continue;
}
if (!csep && altsd->bNumEndpoints >= 2)
csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
- snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n",
+ snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n",
dev->devnum, iface_no, altno);
continue;
}
*/
static void proc_audio_usbbus_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
{
- snd_usb_audio_t *chip = snd_magic_cast(snd_usb_audio_t, entry->private_data, return);
+ snd_usb_audio_t *chip = entry->private_data;
if (! chip->shutdown)
snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum);
}
static void proc_audio_usbid_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
{
- snd_usb_audio_t *chip = snd_magic_cast(snd_usb_audio_t, entry->private_data, return);
+ snd_usb_audio_t *chip = entry->private_data;
if (! chip->shutdown)
snd_iprintf(buffer, "%04x:%04x\n", chip->dev->descriptor.idVendor, chip->dev->descriptor.idProduct);
}
static int snd_usb_audio_free(snd_usb_audio_t *chip)
{
- snd_magic_kfree(chip);
+ kfree(chip);
return 0;
}
static int snd_usb_audio_dev_free(snd_device_t *device)
{
- snd_usb_audio_t *chip = snd_magic_cast(snd_usb_audio_t, device->device_data, return -ENXIO);
+ snd_usb_audio_t *chip = device->device_data;
return snd_usb_audio_free(chip);
}
static snd_device_ops_t ops = {
.dev_free = snd_usb_audio_dev_free,
};
-
+
*rchip = NULL;
if (snd_usb_get_speed(dev) != USB_SPEED_FULL &&
return -ENOMEM;
}
- chip = snd_magic_kcalloc(snd_usb_audio_t, 0, GFP_KERNEL);
+ chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
if (! chip) {
snd_card_free(card);
return -ENOMEM;
/*
* we need to take care of counter, since disconnection can be called also
- * many times as well as usb_audio_probe().
+ * many times as well as usb_audio_probe().
*/
static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
{
if (ptr == (void *)-1L)
return;
- chip = snd_magic_cast(snd_usb_audio_t, ptr, return);
+ chip = ptr;
card = chip->card;
down(®ister_mutex);
chip->shutdown = 1;