sound/core/rawmidi.c

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

File Facts

System
Linux kernel
Corpus path
sound/core/rawmidi.c
Extension
.c
Size
59616 bytes
Lines
2137
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_rawmidi_f_ops = {
	.owner =	THIS_MODULE,
	.read =		snd_rawmidi_read,
	.write =	snd_rawmidi_write,
	.open =		snd_rawmidi_open,
	.release =	snd_rawmidi_release,
	.poll =		snd_rawmidi_poll,
	.unlocked_ioctl =	snd_rawmidi_ioctl,
	.compat_ioctl =	snd_rawmidi_ioctl_compat,
};

static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
					struct snd_rawmidi_str *stream,
					int direction,
					int count)
{
	struct snd_rawmidi_substream *substream;
	int idx;

	for (idx = 0; idx < count; idx++) {
		substream = kzalloc_obj(*substream);
		if (!substream)
			return -ENOMEM;
		substream->stream = direction;
		substream->number = idx;
		substream->rmidi = rmidi;
		substream->pstr = stream;
		spin_lock_init(&substream->lock);
		list_add_tail(&substream->list, &stream->substreams);
		stream->substream_count++;
	}
	return 0;
}

/* used for both rawmidi and ump */
int snd_rawmidi_init(struct snd_rawmidi *rmidi,
		     struct snd_card *card, char *id, int device,
		     int output_count, int input_count,
		     unsigned int info_flags)
{
	int err;
	static const struct snd_device_ops ops = {
		.dev_free = snd_rawmidi_dev_free,
		.dev_register = snd_rawmidi_dev_register,
		.dev_disconnect = snd_rawmidi_dev_disconnect,
	};

	rmidi->card = card;
	rmidi->device = device;
	mutex_init(&rmidi->open_mutex);
	init_waitqueue_head(&rmidi->open_wait);
	INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams);
	INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams);
	rmidi->info_flags = info_flags;

	if (id != NULL)
		strscpy(rmidi->id, id, sizeof(rmidi->id));

	err = snd_device_alloc(&rmidi->dev, card);
	if (err < 0)
		return err;
	if (rawmidi_is_ump(rmidi))
		dev_set_name(rmidi->dev, "umpC%iD%i", card->number, device);
	else
		dev_set_name(rmidi->dev, "midiC%iD%i", card->number, device);

	err = snd_rawmidi_alloc_substreams(rmidi,
					   &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],
					   SNDRV_RAWMIDI_STREAM_INPUT,
					   input_count);
	if (err < 0)
		return err;
	err = snd_rawmidi_alloc_substreams(rmidi,
					   &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT],
					   SNDRV_RAWMIDI_STREAM_OUTPUT,
					   output_count);
	if (err < 0)
		return err;
	err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops);
	if (err < 0)
		return err;
	return 0;
}
EXPORT_SYMBOL_GPL(snd_rawmidi_init);

/**
 * snd_rawmidi_new - create a rawmidi instance
 * @card: the card instance
 * @id: the id string
 * @device: the device index

Annotation

Implementation Notes