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

Commit ba7c2be1 authored by Clemens Ladisch's avatar Clemens Ladisch
Browse files

ALSA: usb-audio: detect implicit feedback on Roland devices



All the Roland/Edirol/BOSS USB audio devices that need implicit feedback
show this unambiguously in their descriptors, so it might be a good idea
to let the driver detect this.

This should make playback work correctly (at least with Jack) with the
following devices:
- BOSS GT-100
- BOSS JS-8 Jam Station
- Edirol M-16DX
- Roland GAIA SH-01

Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent 8f898e92
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -298,6 +298,35 @@ static int deactivate_endpoints(struct snd_usb_substream *subs)
	return 0;
}

static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
				     unsigned int altsetting,
				     struct usb_host_interface **alts,
				     unsigned int *ep)
{
	struct usb_interface *iface;
	struct usb_interface_descriptor *altsd;
	struct usb_endpoint_descriptor *epd;

	iface = usb_ifnum_to_if(dev, ifnum);
	if (!iface || iface->num_altsetting < altsetting + 1)
		return -ENOENT;
	*alts = &iface->altsetting[altsetting];
	altsd = get_iface_desc(*alts);
	if (altsd->bAlternateSetting != altsetting ||
	    altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
	    (altsd->bInterfaceSubClass != 2 &&
	     altsd->bInterfaceProtocol != 2   ) ||
	    altsd->bNumEndpoints < 1)
		return -ENOENT;
	epd = get_endpoint(*alts, 0);
	if (!usb_endpoint_is_isoc_in(epd) ||
	    (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
					USB_ENDPOINT_USAGE_IMPLICIT_FB)
		return -ENOENT;
	*ep = epd->bEndpointAddress;
	return 0;
}

/*
 * find a matching format and set up the interface
 */
@@ -393,6 +422,18 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
			goto add_sync_ep;
		}
	}
	if (is_playback &&
	    attr == USB_ENDPOINT_SYNC_ASYNC &&
	    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
	    altsd->bInterfaceProtocol == 2 &&
	    altsd->bNumEndpoints == 1 &&
	    USB_ID_VENDOR(subs->stream->chip->usb_id) == 0x0582 /* Roland */ &&
	    search_roland_implicit_fb(dev, altsd->bInterfaceNumber + 1,
				      altsd->bAlternateSetting,
				      &alts, &ep) >= 0) {
		implicit_fb = 1;
		goto add_sync_ep;
	}

	if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) ||
	     (!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) &&