Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e584bc3c authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Jaroslav Kysela
Browse files

ALSA: ua101: add Edirol UA-1000 support



Add support for the Edirol UA-1000 to the UA-101 driver.

Both devices behave the same, so we just have to shuffle around some
interface numbers and name strings.

Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent 291186e0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1812,7 +1812,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
  Module snd-ua101
  ----------------

    Module for the Edirol UA-101 audio/MIDI interface.
    Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces.

    This module supports multiple devices, autoprobe and hotplugging.

+3 −3
Original line number Diff line number Diff line
@@ -22,13 +22,13 @@ config SND_USB_AUDIO
	  will be called snd-usb-audio.

config SND_USB_UA101
	tristate "Edirol UA-101 driver (EXPERIMENTAL)"
	tristate "Edirol UA-101/UA-1000 driver (EXPERIMENTAL)"
	depends on EXPERIMENTAL
	select SND_PCM
	select SND_RAWMIDI
	help
	  Say Y here to include support for the Edirol UA-101 audio/MIDI
	  interface.
	  Say Y here to include support for the Edirol UA-101 and UA-1000
	  audio/MIDI interfaces.

	  To compile this driver as a module, choose M here: the module
	  will be called snd-ua101.
+33 −12
Original line number Diff line number Diff line
/*
 * Edirol UA-101 driver
 * Edirol UA-101/UA-1000 driver
 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
 *
 * This driver is free software: you can redistribute it and/or modify
@@ -25,10 +25,10 @@
#include <sound/pcm_params.h>
#include "usbaudio.h"

MODULE_DESCRIPTION("Edirol UA-101 driver");
MODULE_DESCRIPTION("Edirol UA-101/1000 driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_LICENSE("GPL v2");
MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101}}");
MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}");

/* I use my UA-1A for testing because I don't have a UA-101 ... */
#define UA1A_HACK
@@ -1200,13 +1200,30 @@ static int ua101_probe(struct usb_interface *interface,
		.type = QUIRK_MIDI_FIXED_ENDPOINT,
		.data = &midi_ep
	};
	static const int intf_numbers[2][3] = {
		{	/* UA-101 */
			[INTF_PLAYBACK] = 0,
			[INTF_CAPTURE] = 1,
			[INTF_MIDI] = 2,
		},
		{	/* UA-1000 */
			[INTF_CAPTURE] = 1,
			[INTF_PLAYBACK] = 2,
			[INTF_MIDI] = 3,
		},
	};
	struct snd_card *card;
	struct ua101 *ua;
	unsigned int card_index, i;
	int is_ua1000;
	const char *name;
	char usb_path[32];
	int err;

	if (interface->altsetting->desc.bInterfaceNumber != 0)
	is_ua1000 = usb_id->idProduct == 0x0044;

	if (interface->altsetting->desc.bInterfaceNumber !=
	    intf_numbers[is_ua1000][0])
		return -ENODEV;

	mutex_lock(&devices_mutex);
@@ -1250,9 +1267,11 @@ static int ua101_probe(struct usb_interface *interface,
#endif
	ua->intf[0] = interface;
	for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) {
		ua->intf[i] = usb_ifnum_to_if(ua->dev, i);
		ua->intf[i] = usb_ifnum_to_if(ua->dev,
					      intf_numbers[is_ua1000][i]);
		if (!ua->intf[i]) {
			dev_err(&ua->dev->dev, "interface %u not found\n", i);
			dev_err(&ua->dev->dev, "interface %u not found\n",
				intf_numbers[is_ua1000][i]);
			err = -ENXIO;
			goto probe_error;
		}
@@ -1292,11 +1311,12 @@ static int ua101_probe(struct usb_interface *interface,
	}
#endif

	name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101";
	strcpy(card->driver, "UA-101");
	strcpy(card->shortname, "UA-101");
	strcpy(card->shortname, name);
	usb_make_path(ua->dev, usb_path, sizeof(usb_path));
	snprintf(ua->card->longname, sizeof(ua->card->longname),
		 "EDIROL UA-101 (serial %s), %u Hz at %s, %s speed",
		 "EDIROL %s (serial %s), %u Hz at %s, %s speed", name,
		 ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path,
		 ua->dev->speed == USB_SPEED_HIGH ? "high" : "full");

@@ -1314,11 +1334,11 @@ static int ua101_probe(struct usb_interface *interface,
	if (err < 0)
		goto probe_error;

	err = snd_pcm_new(card, "UA-101", 0, 1, 1, &ua->pcm);
	err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm);
	if (err < 0)
		goto probe_error;
	ua->pcm->private_data = ua;
	strcpy(ua->pcm->name, "UA-101");
	strcpy(ua->pcm->name, name);
	snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops);
	snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops);

@@ -1389,8 +1409,9 @@ static struct usb_device_id ua101_ids[] = {
#ifdef UA1A_HACK
	{ USB_DEVICE(0x0582, 0x0018) },
#endif
	{ USB_DEVICE(0x0582, 0x007d) },
	{ USB_DEVICE(0x0582, 0x008d) },
	{ USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */
	{ USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */
	{ USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */
	{ }
};
MODULE_DEVICE_TABLE(usb, ua101_ids);
+0 −53
Original line number Diff line number Diff line
@@ -3116,58 +3116,6 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
	return 0;
}

/*
 * Create a stream for an Edirol UA-1000 interface.
 */
static int create_ua1000_quirk(struct snd_usb_audio *chip,
			       struct usb_interface *iface,
			       const struct snd_usb_audio_quirk *quirk)
{
	static const struct audioformat ua1000_format = {
		.format = SNDRV_PCM_FORMAT_S32_LE,
		.fmt_type = USB_FORMAT_TYPE_I,
		.altsetting = 1,
		.altset_idx = 1,
		.attributes = 0,
		.rates = SNDRV_PCM_RATE_CONTINUOUS,
	};
	struct usb_host_interface *alts;
	struct usb_interface_descriptor *altsd;
	struct audioformat *fp;
	int stream, err;

	if (iface->num_altsetting != 2)
		return -ENXIO;
	alts = &iface->altsetting[1];
	altsd = get_iface_desc(alts);
	if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE ||
	    altsd->bNumEndpoints != 1)
		return -ENXIO;

	fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL);
	if (!fp)
		return -ENOMEM;

	fp->channels = alts->extra[4];
	fp->iface = altsd->bInterfaceNumber;
	fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
	fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
	fp->datainterval = parse_datainterval(chip, alts);
	fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
	fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]);

	stream = (fp->endpoint & USB_DIR_IN)
		? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
	err = add_audio_endpoint(chip, stream, fp);
	if (err < 0) {
		kfree(fp);
		return err;
	}
	/* FIXME: playback must be synchronized to capture */
	usb_set_interface(chip->dev, fp->iface, 0);
	return 0;
}

static int snd_usb_create_quirk(struct snd_usb_audio *chip,
				struct usb_interface *iface,
				const struct snd_usb_audio_quirk *quirk);
@@ -3416,7 +3364,6 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
		[QUIRK_MIDI_CME] = create_any_midi_quirk,
		[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
		[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
		[QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
		[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
		[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk
	};
+1 −2
Original line number Diff line number Diff line
@@ -159,7 +159,6 @@ enum quirk_type {
	QUIRK_MIDI_US122L,
	QUIRK_AUDIO_STANDARD_INTERFACE,
	QUIRK_AUDIO_FIXED_ENDPOINT,
	QUIRK_AUDIO_EDIROL_UA1000,
	QUIRK_AUDIO_EDIROL_UAXX,
	QUIRK_AUDIO_ALIGN_TRANSFER,

@@ -196,7 +195,7 @@ struct snd_usb_midi_endpoint_info {

/* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */

/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */
/* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */

/* for QUIRK_IGNORE_INTERFACE, data is NULL */

Loading