[alsa-devel] [PATCH 2/2] ALSA: usb: handle descriptor with SYNC_NONE illegal value
Pierre-Louis Bossart
pierre-louis.bossart at linux.intel.com
Fri Aug 14 00:42:33 CEST 2015
The M-Audio Transit exposes an interface with a SYNC_NONE attribute.
This is not a valid value according to the USB audio classspec. However
there is a sync endpoint associated to this record. Changing the logic to
try to use this sync endpoint allows for seamless transitions between
altset 2 and altset 3. If any errors happen, the behavior remains the same.
$ more /proc/asound/card1/stream0
M-Audio Transit USB at usb-0000:00:14.0-2, full speed : USB Audio
Playback:
Status: Stop
Interface 1
Altset 1
Format: S24_3LE
Channels: 2
Endpoint: 3 OUT (ADAPTIVE)
Rates: 48001 - 96000 (continuous)
Interface 1
Altset 2
Format: S24_3LE
Channels: 2
Endpoint: 3 OUT (NONE)
Rates: 8000 - 48000 (continuous)
Interface 1
Altset 3
Format: S16_LE
Channels: 2
Endpoint: 3 OUT (ASYNC)
Rates: 8000 - 48000 (continuous)
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
---
sound/usb/pcm.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 7cd7c03..9f29017 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -411,10 +411,17 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
if (altsd->bNumEndpoints < 2)
return 0;
- if ((is_playback && attr != USB_ENDPOINT_SYNC_ASYNC) ||
+ if ((is_playback && attr == USB_ENDPOINT_SYNC_SYNC) ||
+ (is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE) ||
(!is_playback && attr != USB_ENDPOINT_SYNC_ADAPTIVE))
return 0;
+ /*
+ * In case of illegal SYNC_NONE for OUT endpoint, we keep going to see
+ * if we don't find a sync endpoint, as on M-Audio Transit. In case of
+ * error fall back to SYNC mode and don't create sync endpoint
+ */
+
/* check sync-pipe endpoint */
/* ... and check descriptor size before accessing bSynchAddress
because there is a version of the SB Audigy 2 NX firmware lacking
@@ -428,6 +435,8 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
get_endpoint(alts, 1)->bmAttributes,
get_endpoint(alts, 1)->bLength,
get_endpoint(alts, 1)->bSynchAddress);
+ if (is_playback && attr == USB_ENDPOINT_SYNC_NONE)
+ goto no_valid_sync_ep_found;
return -EINVAL;
}
ep = get_endpoint(alts, 1)->bEndpointAddress;
@@ -438,6 +447,8 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
"%d:%d : invalid sync pipe. is_playback %d, ep %02x, bSynchAddress %02x\n",
fmt->iface, fmt->altsetting,
is_playback, ep, get_endpoint(alts, 0)->bSynchAddress);
+ if (is_playback && attr == USB_ENDPOINT_SYNC_NONE)
+ goto no_valid_sync_ep_found;
return -EINVAL;
}
@@ -449,11 +460,15 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
implicit_fb ?
SND_USB_ENDPOINT_TYPE_DATA :
SND_USB_ENDPOINT_TYPE_SYNC);
- if (!subs->sync_endpoint)
+ if (!subs->sync_endpoint) {
+ if (is_playback && attr == USB_ENDPOINT_SYNC_NONE)
+ goto no_valid_sync_ep_found;
return -EINVAL;
+ }
subs->data_endpoint->sync_master = subs->sync_endpoint;
+no_valid_sync_ep_found: /* fall back to synchronous mode */
return 0;
}
--
1.9.1
More information about the Alsa-devel
mailing list