sound/core/seq/oss/seq_oss_midi.c

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

File Facts

System
Linux kernel
Corpus path
sound/core/seq/oss/seq_oss_midi.c
Extension
.c
Size
15409 bytes
Lines
673
Domain
Driver Families
Bucket
sound/core
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

struct seq_oss_midi {
	int seq_device;		/* device number */
	int client;		/* sequencer client number */
	int port;		/* sequencer port number */
	unsigned int flags;	/* port capability */
	int opened;		/* flag for opening */
	unsigned char name[SNDRV_SEQ_OSS_MAX_MIDI_NAME];
	struct snd_midi_event *coder;	/* MIDI event coder */
	struct seq_oss_devinfo *devinfo;	/* assigned OSSseq device */
	snd_use_lock_t use_lock;
	struct mutex open_mutex;
};

DEFINE_FREE(seq_oss_midi, struct seq_oss_midi *, if (!IS_ERR_OR_NULL(_T)) snd_use_lock_free(&(_T)->use_lock))

/*
 * midi device table
 */
static int max_midi_devs;
static struct seq_oss_midi *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];

static DEFINE_SPINLOCK(register_lock);

/*
 * prototypes
 */
static struct seq_oss_midi *get_mdev(int dev);
static struct seq_oss_midi *get_mididev(struct seq_oss_devinfo *dp, int dev);
static int send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev);
static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev);

/*
 * look up the existing ports
 * this looks a very exhausting job.
 */
int
snd_seq_oss_midi_lookup_ports(int client)
{
	struct snd_seq_client_info *clinfo __free(kfree) =
		kzalloc_obj(*clinfo);
	struct snd_seq_port_info *pinfo __free(kfree) =
		kzalloc_obj(*pinfo);

	if (!clinfo || !pinfo)
		return -ENOMEM;
	clinfo->client = -1;
	while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, clinfo) == 0) {
		if (clinfo->client == client)
			continue; /* ignore myself */
		pinfo->addr.client = clinfo->client;
		pinfo->addr.port = -1;
		while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, pinfo) == 0)
			snd_seq_oss_midi_check_new_port(pinfo);
	}
	return 0;
}


/*
 */
static struct seq_oss_midi *
get_mdev(int dev)
{
	struct seq_oss_midi *mdev;

	guard(spinlock_irqsave)(&register_lock);
	mdev = midi_devs[dev];
	if (mdev)
		snd_use_lock_use(&mdev->use_lock);
	return mdev;
}

/*
 * look for the identical slot
 */
static struct seq_oss_midi *
find_slot(int client, int port)
{
	int i;
	struct seq_oss_midi *mdev;

	guard(spinlock_irqsave)(&register_lock);
	for (i = 0; i < max_midi_devs; i++) {
		mdev = midi_devs[i];
		if (mdev && mdev->client == client && mdev->port == port) {
			/* found! */
			snd_use_lock_use(&mdev->use_lock);
			return mdev;
		}
	}

Annotation

Implementation Notes