root/drivers/sound/midibuf.c

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

DEFINITIONS

This source file includes following definitions.
  1. drain_midi_queue
  2. midi_input_intr
  3. midi_output_intr
  4. midi_poll
  5. MIDIbuf_open
  6. MIDIbuf_release
  7. MIDIbuf_write
  8. MIDIbuf_read
  9. MIDIbuf_ioctl
  10. MIDIbuf_select
  11. MIDIbuf_init

   1 /*
   2  * sound/midibuf.c
   3  *
   4  * Device file manager for /dev/midi#
   5  */
   6 /*
   7  * Copyright by Hannu Savolainen 1993-1996
   8  *
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions are
  11  * met: 1. Redistributions of source code must retain the above copyright
  12  * notice, this list of conditions and the following disclaimer. 2.
  13  * Redistributions in binary form must reproduce the above copyright notice,
  14  * this list of conditions and the following disclaimer in the documentation
  15  * and/or other materials provided with the distribution.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 #include <linux/config.h>
  30 
  31 
  32 #include "sound_config.h"
  33 
  34 #if defined(CONFIG_MIDI)
  35 
  36 /*
  37  * Don't make MAX_QUEUE_SIZE larger than 4000
  38  */
  39 
  40 #define MAX_QUEUE_SIZE  4000
  41 
  42 static wait_handle *midi_sleeper[MAX_MIDI_DEV] =
  43 {NULL};
  44 static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] =
  45 {
  46   {0}};
  47 static wait_handle *input_sleeper[MAX_MIDI_DEV] =
  48 {NULL};
  49 static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] =
  50 {
  51   {0}};
  52 
  53 struct midi_buf
  54   {
  55     int             len, head, tail;
  56     unsigned char   queue[MAX_QUEUE_SIZE];
  57   };
  58 
  59 struct midi_parms
  60   {
  61     int             prech_timeout;      /*
  62                                          * Timeout before the first ch
  63                                          */
  64   };
  65 
  66 static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] =
  67 {NULL};
  68 static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] =
  69 {NULL};
  70 static struct midi_parms parms[MAX_MIDI_DEV];
  71 
  72 static void     midi_poll (unsigned long dummy);
  73 
  74 
  75 static struct timer_list poll_timer =
  76 {NULL, NULL, 0, 0, midi_poll};
  77 static volatile int open_devs = 0;
  78 
  79 #define DATA_AVAIL(q) (q->len)
  80 #define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
  81 
  82 #define QUEUE_BYTE(q, data) \
  83         if (SPACE_AVAIL(q)) \
  84         { \
  85           unsigned long flags; \
  86           save_flags(flags);cli(); \
  87           q->queue[q->tail] = (data); \
  88           q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
  89           restore_flags(flags); \
  90         }
  91 
  92 #define REMOVE_BYTE(q, data) \
  93         if (DATA_AVAIL(q)) \
  94         { \
  95           unsigned long flags; \
  96           save_flags(flags);cli(); \
  97           data = q->queue[q->head]; \
  98           q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
  99           restore_flags(flags); \
 100         }
 101 
 102 void
 103 drain_midi_queue (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105 
 106   /*
 107    * Give the Midi driver time to drain its output queues
 108    */
 109 
 110   if (midi_devs[dev]->buffer_status != NULL)
 111     while (!current_got_fatal_signal () &&
 112            midi_devs[dev]->buffer_status (dev))
 113 
 114       {
 115         unsigned long   tl;
 116 
 117         if (HZ / 10)
 118           current_set_timeout (tl = jiffies + (HZ / 10));
 119         else
 120           tl = (unsigned long) -1;
 121         midi_sleep_flag[dev].mode = WK_SLEEP;
 122         module_interruptible_sleep_on (&midi_sleeper[dev]);
 123         if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
 124           {
 125             if (jiffies >= tl)
 126               midi_sleep_flag[dev].mode |= WK_TIMEOUT;
 127           }
 128         midi_sleep_flag[dev].mode &= ~WK_SLEEP;
 129       };
 130 }
 131 
 132 static void
 133 midi_input_intr (int dev, unsigned char data)
     /* [previous][next][first][last][top][bottom][index][help] */
 134 {
 135   if (midi_in_buf[dev] == NULL)
 136     return;
 137 
 138   if (data == 0xfe)             /*
 139                                  * Active sensing
 140                                  */
 141     return;                     /*
 142                                  * Ignore
 143                                  */
 144 
 145   if (SPACE_AVAIL (midi_in_buf[dev]))
 146     {
 147       QUEUE_BYTE (midi_in_buf[dev], data);
 148       if ((input_sleep_flag[dev].mode & WK_SLEEP))
 149         {
 150           input_sleep_flag[dev].mode = WK_WAKEUP;
 151           module_wake_up (&input_sleeper[dev]);
 152         };
 153     }
 154 
 155 }
 156 
 157 static void
 158 midi_output_intr (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160   /*
 161    * Currently NOP
 162    */
 163 }
 164 
 165 static void
 166 midi_poll (unsigned long dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168   unsigned long   flags;
 169   int             dev;
 170 
 171   save_flags (flags);
 172   cli ();
 173   if (open_devs)
 174     {
 175       for (dev = 0; dev < num_midis; dev++)
 176         if (midi_out_buf[dev] != NULL)
 177           {
 178             while (DATA_AVAIL (midi_out_buf[dev]) &&
 179                    midi_devs[dev]->putc (dev,
 180                          midi_out_buf[dev]->queue[midi_out_buf[dev]->head]))
 181               {
 182                 midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
 183                 midi_out_buf[dev]->len--;
 184               }
 185 
 186             if (DATA_AVAIL (midi_out_buf[dev]) < 100 &&
 187                 (midi_sleep_flag[dev].mode & WK_SLEEP))
 188               {
 189                 midi_sleep_flag[dev].mode = WK_WAKEUP;
 190                 module_wake_up (&midi_sleeper[dev]);
 191               };
 192           }
 193 
 194       {
 195         poll_timer.expires = (1) + jiffies;
 196         add_timer (&poll_timer);
 197       };                        /*
 198                                    * Come back later
 199                                  */
 200     }
 201   restore_flags (flags);
 202 }
 203 
 204 int
 205 MIDIbuf_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 206 {
 207   int             mode, err;
 208 
 209   dev = dev >> 4;
 210   mode = file->mode & O_ACCMODE;
 211 
 212   if (num_midis > MAX_MIDI_DEV)
 213     {
 214       printk ("Sound: FATAL ERROR: Too many midi interfaces\n");
 215       num_midis = MAX_MIDI_DEV;
 216     }
 217 
 218   if (dev < 0 || dev >= num_midis)
 219     {
 220       printk ("Sound: Nonexistent MIDI interface %d\n", dev);
 221       return -ENXIO;
 222     }
 223 
 224   /*
 225      *    Interrupts disabled. Be careful
 226    */
 227 
 228   if ((err = midi_devs[dev]->open (dev, mode,
 229                                    midi_input_intr, midi_output_intr)) < 0)
 230     {
 231       return err;
 232     }
 233 
 234   parms[dev].prech_timeout = 0;
 235 
 236   midi_in_buf[dev] = (struct midi_buf *) kmalloc (sizeof (struct midi_buf), GFP_KERNEL);
 237 
 238   if (midi_in_buf[dev] == NULL)
 239     {
 240       printk ("midi: Can't allocate buffer\n");
 241       midi_devs[dev]->close (dev);
 242       return -EIO;
 243     }
 244   midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
 245 
 246   midi_out_buf[dev] = (struct midi_buf *) kmalloc (sizeof (struct midi_buf), GFP_KERNEL);
 247 
 248   if (midi_out_buf[dev] == NULL)
 249     {
 250       printk ("midi: Can't allocate buffer\n");
 251       midi_devs[dev]->close (dev);
 252       kfree (midi_in_buf[dev]);
 253       midi_in_buf[dev] = NULL;
 254       return -EIO;
 255     }
 256   midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
 257   open_devs++;
 258 
 259   midi_sleep_flag[dev].mode = WK_NONE;
 260   input_sleep_flag[dev].mode = WK_NONE;
 261 
 262   if (open_devs < 2)            /* This was first open */
 263     {
 264       ;
 265 
 266       {
 267         poll_timer.expires = (1) + jiffies;
 268         add_timer (&poll_timer);
 269       };                        /* Start polling */
 270     }
 271 
 272   return err;
 273 }
 274 
 275 void
 276 MIDIbuf_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 277 {
 278   int             mode;
 279   unsigned long   flags;
 280 
 281   dev = dev >> 4;
 282   mode = file->mode & O_ACCMODE;
 283 
 284   if (dev < 0 || dev >= num_midis)
 285     return;
 286 
 287   save_flags (flags);
 288   cli ();
 289 
 290   /*
 291      * Wait until the queue is empty
 292    */
 293 
 294   if (mode != OPEN_READ)
 295     {
 296       midi_devs[dev]->putc (dev, 0xfe);         /*
 297                                                    * Active sensing to shut the
 298                                                    * devices
 299                                                  */
 300 
 301       while (!current_got_fatal_signal () &&
 302              DATA_AVAIL (midi_out_buf[dev]))
 303 
 304         {
 305           unsigned long   tl;
 306 
 307           if (0)
 308             current_set_timeout (tl = jiffies + (0));
 309           else
 310             tl = (unsigned long) -1;
 311           midi_sleep_flag[dev].mode = WK_SLEEP;
 312           module_interruptible_sleep_on (&midi_sleeper[dev]);
 313           if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
 314             {
 315               if (jiffies >= tl)
 316                 midi_sleep_flag[dev].mode |= WK_TIMEOUT;
 317             }
 318           midi_sleep_flag[dev].mode &= ~WK_SLEEP;
 319         };                      /*
 320                                    * Sync
 321                                  */
 322 
 323       drain_midi_queue (dev);   /*
 324                                  * Ensure the output queues are empty
 325                                  */
 326     }
 327 
 328   restore_flags (flags);
 329 
 330   midi_devs[dev]->close (dev);
 331 
 332   kfree (midi_in_buf[dev]);
 333   kfree (midi_out_buf[dev]);
 334   midi_in_buf[dev] = NULL;
 335   midi_out_buf[dev] = NULL;
 336   if (open_devs < 2)
 337     del_timer (&poll_timer);;
 338   open_devs--;
 339 }
 340 
 341 int
 342 MIDIbuf_write (int dev, struct fileinfo *file, const char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 343 {
 344   unsigned long   flags;
 345   int             c, n, i;
 346   unsigned char   tmp_data;
 347 
 348   dev = dev >> 4;
 349 
 350   if (!count)
 351     return 0;
 352 
 353   save_flags (flags);
 354   cli ();
 355 
 356   c = 0;
 357 
 358   while (c < count)
 359     {
 360       n = SPACE_AVAIL (midi_out_buf[dev]);
 361 
 362       if (n == 0)               /*
 363                                  * No space just now. We have to sleep
 364                                  */
 365         {
 366 
 367           {
 368             unsigned long   tl;
 369 
 370             if (0)
 371               current_set_timeout (tl = jiffies + (0));
 372             else
 373               tl = (unsigned long) -1;
 374             midi_sleep_flag[dev].mode = WK_SLEEP;
 375             module_interruptible_sleep_on (&midi_sleeper[dev]);
 376             if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
 377               {
 378                 if (jiffies >= tl)
 379                   midi_sleep_flag[dev].mode |= WK_TIMEOUT;
 380               }
 381             midi_sleep_flag[dev].mode &= ~WK_SLEEP;
 382           };
 383           if (current_got_fatal_signal ())
 384             {
 385               restore_flags (flags);
 386               return -EINTR;
 387             }
 388 
 389           n = SPACE_AVAIL (midi_out_buf[dev]);
 390         }
 391 
 392       if (n > (count - c))
 393         n = count - c;
 394 
 395       for (i = 0; i < n; i++)
 396         {
 397           memcpy_fromfs ((char *) &tmp_data, &((buf)[c]), 1);
 398           QUEUE_BYTE (midi_out_buf[dev], tmp_data);
 399           c++;
 400         }
 401     }
 402 
 403   restore_flags (flags);
 404 
 405   return c;
 406 }
 407 
 408 
 409 int
 410 MIDIbuf_read (int dev, struct fileinfo *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 411 {
 412   int             n, c = 0;
 413   unsigned long   flags;
 414   unsigned char   tmp_data;
 415 
 416   dev = dev >> 4;
 417 
 418   save_flags (flags);
 419   cli ();
 420 
 421   if (!DATA_AVAIL (midi_in_buf[dev]))   /*
 422                                          * No data yet, wait
 423                                          */
 424     {
 425 
 426       {
 427         unsigned long   tl;
 428 
 429         if (parms[dev].prech_timeout)
 430           current_set_timeout (tl = jiffies + (parms[dev].prech_timeout));
 431         else
 432           tl = (unsigned long) -1;
 433         input_sleep_flag[dev].mode = WK_SLEEP;
 434         module_interruptible_sleep_on (&input_sleeper[dev]);
 435         if (!(input_sleep_flag[dev].mode & WK_WAKEUP))
 436           {
 437             if (jiffies >= tl)
 438               input_sleep_flag[dev].mode |= WK_TIMEOUT;
 439           }
 440         input_sleep_flag[dev].mode &= ~WK_SLEEP;
 441       };
 442       if (current_got_fatal_signal ())
 443         c = -EINTR;             /*
 444                                    * The user is getting restless
 445                                  */
 446     }
 447 
 448   if (c == 0 && DATA_AVAIL (midi_in_buf[dev]))  /*
 449                                                  * Got some bytes
 450                                                  */
 451     {
 452       n = DATA_AVAIL (midi_in_buf[dev]);
 453       if (n > count)
 454         n = count;
 455       c = 0;
 456 
 457       while (c < n)
 458         {
 459           REMOVE_BYTE (midi_in_buf[dev], tmp_data);
 460           memcpy_tofs (&((buf)[c]), (char *) &tmp_data, 1);
 461           c++;
 462         }
 463     }
 464 
 465   restore_flags (flags);
 466 
 467   return c;
 468 }
 469 
 470 int
 471 MIDIbuf_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 472                unsigned int cmd, caddr_t arg)
 473 {
 474   int             val;
 475 
 476   dev = dev >> 4;
 477 
 478   if (((cmd >> 8) & 0xff) == 'C')
 479     {
 480       if (midi_devs[dev]->coproc)       /* Coprocessor ioctl */
 481         return midi_devs[dev]->coproc->ioctl (midi_devs[dev]->coproc->devc, cmd, arg, 0);
 482       else
 483         printk ("/dev/midi%d: No coprocessor for this device\n", dev);
 484 
 485       return -ENXIO;
 486     }
 487   else
 488     switch (cmd)
 489       {
 490 
 491       case SNDCTL_MIDI_PRETIME:
 492         val = (int) get_fs_long ((long *) arg);
 493         if (val < 0)
 494           val = 0;
 495 
 496         val = (HZ * val) / 10;
 497         parms[dev].prech_timeout = val;
 498         return snd_ioctl_return ((int *) arg, val);
 499         break;
 500 
 501       default:
 502         return midi_devs[dev]->ioctl (dev, cmd, arg);
 503       }
 504 }
 505 
 506 int
 507 MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 508 {
 509   dev = dev >> 4;
 510 
 511   switch (sel_type)
 512     {
 513     case SEL_IN:
 514       if (!DATA_AVAIL (midi_in_buf[dev]))
 515         {
 516           input_sleep_flag[dev].mode = WK_SLEEP;
 517           module_select_wait (&input_sleeper[dev], wait);
 518           return 0;
 519         }
 520       return 1;
 521       break;
 522 
 523     case SEL_OUT:
 524       if (SPACE_AVAIL (midi_out_buf[dev]))
 525         {
 526           midi_sleep_flag[dev].mode = WK_SLEEP;
 527           module_select_wait (&midi_sleeper[dev], wait);
 528           return 0;
 529         }
 530       return 1;
 531       break;
 532 
 533     case SEL_EX:
 534       return 0;
 535     }
 536 
 537   return 0;
 538 }
 539 
 540 
 541 long
 542 MIDIbuf_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 543 {
 544   return mem_start;
 545 }
 546 
 547 #endif

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