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