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

Commit 395ae54b authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Takashi Iwai
Browse files

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: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 63018447
Loading
Loading
Loading
Loading
+16 −2
Original line number Original line Diff line number Diff line
@@ -412,10 +412,17 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
	if (altsd->bNumEndpoints < 2)
	if (altsd->bNumEndpoints < 2)
		return 0;
		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))
	    (!is_playback && attr != USB_ENDPOINT_SYNC_ADAPTIVE))
		return 0;
		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 */
	/* check sync-pipe endpoint */
	/* ... and check descriptor size before accessing bSynchAddress
	/* ... and check descriptor size before accessing bSynchAddress
	   because there is a version of the SB Audigy 2 NX firmware lacking
	   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)->bmAttributes,
			   get_endpoint(alts, 1)->bLength,
			   get_endpoint(alts, 1)->bLength,
			   get_endpoint(alts, 1)->bSynchAddress);
			   get_endpoint(alts, 1)->bSynchAddress);
		if (is_playback && attr == USB_ENDPOINT_SYNC_NONE)
			return 0;
		return -EINVAL;
		return -EINVAL;
	}
	}
	ep = get_endpoint(alts, 1)->bEndpointAddress;
	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",
			"%d:%d : invalid sync pipe. is_playback %d, ep %02x, bSynchAddress %02x\n",
			   fmt->iface, fmt->altsetting,
			   fmt->iface, fmt->altsetting,
			   is_playback, ep, get_endpoint(alts, 0)->bSynchAddress);
			   is_playback, ep, get_endpoint(alts, 0)->bSynchAddress);
		if (is_playback && attr == USB_ENDPOINT_SYNC_NONE)
			return 0;
		return -EINVAL;
		return -EINVAL;
	}
	}


@@ -450,8 +461,11 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
						   implicit_fb ?
						   implicit_fb ?
							SND_USB_ENDPOINT_TYPE_DATA :
							SND_USB_ENDPOINT_TYPE_DATA :
							SND_USB_ENDPOINT_TYPE_SYNC);
							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;
		return -EINVAL;
	}


	subs->data_endpoint->sync_master = subs->sync_endpoint;
	subs->data_endpoint->sync_master = subs->sync_endpoint;