summaryrefslogtreecommitdiff
path: root/sys/dev/midi.c
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2006-04-07 22:41:34 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2006-04-07 22:41:34 +0000
commit6e4f531815188a666ff636e5ab7cd5a893e246c3 (patch)
tree9a010f147be7c73ff596bb2b1444fad0512c6d9f /sys/dev/midi.c
parentac027bced9dbecb8b0b9df43116b66cb9d857f51 (diff)
Add optional flush method to MIDI hardware interface.
Allow umidi(4) to send multiple events in a single USB transfer. This greatly improves the number of interrupts umidi is able to generate. From Alexandre Ratchov.
Diffstat (limited to 'sys/dev/midi.c')
-rw-r--r--sys/dev/midi.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/sys/dev/midi.c b/sys/dev/midi.c
index 881f86d5a01..9c2aaf04bf8 100644
--- a/sys/dev/midi.c
+++ b/sys/dev/midi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.c,v 1.12 2004/09/22 22:17:44 deraadt Exp $ */
+/* $OpenBSD: midi.c,v 1.13 2006/04/07 22:41:32 jsg Exp $ */
/*
* Copyright (c) 2003, 2004 Alexandre Ratchov
@@ -48,6 +48,7 @@
#include <dev/audio_if.h>
#include <dev/midivar.h>
+
int midiopen(dev_t, int, int, struct proc *);
int midiclose(dev_t, int, int, struct proc *);
int midiread(dev_t, struct uio *, int);
@@ -223,34 +224,53 @@ midi_out_do(struct midi_softc *sc)
{
struct midi_buffer *mb = &sc->outbuf;
unsigned i, max;
- unsigned data;
int error;
/*
* If output interrupts are not supported then we write MIDI_MAXWRITE
* bytes instead of 1, and then we wait sc->wait
- */
-
+ */
+
max = sc->props & MIDI_PROP_OUT_INTR ? 1 : MIDI_MAXWRITE;
for (i = max; i != 0;) {
if (mb->used == 0)
break;
-
- MIDIBUF_READ(mb, data);
- error = sc->hw_if->output(sc->hw_hdl, data);
+ error = sc->hw_if->output(sc->hw_hdl, mb->data[mb->start]);
/*
- * EINPROGRESS means that data has been handled,
- * but will not be sent immediately and thus will
- * not generate interrupt, in this case we can
- * send another byte
+ * 0 means that data is being sent, an interrupt will
+ * be generated when the interface becomes ready again
+ *
+ * EINPROGRESS means that data has been queued, but
+ * will not be sent immediately and thus will not
+ * generate interrupt, in this case we can send
+ * another byte. The flush() method can be called
+ * to force the tranfer.
+ *
+ * EAGAIN means that data cannot be queued or sent;
+ * because the interface isn't ready. An interrupt
+ * will be generated once the interface is ready again
+ *
+ * any other (fatal) error code means that data couldn't
+ * be sent and was lost, interrupt will not be generated
*/
if (error == EINPROGRESS) {
+ MIDIBUF_REMOVE(mb, 1);
if (MIDIBUF_ISEMPTY(mb)) {
+ if (sc->hw_if->flush != NULL)
+ sc->hw_if->flush(sc->hw_hdl);
midi_out_stop(sc);
return;
}
- } else
+ } else if (error == 0) {
+ MIDIBUF_REMOVE(mb, 1);
i--;
+ } else if (error == EAGAIN) {
+ break;
+ } else {
+ MIDIBUF_INIT(mb);
+ midi_out_stop(sc);
+ return;
+ }
}
if (!(sc->props & MIDI_PROP_OUT_INTR)) {