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

Commit 4f272341 authored by Tobias Hansen's avatar Tobias Hansen Committed by Takashi Iwai
Browse files

ALSA: snd-usb-us122l: add support for US-144



Adds support for US-144 when attached on USB1.1.
Unlike the US-122L it uses both USB interfaces 0 and 1.

Signed-off-by: default avatarTobias Hansen <Tobias.Hansen@physik.uni-hamburg.de>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 78f28b7c
Loading
Loading
Loading
Loading
+67 −8
Original line number Diff line number Diff line
@@ -66,6 +66,28 @@ static int us122l_create_usbmidi(struct snd_card *card)
					     iface, &quirk);
}

static int us144_create_usbmidi(struct snd_card *card)
{
	static struct snd_usb_midi_endpoint_info quirk_data = {
		.out_ep = 4,
		.in_ep = 3,
		.out_cables =	0x001,
		.in_cables =	0x001
	};
	static struct snd_usb_audio_quirk quirk = {
		.vendor_name =	"US144",
		.product_name =	NAME_ALLCAPS,
		.ifnum = 	0,
		.type = QUIRK_MIDI_US122L,
		.data = &quirk_data
	};
	struct usb_device *dev = US122L(card)->chip.dev;
	struct usb_interface *iface = usb_ifnum_to_if(dev, 0);

	return snd_usb_create_midi_interface(&US122L(card)->chip,
					     iface, &quirk);
}

/*
 * Wrapper for usb_control_msg().
 * Allocates a temp buffer to prevent dmaing from/to the stack.
@@ -171,6 +193,11 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)

	if (!us122l->first)
		us122l->first = file;

	if (us122l->chip.dev->descriptor.idProduct == USB_ID_US144) {
		iface = usb_ifnum_to_if(us122l->chip.dev, 0);
		usb_autopm_get_interface(iface);
	}
	iface = usb_ifnum_to_if(us122l->chip.dev, 1);
	usb_autopm_get_interface(iface);
	return 0;
@@ -179,8 +206,14 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file)
{
	struct us122l	*us122l = hw->private_data;
	struct usb_interface *iface = usb_ifnum_to_if(us122l->chip.dev, 1);
	struct usb_interface *iface;
	snd_printdd(KERN_DEBUG "%p %p\n", hw, file);

	if (us122l->chip.dev->descriptor.idProduct == USB_ID_US144) {
		iface = usb_ifnum_to_if(us122l->chip.dev, 0);
		usb_autopm_put_interface(iface);
	}
	iface = usb_ifnum_to_if(us122l->chip.dev, 1);
	usb_autopm_put_interface(iface);
	if (us122l->first == file)
		us122l->first = NULL;
@@ -443,6 +476,13 @@ static bool us122l_create_card(struct snd_card *card)
	int err;
	struct us122l *us122l = US122L(card);

	if (us122l->chip.dev->descriptor.idProduct == USB_ID_US144) {
		err = usb_set_interface(us122l->chip.dev, 0, 1);
		if (err) {
			snd_printk(KERN_ERR "usb_set_interface error \n");
			return false;
		}
	}
	err = usb_set_interface(us122l->chip.dev, 1, 1);
	if (err) {
		snd_printk(KERN_ERR "usb_set_interface error \n");
@@ -455,6 +495,9 @@ static bool us122l_create_card(struct snd_card *card)
	if (!us122l_start(us122l, 44100, 256))
		return false;

	if (us122l->chip.dev->descriptor.idProduct == USB_ID_US144)
		err = us144_create_usbmidi(card);
	else
		err = us122l_create_usbmidi(card);
	if (err < 0) {
		snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err);
@@ -542,6 +585,7 @@ static int us122l_usb_probe(struct usb_interface *intf,
		return err;
	}

	usb_get_intf(usb_ifnum_to_if(device, 0));
	usb_get_dev(device);
	*cardp = card;
	return 0;
@@ -550,9 +594,16 @@ static int us122l_usb_probe(struct usb_interface *intf,
static int snd_us122l_probe(struct usb_interface *intf,
			    const struct usb_device_id *id)
{
	struct usb_device *device = interface_to_usbdev(intf);
	struct snd_card *card;
	int err;

	if (device->descriptor.idProduct == USB_ID_US144
		&& device->speed == USB_SPEED_HIGH) {
		snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n");
		return -ENOENT;
	}

	snd_printdd(KERN_DEBUG"%p:%i\n",
		    intf, intf->cur_altsetting->desc.bInterfaceNumber);
	if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
@@ -591,7 +642,8 @@ static void snd_us122l_disconnect(struct usb_interface *intf)
		snd_usbmidi_disconnect(p);
	}

	usb_put_intf(intf);
	usb_put_intf(usb_ifnum_to_if(us122l->chip.dev, 0));
	usb_put_intf(usb_ifnum_to_if(us122l->chip.dev, 1));
	usb_put_dev(us122l->chip.dev);

	while (atomic_read(&us122l->mmap_count))
@@ -642,6 +694,13 @@ static int snd_us122l_resume(struct usb_interface *intf)

	mutex_lock(&us122l->mutex);
	/* needed, doesn't restart without: */
	if (us122l->chip.dev->descriptor.idProduct == USB_ID_US144) {
		err = usb_set_interface(us122l->chip.dev, 0, 1);
		if (err) {
			snd_printk(KERN_ERR "usb_set_interface error \n");
			goto unlock;
		}
	}
	err = usb_set_interface(us122l->chip.dev, 1, 1);
	if (err) {
		snd_printk(KERN_ERR "usb_set_interface error \n");
@@ -675,11 +734,11 @@ static struct usb_device_id snd_us122l_usb_id_table[] = {
		.idVendor =	0x0644,
		.idProduct =	USB_ID_US122L
	},
/*  	{ */		/* US-144 maybe works when @USB1.1. Untested. */
/* 		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE, */
/* 		.idVendor =	0x0644, */
/* 		.idProduct =	USB_ID_US144 */
/* 	}, */
	{	/* US-144 only works at USB1.1! Disable module ehci-hcd. */
		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE,
		.idVendor =	0x0644,
		.idProduct =	USB_ID_US144
	},
	{ /* terminator */ }
};