sound/usb/caiaq/audio.c

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

File Facts

System
Linux kernel
Corpus path
sound/usb/caiaq/audio.c
Extension
.c
Size
21966 bytes
Lines
864
Domain
Driver Families
Bucket
sound/usb
Inferred role
Driver Families: implementation source
Status
source 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 (ret) {
			dev_err(dev, "unable to trigger read #%d! (ret %d)\n",
				i, ret);
			cdev->streaming = 0;
			return -EPIPE;
		}
	}

	return 0;
}

static void stream_stop(struct snd_usb_caiaqdev *cdev)
{
	int i;
	struct device *dev = caiaqdev_to_dev(cdev);

	dev_dbg(dev, "%s(%p)\n", __func__, cdev);
	if (!cdev->streaming)
		return;

	cdev->streaming = 0;

	for (i = 0; i < N_URBS; i++) {
		usb_kill_urb(cdev->data_urbs_in[i]);

		if (test_bit(i, &cdev->outurb_active_mask))
			usb_kill_urb(cdev->data_urbs_out[i]);
	}

	cdev->outurb_active_mask = 0;
}

static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
{
	struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream);
	struct device *dev = caiaqdev_to_dev(cdev);

	dev_dbg(dev, "%s(%p)\n", __func__, substream);
	substream->runtime->hw = cdev->pcm_info;
	snd_pcm_limit_hw_rates(substream->runtime);

	return 0;
}

static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
{
	struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream);
	struct device *dev = caiaqdev_to_dev(cdev);

	dev_dbg(dev, "%s(%p)\n", __func__, substream);
	if (all_substreams_zero(cdev->sub_playback) &&
	    all_substreams_zero(cdev->sub_capture)) {
		/* when the last client has stopped streaming,
		 * all sample rates are allowed again */
		stream_stop(cdev);
		cdev->pcm_info.rates = cdev->samplerates;
	}

	return 0;
}

static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
{
	struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub);
	deactivate_substream(cdev, sub);
	return 0;
}

static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
{
	int bytes_per_sample, bpp, ret;
	int index = substream->number;
	struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct device *dev = caiaqdev_to_dev(cdev);

	dev_dbg(dev, "%s(%p)\n", __func__, substream);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		int out_pos;

		switch (cdev->spec.data_alignment) {
		case 0:
		case 2:
			out_pos = BYTES_PER_SAMPLE + 1;
			break;
		case 3:
		default:
			out_pos = 0;
			break;

Annotation

Implementation Notes