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