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