diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2006-04-07 22:41:34 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2006-04-07 22:41:34 +0000 |
commit | 6e4f531815188a666ff636e5ab7cd5a893e246c3 (patch) | |
tree | 9a010f147be7c73ff596bb2b1444fad0512c6d9f /sys/dev/midi.c | |
parent | ac027bced9dbecb8b0b9df43116b66cb9d857f51 (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.c | 44 |
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)) { |