// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * OSS compatible sequencer driver
 *
 * seq_oss_readq.c - MIDI input queue
 *
 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
 */

#include "seq_oss_readq.h"
#include "seq_oss_event.h"
#include <sound/seq_oss_legacy.h>
#include "../seq_lock.h"
#include <linux/wait.h>
#include <linux/slab.h>

/*
 * constants
 */
//#define SNDRV_SEQ_OSS_MAX_TIMEOUT	(unsigned long)(-1)
#define SNDRV_SEQ_OSS_MAX_TIMEOUT	(HZ * 3600)


/*
 * prototypes
 */


/*
 * create a read queue
 */
struct seq_oss_readq *
snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen)
{
	struct seq_oss_readq *q;

	q = kzalloc(sizeof(*q), GFP_KERNEL);
	if (!q)
		return NULL;

	q->q = kcalloc(maxlen, sizeof(union evrec), GFP_KERNEL);
	if (!q->q) {
		kfree(q);
		return NULL;
	}

	q->maxlen = maxlen;
	q->qlen = 0;
	q->head = q->tail = 0;
	init_waitqueue_head(&q->midi_sleep);
	spin_lock_init(&q->lock);
	q->pre_event_timeout = SNDRV_SEQ_OSS_MAX_TIMEOUT;
	q->input_time = (unsigned long)-1;

	return q;
}

/*
 * delete the read queue
 */
void
snd_seq_oss_readq_delete(struct seq_oss_readq *q)
{
	if (q) {
		kfree(q->q);
		kfree(q);
	}
}

/*
 * reset the read queue
 */
void
snd_seq_oss_readq_clear(struct seq_oss_readq *q)
{
	if (q->qlen) {
		q->qlen = 0;
		q->head = q->tail = 0;
	}
	/* if someone sleeping, wake'em up */
	wake_up(&q->midi_sleep);
	q->input_time = (unsigned long)-1;
}

/*
 * put a midi byte
 */
int
snd_seq_oss_readq_puts(struct seq_oss_readq *q, int dev, unsigned char *data, int len)
{
	union evrec rec;
	int result;

	memset(&rec, 0, sizeof(rec));
	rec.c[0] = SEQ_MIDIPUTC;
	rec.c[2] = dev;

	while (len-- > 0) {
		rec.c[1] = *data++;
		result = snd_seq_oss_readq_put_event(q, &rec);
		if (result < 0)
			return result;
	}
	return 0;
}

/*
 * put MIDI sysex bytes; the event buffer may be chained, thus it has
 * to be expanded via snd_seq_dump_var_event().
 */
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
 */
int
snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
{
	unsigned long flags;

	spin_lock_irqsave(&q->lock, flags);
	if (q->qlen >= q->maxlen - 1) {
		spin_unlock_irqrestore(&q->lock, flags);
		return -ENOMEM;
	}

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

	/* wake up sleeper */
	wake_up(&q->midi_sleep);

	spin_unlock_irqrestore(&q->lock, flags);

	return 0;
}


/*
 * 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
 */
void
snd_seq_oss_readq_free(struct seq_oss_readq *q)
{
	if (q->qlen > 0) {
		q->head = (q->head + 1) % q->maxlen;
		q->qlen--;
	}
}

/*
 * polling/select:
 * return non-zero if readq is not empty.
 */
unsigned int
snd_seq_oss_readq_poll(struct seq_oss_readq *q, struct file *file, poll_table *wait)
{
	poll_wait(file, &q->midi_sleep, wait);
	return q->qlen;
}

/*
 * put a timestamp
 */
int
snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *q, unsigned long curt, int seq_mode)
{
	if (curt != q->input_time) {
		union evrec rec;
		memset(&rec, 0, sizeof(rec));
		switch (seq_mode) {
		case SNDRV_SEQ_OSS_MODE_SYNTH:
			rec.echo = (curt << 8) | SEQ_WAIT;
			snd_seq_oss_readq_put_event(q, &rec);
			break;
		case SNDRV_SEQ_OSS_MODE_MUSIC:
			rec.t.code = EV_TIMING;
			rec.t.cmd = TMR_WAIT_ABS;
			rec.t.time = curt;
			snd_seq_oss_readq_put_event(q, &rec);
			break;
		}
		q->input_time = curt;
	}
	return 0;
}


#ifdef CONFIG_SND_PROC_FS
/*
 * proc interface
 */
void
snd_seq_oss_readq_info_read(struct seq_oss_readq *q, struct snd_info_buffer *buf)
{
	snd_iprintf(buf, "  read queue [%s] length = %d : tick = %ld\n",
		    (waitqueue_active(&q->midi_sleep) ? "sleeping":"running"),
		    q->qlen, q->input_time);
}
#endif /* CONFIG_SND_PROC_FS */
