|
@@ -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)) &&
|