sound/core/seq/oss/seq_oss_readq.c

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

File Facts

System
Linux kernel
Corpus path
sound/core/seq/oss/seq_oss_readq.c
Extension
.c
Size
4927 bytes
Lines
263
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 readq_sysex_ctx {
	struct seq_oss_readq *readq;
	int dev;
};

static int readq_dump_sysex(void *ptr, void *buf, int count)
{
	struct readq_sysex_ctx *ctx = ptr;

	return snd_seq_oss_readq_puts(ctx->readq, ctx->dev, buf, count);
}

int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev,
			    struct snd_seq_event *ev)
{
	struct readq_sysex_ctx ctx = {
		.readq = q,
		.dev = dev
	};

	if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
		return 0;
	return snd_seq_dump_var_event(ev, readq_dump_sysex, &ctx);
}

/*
 * copy an event to input queue:
 * return zero if enqueued
 * caller must hold lock
 */
static int snd_seq_oss_readq_put_event_locked(struct seq_oss_readq *q,
					      union evrec *ev)
{
	if (q->qlen >= q->maxlen - 1)
		return -ENOMEM;

	memcpy(&q->q[q->tail], ev, sizeof(*ev));
	q->tail = (q->tail + 1) % q->maxlen;
	q->qlen++;

	return 0;
}

/*
 * copy an event to input queue:
 * return zero if enqueued
 */
int
snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
{
	int rc;

	scoped_guard(spinlock_irqsave, &q->lock) {
		rc = snd_seq_oss_readq_put_event_locked(q, ev);
		if (!rc)
			wake_up(&q->midi_sleep);
	}

	return rc;
}


/*
 * pop queue
 * caller must hold lock
 */
int
snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec)
{
	if (q->qlen == 0)
		return -EAGAIN;
	memcpy(rec, &q->q[q->head], sizeof(*rec));
	return 0;
}

/*
 * sleep until ready
 */
void
snd_seq_oss_readq_wait(struct seq_oss_readq *q)
{
	wait_event_interruptible_timeout(q->midi_sleep,
					 (q->qlen > 0 || q->head == q->tail),
					 q->pre_event_timeout);
}

/*
 * drain one record
 * caller must hold lock
 */

Annotation

Implementation Notes