Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 offs, 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         if (format != SYSEX_PATCH)
495         {
496 /*                printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/
497                   return -EINVAL;
498         }
499         if (count < hdr_size)
500         {
501 /*              printk("MIDI Error: Patch header too short\n");*/
502                 return -EINVAL;
503         }
504         count -= hdr_size;
505 
506         /*
507          * Copy the header from user space but ignore the first bytes which have
508          * been transferred already.
509          */
510 
511         if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs))
512                 return -EFAULT;
513  
514         if (count < sysex.len)
515         {
516 /*              printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/
517                 sysex.len = count;
518         }
519         left = sysex.len;
520         src_offs = 0;
521 
522         for (i = 0; i < left && !signal_pending(current); i++)
523         {
524                 unsigned char   data;
525 
526                 get_user(*(unsigned char *) &data, (unsigned char __user *) &((addr)[hdr_size + i]));
527 
528                 eox_seen = (i > 0 && data & 0x80);      /* End of sysex */
529 
530                 if (eox_seen && data != 0xf7)
531                         data = 0xf7;
532 
533                 if (i == 0)
534                 {
535                         if (data != 0xf0)
536                         {
537                                 printk(KERN_WARNING "midi_synth: Sysex start missing\n");
538                                 return -EINVAL;
539                         }
540                 }
541                 while (!midi_devs[orig_dev]->outputc(orig_dev, (unsigned char) (data & 0xff)) &&
542                         !signal_pending(current))
543                         schedule();
544 
545                 if (!first_byte && data & 0x80)
546                         return 0;
547                 first_byte = 0;
548         }
549 
550         if (!eox_seen)
551                 midi_outc(orig_dev, 0xf7);
552         return 0;
553 }
554 EXPORT_SYMBOL(midi_synth_load_patch);
555 
556 void midi_synth_panning(int dev, int channel, int pressure)
557 {
558 }
559 EXPORT_SYMBOL(midi_synth_panning);
560 
561 void midi_synth_aftertouch(int dev, int channel, int pressure)
562 {
563         int             orig_dev = synth_devs[dev]->midi_dev;
564         int             msg, chn;
565 
566         if (pressure < 0 || pressure > 127)
567                 return;
568         if (channel < 0 || channel > 15)
569                 return;
570 
571         leave_sysex(dev);
572 
573         msg = prev_out_status[orig_dev] & 0xf0;
574         chn = prev_out_status[orig_dev] & 0x0f;
575 
576         if (msg != 0xd0 || chn != channel)      /*
577                                                  * Test for running status
578                                                  */
579           {
580                   if (!prefix_cmd(orig_dev, 0xd0 | (channel & 0x0f)))
581                           return;
582                   midi_outc(orig_dev, 0xd0 | (channel & 0x0f));         /*
583                                                                          * Channel pressure
584                                                                          */
585         } else if (!prefix_cmd(orig_dev, pressure))
586                 return;
587 
588         midi_outc(orig_dev, pressure);
589 }
590 EXPORT_SYMBOL(midi_synth_aftertouch);
591 
592 void
593 midi_synth_controller(int dev, int channel, int ctrl_num, int value)
594 {
595         int             orig_dev = synth_devs[dev]->midi_dev;
596         int             chn, msg;
597 
598         if (ctrl_num < 0 || ctrl_num > 127)
599                 return;
600         if (channel < 0 || channel > 15)
601                 return;
602 
603         leave_sysex(dev);
604 
605         msg = prev_out_status[orig_dev] & 0xf0;
606         chn = prev_out_status[orig_dev] & 0x0f;
607 
608         if (msg != 0xb0 || chn != channel)
609           {
610                   if (!prefix_cmd(orig_dev, 0xb0 | (channel & 0x0f)))
611                           return;
612                   midi_outc(orig_dev, 0xb0 | (channel & 0x0f));
613         } else if (!prefix_cmd(orig_dev, ctrl_num))
614                 return;
615 
616         midi_outc(orig_dev, ctrl_num);
617         midi_outc(orig_dev, value & 0x7f);
618 }
619 EXPORT_SYMBOL(midi_synth_controller);
620 
621 void
622 midi_synth_bender(int dev, int channel, int value)
623 {
624         int             orig_dev = synth_devs[dev]->midi_dev;
625         int             msg, prev_chn;
626 
627         if (channel < 0 || channel > 15)
628                 return;
629 
630         if (value < 0 || value > 16383)
631                 return;
632 
633         leave_sysex(dev);
634 
635         msg = prev_out_status[orig_dev] & 0xf0;
636         prev_chn = prev_out_status[orig_dev] & 0x0f;
637 
638         if (msg != 0xd0 || prev_chn != channel)         /*
639                                                          * Test for running status
640                                                          */
641           {
642                   if (!prefix_cmd(orig_dev, 0xe0 | (channel & 0x0f)))
643                           return;
644                   midi_outc(orig_dev, 0xe0 | (channel & 0x0f));
645         } else if (!prefix_cmd(orig_dev, value & 0x7f))
646                 return;
647 
648         midi_outc(orig_dev, value & 0x7f);
649         midi_outc(orig_dev, (value >> 7) & 0x7f);
650 }
651 EXPORT_SYMBOL(midi_synth_bender);
652 
653 void
654 midi_synth_setup_voice(int dev, int voice, int channel)
655 {
656 }
657 EXPORT_SYMBOL(midi_synth_setup_voice);
658 
659 int
660 midi_synth_send_sysex(int dev, unsigned char *bytes, int len)
661 {
662         int             orig_dev = synth_devs[dev]->midi_dev;
663         int             i;
664 
665         for (i = 0; i < len; i++)
666           {
667                   switch (bytes[i])
668                     {
669                     case 0xf0:  /* Start sysex */
670                             if (!prefix_cmd(orig_dev, 0xf0))
671                                     return 0;
672                             sysex_state[dev] = 1;
673                             break;
674 
675                     case 0xf7:  /* End sysex */
676                             if (!sysex_state[dev])      /* Orphan sysex end */
677                                     return 0;
678                             sysex_state[dev] = 0;
679                             break;
680 
681                     default:
682                             if (!sysex_state[dev])
683                                     return 0;
684 
685                             if (bytes[i] & 0x80)        /* Error. Another message before sysex end */
686                               {
687                                       bytes[i] = 0xf7;  /* Sysex end */
688                                       sysex_state[dev] = 0;
689                               }
690                     }
691 
692                   if (!midi_devs[orig_dev]->outputc(orig_dev, bytes[i]))
693                     {
694 /*
695  * Hardware level buffer is full. Abort the sysex message.
696  */
697 
698                             int             timeout = 0;
699 
700                             bytes[i] = 0xf7;
701                             sysex_state[dev] = 0;
702 
703                             while (!midi_devs[orig_dev]->outputc(orig_dev, bytes[i]) &&
704                                    timeout < 1000)
705                                     timeout++;
706                     }
707                   if (!sysex_state[dev])
708                           return 0;
709           }
710 
711         return 0;
712 }
713 EXPORT_SYMBOL(midi_synth_send_sysex);
714 
715 
  This page was automatically generated by the LXR engine.