]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * sound/midi_synth.c | |
3 | * | |
4 | * High level midi sequencer manager for dumb MIDI interfaces. | |
5 | */ | |
6 | /* | |
7 | * Copyright (C) by Hannu Savolainen 1993-1997 | |
8 | * | |
9 | * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) | |
10 | * Version 2 (June 1991). See the "COPYING" file distributed with this software | |
11 | * for more info. | |
12 | */ | |
13 | /* | |
14 | * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) | |
15 | * Andrew Veliath : fixed running status in MIDI input state machine | |
16 | */ | |
17 | #define USE_SEQ_MACROS | |
18 | #define USE_SIMPLE_MACROS | |
19 | ||
20 | #include "sound_config.h" | |
21 | ||
22 | #define _MIDI_SYNTH_C_ | |
23 | ||
24 | #include "midi_synth.h" | |
25 | ||
26 | static int midi2synth[MAX_MIDI_DEV]; | |
27 | static int sysex_state[MAX_MIDI_DEV] = | |
28 | {0}; | |
29 | static unsigned char prev_out_status[MAX_MIDI_DEV]; | |
30 | ||
31 | #define STORE(cmd) \ | |
32 | { \ | |
33 | int len; \ | |
34 | unsigned char obuf[8]; \ | |
35 | cmd; \ | |
36 | seq_input_event(obuf, len); \ | |
37 | } | |
38 | ||
39 | #define _seqbuf obuf | |
40 | #define _seqbufptr 0 | |
41 | #define _SEQ_ADVBUF(x) len=x | |
42 | ||
43 | void | |
44 | do_midi_msg(int synthno, unsigned char *msg, int mlen) | |
45 | { | |
46 | switch (msg[0] & 0xf0) | |
47 | { | |
48 | case 0x90: | |
49 | if (msg[2] != 0) | |
50 | { | |
51 | STORE(SEQ_START_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2])); | |
52 | break; | |
53 | } | |
54 | msg[2] = 64; | |
55 | ||
56 | case 0x80: | |
57 | STORE(SEQ_STOP_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2])); | |
58 | break; | |
59 | ||
60 | case 0xA0: | |
61 | STORE(SEQ_KEY_PRESSURE(synthno, msg[0] & 0x0f, msg[1], msg[2])); | |
62 | break; | |
63 | ||
64 | case 0xB0: | |
65 | STORE(SEQ_CONTROL(synthno, msg[0] & 0x0f, | |
66 | msg[1], msg[2])); | |
67 | break; | |
68 | ||
69 | case 0xC0: | |
70 | STORE(SEQ_SET_PATCH(synthno, msg[0] & 0x0f, msg[1])); | |
71 | break; | |
72 | ||
73 | case 0xD0: | |
74 | STORE(SEQ_CHN_PRESSURE(synthno, msg[0] & 0x0f, msg[1])); | |
75 | break; | |
76 | ||
77 | case 0xE0: | |
78 | STORE(SEQ_BENDER(synthno, msg[0] & 0x0f, | |
79 | (msg[1] & 0x7f) | ((msg[2] & 0x7f) << 7))); | |
80 | break; | |
81 | ||
82 | default: | |
83 | /* printk( "MPU: Unknown midi channel message %02x\n", msg[0]); */ | |
84 | ; | |
85 | } | |
86 | } | |
87 | ||
88 | static void | |
89 | midi_outc(int midi_dev, int data) | |
90 | { | |
91 | int timeout; | |
92 | ||
93 | for (timeout = 0; timeout < 3200; timeout++) | |
94 | if (midi_devs[midi_dev]->outputc(midi_dev, (unsigned char) (data & 0xff))) | |
95 | { | |
96 | if (data & 0x80) /* | |
97 | * Status byte | |
98 | */ | |
99 | prev_out_status[midi_dev] = | |
100 | (unsigned char) (data & 0xff); /* | |
101 | * Store for running status | |
102 | */ | |
103 | return; /* | |
104 | * Mission complete | |
105 | */ | |
106 | } | |
107 | /* | |
108 | * Sorry! No space on buffers. | |
109 | */ | |
110 | printk("Midi send timed out\n"); | |
111 | } | |
112 | ||
113 | static int | |
114 | prefix_cmd(int midi_dev, unsigned char status) | |
115 | { | |
116 | if ((char *) midi_devs[midi_dev]->prefix_cmd == NULL) | |
117 | return 1; | |
118 | ||
119 | return midi_devs[midi_dev]->prefix_cmd(midi_dev, status); | |
120 | } | |
121 | ||
122 | static void | |
123 | midi_synth_input(int orig_dev, unsigned char data) | |
124 | { | |
125 | int dev; | |
126 | struct midi_input_info *inc; | |
127 | ||
128 | static unsigned char len_tab[] = /* # of data bytes following a status | |
129 | */ | |
130 | { | |
131 | 2, /* 8x */ | |
132 | 2, /* 9x */ | |
133 | 2, /* Ax */ | |
134 | 2, /* Bx */ | |
135 | 1, /* Cx */ | |
136 | 1, /* Dx */ | |
137 | 2, /* Ex */ | |
138 | 0 /* Fx */ | |
139 | }; | |
140 | ||
141 | if (orig_dev < 0 || orig_dev > num_midis || midi_devs[orig_dev] == NULL) | |
142 | return; | |
143 | ||
144 | if (data == 0xfe) /* Ignore active sensing */ | |
145 | return; | |
146 | ||
147 | dev = midi2synth[orig_dev]; | |
148 | inc = &midi_devs[orig_dev]->in_info; | |
149 | ||
150 | switch (inc->m_state) | |
151 | { | |
152 | case MST_INIT: | |
153 | if (data & 0x80) /* MIDI status byte */ | |
154 | { | |
155 | if ((data & 0xf0) == 0xf0) /* Common message */ | |
156 | { | |
157 | switch (data) | |
158 | { | |
159 | case 0xf0: /* Sysex */ | |
160 | inc->m_state = MST_SYSEX; | |
161 | break; /* Sysex */ | |
162 | ||
163 | case 0xf1: /* MTC quarter frame */ | |
164 | case 0xf3: /* Song select */ | |
165 | inc->m_state = MST_DATA; | |
166 | inc->m_ptr = 1; | |
167 | inc->m_left = 1; | |
168 | inc->m_buf[0] = data; | |
169 | break; | |
170 | ||
171 | case 0xf2: /* Song position pointer */ | |
172 | inc->m_state = MST_DATA; | |
173 | inc->m_ptr = 1; | |
174 | inc->m_left = 2; | |
175 | inc->m_buf[0] = data; | |
176 | break; | |
177 | ||
178 | default: | |
179 | inc->m_buf[0] = data; | |
180 | inc->m_ptr = 1; | |
181 | do_midi_msg(dev, inc->m_buf, inc->m_ptr); | |
182 | inc->m_ptr = 0; | |
183 | inc->m_left = 0; | |
184 | } | |
185 | } else | |
186 | { | |
187 | inc->m_state = MST_DATA; | |
188 | inc->m_ptr = 1; | |
189 | inc->m_left = len_tab[(data >> 4) - 8]; | |
190 | inc->m_buf[0] = inc->m_prev_status = data; | |
191 | } | |
192 | } else if (inc->m_prev_status & 0x80) { | |
193 | /* Data byte (use running status) */ | |
194 | inc->m_ptr = 2; | |
195 | inc->m_buf[1] = data; | |
196 | inc->m_buf[0] = inc->m_prev_status; | |
197 | inc->m_left = len_tab[(inc->m_buf[0] >> 4) - 8] - 1; | |
198 | if (inc->m_left > 0) | |
199 | inc->m_state = MST_DATA; /* Not done yet */ | |
200 | else { | |
201 | inc->m_state = MST_INIT; | |
202 | do_midi_msg(dev, inc->m_buf, inc->m_ptr); | |
203 | inc->m_ptr = 0; | |
204 | } | |
205 | } | |
206 | break; /* MST_INIT */ | |
207 | ||
208 | case MST_DATA: | |
209 | inc->m_buf[inc->m_ptr++] = data; | |
210 | if (--inc->m_left <= 0) | |
211 | { | |
212 | inc->m_state = MST_INIT; | |
213 | do_midi_msg(dev, inc->m_buf, inc->m_ptr); | |
214 | inc->m_ptr = 0; | |
215 | } | |
216 | break; /* MST_DATA */ | |
217 | ||
218 | case MST_SYSEX: | |
219 | if (data == 0xf7) /* Sysex end */ | |
220 | { | |
221 | inc->m_state = MST_INIT; | |
222 | inc->m_left = 0; | |
223 | inc->m_ptr = 0; | |
224 | } | |
225 | break; /* MST_SYSEX */ | |
226 | ||
227 | default: | |
228 | printk("MIDI%d: Unexpected state %d (%02x)\n", orig_dev, inc->m_state, (int) data); | |
229 | inc->m_state = MST_INIT; | |
230 | } | |
231 | } | |
232 | ||
233 | static void | |
234 | leave_sysex(int dev) | |
235 | { | |
236 | int orig_dev = synth_devs[dev]->midi_dev; | |
237 | int timeout = 0; | |
238 | ||
239 | if (!sysex_state[dev]) | |
240 | return; | |
241 | ||
242 | sysex_state[dev] = 0; | |
243 | ||
244 | while (!midi_devs[orig_dev]->outputc(orig_dev, 0xf7) && | |
245 | timeout < 1000) | |
246 | timeout++; | |
247 | ||
248 | sysex_state[dev] = 0; | |
249 | } | |
250 | ||
251 | static void | |
252 | midi_synth_output(int dev) | |
253 | { | |
254 | /* | |
255 | * Currently NOP | |
256 | */ | |
257 | } | |
258 | ||
259 | int midi_synth_ioctl(int dev, unsigned int cmd, void __user *arg) | |
260 | { | |
261 | /* | |
262 | * int orig_dev = synth_devs[dev]->midi_dev; | |
263 | */ | |
264 | ||
265 | switch (cmd) { | |
266 | ||
267 | case SNDCTL_SYNTH_INFO: | |
268 | if (__copy_to_user(arg, synth_devs[dev]->info, sizeof(struct synth_info))) | |
269 | return -EFAULT; | |
270 | return 0; | |
271 | ||
272 | case SNDCTL_SYNTH_MEMAVL: | |
273 | return 0x7fffffff; | |
274 | ||
275 | default: | |
276 | return -EINVAL; | |
277 | } | |
278 | } | |
279 | ||
280 | int | |
281 | midi_synth_kill_note(int dev, int channel, int note, int velocity) | |
282 | { | |
283 | int orig_dev = synth_devs[dev]->midi_dev; | |
284 | int msg, chn; | |
285 | ||
286 | if (note < 0 || note > 127) | |
287 | return 0; | |
288 | if (channel < 0 || channel > 15) | |
289 | return 0; | |
290 | if (velocity < 0) | |
291 | velocity = 0; | |
292 | if (velocity > 127) | |
293 | velocity = 127; | |
294 | ||
295 | leave_sysex(dev); | |
296 | ||
297 | msg = prev_out_status[orig_dev] & 0xf0; | |
298 | chn = prev_out_status[orig_dev] & 0x0f; | |
299 | ||
300 | if (chn == channel && ((msg == 0x90 && velocity == 64) || msg == 0x80)) | |
301 | { /* | |
302 | * Use running status | |
303 | */ | |
304 | if (!prefix_cmd(orig_dev, note)) | |
305 | return 0; | |
306 | ||
307 | midi_outc(orig_dev, note); | |
308 | ||
309 | if (msg == 0x90) /* | |
310 | * Running status = Note on | |
311 | */ | |
312 | midi_outc(orig_dev, 0); /* | |
313 | * Note on with velocity 0 == note | |
314 | * off | |
315 | */ | |
316 | else | |
317 | midi_outc(orig_dev, velocity); | |
318 | } else | |
319 | { | |
320 | if (velocity == 64) | |
321 | { | |
322 | if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f))) | |
323 | return 0; | |
324 | midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /* | |
325 | * Note on | |
326 | */ | |
327 | midi_outc(orig_dev, note); | |
328 | midi_outc(orig_dev, 0); /* | |
329 | * Zero G | |
330 | */ | |
331 | } else | |
332 | { | |
333 | if (!prefix_cmd(orig_dev, 0x80 | (channel & 0x0f))) | |
334 | return 0; | |
335 | midi_outc(orig_dev, 0x80 | (channel & 0x0f)); /* | |
336 | * Note off | |
337 | */ | |
338 | midi_outc(orig_dev, note); | |
339 | midi_outc(orig_dev, velocity); | |
340 | } | |
341 | } | |
342 | ||
343 | return 0; | |
344 | } | |
345 | ||
346 | int | |
347 | midi_synth_set_instr(int dev, int channel, int instr_no) | |
348 | { | |
349 | int orig_dev = synth_devs[dev]->midi_dev; | |
350 | ||
351 | if (instr_no < 0 || instr_no > 127) | |
352 | instr_no = 0; | |
353 | if (channel < 0 || channel > 15) | |
354 | return 0; | |
355 | ||
356 | leave_sysex(dev); | |
357 | ||
358 | if (!prefix_cmd(orig_dev, 0xc0 | (channel & 0x0f))) | |
359 | return 0; | |
360 | midi_outc(orig_dev, 0xc0 | (channel & 0x0f)); /* | |
361 | * Program change | |
362 | */ | |
363 | midi_outc(orig_dev, instr_no); | |
364 | ||
365 | return 0; | |
366 | } | |
367 | ||
368 | int | |
369 | midi_synth_start_note(int dev, int channel, int note, int velocity) | |
370 | { | |
371 | int orig_dev = synth_devs[dev]->midi_dev; | |
372 | int msg, chn; | |
373 | ||
374 | if (note < 0 || note > 127) | |
375 | return 0; | |
376 | if (channel < 0 || channel > 15) | |
377 | return 0; | |
378 | if (velocity < 0) | |
379 | velocity = 0; | |
380 | if (velocity > 127) | |
381 | velocity = 127; | |
382 | ||
383 | leave_sysex(dev); | |
384 | ||
385 | msg = prev_out_status[orig_dev] & 0xf0; | |
386 | chn = prev_out_status[orig_dev] & 0x0f; | |
387 | ||
388 | if (chn == channel && msg == 0x90) | |
389 | { /* | |
390 | * Use running status | |
391 | */ | |
392 | if (!prefix_cmd(orig_dev, note)) | |
393 | return 0; | |
394 | midi_outc(orig_dev, note); | |
395 | midi_outc(orig_dev, velocity); | |
396 | } else | |
397 | { | |
398 | if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f))) | |
399 | return 0; | |
400 | midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /* | |
401 | * Note on | |
402 | */ | |
403 | midi_outc(orig_dev, note); | |
404 | midi_outc(orig_dev, velocity); | |
405 | } | |
406 | return 0; | |
407 | } | |
408 | ||
409 | void | |
410 | midi_synth_reset(int dev) | |
411 | { | |
412 | ||
413 | leave_sysex(dev); | |
414 | } | |
415 | ||
416 | int | |
417 | midi_synth_open(int dev, int mode) | |
418 | { | |
419 | int orig_dev = synth_devs[dev]->midi_dev; | |
420 | int err; | |
421 | struct midi_input_info *inc; | |
422 | ||
423 | if (orig_dev < 0 || orig_dev > num_midis || midi_devs[orig_dev] == NULL) | |
424 | return -ENXIO; | |
425 | ||
426 | midi2synth[orig_dev] = dev; | |
427 | sysex_state[dev] = 0; | |
428 | prev_out_status[orig_dev] = 0; | |
429 | ||
430 | if ((err = midi_devs[orig_dev]->open(orig_dev, mode, | |
431 | midi_synth_input, midi_synth_output)) < 0) | |
432 | return err; | |
433 | inc = &midi_devs[orig_dev]->in_info; | |
434 | ||
435 | /* save_flags(flags); | |
436 | cli(); | |
437 | don't know against what irqhandler to protect*/ | |
438 | inc->m_busy = 0; | |
439 | inc->m_state = MST_INIT; | |
440 | inc->m_ptr = 0; | |
441 | inc->m_left = 0; | |
442 | inc->m_prev_status = 0x00; | |
443 | /* restore_flags(flags); */ | |
444 | ||
445 | return 1; | |
446 | } | |
447 | ||
448 | void | |
449 | midi_synth_close(int dev) | |
450 | { | |
451 | int orig_dev = synth_devs[dev]->midi_dev; | |
452 | ||
453 | leave_sysex(dev); | |
454 | ||
455 | /* | |
456 | * Shut up the synths by sending just single active sensing message. | |
457 | */ | |
458 | midi_devs[orig_dev]->outputc(orig_dev, 0xfe); | |
459 | ||
460 | midi_devs[orig_dev]->close(orig_dev); | |
461 | } | |
462 | ||
463 | void | |
464 | midi_synth_hw_control(int dev, unsigned char *event) | |
465 | { | |
466 | } | |
467 | ||
468 | int | |
469 | midi_synth_load_patch(int dev, int format, const char __user *addr, | |
470 | int offs, int count, int pmgr_flag) | |
471 | { | |
472 | int orig_dev = synth_devs[dev]->midi_dev; | |
473 | ||
474 | struct sysex_info sysex; | |
475 | int i; | |
476 | unsigned long left, src_offs, eox_seen = 0; | |
477 | int first_byte = 1; | |
478 | int hdr_size = (unsigned long) &sysex.data[0] - (unsigned long) &sysex; | |
479 | ||
480 | leave_sysex(dev); | |
481 | ||
482 | if (!prefix_cmd(orig_dev, 0xf0)) | |
483 | return 0; | |
484 | ||
485 | if (format != SYSEX_PATCH) | |
486 | { | |
487 | /* printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/ | |
488 | return -EINVAL; | |
489 | } | |
490 | if (count < hdr_size) | |
491 | { | |
492 | /* printk("MIDI Error: Patch header too short\n");*/ | |
493 | return -EINVAL; | |
494 | } | |
495 | count -= hdr_size; | |
496 | ||
497 | /* | |
498 | * Copy the header from user space but ignore the first bytes which have | |
499 | * been transferred already. | |
500 | */ | |
501 | ||
502 | if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs)) | |
503 | return -EFAULT; | |
504 | ||
505 | if (count < sysex.len) | |
506 | { | |
507 | /* printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/ | |
508 | sysex.len = count; | |
509 | } | |
510 | left = sysex.len; | |
511 | src_offs = 0; | |
512 | ||
513 | for (i = 0; i < left && !signal_pending(current); i++) | |
514 | { | |
515 | unsigned char data; | |
516 | ||
517 | get_user(*(unsigned char *) &data, (unsigned char __user *) &((addr)[hdr_size + i])); | |
518 | ||
519 | eox_seen = (i > 0 && data & 0x80); /* End of sysex */ | |
520 | ||
521 | if (eox_seen && data != 0xf7) | |
522 | data = 0xf7; | |
523 | ||
524 | if (i == 0) | |
525 | { | |
526 | if (data != 0xf0) | |
527 | { | |
528 | printk(KERN_WARNING "midi_synth: Sysex start missing\n"); | |
529 | return -EINVAL; | |
530 | } | |
531 | } | |
532 | while (!midi_devs[orig_dev]->outputc(orig_dev, (unsigned char) (data & 0xff)) && | |
533 | !signal_pending(current)) | |
534 | schedule(); | |
535 | ||
536 | if (!first_byte && data & 0x80) | |
537 | return 0; | |
538 | first_byte = 0; | |
539 | } | |
540 | ||
541 | if (!eox_seen) | |
542 | midi_outc(orig_dev, 0xf7); | |
543 | return 0; | |
544 | } | |
545 | ||
546 | void midi_synth_panning(int dev, int channel, int pressure) | |
547 | { | |
548 | } | |
549 | ||
550 | void midi_synth_aftertouch(int dev, int channel, int pressure) | |
551 | { | |
552 | int orig_dev = synth_devs[dev]->midi_dev; | |
553 | int msg, chn; | |
554 | ||
555 | if (pressure < 0 || pressure > 127) | |
556 | return; | |
557 | if (channel < 0 || channel > 15) | |
558 | return; | |
559 | ||
560 | leave_sysex(dev); | |
561 | ||
562 | msg = prev_out_status[orig_dev] & 0xf0; | |
563 | chn = prev_out_status[orig_dev] & 0x0f; | |
564 | ||
565 | if (msg != 0xd0 || chn != channel) /* | |
566 | * Test for running status | |
567 | */ | |
568 | { | |
569 | if (!prefix_cmd(orig_dev, 0xd0 | (channel & 0x0f))) | |
570 | return; | |
571 | midi_outc(orig_dev, 0xd0 | (channel & 0x0f)); /* | |
572 | * Channel pressure | |
573 | */ | |
574 | } else if (!prefix_cmd(orig_dev, pressure)) | |
575 | return; | |
576 | ||
577 | midi_outc(orig_dev, pressure); | |
578 | } | |
579 | ||
580 | void | |
581 | midi_synth_controller(int dev, int channel, int ctrl_num, int value) | |
582 | { | |
583 | int orig_dev = synth_devs[dev]->midi_dev; | |
584 | int chn, msg; | |
585 | ||
586 | if (ctrl_num < 0 || ctrl_num > 127) | |
587 | return; | |
588 | if (channel < 0 || channel > 15) | |
589 | return; | |
590 | ||
591 | leave_sysex(dev); | |
592 | ||
593 | msg = prev_out_status[orig_dev] & 0xf0; | |
594 | chn = prev_out_status[orig_dev] & 0x0f; | |
595 | ||
596 | if (msg != 0xb0 || chn != channel) | |
597 | { | |
598 | if (!prefix_cmd(orig_dev, 0xb0 | (channel & 0x0f))) | |
599 | return; | |
600 | midi_outc(orig_dev, 0xb0 | (channel & 0x0f)); | |
601 | } else if (!prefix_cmd(orig_dev, ctrl_num)) | |
602 | return; | |
603 | ||
604 | midi_outc(orig_dev, ctrl_num); | |
605 | midi_outc(orig_dev, value & 0x7f); | |
606 | } | |
607 | ||
608 | void | |
609 | midi_synth_bender(int dev, int channel, int value) | |
610 | { | |
611 | int orig_dev = synth_devs[dev]->midi_dev; | |
612 | int msg, prev_chn; | |
613 | ||
614 | if (channel < 0 || channel > 15) | |
615 | return; | |
616 | ||
617 | if (value < 0 || value > 16383) | |
618 | return; | |
619 | ||
620 | leave_sysex(dev); | |
621 | ||
622 | msg = prev_out_status[orig_dev] & 0xf0; | |
623 | prev_chn = prev_out_status[orig_dev] & 0x0f; | |
624 | ||
625 | if (msg != 0xd0 || prev_chn != channel) /* | |
626 | * Test for running status | |
627 | */ | |
628 | { | |
629 | if (!prefix_cmd(orig_dev, 0xe0 | (channel & 0x0f))) | |
630 | return; | |
631 | midi_outc(orig_dev, 0xe0 | (channel & 0x0f)); | |
632 | } else if (!prefix_cmd(orig_dev, value & 0x7f)) | |
633 | return; | |
634 | ||
635 | midi_outc(orig_dev, value & 0x7f); | |
636 | midi_outc(orig_dev, (value >> 7) & 0x7f); | |
637 | } | |
638 | ||
639 | void | |
640 | midi_synth_setup_voice(int dev, int voice, int channel) | |
641 | { | |
642 | } | |
643 | ||
644 | int | |
645 | midi_synth_send_sysex(int dev, unsigned char *bytes, int len) | |
646 | { | |
647 | int orig_dev = synth_devs[dev]->midi_dev; | |
648 | int i; | |
649 | ||
650 | for (i = 0; i < len; i++) | |
651 | { | |
652 | switch (bytes[i]) | |
653 | { | |
654 | case 0xf0: /* Start sysex */ | |
655 | if (!prefix_cmd(orig_dev, 0xf0)) | |
656 | return 0; | |
657 | sysex_state[dev] = 1; | |
658 | break; | |
659 | ||
660 | case 0xf7: /* End sysex */ | |
661 | if (!sysex_state[dev]) /* Orphan sysex end */ | |
662 | return 0; | |
663 | sysex_state[dev] = 0; | |
664 | break; | |
665 | ||
666 | default: | |
667 | if (!sysex_state[dev]) | |
668 | return 0; | |
669 | ||
670 | if (bytes[i] & 0x80) /* Error. Another message before sysex end */ | |
671 | { | |
672 | bytes[i] = 0xf7; /* Sysex end */ | |
673 | sysex_state[dev] = 0; | |
674 | } | |
675 | } | |
676 | ||
677 | if (!midi_devs[orig_dev]->outputc(orig_dev, bytes[i])) | |
678 | { | |
679 | /* | |
680 | * Hardware level buffer is full. Abort the sysex message. | |
681 | */ | |
682 | ||
683 | int timeout = 0; | |
684 | ||
685 | bytes[i] = 0xf7; | |
686 | sysex_state[dev] = 0; | |
687 | ||
688 | while (!midi_devs[orig_dev]->outputc(orig_dev, bytes[i]) && | |
689 | timeout < 1000) | |
690 | timeout++; | |
691 | } | |
692 | if (!sysex_state[dev]) | |
693 | return 0; | |
694 | } | |
695 | ||
696 | return 0; | |
697 | } |