linux/sound/oss/midi_synth.c
<<
>>
Prefs
   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
  26static int      midi2synth[MAX_MIDI_DEV];
  27static int      sysex_state[MAX_MIDI_DEV] =
  28{0};
  29static 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
  43void
  44do_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}
  87EXPORT_SYMBOL(do_midi_msg);
  88
  89static void
  90midi_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
 114static int
 115prefix_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
 123static void
 124midi_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
 234static void
 235leave_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
 252static void
 253midi_synth_output(int dev)
 254{
 255        /*
 256         * Currently NOP
 257         */
 258}
 259
 260int 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}
 280EXPORT_SYMBOL(midi_synth_ioctl);
 281
 282int
 283midi_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}
 347EXPORT_SYMBOL(midi_synth_kill_note);
 348
 349int
 350midi_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}
 370EXPORT_SYMBOL(midi_synth_set_instr);
 371
 372int
 373midi_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}
 412EXPORT_SYMBOL(midi_synth_start_note);
 413
 414void
 415midi_synth_reset(int dev)
 416{
 417
 418        leave_sysex(dev);
 419}
 420EXPORT_SYMBOL(midi_synth_reset);
 421
 422int
 423midi_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}
 453EXPORT_SYMBOL(midi_synth_open);
 454
 455void
 456midi_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}
 469EXPORT_SYMBOL(midi_synth_close);
 470
 471void
 472midi_synth_hw_control(int dev, unsigned char *event)
 473{
 474}
 475EXPORT_SYMBOL(midi_synth_hw_control);
 476
 477int
 478midi_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}
 552EXPORT_SYMBOL(midi_synth_load_patch);
 553
 554void midi_synth_panning(int dev, int channel, int pressure)
 555{
 556}
 557EXPORT_SYMBOL(midi_synth_panning);
 558
 559void 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}
 588EXPORT_SYMBOL(midi_synth_aftertouch);
 589
 590void
 591midi_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}
 617EXPORT_SYMBOL(midi_synth_controller);
 618
 619void
 620midi_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}
 649EXPORT_SYMBOL(midi_synth_bender);
 650
 651void
 652midi_synth_setup_voice(int dev, int voice, int channel)
 653{
 654}
 655EXPORT_SYMBOL(midi_synth_setup_voice);
 656
 657int
 658midi_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}
 711EXPORT_SYMBOL(midi_synth_send_sysex);
 712
 713
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.