ALSA: usb: handle descriptor with SYNC_NONE illegal value
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@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
630184477e
commit
395ae54bd8
1 changed files with 16 additions and 2 deletions
|
@ -412,10 +412,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 ||
|
||||
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
|
||||
|
@ -429,6 +436,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)
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
ep = get_endpoint(alts, 1)->bEndpointAddress;
|
||||
|
@ -439,6 +448,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)
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -450,8 +461,11 @@ 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)
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
subs->data_endpoint->sync_master = subs->sync_endpoint;
|
||||
|
||||
|
|
Loading…
Reference in a new issue