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