It does work perfectly now, thanks!
First, I just want to remind you that UA-1000/UA-101 seems enabled in snd-usb-audio still (or I need to mix that patch with your last), as it isn't detected for either capture or playback.
Here are the specifics tested:
Roland VG-99 Perfect!: arecord -D hw:VG99 -f S24_3LE -r 44100 -c 2 ./file.wav Recording WAVE './file.wav' : Signed 24 bit Little Endian in 3bytes, Rate 44100 Hz, Stereo ^CAborted by signal Interrupt...
aplay -D hw:VG99 -f S24_3LE -r 44100 -c 2 ./file.wav Playing WAVE './file.wav' : Signed 24 bit Little Endian in 3bytes, Rate 44100 Hz, Stereo
Roland INTEGRA-7 Perfect! (only 96 kHz mode tested): arecord -D hw:INTEGRA7 -f S32_LE -r 96000 -c 2 ./file.wav Recording WAVE './file.wav' : Signed 32 bit Little Endian, Rate 96000 Hz, Stereo ^CAborted by signal Interrupt...
aplay -D hw:INTEGRA7 -f S32_LE -r 96000 -c 2 ./file.wav Playing WAVE './file.wav' : Signed 32 bit Little Endian, Rate 96000 Hz, Stereo
Roland R-26 Perfect! (only 96 kHz mode tested): arecord -D hw:R26AUDIO -f S32_LE -r 96000 -c 2 ./file.wav Recording WAVE './file.wav' : Signed 32 bit Little Endian, Rate 96000 Hz, Stereo ^CAborted by signal Interrupt...
aplay -D hw:R26AUDIO -f S32_LE -r 96000 -c 2 ./file.wav Playing WAVE './file.wav' : Signed 32 bit Little Endian, Rate 96000 Hz, Stereo
Roland Boutique D-05 Perfect!: arecord -D hw:Boutique -f S32_LE -r 96000 -c 2 ./file.wav Recording WAVE './file.wav' : Signed 32 bit Little Endian, Rate 96000 Hz, Stereo ^CAborted by signal Interrupt...
aplay -D hw:Boutique -f S32_LE -r 96000 -c 2 ./file.wav Playing WAVE './file.wav' : Signed 32 bit Little Endian, Rate 96000 Hz, Stereo
EDIROL UA-4FX Perfect! (only tested 48 kHz mode): arecord -D hw:UA4FX -f S24_3LE -r 48000 -c 2 ./file.wav Recording WAVE './file.wav' : Signed 24 bit Little Endian in 3bytes, Rate 48000 Hz, Stereo
aplay -D hw:UA4FX -f S24_3LE -r 48000 -c 2 ./file.wav Playing WAVE './file.wav' : Signed 24 bit Little Endian in 3bytes, Rate 48000 Hz, Stereo
EDIROL UA-25EX Perfect! (only tested 48 kHz mode): arecord -D hw:UA25EX -f S24_3LE -r 48000 -c 2 ./file.wav Recording WAVE './file.wav' : Signed 24 bit Little Endian in 3bytes, Rate 48000 Hz, Stereo
aplay -D hw:UA25EX -f S24_3LE -r 48000 -c 2 ./file.wav Playing WAVE './file.wav' : Signed 24 bit Little Endian in 3bytes, Rate 48000 Hz, Stereo
Unless you decide to simplify it, no improvements seem necessary. Thanks for your grand achievement, Takahashi!
I really appreciate it!,
Lucas
On Wed, Apr 21, 2021 at 3:59 AM Takashi Iwai tiwai@suse.de wrote:
Below is a revised patch. Let me know if this works better.
thanks,
Takashi
--- a/sound/usb/implicit.c +++ b/sound/usb/implicit.c @@ -79,6 +79,7 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
/* Implicit feedback quirk table for capture: only FIXED type */ static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = { +#if 0 IMPLICIT_FB_FIXED_DEV(0x0582, 0x00a6, 0x0d, 0x01), /* Roland JUNO-G */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x00a9, 0x0d, 0x01), /* Roland MC-808 */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x00ad, 0x0d, 0x01), /* Roland SH-201 */ @@ -146,6 +147,7 @@ static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = { IMPLICIT_FB_BOTH_DEV(0x0582, 0x01fd, 0x0d, 0x01), /* Roland Boutique SH-01A */ IMPLICIT_FB_BOTH_DEV(0x0582, 0x01ff, 0x0d, 0x01), /* Roland Boutique D-05 */ IMPLICIT_FB_BOTH_DEV(0x0582, 0x0203, 0x0d, 0x01), /* BOSS AD-10 */ +#endif
{} /* terminator */
}; @@ -204,30 +206,70 @@ static int add_generic_uac2_implicit_fb(struct snd_usb_audio *chip, ifnum, alts); }
-/* Like the function above, but specific to Roland with vendor class and hack */ +static bool roland_sanity_check_iface(struct usb_host_interface *alts) +{
if (alts->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
(alts->desc.bInterfaceSubClass != 2 &&
alts->desc.bInterfaceProtocol != 2) ||
alts->desc.bNumEndpoints < 1)
return false;
return true;
+}
+/* Like the UAC2 case above, but specific to Roland with vendor class and hack */ static int add_roland_implicit_fb(struct snd_usb_audio *chip, struct audioformat *fmt,
unsigned int ifnum,
unsigned int altsetting)
struct usb_host_interface *alts)
{
struct usb_host_interface *alts; struct usb_endpoint_descriptor *epd;
alts = snd_usb_get_host_interface(chip, ifnum, altsetting);
if (!alts)
if (!roland_sanity_check_iface(alts)) return 0;
if (alts->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
(alts->desc.bInterfaceSubClass != 2 &&
alts->desc.bInterfaceProtocol != 2) ||
alts->desc.bNumEndpoints < 1)
/* only when both streams are with ASYNC type */
epd = get_endpoint(alts, 0);
if (!usb_endpoint_is_isoc_out(epd) ||
(epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) !=
USB_ENDPOINT_SYNC_ASYNC)
return 0;
/* check capture EP */
alts = snd_usb_get_host_interface(chip,
alts->desc.bInterfaceNumber + 1,
alts->desc.bAlternateSetting);
if (!alts || !roland_sanity_check_iface(alts)) return 0; epd = get_endpoint(alts, 0); if (!usb_endpoint_is_isoc_in(epd) ||
(epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
USB_ENDPOINT_USAGE_IMPLICIT_FB)
(epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) !=
USB_ENDPOINT_SYNC_ASYNC) return 0;
chip->playback_first = 1; return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress,
0,
ifnum, alts);
alts->desc.bInterfaceNumber, alts);
+}
+/* capture quirk for Roland device; always full-duplex */ +static int add_roland_capture_quirk(struct snd_usb_audio *chip,
struct audioformat *fmt,
struct usb_host_interface *alts)
+{
struct usb_endpoint_descriptor *epd;
if (!roland_sanity_check_iface(alts))
return 0;
epd = get_endpoint(alts, 0);
if (!usb_endpoint_is_isoc_in(epd) ||
(epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) !=
USB_ENDPOINT_SYNC_ASYNC)
return 0;
alts = snd_usb_get_host_interface(chip,
alts->desc.bInterfaceNumber - 1,
alts->desc.bAlternateSetting);
if (!alts || !roland_sanity_check_iface(alts))
return 0;
epd = get_endpoint(alts, 0);
if (!usb_endpoint_is_isoc_out(epd))
return 0;
return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress,
0,
alts->desc.bInterfaceNumber, alts);
}
/* Playback and capture EPs on Pioneer devices share the same iface/altset @@ -365,14 +407,8 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, }
/* Roland/BOSS implicit feedback with vendor spec class */
if (attr == USB_ENDPOINT_SYNC_ASYNC &&
alts->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
alts->desc.bInterfaceProtocol == 2 &&
alts->desc.bNumEndpoints == 1 &&
USB_ID_VENDOR(chip->usb_id) == 0x0582 /* Roland */) {
if (add_roland_implicit_fb(chip, fmt,
alts->desc.bInterfaceNumber +
1,
alts->desc.bAlternateSetting))
if (USB_ID_VENDOR(chip->usb_id) == 0x0582) {
if (add_roland_implicit_fb(chip, fmt, alts) > 0) return 1; }
@@ -404,6 +440,13 @@ static int audioformat_capture_quirk(struct snd_usb_audio *chip, if (p && (p->type == IMPLICIT_FB_FIXED || p->type == IMPLICIT_FB_BOTH)) return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, 0, p->iface, NULL);
/* Roland/BOSS need full-duplex streams */
if (USB_ID_VENDOR(chip->usb_id) == 0x0582) {
if (add_roland_capture_quirk(chip, fmt, alts) > 0)
return 1;
}
if (is_pioneer_implicit_fb(chip, alts)) return 1; /* skip the quirk, also don't handle generic
sync EP */ return 0;