Deleted Added
full compact
midi.c (166322) midi.c (166971)
1/*-
2 * Copyright (c) 2003 Mathew Kanner
3 * Copyright (c) 1998 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Lennart Augustsson (augustss@netbsd.org).
8 *

--- 28 unchanged lines hidden (view full) ---

37
38 /*
39 * Parts of this file started out as NetBSD: midi.c 1.31
40 * They are mostly gone. Still the most obvious will be the state
41 * machine midi_in
42 */
43
44#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2003 Mathew Kanner
3 * Copyright (c) 1998 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Lennart Augustsson (augustss@netbsd.org).
8 *

--- 28 unchanged lines hidden (view full) ---

37
38 /*
39 * Parts of this file started out as NetBSD: midi.c 1.31
40 * They are mostly gone. Still the most obvious will be the state
41 * machine midi_in
42 */
43
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD: head/sys/dev/sound/midi/midi.c 166322 2007-01-28 20:38:07Z joel $");
45__FBSDID("$FreeBSD: head/sys/dev/sound/midi/midi.c 166971 2007-02-25 13:51:52Z netchild $");
46
47#include <sys/param.h>
48#include <sys/queue.h>
49#include <sys/kernel.h>
50#include <sys/lock.h>
51#include <sys/mutex.h>
52#include <sys/proc.h>
53#include <sys/signalvar.h>

--- 40 unchanged lines hidden (view full) ---

94
95/*
96 * /dev/rmidi Structure definitions
97 */
98
99#define MIDI_NAMELEN 16
100struct snd_midi {
101 KOBJ_FIELDS;
46
47#include <sys/param.h>
48#include <sys/queue.h>
49#include <sys/kernel.h>
50#include <sys/lock.h>
51#include <sys/mutex.h>
52#include <sys/proc.h>
53#include <sys/signalvar.h>

--- 40 unchanged lines hidden (view full) ---

94
95/*
96 * /dev/rmidi Structure definitions
97 */
98
99#define MIDI_NAMELEN 16
100struct snd_midi {
101 KOBJ_FIELDS;
102 struct mtx lock; /* Protects all but queues */
103 void *cookie;
102 struct mtx lock; /* Protects all but queues */
103 void *cookie;
104
104
105 int unit; /* Should only be used in midistat */
106 int channel;/* Should only be used in midistat */
105 int unit; /* Should only be used in midistat */
106 int channel; /* Should only be used in midistat */
107
107
108 int busy;
109 int flags; /* File flags */
110 char name[MIDI_NAMELEN];
111 struct mtx qlock; /* Protects inq, outq and flags */
112 MIDIQ_HEAD(, char)inq, outq;
113 int rchan, wchan;
114 struct selinfo rsel, wsel;
115 int hiwat; /* QLEN(outq)>High-water -> disable writes
116 * from userland */
108 int busy;
109 int flags; /* File flags */
110 char name[MIDI_NAMELEN];
111 struct mtx qlock; /* Protects inq, outq and flags */
112 MIDIQ_HEAD(, char) inq, outq;
113 int rchan, wchan;
114 struct selinfo rsel, wsel;
115 int hiwat; /* QLEN(outq)>High-water -> disable
116 * writes from userland */
117 enum midi_states inq_state;
117 enum midi_states inq_state;
118 int inq_status, inq_left; /* Variables for the state
119 * machine in Midi_in, this
120 * is to provide that signals
121 * only get issued only
122 * complete command packets. */
123 struct proc *async;
124 struct cdev *dev;
118 int inq_status, inq_left; /* Variables for the state machine in
119 * Midi_in, this is to provide that
120 * signals only get issued only
121 * complete command packets. */
122 struct proc *async;
123 struct cdev *dev;
125 struct synth_midi *synth;
124 struct synth_midi *synth;
126 int synth_flags;
125 int synth_flags;
127 TAILQ_ENTRY(snd_midi) link;
128};
129
130struct synth_midi {
126 TAILQ_ENTRY(snd_midi) link;
127};
128
129struct synth_midi {
131 KOBJ_FIELDS;
132 struct snd_midi *m;
130 KOBJ_FIELDS;
131 struct snd_midi *m;
133};
134
135static synth_open_t midisynth_open;
136static synth_close_t midisynth_close;
137static synth_writeraw_t midisynth_writeraw;
138static synth_killnote_t midisynth_killnote;
139static synth_startnote_t midisynth_startnote;
140static synth_setinstr_t midisynth_setinstr;
141static synth_alloc_t midisynth_alloc;
142static synth_controller_t midisynth_controller;
143static synth_bender_t midisynth_bender;
144
145
146static kobj_method_t midisynth_methods[] = {
132};
133
134static synth_open_t midisynth_open;
135static synth_close_t midisynth_close;
136static synth_writeraw_t midisynth_writeraw;
137static synth_killnote_t midisynth_killnote;
138static synth_startnote_t midisynth_startnote;
139static synth_setinstr_t midisynth_setinstr;
140static synth_alloc_t midisynth_alloc;
141static synth_controller_t midisynth_controller;
142static synth_bender_t midisynth_bender;
143
144
145static kobj_method_t midisynth_methods[] = {
147 KOBJMETHOD(synth_open,midisynth_open),
148 KOBJMETHOD(synth_close,midisynth_close),
149 KOBJMETHOD(synth_writeraw,midisynth_writeraw),
150 KOBJMETHOD(synth_setinstr,midisynth_setinstr),
151 KOBJMETHOD(synth_startnote,midisynth_startnote),
152 KOBJMETHOD(synth_killnote,midisynth_killnote),
153 KOBJMETHOD(synth_alloc, midisynth_alloc),
154 KOBJMETHOD(synth_controller, midisynth_controller),
155 KOBJMETHOD(synth_bender, midisynth_bender),
156 { 0, 0 }
146 KOBJMETHOD(synth_open, midisynth_open),
147 KOBJMETHOD(synth_close, midisynth_close),
148 KOBJMETHOD(synth_writeraw, midisynth_writeraw),
149 KOBJMETHOD(synth_setinstr, midisynth_setinstr),
150 KOBJMETHOD(synth_startnote, midisynth_startnote),
151 KOBJMETHOD(synth_killnote, midisynth_killnote),
152 KOBJMETHOD(synth_alloc, midisynth_alloc),
153 KOBJMETHOD(synth_controller, midisynth_controller),
154 KOBJMETHOD(synth_bender, midisynth_bender),
155 {0, 0}
157};
158
159DEFINE_CLASS(midisynth, midisynth_methods, 0);
160
161/*
162 * Module Exports & Interface
156};
157
158DEFINE_CLASS(midisynth, midisynth_methods, 0);
159
160/*
161 * Module Exports & Interface
163 *
162 *
164 * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan) int
165 * midi_uninit(struct snd_midi *) 0 == no error EBUSY or other error int
166 * Midi_in(struct midi_chan *, char *buf, int count) int Midi_out(struct
167 * midi_chan *, char *buf, int count)
163 * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan) int
164 * midi_uninit(struct snd_midi *) 0 == no error EBUSY or other error int
165 * Midi_in(struct midi_chan *, char *buf, int count) int Midi_out(struct
166 * midi_chan *, char *buf, int count)
168 *
167 *
169 * midi_{in,out} return actual size transfered
168 * midi_{in,out} return actual size transfered
170 *
169 *
171 */
172
173
174/*
175 * midi_devs tailq, holder of all rmidi instances protected by midistat_lock
176 */
177
178TAILQ_HEAD(, snd_midi) midi_devs;

--- 84 unchanged lines hidden (view full) ---

263
264/*
265 * Register a new rmidi device. cls midi_if interface unit == 0 means
266 * auto-assign new unit number unit != 0 already assigned a unit number, eg.
267 * not the first channel provided by this device. channel, sub-unit
268 * cookie is passed back on MPU calls Typical device drivers will call with
269 * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care
270 * what unit number is used.
170 */
171
172
173/*
174 * midi_devs tailq, holder of all rmidi instances protected by midistat_lock
175 */
176
177TAILQ_HEAD(, snd_midi) midi_devs;

--- 84 unchanged lines hidden (view full) ---

262
263/*
264 * Register a new rmidi device. cls midi_if interface unit == 0 means
265 * auto-assign new unit number unit != 0 already assigned a unit number, eg.
266 * not the first channel provided by this device. channel, sub-unit
267 * cookie is passed back on MPU calls Typical device drivers will call with
268 * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care
269 * what unit number is used.
271 *
270 *
272 * It is an error to call midi_init with an already used unit/channel combo.
271 * It is an error to call midi_init with an already used unit/channel combo.
273 *
272 *
274 * Returns NULL on error
273 * Returns NULL on error
275 *
274 *
276 */
277struct snd_midi *
278midi_init(kobj_class_t cls, int unit, int channel, void *cookie)
279{
280 struct snd_midi *m;
275 */
276struct snd_midi *
277midi_init(kobj_class_t cls, int unit, int channel, void *cookie)
278{
279 struct snd_midi *m;
281 int i;
282 int inqsize, outqsize;
283 MIDI_TYPE *buf;
280 int i;
281 int inqsize, outqsize;
282 MIDI_TYPE *buf;
284
283
285 MIDI_DEBUG(1,printf("midiinit: unit %d/%d.\n", unit, channel));
284 MIDI_DEBUG(1, printf("midiinit: unit %d/%d.\n", unit, channel));
286 mtx_lock(&midistat_lock);
287 /*
288 * Protect against call with existing unit/channel or auto-allocate a
289 * new unit number.
290 */
291 i = -1;
292 TAILQ_FOREACH(m, &midi_devs, link) {
285 mtx_lock(&midistat_lock);
286 /*
287 * Protect against call with existing unit/channel or auto-allocate a
288 * new unit number.
289 */
290 i = -1;
291 TAILQ_FOREACH(m, &midi_devs, link) {
293 mtx_lock(&m->lock);
294 if (unit != 0) {
295 if (m->unit == unit && m->channel == channel) {
296 mtx_unlock(&m->lock);
297 goto err0;
292 mtx_lock(&m->lock);
293 if (unit != 0) {
294 if (m->unit == unit && m->channel == channel) {
295 mtx_unlock(&m->lock);
296 goto err0;
297 }
298 } else {
299 /*
300 * Find a better unit number
301 */
302 if (m->unit > i)
303 i = m->unit;
298 }
304 }
299 } else {
300 /*
301 * Find a better unit number
302 */
303 if (m->unit > i)
304 i = m->unit;
305 }
306 mtx_unlock(&m->lock);
305 mtx_unlock(&m->lock);
307 }
308
309 if (unit == 0)
306 }
307
308 if (unit == 0)
310 unit = i + 1;
309 unit = i + 1;
311
312 MIDI_DEBUG(1, printf("midiinit #2: unit %d/%d.\n", unit, channel));
313 m = malloc(sizeof(*m), M_MIDI, M_NOWAIT | M_ZERO);
314 if (m == NULL)
310
311 MIDI_DEBUG(1, printf("midiinit #2: unit %d/%d.\n", unit, channel));
312 m = malloc(sizeof(*m), M_MIDI, M_NOWAIT | M_ZERO);
313 if (m == NULL)
315 goto err0;
314 goto err0;
316
317 m->synth = malloc(sizeof(*m->synth), M_MIDI, M_NOWAIT | M_ZERO);
318 kobj_init((kobj_t)m->synth, &midisynth_class);
319 m->synth->m = m;
320 kobj_init((kobj_t)m, cls);
321 inqsize = MPU_INQSIZE(m, cookie);
322 outqsize = MPU_OUTQSIZE(m, cookie);
323
324 MIDI_DEBUG(1, printf("midiinit queues %d/%d.\n", inqsize, outqsize));
325 if (!inqsize && !outqsize)
315
316 m->synth = malloc(sizeof(*m->synth), M_MIDI, M_NOWAIT | M_ZERO);
317 kobj_init((kobj_t)m->synth, &midisynth_class);
318 m->synth->m = m;
319 kobj_init((kobj_t)m, cls);
320 inqsize = MPU_INQSIZE(m, cookie);
321 outqsize = MPU_OUTQSIZE(m, cookie);
322
323 MIDI_DEBUG(1, printf("midiinit queues %d/%d.\n", inqsize, outqsize));
324 if (!inqsize && !outqsize)
326 goto err1;
325 goto err1;
327
328 mtx_init(&m->lock, "raw midi", 0, 0);
329 mtx_init(&m->qlock, "q raw midi", 0, 0);
330
331 mtx_lock(&m->lock);
332 mtx_lock(&m->qlock);
333
334 if (inqsize)
326
327 mtx_init(&m->lock, "raw midi", 0, 0);
328 mtx_init(&m->qlock, "q raw midi", 0, 0);
329
330 mtx_lock(&m->lock);
331 mtx_lock(&m->qlock);
332
333 if (inqsize)
335 buf = malloc(sizeof(MIDI_TYPE) * inqsize, M_MIDI, M_NOWAIT);
334 buf = malloc(sizeof(MIDI_TYPE) * inqsize, M_MIDI, M_NOWAIT);
336 else
335 else
337 buf = NULL;
336 buf = NULL;
338
339 MIDIQ_INIT(m->inq, buf, inqsize);
340
341 if (outqsize)
337
338 MIDIQ_INIT(m->inq, buf, inqsize);
339
340 if (outqsize)
342 buf = malloc(sizeof(MIDI_TYPE) * outqsize, M_MIDI, M_NOWAIT);
341 buf = malloc(sizeof(MIDI_TYPE) * outqsize, M_MIDI, M_NOWAIT);
343 else
342 else
344 buf = NULL;
343 buf = NULL;
345 m->hiwat = outqsize / 2;
346
347 MIDIQ_INIT(m->outq, buf, outqsize);
348
349 if ((inqsize && !MIDIQ_BUF(m->inq)) ||
350 (outqsize && !MIDIQ_BUF(m->outq)))
344 m->hiwat = outqsize / 2;
345
346 MIDIQ_INIT(m->outq, buf, outqsize);
347
348 if ((inqsize && !MIDIQ_BUF(m->inq)) ||
349 (outqsize && !MIDIQ_BUF(m->outq)))
351 goto err2;
350 goto err2;
352
353
354 m->busy = 0;
355 m->flags = 0;
356 m->unit = unit;
357 m->channel = channel;
358 m->cookie = cookie;
359
360 if (MPU_INIT(m, cookie))
351
352
353 m->busy = 0;
354 m->flags = 0;
355 m->unit = unit;
356 m->channel = channel;
357 m->cookie = cookie;
358
359 if (MPU_INIT(m, cookie))
361 goto err2;
360 goto err2;
362
363 mtx_unlock(&m->lock);
364 mtx_unlock(&m->qlock);
365
366 TAILQ_INSERT_TAIL(&midi_devs, m, link);
367
368 mtx_unlock(&midistat_lock);
369
370 m->dev = make_dev(&midi_cdevsw,
361
362 mtx_unlock(&m->lock);
363 mtx_unlock(&m->qlock);
364
365 TAILQ_INSERT_TAIL(&midi_devs, m, link);
366
367 mtx_unlock(&midistat_lock);
368
369 m->dev = make_dev(&midi_cdevsw,
371 MIDIMKMINOR(unit, MIDI_DEV_RAW, channel),
372 UID_ROOT, GID_WHEEL, 0666, "midi%d.%d", unit, channel);
370 MIDIMKMINOR(unit, MIDI_DEV_RAW, channel),
371 UID_ROOT, GID_WHEEL, 0666, "midi%d.%d", unit, channel);
373 m->dev->si_drv1 = m;
374
375 return m;
376
377err2: mtx_destroy(&m->qlock);
378 mtx_destroy(&m->lock);
379
380 if (MIDIQ_BUF(m->inq))
372 m->dev->si_drv1 = m;
373
374 return m;
375
376err2: mtx_destroy(&m->qlock);
377 mtx_destroy(&m->lock);
378
379 if (MIDIQ_BUF(m->inq))
381 free(MIDIQ_BUF(m->inq), M_MIDI);
380 free(MIDIQ_BUF(m->inq), M_MIDI);
382 if (MIDIQ_BUF(m->outq))
381 if (MIDIQ_BUF(m->outq))
383 free(MIDIQ_BUF(m->outq), M_MIDI);
382 free(MIDIQ_BUF(m->outq), M_MIDI);
384err1: free(m, M_MIDI);
385err0: mtx_unlock(&midistat_lock);
386 MIDI_DEBUG(1, printf("midi_init ended in error\n"));
387 return NULL;
388}
389
390/*
391 * midi_uninit does not call MIDI_UNINIT, as since this is the implementors
392 * entry point. midi_unint if fact, does not send any methods. A call to
393 * midi_uninit is a defacto promise that you won't manipulate ch anymore
383err1: free(m, M_MIDI);
384err0: mtx_unlock(&midistat_lock);
385 MIDI_DEBUG(1, printf("midi_init ended in error\n"));
386 return NULL;
387}
388
389/*
390 * midi_uninit does not call MIDI_UNINIT, as since this is the implementors
391 * entry point. midi_unint if fact, does not send any methods. A call to
392 * midi_uninit is a defacto promise that you won't manipulate ch anymore
394 *
393 *
395 */
396
397int
394 */
395
396int
398midi_uninit(struct snd_midi * m)
397midi_uninit(struct snd_midi *m)
399{
398{
400 int err;
399 int err;
401
402 err = ENXIO;
403 mtx_lock(&midistat_lock);
404 mtx_lock(&m->lock);
405 if (m->busy) {
400
401 err = ENXIO;
402 mtx_lock(&midistat_lock);
403 mtx_lock(&m->lock);
404 if (m->busy) {
406 if (!(m->rchan || m->wchan))
407 goto err;
405 if (!(m->rchan || m->wchan))
406 goto err;
408
407
409 if (m->rchan) {
410 wakeup(&m->rchan);
411 m->rchan = 0;
412 }
413 if (m->wchan) {
414 wakeup(&m->wchan);
415 m->wchan = 0;
416 }
408 if (m->rchan) {
409 wakeup(&m->rchan);
410 m->rchan = 0;
411 }
412 if (m->wchan) {
413 wakeup(&m->wchan);
414 m->wchan = 0;
415 }
417 }
418 err = midi_destroy(m, 0);
416 }
417 err = midi_destroy(m, 0);
419 if(!err)
418 if (!err)
420 goto exit;
421
422err: mtx_unlock(&m->lock);
423exit: mtx_unlock(&midistat_lock);
424 return err;
425}
426
427/*
428 * midi_in: process all data until the queue is full, then discards the rest.
429 * Since midi_in is a state machine, data discards can cause it to get out of
430 * whack. Process as much as possible. It calls, wakeup, selnotify and
431 * psignal at most once.
432 */
433
434#ifdef notdef
419 goto exit;
420
421err: mtx_unlock(&m->lock);
422exit: mtx_unlock(&midistat_lock);
423 return err;
424}
425
426/*
427 * midi_in: process all data until the queue is full, then discards the rest.
428 * Since midi_in is a state machine, data discards can cause it to get out of
429 * whack. Process as much as possible. It calls, wakeup, selnotify and
430 * psignal at most once.
431 */
432
433#ifdef notdef
435static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0};
436#endif /* notdef */
434static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0};
435
436#endif /* notdef */
437/* Number of bytes in a MIDI command */
438#define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
439#define MIDI_ACK 0xfe
440#define MIDI_IS_STATUS(d) ((d) >= 0x80)
441#define MIDI_IS_COMMON(d) ((d) >= 0xf0)
442
443#define MIDI_SYSEX_START 0xF0
444#define MIDI_SYSEX_END 0xF7
445
446
447int
437/* Number of bytes in a MIDI command */
438#define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
439#define MIDI_ACK 0xfe
440#define MIDI_IS_STATUS(d) ((d) >= 0x80)
441#define MIDI_IS_COMMON(d) ((d) >= 0xf0)
442
443#define MIDI_SYSEX_START 0xF0
444#define MIDI_SYSEX_END 0xF7
445
446
447int
448midi_in(struct snd_midi * m, MIDI_TYPE * buf, int size)
448midi_in(struct snd_midi *m, MIDI_TYPE *buf, int size)
449{
450 /* int i, sig, enq; */
449{
450 /* int i, sig, enq; */
451 int used;
451 int used;
452
452 /* MIDI_TYPE data; */
453 MIDI_DEBUG(5, printf("midi_in: m=%p size=%d\n", m, size));
454
455/*
456 * XXX: locking flub
457 */
458 if (!(m->flags & M_RX))
453 /* MIDI_TYPE data; */
454 MIDI_DEBUG(5, printf("midi_in: m=%p size=%d\n", m, size));
455
456/*
457 * XXX: locking flub
458 */
459 if (!(m->flags & M_RX))
459 return size;
460 return size;
460
461 used = 0;
462
463 mtx_lock(&m->qlock);
464#if 0
465 /*
466 * Don't bother queuing if not in read mode. Discard everything and
467 * return size so the caller doesn't freak out.
468 */
469
470 if (!(m->flags & M_RX))
461
462 used = 0;
463
464 mtx_lock(&m->qlock);
465#if 0
466 /*
467 * Don't bother queuing if not in read mode. Discard everything and
468 * return size so the caller doesn't freak out.
469 */
470
471 if (!(m->flags & M_RX))
471 return size;
472 return size;
472
473 for (i = sig = 0; i < size; i++) {
474
473
474 for (i = sig = 0; i < size; i++) {
475
475 data = buf[i];
476 enq = 0;
477 if (data == MIDI_ACK)
478 continue;
476 data = buf[i];
477 enq = 0;
478 if (data == MIDI_ACK)
479 continue;
479
480
480 switch (m->inq_state) {
481 case MIDI_IN_START:
482 if (MIDI_IS_STATUS(data)) {
483 switch (data) {
484 case 0xf0: /* Sysex */
485 m->inq_state = MIDI_IN_SYSEX;
481 switch (m->inq_state) {
482 case MIDI_IN_START:
483 if (MIDI_IS_STATUS(data)) {
484 switch (data) {
485 case 0xf0: /* Sysex */
486 m->inq_state = MIDI_IN_SYSEX;
487 break;
488 case 0xf1: /* MTC quarter frame */
489 case 0xf3: /* Song select */
490 m->inq_state = MIDI_IN_DATA;
491 enq = 1;
492 m->inq_left = 1;
493 break;
494 case 0xf2: /* Song position pointer */
495 m->inq_state = MIDI_IN_DATA;
496 enq = 1;
497 m->inq_left = 2;
498 break;
499 default:
500 if (MIDI_IS_COMMON(data)) {
501 enq = 1;
502 sig = 1;
503 } else {
504 m->inq_state = MIDI_IN_DATA;
505 enq = 1;
506 m->inq_status = data;
507 m->inq_left = MIDI_LENGTH(data);
508 }
509 break;
510 }
511 } else if (MIDI_IS_STATUS(m->inq_status)) {
512 m->inq_state = MIDI_IN_DATA;
513 if (!MIDIQ_FULL(m->inq)) {
514 used++;
515 MIDIQ_ENQ(m->inq, &m->inq_status, 1);
516 }
517 enq = 1;
518 m->inq_left = MIDI_LENGTH(m->inq_status) - 1;
519 }
486 break;
520 break;
487 case 0xf1: /* MTC quarter frame */
488 case 0xf3: /* Song select */
489 m->inq_state = MIDI_IN_DATA;
521 /*
522 * End of case MIDI_IN_START:
523 */
524
525 case MIDI_IN_DATA:
490 enq = 1;
526 enq = 1;
491 m->inq_left = 1;
527 if (--m->inq_left <= 0)
528 sig = 1;/* deliver data */
492 break;
529 break;
493 case 0xf2: /* Song position pointer */
494 m->inq_state = MIDI_IN_DATA;
495 enq = 1;
496 m->inq_left = 2;
530 case MIDI_IN_SYSEX:
531 if (data == MIDI_SYSEX_END)
532 m->inq_state = MIDI_IN_START;
497 break;
533 break;
498 default:
499 if (MIDI_IS_COMMON(data)) {
500 enq = 1;
501 sig = 1;
502 } else {
503 m->inq_state = MIDI_IN_DATA;
504 enq = 1;
505 m->inq_status = data;
506 m->inq_left = MIDI_LENGTH(data);
507 }
508 break;
509 }
510 } else if (MIDI_IS_STATUS(m->inq_status)) {
511 m->inq_state = MIDI_IN_DATA;
512 if (!MIDIQ_FULL(m->inq)) {
513 used++;
514 MIDIQ_ENQ(m->inq, &m->inq_status, 1);
515 }
516 enq = 1;
517 m->inq_left = MIDI_LENGTH(m->inq_status) - 1;
518 }
534 }
519 break;
520 /*
521 * End of case MIDI_IN_START:
522 */
523
535
524 case MIDI_IN_DATA:
525 enq = 1;
526 if (--m->inq_left <= 0)
527 sig = 1; /* deliver data */
528 break;
529 case MIDI_IN_SYSEX:
530 if (data == MIDI_SYSEX_END)
531 m->inq_state = MIDI_IN_START;
532 break;
533 }
534
535 if (enq)
536 if (!MIDIQ_FULL(m->inq)) {
537 MIDIQ_ENQ(m->inq, &data, 1);
538 used++;
539 }
540 /*
541 * End of the state machines main "for loop"
542 */
536 if (enq)
537 if (!MIDIQ_FULL(m->inq)) {
538 MIDIQ_ENQ(m->inq, &data, 1);
539 used++;
540 }
541 /*
542 * End of the state machines main "for loop"
543 */
543 }
544 if (sig) {
545#endif
544 }
545 if (sig) {
546#endif
546 MIDI_DEBUG(6, printf("midi_in: len %jd avail %jd\n", (intmax_t)MIDIQ_LEN(m->inq), (intmax_t)MIDIQ_AVAIL(m->inq))) ;
547 if (MIDIQ_AVAIL(m->inq) > size) {
548 used=size;
549 MIDIQ_ENQ(m->inq, buf, size);
550 } else {
551 MIDI_DEBUG(4,printf("midi_in: Discarding data qu\n"));
552 mtx_unlock(&m->qlock);
553 return 0;
554 }
555 if (m->rchan) {
556 wakeup(&m->rchan);
557 m->rchan = 0;
558 }
559 selwakeup(&m->rsel);
560 if (m->async) {
561 PROC_LOCK(m->async);
562 psignal(m->async, SIGIO);
563 PROC_UNLOCK(m->async);
564 }
547 MIDI_DEBUG(6, printf("midi_in: len %jd avail %jd\n",
548 (intmax_t)MIDIQ_LEN(m->inq),
549 (intmax_t)MIDIQ_AVAIL(m->inq)));
550 if (MIDIQ_AVAIL(m->inq) > size) {
551 used = size;
552 MIDIQ_ENQ(m->inq, buf, size);
553 } else {
554 MIDI_DEBUG(4, printf("midi_in: Discarding data qu\n"));
555 mtx_unlock(&m->qlock);
556 return 0;
557 }
558 if (m->rchan) {
559 wakeup(&m->rchan);
560 m->rchan = 0;
561 }
562 selwakeup(&m->rsel);
563 if (m->async) {
564 PROC_LOCK(m->async);
565 psignal(m->async, SIGIO);
566 PROC_UNLOCK(m->async);
567 }
565#if 0
566 }
567#endif
568 mtx_unlock(&m->qlock);
569 return used;
570}
571
572/*
573 * midi_out: The only clearer of the M_TXEN flag.
574 */
575int
568#if 0
569 }
570#endif
571 mtx_unlock(&m->qlock);
572 return used;
573}
574
575/*
576 * midi_out: The only clearer of the M_TXEN flag.
577 */
578int
576midi_out(struct snd_midi * m, MIDI_TYPE * buf, int size)
579midi_out(struct snd_midi *m, MIDI_TYPE *buf, int size)
577{
580{
578 int used;
581 int used;
579
580/*
581 * XXX: locking flub
582 */
583 if (!(m->flags & M_TXEN))
584 return 0;
585
582
583/*
584 * XXX: locking flub
585 */
586 if (!(m->flags & M_TXEN))
587 return 0;
588
586 MIDI_DEBUG(2, printf("midi_out: %p\n", m));
589 MIDI_DEBUG(2, printf("midi_out: %p\n", m));
587 mtx_lock(&m->qlock);
588 used = MIN(size, MIDIQ_LEN(m->outq));
589 MIDI_DEBUG(3, printf("midi_out: used %d\n", used));
590 if (used)
590 mtx_lock(&m->qlock);
591 used = MIN(size, MIDIQ_LEN(m->outq));
592 MIDI_DEBUG(3, printf("midi_out: used %d\n", used));
593 if (used)
591 MIDIQ_DEQ(m->outq, buf, used);
594 MIDIQ_DEQ(m->outq, buf, used);
592 if (MIDIQ_EMPTY(m->outq)) {
595 if (MIDIQ_EMPTY(m->outq)) {
593 m->flags &= ~M_TXEN;
594 MPU_CALLBACKP(m, m->cookie, m->flags);
596 m->flags &= ~M_TXEN;
597 MPU_CALLBACKP(m, m->cookie, m->flags);
595 }
598 }
596 if (used && MIDIQ_AVAIL(m->outq) > m->hiwat ) {
599 if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) {
597 if (m->wchan) {
598 wakeup(&m->wchan);
599 m->wchan = 0;
600 }
601 selwakeup(&m->wsel);
600 if (m->wchan) {
601 wakeup(&m->wchan);
602 m->wchan = 0;
603 }
604 selwakeup(&m->wsel);
602 if (m->async) {
605 if (m->async) {
603 PROC_LOCK(m->async);
604 psignal(m->async, SIGIO);
605 PROC_UNLOCK(m->async);
606 }
607 }
608 mtx_unlock(&m->qlock);
609 return used;
610}
611
612
613/*
614 * /dev/rmidi#.# device access functions
615 */
616int
606 PROC_LOCK(m->async);
607 psignal(m->async, SIGIO);
608 PROC_UNLOCK(m->async);
609 }
610 }
611 mtx_unlock(&m->qlock);
612 return used;
613}
614
615
616/*
617 * /dev/rmidi#.# device access functions
618 */
619int
617midi_open(struct cdev *i_dev, int flags, int mode, struct thread * td)
620midi_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
618{
619 struct snd_midi *m = i_dev->si_drv1;
621{
622 struct snd_midi *m = i_dev->si_drv1;
620 int retval;
623 int retval;
621
624
622 MIDI_DEBUG(1,printf("midiopen %p %s %s\n", td,
623 flags & FREAD?"M_RX":"", flags & FWRITE?"M_TX":""));
625 MIDI_DEBUG(1, printf("midiopen %p %s %s\n", td,
626 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
624 if (m == NULL)
627 if (m == NULL)
625 return ENXIO;
628 return ENXIO;
626
627 mtx_lock(&m->lock);
628 mtx_lock(&m->qlock);
629
630 retval = 0;
631
632 if (flags & FREAD) {
629
630 mtx_lock(&m->lock);
631 mtx_lock(&m->qlock);
632
633 retval = 0;
634
635 if (flags & FREAD) {
633 if (MIDIQ_SIZE(m->inq) == 0)
634 retval = ENXIO;
635 else if (m->flags & M_RX)
636 retval = EBUSY;
637 if (retval)
638 goto err;
636 if (MIDIQ_SIZE(m->inq) == 0)
637 retval = ENXIO;
638 else if (m->flags & M_RX)
639 retval = EBUSY;
640 if (retval)
641 goto err;
639 }
640 if (flags & FWRITE) {
642 }
643 if (flags & FWRITE) {
641 if (MIDIQ_SIZE(m->outq) == 0)
642 retval = ENXIO;
643 else if (m->flags & M_TX)
644 retval = EBUSY;
645 if (retval)
646 goto err;
644 if (MIDIQ_SIZE(m->outq) == 0)
645 retval = ENXIO;
646 else if (m->flags & M_TX)
647 retval = EBUSY;
648 if (retval)
649 goto err;
647 }
648 m->busy++;
649
650 m->rchan = 0;
651 m->wchan = 0;
652 m->async = 0;
653
654 if (flags & FREAD) {
650 }
651 m->busy++;
652
653 m->rchan = 0;
654 m->wchan = 0;
655 m->async = 0;
656
657 if (flags & FREAD) {
655 m->flags |= M_RX | M_RXEN;
656 /*
657 * Only clear the inq, the outq might still have data to drain from
658 * a previous session
659 */
660 MIDIQ_CLEAR(m->inq);
658 m->flags |= M_RX | M_RXEN;
659 /*
660 * Only clear the inq, the outq might still have data to drain
661 * from a previous session
662 */
663 MIDIQ_CLEAR(m->inq);
661 };
662
663 if (flags & FWRITE)
664 };
665
666 if (flags & FWRITE)
664 m->flags |= M_TX;
667 m->flags |= M_TX;
665
666 MPU_CALLBACK(m, m->cookie, m->flags);
667
668 MIDI_DEBUG(2, printf("midi_open: opened.\n"));
669
670err: mtx_unlock(&m->qlock);
671 mtx_unlock(&m->lock);
672 return retval;
673}
674
675int
668
669 MPU_CALLBACK(m, m->cookie, m->flags);
670
671 MIDI_DEBUG(2, printf("midi_open: opened.\n"));
672
673err: mtx_unlock(&m->qlock);
674 mtx_unlock(&m->lock);
675 return retval;
676}
677
678int
676midi_close(struct cdev *i_dev, int flags, int mode, struct thread * td)
679midi_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
677{
678 struct snd_midi *m = i_dev->si_drv1;
680{
681 struct snd_midi *m = i_dev->si_drv1;
679 int retval;
680 int oldflags;
682 int retval;
683 int oldflags;
681
682 MIDI_DEBUG(1, printf("midi_close %p %s %s\n", td,
684
685 MIDI_DEBUG(1, printf("midi_close %p %s %s\n", td,
683 flags & FREAD?"M_RX":"", flags & FWRITE?"M_TX":""));
686 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
684
685 if (m == NULL)
687
688 if (m == NULL)
686 return ENXIO;
689 return ENXIO;
687
688 mtx_lock(&m->lock);
689 mtx_lock(&m->qlock);
690
690
691 mtx_lock(&m->lock);
692 mtx_lock(&m->qlock);
693
691 if ( (flags & FREAD && !(m->flags & M_RX)) ||
692 (flags & FWRITE && !(m->flags & M_TX)) ) {
693 retval = ENXIO;
694 goto err;
694 if ((flags & FREAD && !(m->flags & M_RX)) ||
695 (flags & FWRITE && !(m->flags & M_TX))) {
696 retval = ENXIO;
697 goto err;
695 }
698 }
696
697 m->busy--;
698
699 oldflags = m->flags;
700
701 if (flags & FREAD)
699 m->busy--;
700
701 oldflags = m->flags;
702
703 if (flags & FREAD)
702 m->flags &= ~(M_RX | M_RXEN);
704 m->flags &= ~(M_RX | M_RXEN);
703 if (flags & FWRITE)
705 if (flags & FWRITE)
704 m->flags &= ~M_TX;
706 m->flags &= ~M_TX;
705
707
706 if( (m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)) )
708 if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)))
707 MPU_CALLBACK(m, m->cookie, m->flags);
708
709 MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy));
710
711 mtx_unlock(&m->qlock);
712 mtx_unlock(&m->lock);
713 retval = 0;
714err: return retval;
715}
709 MPU_CALLBACK(m, m->cookie, m->flags);
710
711 MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy));
712
713 mtx_unlock(&m->qlock);
714 mtx_unlock(&m->lock);
715 retval = 0;
716err: return retval;
717}
718
716/*
719/*
717 * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon as data is available.
720 * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon
721 * as data is available.
718 */
719int
722 */
723int
720midi_read(struct cdev *i_dev, struct uio * uio, int ioflag)
724midi_read(struct cdev *i_dev, struct uio *uio, int ioflag)
721{
722#define MIDI_RSIZE 32
723 struct snd_midi *m = i_dev->si_drv1;
725{
726#define MIDI_RSIZE 32
727 struct snd_midi *m = i_dev->si_drv1;
724 int retval;
725 int used;
726 char buf[MIDI_RSIZE];
728 int retval;
729 int used;
730 char buf[MIDI_RSIZE];
727
731
728 MIDI_DEBUG(5, printf("midiread: count=%lu\n", (unsigned long)uio->uio_resid));
732 MIDI_DEBUG(5, printf("midiread: count=%lu\n",
733 (unsigned long)uio->uio_resid));
729
730 retval = EIO;
731
732 if (m == NULL)
734
735 retval = EIO;
736
737 if (m == NULL)
733 goto err0;
738 goto err0;
734
735 mtx_lock(&m->lock);
736 mtx_lock(&m->qlock);
737
738 if (!(m->flags & M_RX))
739
740 mtx_lock(&m->lock);
741 mtx_lock(&m->qlock);
742
743 if (!(m->flags & M_RX))
739 goto err1;
744 goto err1;
740
741 while (uio->uio_resid > 0) {
745
746 while (uio->uio_resid > 0) {
742 while (MIDIQ_EMPTY(m->inq)) {
743 retval = EWOULDBLOCK;
744 if (ioflag & O_NONBLOCK)
745 goto err1;
746 mtx_unlock(&m->lock);
747 m->rchan = 1;
748 retval = msleep(&m->rchan, &m->qlock,
749 PCATCH | PDROP, "midi RX", 0);
750 /*
751 * We slept, maybe things have changed since last
752 * dying check
753 */
754 if (retval == EINTR)
755 goto err0;
756 if (m != i_dev->si_drv1)
757 retval = ENXIO;
758 /* if (retval && retval != ERESTART) */
759 if (retval)
760 goto err0;
761 mtx_lock(&m->lock);
762 mtx_lock(&m->qlock);
763 m->rchan = 0;
764 if (!m->busy)
765 goto err1;
766 }
747 while (MIDIQ_EMPTY(m->inq)) {
748 retval = EWOULDBLOCK;
749 if (ioflag & O_NONBLOCK)
750 goto err1;
751 mtx_unlock(&m->lock);
752 m->rchan = 1;
753 retval = msleep(&m->rchan, &m->qlock,
754 PCATCH | PDROP, "midi RX", 0);
755 /*
756 * We slept, maybe things have changed since last
757 * dying check
758 */
759 if (retval == EINTR)
760 goto err0;
761 if (m != i_dev->si_drv1)
762 retval = ENXIO;
763 /* if (retval && retval != ERESTART) */
764 if (retval)
765 goto err0;
766 mtx_lock(&m->lock);
767 mtx_lock(&m->qlock);
768 m->rchan = 0;
769 if (!m->busy)
770 goto err1;
771 }
767 MIDI_DEBUG(6, printf("midi_read start\n"));
772 MIDI_DEBUG(6, printf("midi_read start\n"));
768 /*
769 * At this point, it is certain that m->inq has data
770 */
773 /*
774 * At this point, it is certain that m->inq has data
775 */
771
776
772 used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid);
773 used = MIN(used, MIDI_RSIZE);
777 used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid);
778 used = MIN(used, MIDI_RSIZE);
774
779
775 MIDI_DEBUG(6,printf("midiread: uiomove cc=%d\n", used));
776 MIDIQ_DEQ(m->inq, buf, used);
777 retval = uiomove(buf, used, uio);
778 if (retval)
779 goto err1;
780 MIDI_DEBUG(6, printf("midiread: uiomove cc=%d\n", used));
781 MIDIQ_DEQ(m->inq, buf, used);
782 retval = uiomove(buf, used, uio);
783 if (retval)
784 goto err1;
780 }
781
782 /*
783 * If we Made it here then transfer is good
784 */
785 retval = 0;
786err1: mtx_unlock(&m->qlock);
787 mtx_unlock(&m->lock);
785 }
786
787 /*
788 * If we Made it here then transfer is good
789 */
790 retval = 0;
791err1: mtx_unlock(&m->qlock);
792 mtx_unlock(&m->lock);
788err0: MIDI_DEBUG(4, printf("midi_read: ret %d\n",retval));
793err0: MIDI_DEBUG(4, printf("midi_read: ret %d\n", retval));
789 return retval;
790}
791
792/*
793 * midi_write: The only setter of M_TXEN
794 */
795
796int
794 return retval;
795}
796
797/*
798 * midi_write: The only setter of M_TXEN
799 */
800
801int
797midi_write(struct cdev *i_dev, struct uio * uio, int ioflag)
802midi_write(struct cdev *i_dev, struct uio *uio, int ioflag)
798{
799#define MIDI_WSIZE 32
800 struct snd_midi *m = i_dev->si_drv1;
803{
804#define MIDI_WSIZE 32
805 struct snd_midi *m = i_dev->si_drv1;
801 int retval;
802 int used;
803 char buf[MIDI_WSIZE];
806 int retval;
807 int used;
808 char buf[MIDI_WSIZE];
804
805
809
810
806 MIDI_DEBUG(4, printf("midi_write\n"));
811 MIDI_DEBUG(4, printf("midi_write\n"));
807 retval = 0;
808 if (m == NULL)
812 retval = 0;
813 if (m == NULL)
809 goto err0;
814 goto err0;
810
811 mtx_lock(&m->lock);
812 mtx_lock(&m->qlock);
813
814 if (!(m->flags & M_TX))
815
816 mtx_lock(&m->lock);
817 mtx_lock(&m->qlock);
818
819 if (!(m->flags & M_TX))
815 goto err1;
820 goto err1;
816
817 while (uio->uio_resid > 0) {
821
822 while (uio->uio_resid > 0) {
818 while (MIDIQ_AVAIL(m->outq) == 0) {
819 retval = EWOULDBLOCK;
820 if (ioflag & O_NONBLOCK)
821 goto err1;
822 mtx_unlock(&m->lock);
823 m->wchan = 1;
824 MIDI_DEBUG(3,printf("midi_write msleep\n"));
825 retval = msleep(&m->wchan, &m->qlock,
826 PCATCH | PDROP, "midi TX", 0);
823 while (MIDIQ_AVAIL(m->outq) == 0) {
824 retval = EWOULDBLOCK;
825 if (ioflag & O_NONBLOCK)
826 goto err1;
827 mtx_unlock(&m->lock);
828 m->wchan = 1;
829 MIDI_DEBUG(3, printf("midi_write msleep\n"));
830 retval = msleep(&m->wchan, &m->qlock,
831 PCATCH | PDROP, "midi TX", 0);
832 /*
833 * We slept, maybe things have changed since last
834 * dying check
835 */
836 if (retval == EINTR)
837 goto err0;
838 if (m != i_dev->si_drv1)
839 retval = ENXIO;
840 if (retval)
841 goto err0;
842 mtx_lock(&m->lock);
843 mtx_lock(&m->qlock);
844 m->wchan = 0;
845 if (!m->busy)
846 goto err1;
847 }
848
827 /*
849 /*
828 * We slept, maybe things have changed since last
829 * dying check
830 */
831 if (retval == EINTR)
832 goto err0;
833 if (m != i_dev->si_drv1)
834 retval = ENXIO;
835 if (retval)
836 goto err0;
837 mtx_lock(&m->lock);
838 mtx_lock(&m->qlock);
839 m->wchan = 0;
840 if (!m->busy)
841 goto err1;
842 }
850 * We are certain than data can be placed on the queue
851 */
843
852
844 /*
845 * We are certain than data can be placed on the queue
846 */
853 used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid);
854 used = MIN(used, MIDI_WSIZE);
855 MIDI_DEBUG(5, printf("midiout: resid %d len %jd avail %jd\n",
856 uio->uio_resid, (intmax_t)MIDIQ_LEN(m->outq),
857 (intmax_t)MIDIQ_AVAIL(m->outq)));
847
858
848 used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid);
849 used = MIN(used, MIDI_WSIZE);
850 MIDI_DEBUG(5,printf("midiout: resid %d len %jd avail %jd\n", uio->uio_resid, (intmax_t)MIDIQ_LEN(m->outq), (intmax_t)MIDIQ_AVAIL(m->outq)));
851
859
852
853 MIDI_DEBUG(5,printf("midi_write: uiomove cc=%d\n", used));
854 retval = uiomove(buf, used, uio);
855 if (retval)
856 goto err1;
857 MIDIQ_ENQ(m->outq, buf, used);
858 /*
859 * Inform the bottom half that data can be written
860 */
861 if (!(m->flags & M_TXEN)) {
862 m->flags |= M_TXEN;
863 MPU_CALLBACK(m, m->cookie, m->flags);
864 }
860 MIDI_DEBUG(5, printf("midi_write: uiomove cc=%d\n", used));
861 retval = uiomove(buf, used, uio);
862 if (retval)
863 goto err1;
864 MIDIQ_ENQ(m->outq, buf, used);
865 /*
866 * Inform the bottom half that data can be written
867 */
868 if (!(m->flags & M_TXEN)) {
869 m->flags |= M_TXEN;
870 MPU_CALLBACK(m, m->cookie, m->flags);
871 }
865 }
866 /*
867 * If we Made it here then transfer is good
868 */
869 retval = 0;
870err1: mtx_unlock(&m->qlock);
871 mtx_unlock(&m->lock);
872err0: return retval;
873}
874
875int
872 }
873 /*
874 * If we Made it here then transfer is good
875 */
876 retval = 0;
877err1: mtx_unlock(&m->qlock);
878 mtx_unlock(&m->lock);
879err0: return retval;
880}
881
882int
876midi_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread * td)
883midi_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
884 struct thread *td)
877{
878 return ENXIO;
879}
880
881int
885{
886 return ENXIO;
887}
888
889int
882midi_poll(struct cdev *i_dev, int events, struct thread * td)
890midi_poll(struct cdev *i_dev, int events, struct thread *td)
883{
884 struct snd_midi *m = i_dev->si_drv1;
891{
892 struct snd_midi *m = i_dev->si_drv1;
885 int revents;
893 int revents;
886
887 if (m == NULL)
894
895 if (m == NULL)
888 return 0;
896 return 0;
889
890 revents = 0;
891
892 mtx_lock(&m->lock);
893 mtx_lock(&m->qlock);
894
895 if (events & (POLLIN | POLLRDNORM))
897
898 revents = 0;
899
900 mtx_lock(&m->lock);
901 mtx_lock(&m->qlock);
902
903 if (events & (POLLIN | POLLRDNORM))
896 if (!MIDIQ_EMPTY(m->inq))
897 events |= events & (POLLIN | POLLRDNORM);
904 if (!MIDIQ_EMPTY(m->inq))
905 events |= events & (POLLIN | POLLRDNORM);
898
899 if (events & (POLLOUT | POLLWRNORM))
906
907 if (events & (POLLOUT | POLLWRNORM))
900 if (MIDIQ_AVAIL(m->outq) < m->hiwat)
901 events |= events & (POLLOUT | POLLWRNORM);
908 if (MIDIQ_AVAIL(m->outq) < m->hiwat)
909 events |= events & (POLLOUT | POLLWRNORM);
902
903 if (revents == 0) {
910
911 if (revents == 0) {
904 if (events & (POLLIN | POLLRDNORM))
905 selrecord(td, &m->rsel);
912 if (events & (POLLIN | POLLRDNORM))
913 selrecord(td, &m->rsel);
906
914
907 if (events & (POLLOUT | POLLWRNORM))
908 selrecord(td, &m->wsel);
915 if (events & (POLLOUT | POLLWRNORM))
916 selrecord(td, &m->wsel);
909 }
910 mtx_unlock(&m->lock);
911 mtx_unlock(&m->qlock);
912
913 return (revents);
914}
915
916/*
917 * /dev/midistat device functions
917 }
918 mtx_unlock(&m->lock);
919 mtx_unlock(&m->qlock);
920
921 return (revents);
922}
923
924/*
925 * /dev/midistat device functions
918 *
926 *
919 */
920static int
927 */
928static int
921midistat_open(struct cdev *i_dev, int flags, int mode, struct thread * td)
929midistat_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
922{
930{
923 int error;
931 int error;
924
932
925 MIDI_DEBUG(1,printf("midistat_open\n"));
933 MIDI_DEBUG(1, printf("midistat_open\n"));
926 mtx_lock(&midistat_lock);
927
928 if (midistat_isopen) {
934 mtx_lock(&midistat_lock);
935
936 if (midistat_isopen) {
929 mtx_unlock(&midistat_lock);
930 return EBUSY;
937 mtx_unlock(&midistat_lock);
938 return EBUSY;
931 }
932 midistat_isopen = 1;
933 mtx_unlock(&midistat_lock);
934
935 if (sbuf_new(&midistat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) {
939 }
940 midistat_isopen = 1;
941 mtx_unlock(&midistat_lock);
942
943 if (sbuf_new(&midistat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) {
936 error = ENXIO;
937 mtx_lock(&midistat_lock);
938 goto out;
944 error = ENXIO;
945 mtx_lock(&midistat_lock);
946 goto out;
939 }
947 }
940
941 mtx_lock(&midistat_lock);
942 midistat_bufptr = 0;
943 error = (midistat_prepare(&midistat_sbuf) > 0) ? 0 : ENOMEM;
944
945out: if (error)
948 mtx_lock(&midistat_lock);
949 midistat_bufptr = 0;
950 error = (midistat_prepare(&midistat_sbuf) > 0) ? 0 : ENOMEM;
951
952out: if (error)
946 midistat_isopen = 0;
953 midistat_isopen = 0;
947 mtx_unlock(&midistat_lock);
948 return error;
949}
950
951static int
954 mtx_unlock(&midistat_lock);
955 return error;
956}
957
958static int
952midistat_close(struct cdev *i_dev, int flags, int mode, struct thread * td)
959midistat_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
953{
960{
954 MIDI_DEBUG(1,printf("midistat_close\n"));
961 MIDI_DEBUG(1, printf("midistat_close\n"));
955 mtx_lock(&midistat_lock);
956 if (!midistat_isopen) {
962 mtx_lock(&midistat_lock);
963 if (!midistat_isopen) {
957 mtx_unlock(&midistat_lock);
958 return EBADF;
964 mtx_unlock(&midistat_lock);
965 return EBADF;
959 }
960 sbuf_delete(&midistat_sbuf);
961 midistat_isopen = 0;
962
963 mtx_unlock(&midistat_lock);
964 return 0;
965}
966
967static int
966 }
967 sbuf_delete(&midistat_sbuf);
968 midistat_isopen = 0;
969
970 mtx_unlock(&midistat_lock);
971 return 0;
972}
973
974static int
968midistat_read(struct cdev *i_dev, struct uio * buf, int flag)
975midistat_read(struct cdev *i_dev, struct uio *buf, int flag)
969{
976{
970 int l, err;
977 int l, err;
971
978
972 MIDI_DEBUG(4,printf("midistat_read\n"));
979 MIDI_DEBUG(4, printf("midistat_read\n"));
973 mtx_lock(&midistat_lock);
974 if (!midistat_isopen) {
980 mtx_lock(&midistat_lock);
981 if (!midistat_isopen) {
975 mtx_unlock(&midistat_lock);
976 return EBADF;
982 mtx_unlock(&midistat_lock);
983 return EBADF;
977 }
978 l = min(buf->uio_resid, sbuf_len(&midistat_sbuf) - midistat_bufptr);
979 err = 0;
980 if (l > 0) {
984 }
985 l = min(buf->uio_resid, sbuf_len(&midistat_sbuf) - midistat_bufptr);
986 err = 0;
987 if (l > 0) {
981 mtx_unlock(&midistat_lock);
982 err = uiomove(sbuf_data(&midistat_sbuf) + midistat_bufptr, l, buf);
983 mtx_lock(&midistat_lock);
988 mtx_unlock(&midistat_lock);
989 err = uiomove(sbuf_data(&midistat_sbuf) + midistat_bufptr, l,
990 buf);
991 mtx_lock(&midistat_lock);
984 } else
992 } else
985 l = 0;
993 l = 0;
986 midistat_bufptr += l;
987 mtx_unlock(&midistat_lock);
988 return err;
989}
990
991/*
992 * Module library functions
993 */
994
995static int
994 midistat_bufptr += l;
995 mtx_unlock(&midistat_lock);
996 return err;
997}
998
999/*
1000 * Module library functions
1001 */
1002
1003static int
996midistat_prepare(struct sbuf * s)
1004midistat_prepare(struct sbuf *s)
997{
998 struct snd_midi *m;
999
1000 mtx_assert(&midistat_lock, MA_OWNED);
1001
1002 sbuf_printf(s, "FreeBSD Midi Driver (midi2)\n");
1003 if (TAILQ_EMPTY(&midi_devs)) {
1005{
1006 struct snd_midi *m;
1007
1008 mtx_assert(&midistat_lock, MA_OWNED);
1009
1010 sbuf_printf(s, "FreeBSD Midi Driver (midi2)\n");
1011 if (TAILQ_EMPTY(&midi_devs)) {
1004 sbuf_printf(s, "No devices installed.\n");
1005 sbuf_finish(s);
1006 return sbuf_len(s);
1012 sbuf_printf(s, "No devices installed.\n");
1013 sbuf_finish(s);
1014 return sbuf_len(s);
1007 }
1008 sbuf_printf(s, "Installed devices:\n");
1009
1010 TAILQ_FOREACH(m, &midi_devs, link) {
1015 }
1016 sbuf_printf(s, "Installed devices:\n");
1017
1018 TAILQ_FOREACH(m, &midi_devs, link) {
1011 mtx_lock(&m->lock);
1012 sbuf_printf(s, "%s [%d/%d:%s]", m->name, m->unit, m->channel,
1019 mtx_lock(&m->lock);
1020 sbuf_printf(s, "%s [%d/%d:%s]", m->name, m->unit, m->channel,
1013 MPU_PROVIDER(m, m->cookie));
1021 MPU_PROVIDER(m, m->cookie));
1014 sbuf_printf(s, "%s", MPU_DESCR(m, m->cookie, midistat_verbose));
1015 sbuf_printf(s, "\n");
1016 mtx_unlock(&m->lock);
1022 sbuf_printf(s, "%s", MPU_DESCR(m, m->cookie, midistat_verbose));
1023 sbuf_printf(s, "\n");
1024 mtx_unlock(&m->lock);
1017 }
1018
1019 sbuf_finish(s);
1020 return sbuf_len(s);
1021}
1022
1023#ifdef notdef
1024/*
1025 * Convert IOCTL command to string for debugging
1026 */
1027
1025 }
1026
1027 sbuf_finish(s);
1028 return sbuf_len(s);
1029}
1030
1031#ifdef notdef
1032/*
1033 * Convert IOCTL command to string for debugging
1034 */
1035
1028static char *
1036static char *
1029midi_cmdname(int cmd)
1030{
1031 static struct {
1037midi_cmdname(int cmd)
1038{
1039 static struct {
1032 int cmd;
1033 char *name;
1034 } *tab, cmdtab_midiioctl[] = {
1040 int cmd;
1041 char *name;
1042 } *tab, cmdtab_midiioctl[] = {
1035#define A(x) {x, ## x}
1043#define A(x) {x, ## x}
1036 /*
1037 * Once we have some real IOCTLs define, the following will
1038 * be relavant.
1039 *
1040 * A(SNDCTL_MIDI_PRETIME), A(SNDCTL_MIDI_MPUMODE),
1041 * A(SNDCTL_MIDI_MPUCMD), A(SNDCTL_SYNTH_INFO),
1042 * A(SNDCTL_MIDI_INFO), A(SNDCTL_SYNTH_MEMAVL),
1043 * A(SNDCTL_FM_LOAD_INSTR), A(SNDCTL_FM_4OP_ENABLE),
1044 * A(MIOSPASSTHRU), A(MIOGPASSTHRU), A(AIONWRITE),
1045 * A(AIOGSIZE), A(AIOSSIZE), A(AIOGFMT), A(AIOSFMT),
1046 * A(AIOGMIX), A(AIOSMIX), A(AIOSTOP), A(AIOSYNC),
1047 * A(AIOGCAP),
1048 */
1044 /*
1045 * Once we have some real IOCTLs define, the following will
1046 * be relavant.
1047 *
1048 * A(SNDCTL_MIDI_PRETIME), A(SNDCTL_MIDI_MPUMODE),
1049 * A(SNDCTL_MIDI_MPUCMD), A(SNDCTL_SYNTH_INFO),
1050 * A(SNDCTL_MIDI_INFO), A(SNDCTL_SYNTH_MEMAVL),
1051 * A(SNDCTL_FM_LOAD_INSTR), A(SNDCTL_FM_4OP_ENABLE),
1052 * A(MIOSPASSTHRU), A(MIOGPASSTHRU), A(AIONWRITE),
1053 * A(AIOGSIZE), A(AIOSSIZE), A(AIOGFMT), A(AIOSFMT),
1054 * A(AIOGMIX), A(AIOSMIX), A(AIOSTOP), A(AIOSYNC),
1055 * A(AIOGCAP),
1056 */
1049#undef A
1057#undef A
1050 {
1051 -1, "unknown"
1052 },
1058 {
1059 -1, "unknown"
1060 },
1053 };
1054
1061 };
1062
1055 for (tab = cmdtab_midiioctl; tab->cmd != cmd && tab->cmd != -1; tab++)
1056 ;
1063 for (tab = cmdtab_midiioctl; tab->cmd != cmd && tab->cmd != -1; tab++);
1057 return tab->name;
1058}
1064 return tab->name;
1065}
1059#endif /* notdef */
1060
1066
1067#endif /* notdef */
1068
1061/*
1062 * midisynth
1063 */
1064
1065
1066int
1067midisynth_open(void *n, void *arg, int flags)
1068{
1069/*
1070 * midisynth
1071 */
1072
1073
1074int
1075midisynth_open(void *n, void *arg, int flags)
1076{
1069 struct snd_midi *m = ((struct synth_midi * ) n)->m;
1070 int retval;
1077 struct snd_midi *m = ((struct synth_midi *)n)->m;
1078 int retval;
1071
1079
1072 MIDI_DEBUG(1,printf("midisynth_open %s %s\n",
1073 flags & FREAD?"M_RX":"", flags & FWRITE?"M_TX":""));
1080 MIDI_DEBUG(1, printf("midisynth_open %s %s\n",
1081 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
1074
1075 if (m == NULL)
1082
1083 if (m == NULL)
1076 return ENXIO;
1084 return ENXIO;
1077
1078 mtx_lock(&m->lock);
1079 mtx_lock(&m->qlock);
1080
1081 retval = 0;
1082
1083 if (flags & FREAD) {
1085
1086 mtx_lock(&m->lock);
1087 mtx_lock(&m->qlock);
1088
1089 retval = 0;
1090
1091 if (flags & FREAD) {
1084 if (MIDIQ_SIZE(m->inq) == 0)
1085 retval = ENXIO;
1086 else if (m->flags & M_RX)
1087 retval = EBUSY;
1088 if (retval)
1089 goto err;
1092 if (MIDIQ_SIZE(m->inq) == 0)
1093 retval = ENXIO;
1094 else if (m->flags & M_RX)
1095 retval = EBUSY;
1096 if (retval)
1097 goto err;
1090 }
1091 if (flags & FWRITE) {
1098 }
1099 if (flags & FWRITE) {
1092 if (MIDIQ_SIZE(m->outq) == 0)
1093 retval = ENXIO;
1094 else if (m->flags & M_TX)
1095 retval = EBUSY;
1096 if (retval)
1097 goto err;
1100 if (MIDIQ_SIZE(m->outq) == 0)
1101 retval = ENXIO;
1102 else if (m->flags & M_TX)
1103 retval = EBUSY;
1104 if (retval)
1105 goto err;
1098 }
1099 m->busy++;
1100
1101 /*
1102 * TODO: Consider m->async = 0;
1103 */
1104
1105 if (flags & FREAD) {
1106 }
1107 m->busy++;
1108
1109 /*
1110 * TODO: Consider m->async = 0;
1111 */
1112
1113 if (flags & FREAD) {
1106 m->flags |= M_RX | M_RXEN;
1107 /*
1108 * Only clear the inq, the outq might still have data to drain from
1109 * a previous session
1110 */
1111 MIDIQ_CLEAR(m->inq);
1112 m->rchan = 0;
1114 m->flags |= M_RX | M_RXEN;
1115 /*
1116 * Only clear the inq, the outq might still have data to drain
1117 * from a previous session
1118 */
1119 MIDIQ_CLEAR(m->inq);
1120 m->rchan = 0;
1113 };
1114
1115 if (flags & FWRITE) {
1121 };
1122
1123 if (flags & FWRITE) {
1116 m->flags |= M_TX;
1117 m->wchan = 0;
1124 m->flags |= M_TX;
1125 m->wchan = 0;
1118 }
1126 }
1119
1120 m->synth_flags = flags & (FREAD | FWRITE);
1127 m->synth_flags = flags & (FREAD | FWRITE);
1121
1128
1122 MPU_CALLBACK(m, m->cookie, m->flags);
1123
1124
1125err: mtx_unlock(&m->qlock);
1126 mtx_unlock(&m->lock);
1127 MIDI_DEBUG(2, printf("midisynth_open: return %d.\n", retval));
1128 return retval;
1129}
1130
1131int
1132midisynth_close(void *n)
1133{
1134 struct snd_midi *m = ((struct synth_midi *)n)->m;
1129 MPU_CALLBACK(m, m->cookie, m->flags);
1130
1131
1132err: mtx_unlock(&m->qlock);
1133 mtx_unlock(&m->lock);
1134 MIDI_DEBUG(2, printf("midisynth_open: return %d.\n", retval));
1135 return retval;
1136}
1137
1138int
1139midisynth_close(void *n)
1140{
1141 struct snd_midi *m = ((struct synth_midi *)n)->m;
1135 int retval;
1136 int oldflags;
1142 int retval;
1143 int oldflags;
1137
1138 MIDI_DEBUG(1, printf("midisynth_close %s %s\n",
1144
1145 MIDI_DEBUG(1, printf("midisynth_close %s %s\n",
1139 m->synth_flags & FREAD ? "M_RX" : "",
1140 m->synth_flags & FWRITE ? "M_TX" : ""));
1146 m->synth_flags & FREAD ? "M_RX" : "",
1147 m->synth_flags & FWRITE ? "M_TX" : ""));
1141
1142 if (m == NULL)
1148
1149 if (m == NULL)
1143 return ENXIO;
1150 return ENXIO;
1144
1145 mtx_lock(&m->lock);
1146 mtx_lock(&m->qlock);
1147
1151
1152 mtx_lock(&m->lock);
1153 mtx_lock(&m->qlock);
1154
1148 if ( (m->synth_flags & FREAD && !(m->flags & M_RX)) ||
1149 (m->synth_flags & FWRITE && !(m->flags & M_TX)) ) {
1150 retval = ENXIO;
1151 goto err;
1155 if ((m->synth_flags & FREAD && !(m->flags & M_RX)) ||
1156 (m->synth_flags & FWRITE && !(m->flags & M_TX))) {
1157 retval = ENXIO;
1158 goto err;
1152 }
1159 }
1153
1154 m->busy--;
1155
1156 oldflags = m->flags;
1157
1158 if (m->synth_flags & FREAD)
1160 m->busy--;
1161
1162 oldflags = m->flags;
1163
1164 if (m->synth_flags & FREAD)
1159 m->flags &= ~(M_RX | M_RXEN);
1165 m->flags &= ~(M_RX | M_RXEN);
1160 if (m->synth_flags & FWRITE)
1166 if (m->synth_flags & FWRITE)
1161 m->flags &= ~M_TX;
1167 m->flags &= ~M_TX;
1162
1168
1163 if( (m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)) )
1169 if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)))
1164 MPU_CALLBACK(m, m->cookie, m->flags);
1165
1166 MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy));
1167
1168 mtx_unlock(&m->qlock);
1169 mtx_unlock(&m->lock);
1170 retval = 0;
1171err: return retval;
1172}
1173
1174/*
1175 * Always blocking.
1176 */
1177
1178int
1179midisynth_writeraw(void *n, uint8_t *buf, size_t len)
1180{
1170 MPU_CALLBACK(m, m->cookie, m->flags);
1171
1172 MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy));
1173
1174 mtx_unlock(&m->qlock);
1175 mtx_unlock(&m->lock);
1176 retval = 0;
1177err: return retval;
1178}
1179
1180/*
1181 * Always blocking.
1182 */
1183
1184int
1185midisynth_writeraw(void *n, uint8_t *buf, size_t len)
1186{
1181 struct snd_midi *m = ((struct synth_midi *)n)->m;
1182 int retval;
1183 int used;
1187 struct snd_midi *m = ((struct synth_midi *)n)->m;
1188 int retval;
1189 int used;
1184 int i;
1185
1190 int i;
1191
1186 MIDI_DEBUG(4, printf("midisynth_writeraw\n"));
1192 MIDI_DEBUG(4, printf("midisynth_writeraw\n"));
1187
1188 retval = 0;
1189
1190 if (m == NULL)
1193
1194 retval = 0;
1195
1196 if (m == NULL)
1191 return ENXIO;
1197 return ENXIO;
1192
1193 mtx_lock(&m->lock);
1194 mtx_lock(&m->qlock);
1195
1196 if (!(m->flags & M_TX))
1198
1199 mtx_lock(&m->lock);
1200 mtx_lock(&m->qlock);
1201
1202 if (!(m->flags & M_TX))
1197 goto err1;
1203 goto err1;
1198
1199 if (midi_dumpraw)
1204
1205 if (midi_dumpraw)
1200 printf("midi dump: ");
1206 printf("midi dump: ");
1201
1202 while (len > 0) {
1207
1208 while (len > 0) {
1203 while (MIDIQ_AVAIL(m->outq) == 0) {
1204 if (!(m->flags & M_TXEN)) {
1205 m->flags |= M_TXEN;
1206 MPU_CALLBACK(m, m->cookie, m->flags);
1207 }
1208 mtx_unlock(&m->lock);
1209 m->wchan = 1;
1210 MIDI_DEBUG(3,printf("midisynth_writeraw msleep\n"));
1211 retval = msleep(&m->wchan, &m->qlock,
1212 PCATCH | PDROP, "midi TX", 0);
1213 /*
1214 * We slept, maybe things have changed since last
1215 * dying check
1216 */
1217 if (retval == EINTR)
1218 goto err0;
1209 while (MIDIQ_AVAIL(m->outq) == 0) {
1210 if (!(m->flags & M_TXEN)) {
1211 m->flags |= M_TXEN;
1212 MPU_CALLBACK(m, m->cookie, m->flags);
1213 }
1214 mtx_unlock(&m->lock);
1215 m->wchan = 1;
1216 MIDI_DEBUG(3, printf("midisynth_writeraw msleep\n"));
1217 retval = msleep(&m->wchan, &m->qlock,
1218 PCATCH | PDROP, "midi TX", 0);
1219 /*
1220 * We slept, maybe things have changed since last
1221 * dying check
1222 */
1223 if (retval == EINTR)
1224 goto err0;
1219
1225
1220 if (retval)
1221 goto err0;
1222 mtx_lock(&m->lock);
1223 mtx_lock(&m->qlock);
1224 m->wchan = 0;
1225 if (!m->busy)
1226 goto err1;
1227 }
1226 if (retval)
1227 goto err0;
1228 mtx_lock(&m->lock);
1229 mtx_lock(&m->qlock);
1230 m->wchan = 0;
1231 if (!m->busy)
1232 goto err1;
1233 }
1228
1234
1229 /*
1230 * We are certain than data can be placed on the queue
1231 */
1235 /*
1236 * We are certain than data can be placed on the queue
1237 */
1232
1238
1233 used = MIN(MIDIQ_AVAIL(m->outq), len);
1234 used = MIN(used, MIDI_WSIZE);
1235 MIDI_DEBUG(5,printf("midi_synth: resid %zu len %jd avail %jd\n",
1236 len, (intmax_t)MIDIQ_LEN(m->outq),
1237 (intmax_t)MIDIQ_AVAIL(m->outq)));
1239 used = MIN(MIDIQ_AVAIL(m->outq), len);
1240 used = MIN(used, MIDI_WSIZE);
1241 MIDI_DEBUG(5,
1242 printf("midi_synth: resid %zu len %jd avail %jd\n",
1243 len, (intmax_t)MIDIQ_LEN(m->outq),
1244 (intmax_t)MIDIQ_AVAIL(m->outq)));
1238
1245
1239 if (midi_dumpraw)
1240 for(i=0;i<used;i++) printf("%x ", buf[i]);
1246 if (midi_dumpraw)
1247 for (i = 0; i < used; i++)
1248 printf("%x ", buf[i]);
1241
1249
1242 MIDIQ_ENQ(m->outq, buf, used);
1243 len -= used;
1250 MIDIQ_ENQ(m->outq, buf, used);
1251 len -= used;
1244
1252
1245 /*
1246 * Inform the bottom half that data can be written
1247 */
1248 if (!(m->flags & M_TXEN)) {
1249 m->flags |= M_TXEN;
1250 MPU_CALLBACK(m, m->cookie, m->flags);
1251 }
1253 /*
1254 * Inform the bottom half that data can be written
1255 */
1256 if (!(m->flags & M_TXEN)) {
1257 m->flags |= M_TXEN;
1258 MPU_CALLBACK(m, m->cookie, m->flags);
1259 }
1252 }
1253 /*
1254 * If we Made it here then transfer is good
1255 */
1256 if (midi_dumpraw)
1260 }
1261 /*
1262 * If we Made it here then transfer is good
1263 */
1264 if (midi_dumpraw)
1257 printf("\n");
1265 printf("\n");
1258
1259 retval = 0;
1260err1: mtx_unlock(&m->qlock);
1261 mtx_unlock(&m->lock);
1262err0: return retval;
1263}
1264
1265static int
1266midisynth_killnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
1267{
1268 u_char c[3];
1269
1270
1271 if (note > 127 || chn > 15)
1272 return (EINVAL);
1273
1274 if (vel > 127)
1266
1267 retval = 0;
1268err1: mtx_unlock(&m->qlock);
1269 mtx_unlock(&m->lock);
1270err0: return retval;
1271}
1272
1273static int
1274midisynth_killnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
1275{
1276 u_char c[3];
1277
1278
1279 if (note > 127 || chn > 15)
1280 return (EINVAL);
1281
1282 if (vel > 127)
1275 vel = 127;
1283 vel = 127;
1276
1277 if (vel == 64) {
1284
1285 if (vel == 64) {
1278 c[0] = 0x90 | (chn & 0x0f); /* Note on. */
1286 c[0] = 0x90 | (chn & 0x0f); /* Note on. */
1279 c[1] = (u_char)note;
1280 c[2] = 0;
1281 } else {
1287 c[1] = (u_char)note;
1288 c[2] = 0;
1289 } else {
1282 c[0] = 0x80 | (chn & 0x0f); /* Note off. */
1290 c[0] = 0x80 | (chn & 0x0f); /* Note off. */
1283 c[1] = (u_char)note;
1284 c[2] = (u_char)vel;
1285 }
1286
1287 return midisynth_writeraw(n, c, 3);
1288}
1289
1290static int
1291midisynth_setinstr(void *n, uint8_t chn, uint16_t instr)
1292{
1293 u_char c[2];
1294
1295 if (instr > 127 || chn > 15)
1296 return EINVAL;
1297
1291 c[1] = (u_char)note;
1292 c[2] = (u_char)vel;
1293 }
1294
1295 return midisynth_writeraw(n, c, 3);
1296}
1297
1298static int
1299midisynth_setinstr(void *n, uint8_t chn, uint16_t instr)
1300{
1301 u_char c[2];
1302
1303 if (instr > 127 || chn > 15)
1304 return EINVAL;
1305
1298 c[0] = 0xc0 | (chn & 0x0f); /* Progamme change. */
1306 c[0] = 0xc0 | (chn & 0x0f); /* Progamme change. */
1299 c[1] = instr + midi_instroff;
1300
1301 return midisynth_writeraw(n, c, 2);
1302}
1303
1304static int
1305midisynth_startnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
1306{
1307 u_char c[3];
1308
1309 if (note > 127 || chn > 15)
1310 return EINVAL;
1311
1312 if (vel > 127)
1307 c[1] = instr + midi_instroff;
1308
1309 return midisynth_writeraw(n, c, 2);
1310}
1311
1312static int
1313midisynth_startnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
1314{
1315 u_char c[3];
1316
1317 if (note > 127 || chn > 15)
1318 return EINVAL;
1319
1320 if (vel > 127)
1313 vel = 127;
1321 vel = 127;
1314
1322
1315 c[0] = 0x90 | (chn & 0x0f); /* Note on. */
1323 c[0] = 0x90 | (chn & 0x0f); /* Note on. */
1316 c[1] = (u_char)note;
1317 c[2] = (u_char)vel;
1318
1319 return midisynth_writeraw(n, c, 3);
1320}
1321static int
1322midisynth_alloc(void *n, uint8_t chan, uint8_t note)
1323{
1324 return chan;
1325}
1326
1327static int
1328midisynth_controller(void *n, uint8_t chn, uint8_t ctrlnum, uint16_t val)
1329{
1330 u_char c[3];
1331
1332 if (ctrlnum > 127 || chn > 15)
1324 c[1] = (u_char)note;
1325 c[2] = (u_char)vel;
1326
1327 return midisynth_writeraw(n, c, 3);
1328}
1329static int
1330midisynth_alloc(void *n, uint8_t chan, uint8_t note)
1331{
1332 return chan;
1333}
1334
1335static int
1336midisynth_controller(void *n, uint8_t chn, uint8_t ctrlnum, uint16_t val)
1337{
1338 u_char c[3];
1339
1340 if (ctrlnum > 127 || chn > 15)
1333 return EINVAL;
1341 return EINVAL;
1334
1342
1335 c[0] = 0xb0 | (chn & 0x0f); /* Control Message. */
1343 c[0] = 0xb0 | (chn & 0x0f); /* Control Message. */
1336 c[1] = ctrlnum;
1337 c[2] = val;
1338 return midisynth_writeraw(n, c, 3);
1339}
1340
1341static int
1342midisynth_bender(void *n, uint8_t chn, uint16_t val)
1343{
1344 u_char c[3];
1345
1346
1347 if (val > 16383 || chn > 15)
1344 c[1] = ctrlnum;
1345 c[2] = val;
1346 return midisynth_writeraw(n, c, 3);
1347}
1348
1349static int
1350midisynth_bender(void *n, uint8_t chn, uint16_t val)
1351{
1352 u_char c[3];
1353
1354
1355 if (val > 16383 || chn > 15)
1348 return EINVAL;
1356 return EINVAL;
1349
1357
1350 c[0] = 0xe0 | (chn & 0x0f); /* Pitch bend. */
1358 c[0] = 0xe0 | (chn & 0x0f); /* Pitch bend. */
1351 c[1] = (u_char)val & 0x7f;
1352 c[2] = (u_char)(val >> 7) & 0x7f;
1353
1354 return midisynth_writeraw(n, c, 3);
1355}
1356
1357/*
1358 * Single point of midi destructions.
1359 */
1360static int
1359 c[1] = (u_char)val & 0x7f;
1360 c[2] = (u_char)(val >> 7) & 0x7f;
1361
1362 return midisynth_writeraw(n, c, 3);
1363}
1364
1365/*
1366 * Single point of midi destructions.
1367 */
1368static int
1361midi_destroy(struct snd_midi * m, int midiuninit)
1369midi_destroy(struct snd_midi *m, int midiuninit)
1362{
1363
1364 mtx_assert(&midistat_lock, MA_OWNED);
1365 mtx_assert(&m->lock, MA_OWNED);
1366
1370{
1371
1372 mtx_assert(&midistat_lock, MA_OWNED);
1373 mtx_assert(&m->lock, MA_OWNED);
1374
1367 MIDI_DEBUG(3,printf("midi_destroy\n"));
1375 MIDI_DEBUG(3, printf("midi_destroy\n"));
1368 m->dev->si_drv1 = NULL;
1369 destroy_dev(m->dev);
1370 TAILQ_REMOVE(&midi_devs, m, link);
1371 if (midiuninit)
1376 m->dev->si_drv1 = NULL;
1377 destroy_dev(m->dev);
1378 TAILQ_REMOVE(&midi_devs, m, link);
1379 if (midiuninit)
1372 MPU_UNINIT(m, m->cookie);
1380 MPU_UNINIT(m, m->cookie);
1373 free(MIDIQ_BUF(m->inq), M_MIDI);
1374 free(MIDIQ_BUF(m->outq), M_MIDI);
1375 mtx_destroy(&m->qlock);
1376 mtx_destroy(&m->lock);
1377 free(m, M_MIDI);
1378 return 0;
1379}
1380
1381/*
1382 * Load and unload functions, creates the /dev/midistat device
1383 */
1384
1385static int
1386midi_load()
1387{
1388 mtx_init(&midistat_lock, "midistat lock", 0, 0);
1381 free(MIDIQ_BUF(m->inq), M_MIDI);
1382 free(MIDIQ_BUF(m->outq), M_MIDI);
1383 mtx_destroy(&m->qlock);
1384 mtx_destroy(&m->lock);
1385 free(m, M_MIDI);
1386 return 0;
1387}
1388
1389/*
1390 * Load and unload functions, creates the /dev/midistat device
1391 */
1392
1393static int
1394midi_load()
1395{
1396 mtx_init(&midistat_lock, "midistat lock", 0, 0);
1389 TAILQ_INIT(&midi_devs); /* Initialize the queue. */
1397 TAILQ_INIT(&midi_devs); /* Initialize the queue. */
1390
1391 midistat_dev = make_dev(&midistat_cdevsw,
1398
1399 midistat_dev = make_dev(&midistat_cdevsw,
1392 MIDIMKMINOR(0, MIDI_DEV_MIDICTL, 0),
1393 UID_ROOT, GID_WHEEL, 0666, "midistat");
1400 MIDIMKMINOR(0, MIDI_DEV_MIDICTL, 0),
1401 UID_ROOT, GID_WHEEL, 0666, "midistat");
1394
1395 return 0;
1396}
1397
1398static int
1399midi_unload()
1400{
1401 struct snd_midi *m;
1402
1403 return 0;
1404}
1405
1406static int
1407midi_unload()
1408{
1409 struct snd_midi *m;
1402 int retval;
1410 int retval;
1403
1411
1404 MIDI_DEBUG(1,printf("midi_unload()\n"));
1412 MIDI_DEBUG(1, printf("midi_unload()\n"));
1405 retval = EBUSY;
1406 mtx_lock(&midistat_lock);
1407 if (midistat_isopen)
1413 retval = EBUSY;
1414 mtx_lock(&midistat_lock);
1415 if (midistat_isopen)
1408 goto exit0;
1416 goto exit0;
1409
1410 TAILQ_FOREACH(m, &midi_devs, link) {
1417
1418 TAILQ_FOREACH(m, &midi_devs, link) {
1411 mtx_lock(&m->lock);
1412 if (m->busy)
1413 retval = EBUSY;
1414 else
1415 retval = midi_destroy(m, 1);
1416 if (retval)
1417 goto exit1;
1419 mtx_lock(&m->lock);
1420 if (m->busy)
1421 retval = EBUSY;
1422 else
1423 retval = midi_destroy(m, 1);
1424 if (retval)
1425 goto exit1;
1418 }
1419
1420 destroy_dev(midistat_dev);
1421 /*
1422 * Made it here then unload is complete
1423 */
1424 mtx_destroy(&midistat_lock);
1425 return 0;
1426
1427exit1:
1428 mtx_unlock(&m->lock);
1429exit0:
1430 mtx_unlock(&midistat_lock);
1426 }
1427
1428 destroy_dev(midistat_dev);
1429 /*
1430 * Made it here then unload is complete
1431 */
1432 mtx_destroy(&midistat_lock);
1433 return 0;
1434
1435exit1:
1436 mtx_unlock(&m->lock);
1437exit0:
1438 mtx_unlock(&midistat_lock);
1431 if(retval) MIDI_DEBUG(2,printf("midi_unload: failed\n"));
1439 if (retval)
1440 MIDI_DEBUG(2, printf("midi_unload: failed\n"));
1432 return retval;
1433}
1434
1435extern int seq_modevent(module_t mod, int type, void *data);
1436
1437static int
1438midi_modevent(module_t mod, int type, void *data)
1439{
1441 return retval;
1442}
1443
1444extern int seq_modevent(module_t mod, int type, void *data);
1445
1446static int
1447midi_modevent(module_t mod, int type, void *data)
1448{
1440 int retval;
1449 int retval;
1441
1442 retval = 0;
1443
1444 switch (type) {
1445 case MOD_LOAD:
1450
1451 retval = 0;
1452
1453 switch (type) {
1454 case MOD_LOAD:
1446 retval = midi_load();
1447 if (retval == 0)
1448 retval = seq_modevent(mod, type, data);
1449 break;
1455 retval = midi_load();
1456 if (retval == 0)
1457 retval = seq_modevent(mod, type, data);
1458 break;
1450
1451 case MOD_UNLOAD:
1459
1460 case MOD_UNLOAD:
1452 retval = midi_unload();
1453 if (retval == 0)
1454 retval = seq_modevent(mod, type, data);
1455 break;
1461 retval = midi_unload();
1462 if (retval == 0)
1463 retval = seq_modevent(mod, type, data);
1464 break;
1456
1457 default:
1465
1466 default:
1458 break;
1467 break;
1459 }
1460
1461 return retval;
1462}
1463
1464kobj_t
1465midimapper_addseq(void *arg1, int *unit, void **cookie)
1466{
1467 unit = 0;
1468
1468 }
1469
1470 return retval;
1471}
1472
1473kobj_t
1474midimapper_addseq(void *arg1, int *unit, void **cookie)
1475{
1476 unit = 0;
1477
1469 return (kobj_t) arg1;
1478 return (kobj_t)arg1;
1470}
1471
1472int
1473midimapper_open(void *arg1, void **cookie)
1474{
1475 int retval = 0;
1476 struct snd_midi *m;
1477
1479}
1480
1481int
1482midimapper_open(void *arg1, void **cookie)
1483{
1484 int retval = 0;
1485 struct snd_midi *m;
1486
1478 mtx_lock(&midistat_lock);
1487 mtx_lock(&midistat_lock);
1479
1488
1480 TAILQ_FOREACH(m, &midi_devs, link) {
1481 retval++;
1482 }
1489 TAILQ_FOREACH(m, &midi_devs, link) {
1490 retval++;
1491 }
1483
1492
1484 mtx_unlock(&midistat_lock);
1485 return retval;
1493 mtx_unlock(&midistat_lock);
1494 return retval;
1486}
1487
1488int
1489midimapper_close(void *arg1, void *cookie)
1490{
1491 return 0;
1492}
1493
1494kobj_t
1495midimapper_fetch_synth(void *arg, void *cookie, int unit)
1496{
1497 struct snd_midi *m;
1498 int retval = 0;
1499
1500 mtx_lock(&midistat_lock);
1501
1502 TAILQ_FOREACH(m, &midi_devs, link) {
1495}
1496
1497int
1498midimapper_close(void *arg1, void *cookie)
1499{
1500 return 0;
1501}
1502
1503kobj_t
1504midimapper_fetch_synth(void *arg, void *cookie, int unit)
1505{
1506 struct snd_midi *m;
1507 int retval = 0;
1508
1509 mtx_lock(&midistat_lock);
1510
1511 TAILQ_FOREACH(m, &midi_devs, link) {
1503 if (unit == retval) {
1504 mtx_unlock(&midistat_lock);
1505 return (kobj_t)m->synth;
1506 }
1507 retval++;
1512 if (unit == retval) {
1513 mtx_unlock(&midistat_lock);
1514 return (kobj_t)m->synth;
1515 }
1516 retval++;
1508 }
1509
1510 mtx_unlock(&midistat_lock);
1511 return NULL;
1512}
1513
1514DEV_MODULE(midi, midi_modevent, NULL);
1515MODULE_VERSION(midi, 1);
1517 }
1518
1519 mtx_unlock(&midistat_lock);
1520 return NULL;
1521}
1522
1523DEV_MODULE(midi, midi_modevent, NULL);
1524MODULE_VERSION(midi, 1);