1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * OSS compatible sequencer driver
5 * seq_oss_readq.c - MIDI input queue
7 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
10 #include "seq_oss_readq.h"
11 #include "seq_oss_event.h"
12 #include <sound/seq_oss_legacy.h>
13 #include "../seq_lock.h"
14 #include <linux/wait.h>
15 #include <linux/slab.h>
20 //#define SNDRV_SEQ_OSS_MAX_TIMEOUT (unsigned long)(-1)
21 #define SNDRV_SEQ_OSS_MAX_TIMEOUT (HZ * 3600)
32 struct seq_oss_readq
*
33 snd_seq_oss_readq_new(struct seq_oss_devinfo
*dp
, int maxlen
)
35 struct seq_oss_readq
*q
;
37 q
= kzalloc(sizeof(*q
), GFP_KERNEL
);
41 q
->q
= kcalloc(maxlen
, sizeof(union evrec
), GFP_KERNEL
);
49 q
->head
= q
->tail
= 0;
50 init_waitqueue_head(&q
->midi_sleep
);
51 spin_lock_init(&q
->lock
);
52 q
->pre_event_timeout
= SNDRV_SEQ_OSS_MAX_TIMEOUT
;
53 q
->input_time
= (unsigned long)-1;
59 * delete the read queue
62 snd_seq_oss_readq_delete(struct seq_oss_readq
*q
)
71 * reset the read queue
74 snd_seq_oss_readq_clear(struct seq_oss_readq
*q
)
78 q
->head
= q
->tail
= 0;
80 /* if someone sleeping, wake'em up */
81 wake_up(&q
->midi_sleep
);
82 q
->input_time
= (unsigned long)-1;
89 snd_seq_oss_readq_puts(struct seq_oss_readq
*q
, int dev
, unsigned char *data
, int len
)
94 memset(&rec
, 0, sizeof(rec
));
95 rec
.c
[0] = SEQ_MIDIPUTC
;
100 result
= snd_seq_oss_readq_put_event(q
, &rec
);
108 * put MIDI sysex bytes; the event buffer may be chained, thus it has
109 * to be expanded via snd_seq_dump_var_event().
111 struct readq_sysex_ctx
{
112 struct seq_oss_readq
*readq
;
116 static int readq_dump_sysex(void *ptr
, void *buf
, int count
)
118 struct readq_sysex_ctx
*ctx
= ptr
;
120 return snd_seq_oss_readq_puts(ctx
->readq
, ctx
->dev
, buf
, count
);
123 int snd_seq_oss_readq_sysex(struct seq_oss_readq
*q
, int dev
,
124 struct snd_seq_event
*ev
)
126 struct readq_sysex_ctx ctx
= {
131 if ((ev
->flags
& SNDRV_SEQ_EVENT_LENGTH_MASK
) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE
)
133 return snd_seq_dump_var_event(ev
, readq_dump_sysex
, &ctx
);
137 * copy an event to input queue:
138 * return zero if enqueued
141 snd_seq_oss_readq_put_event(struct seq_oss_readq
*q
, union evrec
*ev
)
145 spin_lock_irqsave(&q
->lock
, flags
);
146 if (q
->qlen
>= q
->maxlen
- 1) {
147 spin_unlock_irqrestore(&q
->lock
, flags
);
151 memcpy(&q
->q
[q
->tail
], ev
, sizeof(*ev
));
152 q
->tail
= (q
->tail
+ 1) % q
->maxlen
;
155 /* wake up sleeper */
156 wake_up(&q
->midi_sleep
);
158 spin_unlock_irqrestore(&q
->lock
, flags
);
166 * caller must hold lock
169 snd_seq_oss_readq_pick(struct seq_oss_readq
*q
, union evrec
*rec
)
173 memcpy(rec
, &q
->q
[q
->head
], sizeof(*rec
));
181 snd_seq_oss_readq_wait(struct seq_oss_readq
*q
)
183 wait_event_interruptible_timeout(q
->midi_sleep
,
184 (q
->qlen
> 0 || q
->head
== q
->tail
),
185 q
->pre_event_timeout
);
190 * caller must hold lock
193 snd_seq_oss_readq_free(struct seq_oss_readq
*q
)
196 q
->head
= (q
->head
+ 1) % q
->maxlen
;
203 * return non-zero if readq is not empty.
206 snd_seq_oss_readq_poll(struct seq_oss_readq
*q
, struct file
*file
, poll_table
*wait
)
208 poll_wait(file
, &q
->midi_sleep
, wait
);
216 snd_seq_oss_readq_put_timestamp(struct seq_oss_readq
*q
, unsigned long curt
, int seq_mode
)
218 if (curt
!= q
->input_time
) {
220 memset(&rec
, 0, sizeof(rec
));
222 case SNDRV_SEQ_OSS_MODE_SYNTH
:
223 rec
.echo
= (curt
<< 8) | SEQ_WAIT
;
224 snd_seq_oss_readq_put_event(q
, &rec
);
226 case SNDRV_SEQ_OSS_MODE_MUSIC
:
227 rec
.t
.code
= EV_TIMING
;
228 rec
.t
.cmd
= TMR_WAIT_ABS
;
230 snd_seq_oss_readq_put_event(q
, &rec
);
233 q
->input_time
= curt
;
239 #ifdef CONFIG_SND_PROC_FS
244 snd_seq_oss_readq_info_read(struct seq_oss_readq
*q
, struct snd_info_buffer
*buf
)
246 snd_iprintf(buf
, " read queue [%s] length = %d : tick = %ld\n",
247 (waitqueue_active(&q
->midi_sleep
) ? "sleeping":"running"),
248 q
->qlen
, q
->input_time
);
250 #endif /* CONFIG_SND_PROC_FS */