Annotation of sys/dev/midi.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: midi.c,v 1.16 2006/12/21 02:28:47 krw Exp $ */
2:
3: /*
4: * Copyright (c) 2003, 2004 Alexandre Ratchov
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: /*
20: * TODO
21: * - put the sequencer stuff in sequencer.c and sequencervar.h
22: * there is no reason to have it here. The sequencer
23: * driver need only to open the midi hw_if thus it does not
24: * need this driver
25: */
26:
27: #include "midi.h"
28: #include "sequencer.h"
29: #if NMIDI > 0
30:
31: #include <sys/param.h>
32: #include <sys/fcntl.h>
33: #include <sys/systm.h>
34: #include <sys/ioctl.h>
35: #include <sys/exec.h>
36: #include <sys/conf.h>
37: #include <sys/lkm.h>
38: #include <sys/proc.h>
39: #include <sys/poll.h>
40: #include <sys/kernel.h>
41: #include <sys/timeout.h>
42: #include <sys/vnode.h>
43: #include <sys/signalvar.h>
44: #include <sys/malloc.h>
45: #include <sys/device.h>
46:
47: #include <dev/midi_if.h>
48: #include <dev/audio_if.h>
49: #include <dev/midivar.h>
50:
51:
52: int midiopen(dev_t, int, int, struct proc *);
53: int midiclose(dev_t, int, int, struct proc *);
54: int midiread(dev_t, struct uio *, int);
55: int midiwrite(dev_t, struct uio *, int);
56: int midipoll(dev_t, int, struct proc *);
57: int midiioctl(dev_t, u_long, caddr_t, int, struct proc *);
58: int midiprobe(struct device *, void *, void *);
59: void midiattach(struct device *, struct device *, void *);
60: int mididetach(struct device *, int);
61: int midiprint(void *, const char *);
62:
63: void midi_iintr(void *, int);
64: void midi_ointr(void *);
65: void midi_out_start(struct midi_softc *);
66: void midi_out_stop(struct midi_softc *);
67: void midi_out_do(struct midi_softc *);
68: void midi_attach(struct midi_softc *, struct device *);
69:
70:
71: #if NSEQUENCER > 0
72: int midi_unit_count(void);
73: struct midi_hw_if *midi_get_hwif(int);
74: void midi_toevent(struct midi_softc *, int);
75: int midi_writebytes(int, u_char *, int);
76: void midiseq_in(struct midi_dev *, u_char *, int);
77: #endif
78:
79: struct cfattach midi_ca = {
80: sizeof(struct midi_softc), midiprobe, midiattach, mididetach
81: };
82:
83: struct cfdriver midi_cd = {
84: NULL, "midi", DV_DULL
85: };
86:
87:
88: void
89: midi_iintr(void *addr, int data)
90: {
91: struct midi_softc *sc = (struct midi_softc *)addr;
92: struct midi_buffer *mb = &sc->inbuf;
93:
94: if (sc->isdying || !sc->isopen || !(sc->flags & FREAD)) return;
95:
96: #if NSEQUENCER > 0
97: if (sc->seqopen) {
98: midi_toevent(sc, data);
99: return;
100: }
101: #endif
102: if (MIDIBUF_ISFULL(mb))
103: return; /* discard data */
104: if (MIDIBUF_ISEMPTY(mb)) {
105: if (sc->rchan) {
106: sc->rchan = 0;
107: wakeup(&sc->rchan);
108: }
109: selwakeup(&sc->rsel);
110: if (sc->async)
111: psignal(sc->async, SIGIO);
112: }
113: MIDIBUF_WRITE(mb, data);
114: }
115:
116:
117: int
118: midiread(dev_t dev, struct uio *uio, int ioflag)
119: {
120: struct midi_softc *sc = MIDI_DEV2SC(dev);
121: struct midi_buffer *mb = &sc->inbuf;
122: unsigned count;
123: int s, error;
124:
125: if (!(sc->flags & FREAD))
126: return ENXIO;
127:
128: /* if there is no data then sleep (unless IO_NDELAY flag is set) */
129:
130: s = splaudio();
131: while(MIDIBUF_ISEMPTY(mb)) {
132: if (sc->isdying) {
133: splx(s);
134: return EIO;
135: }
136: if (ioflag & IO_NDELAY) {
137: splx(s);
138: return EWOULDBLOCK;
139: }
140: sc->rchan = 1;
141: error = tsleep(&sc->rchan, PWAIT|PCATCH, "mid_rd", 0);
142: if (error) {
143: splx(s);
144: return error;
145: }
146: }
147:
148: /* at this stage, there is at least 1 byte */
149:
150: while (uio->uio_resid > 0 && mb->used > 0) {
151: count = MIDIBUF_SIZE - mb->start;
152: if (count > mb->used)
153: count = mb->used;
154: if (count > uio->uio_resid)
155: count = uio->uio_resid;
156: error = uiomove(mb->data + mb->start, count, uio);
157: if (error) {
158: splx(s);
159: return error;
160: }
161: MIDIBUF_REMOVE(mb, count);
162: }
163: splx(s);
164: return 0;
165: }
166:
167:
168: void
169: midi_ointr(void *addr)
170: {
171: struct midi_softc *sc = (struct midi_softc *)addr;
172: struct midi_buffer *mb;
173: int s;
174:
175: if (sc->isopen && !sc->isdying) {
176: #ifdef MIDI_DEBUG
177: if (!sc->isbusy) {
178: printf("midi_ointr: output should be busy\n");
179: }
180: #endif
181: mb = &sc->outbuf;
182: s = splaudio();
183: if (mb->used == 0)
184: midi_out_stop(sc);
185: else
186: midi_out_do(sc); /* restart output */
187: splx(s);
188: }
189: }
190:
191:
192: void
193: midi_out_start(struct midi_softc *sc)
194: {
195: if (!sc->isbusy) {
196: sc->isbusy = 1;
197: midi_out_do(sc);
198: }
199: }
200:
201: void
202: midi_out_stop(struct midi_softc *sc)
203: {
204: sc->isbusy = 0;
205: if (sc->wchan) {
206: sc->wchan = 0;
207: wakeup(&sc->wchan);
208: }
209: selwakeup(&sc->wsel);
210: if (sc->async)
211: psignal(sc->async, SIGIO);
212: }
213:
214:
215: /*
216: * drain output buffer, must be called with
217: * interrupts disabled
218: */
219: void
220: midi_out_do(struct midi_softc *sc)
221: {
222: struct midi_buffer *mb = &sc->outbuf;
223: unsigned i, max;
224: int error;
225:
226: /*
227: * If output interrupts are not supported then we write MIDI_MAXWRITE
228: * bytes instead of 1, and then we wait sc->wait
229: */
230:
231: max = sc->props & MIDI_PROP_OUT_INTR ? 1 : MIDI_MAXWRITE;
232: for (i = max; i != 0;) {
233: if (mb->used == 0)
234: break;
235: error = sc->hw_if->output(sc->hw_hdl, mb->data[mb->start]);
236: /*
237: * 0 means that data is being sent, an interrupt will
238: * be generated when the interface becomes ready again
239: *
240: * EINPROGRESS means that data has been queued, but
241: * will not be sent immediately and thus will not
242: * generate interrupt, in this case we can send
243: * another byte. The flush() method can be called
244: * to force the transfer.
245: *
246: * EAGAIN means that data cannot be queued or sent;
247: * because the interface isn't ready. An interrupt
248: * will be generated once the interface is ready again
249: *
250: * any other (fatal) error code means that data couldn't
251: * be sent and was lost, interrupt will not be generated
252: */
253: if (error == EINPROGRESS) {
254: MIDIBUF_REMOVE(mb, 1);
255: if (MIDIBUF_ISEMPTY(mb)) {
256: if (sc->hw_if->flush != NULL)
257: sc->hw_if->flush(sc->hw_hdl);
258: midi_out_stop(sc);
259: return;
260: }
261: } else if (error == 0) {
262: MIDIBUF_REMOVE(mb, 1);
263: i--;
264: } else if (error == EAGAIN) {
265: break;
266: } else {
267: MIDIBUF_INIT(mb);
268: midi_out_stop(sc);
269: return;
270: }
271: }
272:
273: if (!(sc->props & MIDI_PROP_OUT_INTR)) {
274: if (MIDIBUF_ISEMPTY(mb))
275: midi_out_stop(sc);
276: else
277: timeout_add(&sc->timeo, sc->wait);
278: }
279: }
280:
281:
282: int
283: midiwrite(dev_t dev, struct uio *uio, int ioflag)
284: {
285: struct midi_softc *sc = MIDI_DEV2SC(dev);
286: struct midi_buffer *mb = &sc->outbuf;
287: unsigned count;
288: int s, error;
289:
290: if (!(sc->flags & FWRITE))
291: return ENXIO;
292: if (sc->isdying)
293: return EIO;
294:
295: /*
296: * If IO_NDELAY flag is set then check if there is enough room
297: * in the buffer to store at least one byte. If not then dont
298: * start the write process.
299: */
300:
301: if ((ioflag & IO_NDELAY) && MIDIBUF_ISFULL(mb) &&
302: (uio->uio_resid > 0))
303: return EWOULDBLOCK;
304:
305: while (uio->uio_resid > 0) {
306: s = splaudio();
307: while (MIDIBUF_ISFULL(mb)) {
308: if (ioflag & IO_NDELAY) {
309: /*
310: * At this stage at least one byte is already
311: * moved so we do not return EWOULDBLOCK
312: */
313: splx(s);
314: return 0;
315: }
316: sc->wchan = 1;
317: error = tsleep(&sc->wchan, PWAIT|PCATCH, "mid_wr", 0);
318: if (error) {
319: splx(s);
320: return error;
321: }
322: if (sc->isdying) {
323: splx(s);
324: return EIO;
325: }
326: }
327:
328: count = MIDIBUF_SIZE - MIDIBUF_END(mb);
329: if (count > MIDIBUF_AVAIL(mb))
330: count = MIDIBUF_AVAIL(mb);
331: if (count > uio->uio_resid)
332: count = uio->uio_resid;
333: error = uiomove(mb->data + MIDIBUF_END(mb), count, uio);
334: if (error) {
335: splx(s);
336: return error;
337: }
338: mb->used += count;
339: midi_out_start(sc);
340: splx(s);
341: }
342: return 0;
343: }
344:
345:
346: int
347: midipoll(dev_t dev, int events, struct proc *p)
348: {
349: struct midi_softc *sc = MIDI_DEV2SC(dev);
350: int s, revents;
351:
352: if (sc->isdying)
353: return POLLERR;
354:
355: revents = 0;
356: s = splaudio();
357: if (events & (POLLIN | POLLRDNORM)) {
358: if (!MIDIBUF_ISEMPTY(&sc->inbuf))
359: revents |= events & (POLLIN | POLLRDNORM);
360: }
361: if (events & (POLLOUT | POLLWRNORM)) {
362: if (!MIDIBUF_ISFULL(&sc->outbuf))
363: revents |= events & (POLLOUT | POLLWRNORM);
364: }
365: if (revents == 0) {
366: if (events & (POLLIN | POLLRDNORM))
367: selrecord(p, &sc->rsel);
368: if (events & (POLLOUT | POLLWRNORM))
369: selrecord(p, &sc->wsel);
370: }
371: splx(s);
372: return (revents);
373: }
374:
375:
376: int
377: midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
378: {
379: struct midi_softc *sc = MIDI_DEV2SC(dev);
380:
381: if (sc->isdying) return EIO;
382:
383: switch(cmd) {
384: case FIONBIO:
385: /* All handled in the upper FS layer */
386: break;
387: case FIOASYNC:
388: if (*(int *)addr) {
389: if (sc->async) return EBUSY;
390: sc->async = p;
391: } else
392: sc->async = 0;
393: break;
394: default:
395: return ENOTTY;
396: break;
397: }
398: return 0;
399: }
400:
401:
402: int
403: midiopen(dev_t dev, int flags, int mode, struct proc *p)
404: {
405: struct midi_softc *sc;
406: int err;
407:
408: if (MIDI_UNIT(dev) >= midi_cd.cd_ndevs)
409: return ENXIO;
410: sc = MIDI_DEV2SC(dev);
411: if (sc == NULL) /* there may be more units than devices */
412: return ENXIO;
413: if (sc->isdying)
414: return EIO;
415: if (sc->isopen)
416: return EBUSY;
417:
418: MIDIBUF_INIT(&sc->inbuf);
419: MIDIBUF_INIT(&sc->outbuf);
420: sc->isbusy = 0;
421: sc->rchan = sc->wchan = 0;
422: sc->async = 0;
423: sc->flags = flags;
424:
425: err = sc->hw_if->open(sc->hw_hdl, flags, midi_iintr, midi_ointr, sc);
426: if (err)
427: return err;
428: sc->isopen = 1;
429: #if NSEQUENCER > 0
430: sc->seq_md = 0;
431: sc->seqopen = 0;
432: sc->evstatus = 0xff;
433: #endif
434: return 0;
435: }
436:
437:
438: int
439: midiclose(dev_t dev, int fflag, int devtype, struct proc *p)
440: {
441: struct midi_softc *sc = MIDI_DEV2SC(dev);
442: struct midi_buffer *mb;
443: int error;
444: int s;
445:
446: mb = &sc->outbuf;
447: if (!sc->isdying) {
448: /* start draining output buffer */
449: s = splaudio();
450: if (!MIDIBUF_ISEMPTY(mb))
451: midi_out_start(sc);
452: while (sc->isbusy) {
453: sc->wchan = 1;
454: error = tsleep(&sc->wchan, PWAIT|PCATCH, "mid_dr", 0);
455: if (error || sc->isdying)
456: break;
457: }
458: splx(s);
459: }
460:
461: /*
462: * some hw_if->close() reset immediately the midi uart
463: * which flushes the internal buffer of the uart device,
464: * so we may lose some (important) data. To avoid this, we sleep 2*wait,
465: * which gives the time to the uart to drain its internal buffers.
466: *
467: * Note: we'd better sleep in the corresponding hw_if->close()
468: */
469:
470: tsleep(&sc->wchan, PWAIT|PCATCH, "mid_cl", 2 * sc->wait);
471: sc->hw_if->close(sc->hw_hdl);
472: sc->isopen = 0;
473: return 0;
474: }
475:
476:
477: int
478: midiprobe(struct device *parent, void *match, void *aux)
479: {
480: struct audio_attach_args *sa = aux;
481: return (sa != NULL && (sa->type == AUDIODEV_TYPE_MIDI) ? 1 : 0);
482: }
483:
484:
485: void
486: midi_attach(struct midi_softc *sc, struct device *parent)
487: {
488: struct midi_info mi;
489:
490: sc->isdying = 0;
491: sc->wait = (hz * MIDI_MAXWRITE) / MIDI_RATE;
492: if (sc->wait == 0)
493: sc->wait = 1;
494: sc->hw_if->getinfo(sc->hw_hdl, &mi);
495: sc->props = mi.props;
496: sc->isopen = 0;
497: timeout_set(&sc->timeo, midi_ointr, sc);
498: printf(": <%s>\n", mi.name);
499: }
500:
501:
502: void
503: midiattach(struct device *parent, struct device *self, void *aux)
504: {
505: struct midi_softc *sc = (struct midi_softc *)self;
506: struct audio_attach_args *sa = (struct audio_attach_args *)aux;
507: struct midi_hw_if *hwif = sa->hwif;
508: void *hdl = sa->hdl;
509:
510: #ifdef DIAGNOSTIC
511: if (hwif == 0 ||
512: hwif->open == 0 ||
513: hwif->close == 0 ||
514: hwif->output == 0 ||
515: hwif->getinfo == 0) {
516: printf("midi: missing method\n");
517: return;
518: }
519: #endif
520: sc->hw_if = hwif;
521: sc->hw_hdl = hdl;
522: midi_attach(sc, parent);
523: }
524:
525:
526: int
527: mididetach(struct device *self, int flags)
528: {
529: struct midi_softc *sc = (struct midi_softc *)self;
530: int maj, mn;
531:
532: sc->isdying = 1;
533: if (sc->wchan) {
534: sc->wchan = 0;
535: wakeup(&sc->wchan);
536: }
537: if (sc->rchan) {
538: sc->rchan = 0;
539: wakeup(&sc->rchan);
540: }
541:
542: /* locate the major number */
543: for (maj = 0; maj < nchrdev; maj++)
544: if (cdevsw[maj].d_open == midiopen)
545: break;
546:
547: /* Nuke the vnodes for any open instances (calls close). */
548: mn = self->dv_unit;
549: vdevgone(maj, mn, mn, VCHR);
550:
551: return 0;
552: }
553:
554:
555: int
556: midiprint(void *aux, const char *pnp)
557: {
558: if (pnp)
559: printf("midi at %s", pnp);
560: return (UNCONF);
561: }
562:
563:
564: void
565: midi_getinfo(dev_t dev, struct midi_info *mi)
566: {
567: struct midi_softc *sc = MIDI_DEV2SC(dev);
568: if (MIDI_UNIT(dev) >= midi_cd.cd_ndevs || sc == NULL || sc->isdying) {
569: mi->name = "unconfigured";
570: mi->props = 0;
571: return;
572: }
573: sc->hw_if->getinfo(sc->hw_hdl, mi);
574: }
575:
576:
577: struct device *
578: midi_attach_mi(struct midi_hw_if *hwif, void *hdl, struct device *dev)
579: {
580: struct audio_attach_args arg;
581:
582: arg.type = AUDIODEV_TYPE_MIDI;
583: arg.hwif = hwif;
584: arg.hdl = hdl;
585: return config_found(dev, &arg, midiprint);
586: }
587:
588:
589: int
590: midi_unit_count(void)
591: {
592: return midi_cd.cd_ndevs;
593: }
594:
595:
596: #if NSEQUENCER > 0
597: #define MIDI_EVLEN(status) (midi_evlen[((status) >> 4) & 7])
598: unsigned midi_evlen[] = { 2, 2, 2, 2, 1, 1, 2 };
599:
600: void
601: midi_toevent(struct midi_softc *sc, int data)
602: {
603: unsigned char mesg[3];
604:
605: if (data >= 0xf8) { /* is it a realtime message ? */
606: switch(data) {
607: case 0xf8: /* midi timer tic */
608: case 0xfa: /* midi timer start */
609: case 0xfb: /* midi timer continue (after stop) */
610: case 0xfc: /* midi timer stop */
611: mesg[0] = data;
612: midiseq_in(sc->seq_md, mesg, 1);
613: break;
614: default:
615: break;
616: }
617: } else if (data >= 0x80) { /* is it a common or voice message ? */
618: sc->evstatus = data;
619: sc->evindex = 0;
620: } else { /* else it is a data byte */
621: /* strip common messages and bogus data */
622: if (sc->evstatus >= 0xf0 || sc->evstatus < 0x80)
623: return;
624:
625: sc->evdata[sc->evindex++] = data;
626: if (sc->evindex == MIDI_EVLEN(sc->evstatus)) {
627: sc->evindex = 0;
628: mesg[0] = sc->evstatus;
629: mesg[1] = sc->evdata[0];
630: mesg[2] = sc->evdata[1];
631: midiseq_in(sc->seq_md, mesg, 1 + MIDI_EVLEN(sc->evstatus));
632: }
633: }
634: }
635:
636:
637: int
638: midi_writebytes(int unit, unsigned char *mesg, int mesglen)
639: {
640: struct midi_softc *sc = midi_cd.cd_devs[unit];
641: struct midi_buffer *mb = &sc->outbuf;
642: unsigned count;
643: int s;
644:
645: s = splaudio();
646: if (mesglen > MIDIBUF_AVAIL(mb)) {
647: splx(s);
648: return EWOULDBLOCK;
649: }
650:
651: while (mesglen > 0) {
652: count = MIDIBUF_SIZE - MIDIBUF_END(mb);
653: if (count > MIDIBUF_AVAIL(mb)) count = MIDIBUF_AVAIL(mb);
654: if (count > mesglen) count = mesglen;
655: bcopy(mesg, mb->data + MIDIBUF_END(mb), count);
656: mb->used += count;
657: mesg += count;
658: mesglen -= count;
659: midi_out_start(sc);
660: }
661: splx(s);
662: return 0;
663: }
664:
665: #endif /* NSEQUENCER > 0 */
666: #endif /* NMIDI > 0 */
CVSweb