sound/core/timer.c

Source file repositories/reference/linux-study-clean/sound/core/timer.c

File Facts

System
Linux kernel
Corpus path
sound/core/timer.c
Extension
.c
Size
65631 bytes
Lines
2594
Domain
Driver Families
Bucket
sound/core
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations snd_utimer_fops = {
	.llseek = noop_llseek,
	.release = snd_utimer_release,
	.unlocked_ioctl = snd_utimer_ioctl,
};

static int snd_utimer_start(struct snd_timer *t)
{
	return 0;
}

static int snd_utimer_stop(struct snd_timer *t)
{
	return 0;
}

static int snd_utimer_open(struct snd_timer *t)
{
	return 0;
}

static int snd_utimer_close(struct snd_timer *t)
{
	return 0;
}

static const struct snd_timer_hardware timer_hw = {
	.flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_WORK,
	.open = snd_utimer_open,
	.close = snd_utimer_close,
	.start = snd_utimer_start,
	.stop = snd_utimer_stop,
};

static int snd_utimer_create(struct snd_timer_uinfo *utimer_info,
			     struct snd_utimer **r_utimer)
{
	struct snd_utimer *utimer;
	struct snd_timer *timer;
	struct snd_timer_id tid;
	int utimer_id;
	int err = 0;

	if (!utimer_info || utimer_info->resolution == 0)
		return -EINVAL;

	utimer = kzalloc_obj(*utimer);
	if (!utimer)
		return -ENOMEM;

	/* We hold the ioctl lock here so we won't get a race condition when allocating id */
	utimer_id = snd_utimer_take_id();
	if (utimer_id < 0) {
		err = utimer_id;
		goto err_take_id;
	}

	utimer->id = utimer_id;

	utimer->name = kasprintf(GFP_KERNEL, "snd-utimer%d", utimer_id);
	if (!utimer->name) {
		err = -ENOMEM;
		goto err_get_name;
	}

	tid.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
	tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL;
	tid.card = -1;
	tid.device = SNDRV_TIMER_GLOBAL_UDRIVEN;
	tid.subdevice = utimer_id;

	err = snd_timer_new(NULL, utimer->name, &tid, &timer);
	if (err < 0) {
		pr_err("Can't create userspace-driven timer\n");
		goto err_timer_new;
	}

	timer->module = THIS_MODULE;
	timer->hw = timer_hw;
	timer->hw.resolution = utimer_info->resolution;
	timer->hw.ticks = 1;
	timer->max_instances = MAX_SLAVE_INSTANCES;

	utimer->timer = timer;

	err = snd_timer_global_register(timer);
	if (err < 0) {
		pr_err("Can't register a userspace-driven timer\n");
		goto err_timer_reg;
	}

Annotation

Implementation Notes