sound/usb/pcm.c

Source file repositories/reference/linux-study-clean/sound/usb/pcm.c

File Facts

System
Linux kernel
Corpus path
sound/usb/pcm.c
Extension
.c
Size
50707 bytes
Lines
1834
Domain
Driver Families
Bucket
sound/usb
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (strict_match) {
			if (!(fp->formats & pcm_format_to_bits(format)))
				continue;
			if (fp->channels != channels)
				continue;
		}
		if (rate < fp->rate_min || rate > fp->rate_max)
			continue;
		if (!(fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) {
			unsigned int i;
			for (i = 0; i < fp->nr_rates; i++)
				if (fp->rate_table[i] == rate)
					break;
			if (i >= fp->nr_rates)
				continue;
		}
		attr = fp->ep_attr & USB_ENDPOINT_SYNCTYPE;
		if (!found) {
			found = fp;
			cur_attr = attr;
			continue;
		}
		/* avoid async out and adaptive in if the other method
		 * supports the same format.
		 * this is a workaround for the case like
		 * M-audio audiophile USB.
		 */
		if (subs && attr != cur_attr) {
			if ((attr == USB_ENDPOINT_SYNC_ASYNC &&
			     subs->direction == SNDRV_PCM_STREAM_PLAYBACK) ||
			    (attr == USB_ENDPOINT_SYNC_ADAPTIVE &&
			     subs->direction == SNDRV_PCM_STREAM_CAPTURE))
				continue;
			if ((cur_attr == USB_ENDPOINT_SYNC_ASYNC &&
			     subs->direction == SNDRV_PCM_STREAM_PLAYBACK) ||
			    (cur_attr == USB_ENDPOINT_SYNC_ADAPTIVE &&
			     subs->direction == SNDRV_PCM_STREAM_CAPTURE)) {
				found = fp;
				cur_attr = attr;
				continue;
			}
		}
		/* find the format with the largest max. packet size */
		if (fp->maxpacksize > found->maxpacksize) {
			found = fp;
			cur_attr = attr;
		}
	}
	return found;
}

const struct audioformat *
snd_usb_find_format(struct list_head *fmt_list_head, snd_pcm_format_t format,
		    unsigned int rate, unsigned int channels, bool strict_match,
		    struct snd_usb_substream *subs)
{
	return find_format(fmt_list_head, format, rate, channels, strict_match,
			subs);
}
EXPORT_SYMBOL_GPL(snd_usb_find_format);

static const struct audioformat *
find_substream_format(struct snd_usb_substream *subs,
		      const struct snd_pcm_hw_params *params)
{
	return find_format(&subs->fmt_list, params_format(params),
			   params_rate(params), params_channels(params),
			   true, subs);
}

const struct audioformat *
snd_usb_find_substream_format(struct snd_usb_substream *subs,
			      const struct snd_pcm_hw_params *params)
{
	return find_substream_format(subs, params);
}
EXPORT_SYMBOL_GPL(snd_usb_find_substream_format);

bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs)
{
	const struct audioformat *fp;
	struct snd_usb_audio *chip;
	int rate = -1;

	if (!subs)
		return false;
	chip = subs->stream->chip;
	if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE))
		return false;
	list_for_each_entry(fp, &subs->fmt_list, list) {

Annotation

Implementation Notes