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); |