sound/core/seq/seq_memory.c

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

File Facts

System
Linux kernel
Corpus path
sound/core/seq/seq_memory.c
Extension
.c
Size
13102 bytes
Lines
563
Domain
Driver Families
Bucket
sound/core
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

while (len > 0) {
			int size = sizeof(buf);
			if (len < size)
				size = len;
			if (copy_from_user(buf, curptr, size))
				return -EFAULT;
			err = func(private_data, buf, size);
			if (err < 0)
				return err;
			curptr += size;
			len -= size;
		}
		return 0;
	}
	if (!(event->data.ext.len & SNDRV_SEQ_EXT_CHAINED))
		return func(private_data, event->data.ext.ptr + offset,
			    len - offset);

	cell = (struct snd_seq_event_cell *)event->data.ext.ptr;
	for (; len > 0 && cell; cell = cell->next) {
		int size = sizeof(struct snd_seq_event);
		char *curptr = (char *)&cell->event;

		if (offset >= size) {
			offset -= size;
			len -= size;
			continue;
		}
		if (len < size)
			size = len;
		err = func(private_data, curptr + offset, size - offset);
		if (err < 0)
			return err;
		offset = 0;
		len -= size;
	}
	return 0;
}

int snd_seq_dump_var_event(const struct snd_seq_event *event,
			   snd_seq_dump_func_t func, void *private_data)
{
	return dump_var_event(event, func, private_data, 0, 0);
}
EXPORT_SYMBOL(snd_seq_dump_var_event);


/*
 * exported:
 * expand the variable length event to linear buffer space.
 */

static int seq_copy_in_kernel(void *ptr, void *src, int size)
{
	char **bufptr = ptr;

	memcpy(*bufptr, src, size);
	*bufptr += size;
	return 0;
}

static int seq_copy_in_user(void *ptr, void *src, int size)
{
	char __user **bufptr = ptr;

	if (copy_to_user(*bufptr, src, size))
		return -EFAULT;
	*bufptr += size;
	return 0;
}

static int expand_var_event(const struct snd_seq_event *event,
			    int offset, int size, char *buf, bool in_kernel)
{
	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
		if (! in_kernel)
			return -EINVAL;
		if (copy_from_user(buf,
				   (char __force __user *)event->data.ext.ptr + offset,
				   size))
			return -EFAULT;
		return 0;
	}
	return dump_var_event(event,
			     in_kernel ? seq_copy_in_kernel : seq_copy_in_user,
			     &buf, offset, size);
}

int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char *buf,
			     int in_kernel, int size_aligned)

Annotation

Implementation Notes