root/drivers/sound/midi_synth.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. midi_outc
  2. prefix_cmd
  3. midi_synth_input
  4. midi_synth_output
  5. midi_synth_ioctl
  6. midi_synth_kill_note
  7. midi_synth_set_instr
  8. midi_synth_start_note
  9. midi_synth_reset
  10. midi_synth_open
  11. midi_synth_close
  12. midi_synth_hw_control
  13. midi_synth_load_patch
  14. midi_synth_panning
  15. midi_synth_aftertouch
  16. midi_synth_controller
  17. midi_synth_patchmgr
  18. midi_synth_bender

   1 /*
   2  * sound/midi_synth.c
   3  *
   4  * High level midi sequencer manager for dumb MIDI interfaces.
   5  *
   6  * Copyright by Hannu Savolainen 1993
   7  *
   8  * Redistribution and use in source and binary forms, with or without
   9  * modification, are permitted provided that the following conditions are
  10  * met: 1. Redistributions of source code must retain the above copyright
  11  * notice, this list of conditions and the following disclaimer. 2.
  12  * Redistributions in binary form must reproduce the above copyright notice,
  13  * this list of conditions and the following disclaimer in the documentation
  14  * and/or other materials provided with the distribution.
  15  *
  16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26  * SUCH DAMAGE.
  27  *
  28  */
  29 
  30 #include "sound_config.h"
  31 
  32 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI)
  33 
  34 #define _MIDI_SYNTH_C_
  35 
  36 DEFINE_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag);
  37 
  38 #include "midi_synth.h"
  39 
  40 static int      midi2synth[MAX_MIDI_DEV];
  41 static unsigned char prev_out_status[MAX_MIDI_DEV];
  42 
  43 static void
  44 midi_outc (int midi_dev, int data)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46   int             timeout;
  47 
  48   for (timeout = 0; timeout < 32000; timeout++)
  49     if (midi_devs[midi_dev]->putc (midi_dev, (unsigned char) (data & 0xff)))
  50       {
  51         if (data & 0x80)        /*
  52                                  * Status byte
  53                                  */
  54           prev_out_status[midi_dev] =
  55             (unsigned char) (data & 0xff);      /*
  56                                                  * Store for running status
  57                                                  */
  58         return;                 /*
  59                                  * Mission complete
  60                                  */
  61       }
  62 
  63   /*
  64    * Sorry! No space on buffers.
  65    */
  66   printk ("Midi send timed out\n");
  67 }
  68 
  69 static int
  70 prefix_cmd (int midi_dev, unsigned char status)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72   if (midi_devs[midi_dev]->prefix_cmd == NULL)
  73     return 1;
  74 
  75   return midi_devs[midi_dev]->prefix_cmd (midi_dev, status);
  76 }
  77 
  78 static void
  79 midi_synth_input (int dev, unsigned char data)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81   int             orig_dev;
  82 
  83   if (dev < 0 || dev > num_synths)
  84     return;
  85 
  86   if (data == 0xfe)             /* Ignore active sensing */
  87     return;
  88 
  89   orig_dev = midi2synth[dev];
  90 
  91 }
  92 
  93 static void
  94 midi_synth_output (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  95 {
  96   /*
  97    * Currently NOP
  98    */
  99 }
 100 
 101 int
 102 midi_synth_ioctl (int dev,
     /* [previous][next][first][last][top][bottom][index][help] */
 103                   unsigned int cmd, unsigned int arg)
 104 {
 105   /*
 106    * int orig_dev = synth_devs[dev]->midi_dev;
 107    */
 108 
 109   switch (cmd)
 110     {
 111 
 112     case SNDCTL_SYNTH_INFO:
 113       IOCTL_TO_USER ((char *) arg, 0, synth_devs[dev]->info,
 114                      sizeof (struct synth_info));
 115 
 116       return 0;
 117       break;
 118 
 119     case SNDCTL_SYNTH_MEMAVL:
 120       return 0x7fffffff;
 121       break;
 122 
 123     default:
 124       return RET_ERROR (EINVAL);
 125     }
 126 }
 127 
 128 int
 129 midi_synth_kill_note (int dev, int channel, int note, int velocity)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131   int             orig_dev = synth_devs[dev]->midi_dev;
 132   int             msg, chn;
 133 
 134   if (note < 0 || note > 127)
 135     return 0;
 136   if (channel < 0 || channel > 15)
 137     return 0;
 138   if (velocity < 0)
 139     velocity = 0;
 140   if (velocity > 127)
 141     velocity = 127;
 142 
 143   msg = prev_out_status[orig_dev] & 0xf0;
 144   chn = prev_out_status[orig_dev] & 0x0f;
 145 
 146   if (chn == channel && ((msg == 0x90 && velocity == 64) || msg == 0x80))
 147     {                           /*
 148                                  * Use running status
 149                                  */
 150       if (!prefix_cmd (orig_dev, note))
 151         return 0;
 152 
 153       midi_outc (orig_dev, note);
 154 
 155       if (msg == 0x90)          /*
 156                                  * Running status = Note on
 157                                  */
 158         midi_outc (orig_dev, 0);/*
 159                                          * Note on with velocity 0 == note
 160                                          * off
 161                                          */
 162       else
 163         midi_outc (orig_dev, velocity);
 164     }
 165   else
 166     {
 167       if (velocity == 64)
 168         {
 169           if (!prefix_cmd (orig_dev, 0x90 | (channel & 0x0f)))
 170             return 0;
 171           midi_outc (orig_dev, 0x90 | (channel & 0x0f));        /*
 172                                                                  * Note on
 173                                                                  */
 174           midi_outc (orig_dev, note);
 175           midi_outc (orig_dev, 0);      /*
 176                                          * Zero G
 177                                          */
 178         }
 179       else
 180         {
 181           if (!prefix_cmd (orig_dev, 0x80 | (channel & 0x0f)))
 182             return 0;
 183           midi_outc (orig_dev, 0x80 | (channel & 0x0f));        /*
 184                                                                  * Note off
 185                                                                  */
 186           midi_outc (orig_dev, note);
 187           midi_outc (orig_dev, velocity);
 188         }
 189     }
 190 
 191   return 0;
 192 }
 193 
 194 int
 195 midi_synth_set_instr (int dev, int channel, int instr_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197   int             orig_dev = synth_devs[dev]->midi_dev;
 198 
 199   if (instr_no < 0 || instr_no > 127)
 200     return 0;
 201   if (channel < 0 || channel > 15)
 202     return 0;
 203 
 204   if (!prefix_cmd (orig_dev, 0xc0 | (channel & 0x0f)))
 205     return 0;
 206   midi_outc (orig_dev, 0xc0 | (channel & 0x0f));        /*
 207                                                          * Program change
 208                                                          */
 209   midi_outc (orig_dev, instr_no);
 210 
 211   return 0;
 212 }
 213 
 214 int
 215 midi_synth_start_note (int dev, int channel, int note, int velocity)
     /* [previous][next][first][last][top][bottom][index][help] */
 216 {
 217   int             orig_dev = synth_devs[dev]->midi_dev;
 218   int             msg, chn;
 219 
 220   if (note < 0 || note > 127)
 221     return 0;
 222   if (channel < 0 || channel > 15)
 223     return 0;
 224   if (velocity < 0)
 225     velocity = 0;
 226   if (velocity > 127)
 227     velocity = 127;
 228 
 229   msg = prev_out_status[orig_dev] & 0xf0;
 230   chn = prev_out_status[orig_dev] & 0x0f;
 231 
 232   if (chn == channel && msg == 0x90)
 233     {                           /*
 234                                  * Use running status
 235                                  */
 236       if (!prefix_cmd (orig_dev, note))
 237         return 0;
 238       midi_outc (orig_dev, note);
 239       midi_outc (orig_dev, velocity);
 240     }
 241   else
 242     {
 243       if (!prefix_cmd (orig_dev, 0x90 | (channel & 0x0f)))
 244         return 0;
 245       midi_outc (orig_dev, 0x90 | (channel & 0x0f));    /*
 246                                                          * Note on
 247                                                          */
 248       midi_outc (orig_dev, note);
 249       midi_outc (orig_dev, velocity);
 250     }
 251   return 0;
 252 }
 253 
 254 void
 255 midi_synth_reset (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 256 {
 257 }
 258 
 259 int
 260 midi_synth_open (int dev, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 261 {
 262   int             orig_dev = synth_devs[dev]->midi_dev;
 263   int             err;
 264 
 265   if (orig_dev < 0 || orig_dev > num_midis)
 266     return RET_ERROR (ENXIO);
 267 
 268   midi2synth[orig_dev] = dev;
 269   prev_out_status[orig_dev] = 0;
 270 
 271   if ((err = midi_devs[orig_dev]->open (orig_dev, mode,
 272                                   midi_synth_input, midi_synth_output)) < 0)
 273     return err;
 274 
 275   return 1;
 276 }
 277 
 278 void
 279 midi_synth_close (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281   int             orig_dev = synth_devs[dev]->midi_dev;
 282 
 283   /*
 284  * Shut up the synths by sending just single active sensing message.
 285  */
 286   midi_devs[orig_dev]->putc (orig_dev, 0xfe);
 287 
 288   midi_devs[orig_dev]->close (orig_dev);
 289 }
 290 
 291 void
 292 midi_synth_hw_control (int dev, unsigned char *event)
     /* [previous][next][first][last][top][bottom][index][help] */
 293 {
 294 }
 295 
 296 int
 297 midi_synth_load_patch (int dev, int format, snd_rw_buf * addr,
     /* [previous][next][first][last][top][bottom][index][help] */
 298                        int offs, int count, int pmgr_flag)
 299 {
 300   int             orig_dev = synth_devs[dev]->midi_dev;
 301 
 302   struct sysex_info sysex;
 303   int             i;
 304   unsigned long   left, src_offs, eox_seen = 0;
 305   int             first_byte = 1;
 306 
 307   if (!prefix_cmd (orig_dev, 0xf0))
 308     return 0;
 309 
 310   if (format != SYSEX_PATCH)
 311     {
 312       printk ("MIDI Error: Invalid patch format (key) 0x%x\n", format);
 313       return RET_ERROR (EINVAL);
 314     }
 315 
 316   if (count < sizeof (struct sysex_info))
 317     {
 318       printk ("MIDI Error: Patch header too short\n");
 319       return RET_ERROR (EINVAL);
 320     }
 321 
 322   count -= sizeof (struct sysex_info);
 323 
 324   /*
 325    * Copy the header from user space but ignore the first bytes which have
 326    * been transferred already.
 327    */
 328 
 329   COPY_FROM_USER (&((char *) &sysex)[offs], addr, offs, sizeof (struct sysex_info) - offs);
 330 
 331   if (count < sysex.len)
 332     {
 333       printk ("MIDI Warning: Sysex record too short (%d<%d)\n",
 334               count, (int) sysex.len);
 335       sysex.len = count;
 336     }
 337 
 338   left = sysex.len;
 339   src_offs = 0;
 340 
 341   RESET_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag);
 342 
 343   for (i = 0; i < left && !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag); i++)
 344     {
 345       unsigned char   data;
 346 
 347       GET_BYTE_FROM_USER (data, addr, sizeof (struct sysex_info) + i);
 348 
 349       if (first_byte && data != 0xf0)
 350         midi_outc (orig_dev, 0xf0);     /* Sysex start */
 351 
 352       eox_seen = (data == 0xf7);/*
 353                                          * Last byte was end of sysex
 354                                          */
 355 
 356       if (i == 0)
 357         {
 358           if (data != 0xf0)     /*
 359                                  * Sysex start
 360                                  */
 361             return RET_ERROR (EINVAL);
 362         }
 363 
 364       while (!midi_devs[orig_dev]->putc (orig_dev, (unsigned char) (data & 0xff)) &&
 365              !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag))
 366         DO_SLEEP (sysex_sleeper, sysex_sleep_flag, 1);  /* Wait for timeout */
 367 
 368       if (!first_byte && data & 0x80)
 369         return 0;
 370       first_byte = 0;
 371     }
 372 
 373   if (!eox_seen)
 374     midi_outc (orig_dev, 0xf7);
 375   return 0;
 376 }
 377 
 378 void
 379 midi_synth_panning (int dev, int channel, int pressure)
     /* [previous][next][first][last][top][bottom][index][help] */
 380 {
 381 }
 382 
 383 void
 384 midi_synth_aftertouch (int dev, int channel, int pressure)
     /* [previous][next][first][last][top][bottom][index][help] */
 385 {
 386   int             orig_dev = synth_devs[dev]->midi_dev;
 387   int             msg, chn;
 388 
 389   if (pressure < 0 || pressure > 127)
 390     return;
 391   if (channel < 0 || channel > 15)
 392     return;
 393 
 394   msg = prev_out_status[orig_dev] & 0xf0;
 395   chn = prev_out_status[orig_dev] & 0x0f;
 396 
 397   if (msg != 0xd0 || chn != channel)    /*
 398                                          * Test for running status
 399                                          */
 400     {
 401       if (!prefix_cmd (orig_dev, 0xd0 | (channel & 0x0f)))
 402         return;
 403       midi_outc (orig_dev, 0xd0 | (channel & 0x0f));    /*
 404                                                          * Channel pressure
 405                                                          */
 406     }
 407   else if (!prefix_cmd (orig_dev, pressure))
 408     return;
 409   midi_outc (orig_dev, pressure);
 410 }
 411 
 412 void
 413 midi_synth_controller (int dev, int channel, int ctrl_num, int value)
     /* [previous][next][first][last][top][bottom][index][help] */
 414 {
 415   int             orig_dev = synth_devs[dev]->midi_dev;
 416   int             chn, msg;
 417 
 418   if (ctrl_num < 1 || ctrl_num > 127)
 419     return;                     /* NOTE! Controller # 0 ignored */
 420   if (channel < 0 || channel > 15)
 421     return;
 422 
 423   msg = prev_out_status[orig_dev] & 0xf0;
 424   chn = prev_out_status[orig_dev] & 0x0f;
 425 
 426   if (msg != 0xb0 || chn != channel)
 427     {
 428       if (!prefix_cmd (orig_dev, 0xb0 | (channel & 0x0f)))
 429         return;
 430       midi_outc (orig_dev, 0xb0 | (channel & 0x0f));
 431     }
 432   else if (!prefix_cmd (orig_dev, ctrl_num))
 433     return;
 434 
 435   midi_outc (orig_dev, ctrl_num);
 436   midi_outc (orig_dev, value & 0x7f);
 437 }
 438 
 439 int
 440 midi_synth_patchmgr (int dev, struct patmgr_info *rec)
     /* [previous][next][first][last][top][bottom][index][help] */
 441 {
 442   return RET_ERROR (EINVAL);
 443 }
 444 
 445 void
 446 midi_synth_bender (int dev, int channel, int value)
     /* [previous][next][first][last][top][bottom][index][help] */
 447 {
 448   int             orig_dev = synth_devs[dev]->midi_dev;
 449   int             msg, prev_chn;
 450 
 451   if (channel < 0 || channel > 15)
 452     return;
 453 
 454   if (value < 0 || value > 16383)
 455     return;
 456 
 457   msg = prev_out_status[orig_dev] & 0xf0;
 458   prev_chn = prev_out_status[orig_dev] & 0x0f;
 459 
 460   if (msg != 0xd0 || prev_chn != channel)       /*
 461                                                  * * Test for running status  */
 462     {
 463       if (!prefix_cmd (orig_dev, 0xe0 | (channel & 0x0f)))
 464         return;
 465       midi_outc (orig_dev, 0xe0 | (channel & 0x0f));
 466     }
 467   else if (!prefix_cmd (orig_dev, value & 0x7f))
 468     return;
 469 
 470   midi_outc (orig_dev, value & 0x7f);
 471   midi_outc (orig_dev, (value >> 7) & 0x7f);
 472 }
 473 
 474 #endif

/* [previous][next][first][last][top][bottom][index][help] */