xref: /openbsd-src/sys/dev/midi.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
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 */
667